Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/agent0ai/space-agent/llms.txt

Use this file to discover all available pages before exploring further.

Space Agent’s security model separates concerns cleanly: backend secrets live outside the logical app tree, session cookies are HttpOnly and SameSite=Strict, user auth files are sealed with server-held keys that are never stored in the app tree, and Git-backed history is designed so a rollback can never restore old credentials. This page covers what to configure and what to avoid before exposing your server to the internet.

Backend Auth Secrets

For any production or multi-instance deployment, you must supply explicit shared secrets for password verification and session signing. Without these, the server generates and stores keys locally in server/data/auth_keys.json, which works for single-instance development but breaks cross-instance session validation and is not suitable for restartable production environments.
Never commit server/data/auth_keys.json to version control. It is gitignored by default, but if you copy or archive the repository manually, make sure this file is excluded. Anyone who obtains these keys can forge session tokens and unseal password verifiers.

Required environment variables

VariablePurpose
SPACE_AUTH_PASSWORD_SEAL_KEYSeals SCRAM password verifier envelopes in meta/password.json. All instances must share the same value or password login will fail.
SPACE_AUTH_SESSION_HMAC_KEYSigns session token metadata stored in meta/logins.json. Mismatched keys across instances invalidate all sessions on restart.
SPACE_AUTH_DATA_DIROverrides the default server/data/ directory for local fallback auth key storage and per-user userCrypto server shares. Useful when you want auth state at a specific path on a shared volume.
Set these in your process environment or secrets manager before starting the server:
export SPACE_AUTH_PASSWORD_SEAL_KEY="$(openssl rand -hex 32)"
export SPACE_AUTH_SESSION_HMAC_KEY="$(openssl rand -hex 32)"
node space supervise CUSTOMWARE_PATH=/srv/space/customware
For multi-instance or autoscaled deployments, every instance must receive identical SPACE_AUTH_PASSWORD_SEAL_KEY and SPACE_AUTH_SESSION_HMAC_KEY values. Instances with different keys cannot validate each other’s session cookies or read each other’s sealed password verifiers.

Local fallback (single-instance only)

When neither secret is injected via environment variable, the server falls back to generating keys and storing them in server/data/auth_keys.json (or SPACE_AUTH_DATA_DIR/auth_keys.json when that override is set). node space supervise injects these same canonical keys into every child serve process so sessions remain valid across zero-downtime restarts.
The local fallback is sufficient for a single-instance deployment on a persistent filesystem. If your server restarts and server/data/auth_keys.json is preserved, sessions survive the restart. If the file is lost (e.g. ephemeral container storage), all active sessions are invalidated.
The server issues a space_session cookie with the following properties:
  • HttpOnly — not accessible to JavaScript running in the browser
  • SameSite=Strict — not sent on cross-origin requests
  • Path / — scoped to the entire server origin
  • Max age: 30 days
The raw cookie value is a bearer token, but meta/logins.json stores only backend-keyed verifiers plus signed metadata — reading the app-side session files never reveals a replayable cookie value. Each stored session record also carries a backend-generated sessionId that the browser uses for session-scoped userCrypto cache binding without exposing the raw token.

Network Hardening

Use a reverse proxy

HOST=0.0.0.0 and PORT=3000 make the server reachable on all interfaces. In production, never expose port 3000 directly to the internet. Place nginx, Caddy, or a similar reverse proxy in front of Space Agent and proxy through port 443 with TLS termination.
# Server binds on all interfaces for the reverse proxy to reach
node space set HOST=0.0.0.0
node space set PORT=3000
A minimal nginx location block (illustrative example — adapt to your own proxy setup):
location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
Block direct access to port 3000 at the firewall level. Only the reverse proxy should be able to reach the Space Agent port. Exposing port 3000 directly bypasses TLS and any proxy-level rate limiting or WAF rules you have in place.

Locking down login

If you do not want public password login (for example on an internal-only server where you manage sessions manually), disable it:
node space set LOGIN_ALLOWED=false
The public /login shell stays available but shows a “Login is disabled” message. Existing authenticated sessions continue to work normally.

CUSTOMWARE_PATH Isolation

CUSTOMWARE_PATH defaults to an empty string, which means writable L1 and L2 state lives inside the source checkout at app/L1/ and app/L2/. For any production server, always set this to an absolute path outside the checkout before creating users. Keeping user and group data separate from the application code is a critical security and operational practice — it ensures that source updates never touch user credentials or workspace files.
node space set CUSTOMWARE_PATH=/srv/space/customware

