Cloud Auth

Cloud auth is what lets you safely put the panel somewhere beyond a trusted LAN — a single seeded login, in front of the CEO's view of the company. It is off by default; while off, RoboCo behaves byte-for-byte as it always has (header-trust — see Security).

This is not a general multi-user login system

There is exactly one user: you, the CEO. There is no registration route, no invite flow, no roles beyond CEO. Cloud auth exists to put a lock on the door, not to onboard a team.

What it does

With ROBOCO_CLOUD_AUTH_ENABLED=true:

  • Exactly one user is seeded — from ROBOCO_CLOUD_AUTH_EMAIL / ROBOCO_CLOUD_AUTH_PASSWORD — the moment the flag is armed. No registration router is mounted; there is no way to create a second account.
  • A login issues a session cookie (roboco_session) — an HTTP-only, SameSite=Lax, secure-only cookie carrying a signed JWT.
  • The session is sliding: every authenticated request re-mints and re-sets the cookie, so an active session never lapses. Only genuine inactivity past ROBOCO_CLOUD_AUTH_COOKIE_MAX_AGE (default 2,592,000 seconds — 30 days) logs you out.
  • Rotating your seeded password invalidates every previously-issued session cookie immediately — the token carries a fingerprint of the current password hash, so an old cookie stops working the moment the password changes, without needing a token-revocation list.
  • With the flag off, GET /auth/status still always responds (the panel's middleware polls it before every navigation to know whether to show a login screen); the login/logout routes themselves don't exist until the flag is on.

It closes the header-spoof hole, not just adds a login screen

Cloud auth isn't only "add a password before the dashboard." It changes what the API trusts. Off, every request is header-trust: whoever sets X-Agent-Role: ceo is the CEO for that request — the whole point of the default LAN-only posture. On, header-trust for the CEO role is killed:

  • A caller with a valid agent HMAC token (X-Agent-Token) is verified exactly as before — the agent fleet is untouched by this flag.
  • A caller claiming a role without a verifiable token is treated as a spoof and rejected with 401 — including a claimed ceo role.
  • The only way to authenticate as the CEO without a token is a valid session cookie.

The login page isn't the only thing that can mint that cookie: with the Telegram Mini App armed (its own env-only flag, on top of cloud auth), opening the bot's menu button validates Telegram's signed launch data server-side and issues the identical roboco_session cookie — a second front door onto the same session mechanism, not a second trust path.

See API auth for how these two paths — the session cookie and the agent token — sit side by side.

Required configuration

VariableRequired?Notes
ROBOCO_CLOUD_AUTH_ENABLEDMaster switchOff by default. Not a panel toggle — it changes authentication behavior, so it's environment-only.
ROBOCO_CLOUD_AUTH_EMAILYes, when enabledLogin email for the single seeded user.
ROBOCO_CLOUD_AUTH_PASSWORDYes, when enabledLogin password for the single seeded user. Hashed at startup; never stored in plain text.
ROBOCO_CLOUD_AUTH_SECRETYes, when enabled — fails loud otherwiseSigns the session JWT. Generate with python -c 'import secrets; print(secrets.token_hex(32))'.
ROBOCO_CLOUD_AUTH_COOKIE_MAX_AGENo (default 2592000, 30 days)Sliding session lifetime in seconds.
Startup fails loud without the secret

If ROBOCO_CLOUD_AUTH_ENABLED=true and ROBOCO_CLOUD_AUTH_SECRET is unset, the orchestrator refuses to start — it will not silently mint unsigned sessions. Set the secret before you flip the flag, or the process won't come up at all.

The cookie is secure-only — you must be behind TLS

CookieTransport is configured cookie_secure=True. Browsers will not send a secure cookie over plain HTTP, so if you arm this flag without terminating TLS in front of RoboCo, login will appear to silently fail — the cookie is set by the response but never sent back on the next request. Terminate HTTPS before you enable cloud auth, whether that's a reverse proxy you add in front of nginx or a tunnel that provides TLS for you.

Enable it

  1. Decide on the login email/password for the one CEO user.
  2. Generate a session secret: python -c 'import secrets; print(secrets.token_hex(32))'.
  3. Put all three in your environment:
bash
1ROBOCO_CLOUD_AUTH_ENABLED=true2ROBOCO_CLOUD_AUTH_EMAIL=you@example.com3ROBOCO_CLOUD_AUTH_PASSWORD=<a strong password>4ROBOCO_CLOUD_AUTH_SECRET=<from the command above>5# ROBOCO_CLOUD_AUTH_COOKIE_MAX_AGE=2592000   # default, 30 days
  1. Make sure whatever sits in front of RoboCo terminates TLS.
  2. Leave ROBOCO_PANEL_AGENT_TOKEN unset — a set panel token bypasses login entirely (the panel would authenticate as the CEO via the injected HMAC token instead of a session), which defeats the point of arming a login.
  3. Restart the backend.
Test-deploying before credentials exist

If you want to bring the stack up before you've settled on real credentials, set ROBOCO_CLOUD_AUTH_ENABLED=false for that run — the compose defaults on the NAS path arm this flag, so an operator who hasn't set the three values yet should explicitly disable it rather than let the process fail to start.

What changes when it's on

  • The panel shows a login screen instead of going straight to the Command Center; GET /auth/status is what it polls to decide.
  • Every API request must carry either a valid X-Agent-Token or a valid session cookie — a bare role header is no longer trusted for ceo.
  • Logging in mints a 30-day sliding session; changing the seeded password invalidates every session at once.

Next

API auth — the session cookie and the agent HMAC token, side by side. → Telegram bridge — the Mini App, a second way to mint this session, from your phone. → Security — the full trust model, on or off. → back to Optional subsystems.

llms.txt