What lives in CUSTOMWARE_PATH

  • L1/<group>/ — group configuration and shared modules
  • L2/<username>/ — user workspaces, auth files, module trees
  • share/spaces/ — hosted cloud-share archives (when enabled)

What stays in the source checkout

  • app/L0/ — firmware (read-only)
  • server/ — server runtime code
  • commands/ — CLI commands
  • .env — parameter configuration
With this separation:
  • node space update and node space supervise’s automatic updates only touch the source checkout. User data at CUSTOMWARE_PATH is never modified.
  • The source checkout can be replaced or rolled back without touching any user credentials or workspace files.
  • node space supervise normalizes CUSTOMWARE_PATH to an absolute path before passing it to every child process, so all release checkouts share the same writable roots.

Per-User userCrypto Server Shares

Space Agent uses a split-key design for browser-side encryption. The browser holds an encrypted master key blob in localStorage; the server holds a backend-only “server share” required to decrypt it. Where server shares are stored:
  • Default: server/data/user_crypto/<username>.json (gitignored)
  • With SPACE_AUTH_DATA_DIR set: SPACE_AUTH_DATA_DIR/user_crypto/<username>.json
The plaintext server share is never stored in the logical app tree. L2/<username>/meta/user_crypto.json contains only a backend-sealed envelope — it requires SPACE_AUTH_PASSWORD_SEAL_KEY to open and is therefore useless to an attacker who only has access to the app tree files.
Admin or CLI password resets cannot rewrap the browser-owned master key. They instead invalidate user_crypto.json and delete the server share. The user’s encrypted data remains protected; they will need to re-provision their encryption state on next login.

Git History and Rollback Safety

When CUSTOMWARE_GIT_HISTORY=true (the default), each writable L1 group and L2 user folder is a local Git repository that records changes over time. Auth files are excluded from history by design:
  • meta/password.json — excluded from L2 history
  • meta/logins.json — excluded from L2 history
  • meta/user_crypto.json — excluded from L2 history
When a rollback is performed, these files are preserved at their current state rather than being restored from the old commit. This means:
  • Rolling back never restores an old password verifier
  • Rolling back never logs a user out (no old session records)
  • Rolling back never replaces the current wrapped browser key with an older version
Do not manually edit meta/password.json, meta/logins.json, or meta/user_crypto.json. These files contain backend-sealed cryptographic material. Hand-authored entries will be rejected by the auth service.

GitHub Token for Updates

When node space update or node space supervise’s automatic update flow needs to fetch from a private GitHub repository, set SPACE_GITHUB_TOKEN in the environment:
export SPACE_GITHUB_TOKEN=ghp_your_token_here
node space supervise CUSTOMWARE_PATH=/srv/space/customware
When this variable is not set, GitHub requests are made without authentication (suitable for public repositories). The same token is used by both manual node space update and the supervisor’s automatic release staging, so one environment variable covers both flows.

Admin Shell Security

The /admin route is hardened in two ways:
  1. Access control: Only members of the _admin group can access admin features. All requests to /admin are authenticated in the same way as the main app.
  2. Layer clamping: /admin forces maxLayer=0 for all module and extension resolution. This means admin UI is served exclusively from L0 firmware — no L1 group or L2 user customware can modify the admin shell. Even if a user’s or group’s customware layer contains a broken or malicious module, the admin panel remains on known-good firmware code.
This combination gives administrators a stable, unmodifiable control plane to diagnose and fix problems even when user-space customizations break the regular app shell.

Security Checklist

Before exposing your Space Agent server to the internet, verify:
  • Not running as root — dedicated service account with ownership of CUSTOMWARE_PATH
  • SPACE_AUTH_PASSWORD_SEAL_KEY and SPACE_AUTH_SESSION_HMAC_KEY set to strong random values
  • server/data/auth_keys.json excluded from any repository archives or backups that are stored insecurely
  • CUSTOMWARE_PATH set to a directory outside the source checkout
  • Port 3000 blocked at the firewall — only accessible via reverse proxy
  • TLS termination configured at the reverse proxy
  • Admin password changed from the default "change-me-now" placeholder
  • SINGLE_USER_APP=true not set on a multi-user or publicly accessible server
  • ALLOW_GUEST_USERS set deliberately — enabled only if you want public guest access
  • USER_FOLDER_SIZE_LIMIT_BYTES set if you need to cap per-user disk usage

Build docs developers (and LLMs) love