Reference

Security

Astrodock is built for one trusted operator on a single-tenant box — your own machine or a VPS you control. It is powerful by design, with a few deliberately sharp edges. This page explains the trust model in plain terms; the complete threat model lives in SECURITY.md in the repo.

Read this before going public

Astrodock is not multi-tenant SaaS. It must not be exposed to untrusted users or untrusted networks without extra hardening. For the full, authoritative threat model and the remaining known limitations, read SECURITY.md in the repository.

The trust model

The whole design assumes a single box run by a trusted person:

What protects you

Within that model, Astrodock has real protections:

The deliberate sharp edges

These are intentional, accepted under the trusted-operator model — stated plainly so you can decide with eyes open:

The runner builds and runs your code

Deploys run npm ci (which can run postinstall scripts), your buildCommand, and your app on the runner. Connect only repos you trust.

Dockerfile apps use a mounted Docker socket

runtime.type: "docker" builds and runs sibling containers via /var/run/docker.sock, which is ≈ root on the host. Put only trusted Dockerfile apps on the box.

There is no shell into your apps

Earlier versions had a per-app terminal. It ran commands inside the control plane — the one container holding the key that decrypts every app's secrets — so it has been removed rather than fixed. The Operations tab replaces it: browse the deployed files, see which configuration reached the running process, and run the commands the app declares in its app.json. Those are code you committed, not a string composed at runtime.

Cloud metadata and your apps

Cloud providers serve information about the machine over HTTP at 169.254.169.254. Containers can usually reach it, because that traffic routes out through the host — which means an app you deploy can read it too.

What that discloses depends on the provider. On DigitalOcean it's the droplet's user-data (including anything you put in an initialization script), its SSH public keys and its tags. On AWS the same endpoint hands out IAM role credentials, which is considerably worse. Since Astrodock's entire job is running code you or an AI agent wrote on this box, it's worth closing.

Astrodock checks this for you — Settings → Readiness probes it from a throwaway container and warns if it's reachable. It does not block it automatically, for the same reason it doesn't manage your firewall: the fix means writing host firewall rules that can collide with your own and are awkward to undo on a remote machine.

To close it:

iptables -I DOCKER-USER -d 169.254.169.254 -j DROP

It has to go in the DOCKER-USER chain — Docker inserts its own rules ahead of the usual ones, so a plain ufw or INPUT rule won't take effect. Make it persist across reboots with iptables-persistent, or your distribution's equivalent.

If you use the metadata service yourself

Some setups legitimately read metadata from within containers. If yours does, scope the rule to the app containers rather than dropping it wholesale.

Operator checklist

A short list to get the protections that aren't automatic:

  1. Set the strong secrets

    Set unique, random values for ASTRODOCK_ADMIN_JWT_SECRET, ASTRODOCK_SECRET_KEY, and ASTRODOCK_RUNNER_TOKEN (plus the Postgres and object-store passwords and a strong admin password). Generate each with openssl rand -hex 32. Never commit .env.

  2. Firewall everything except 80/443

    Caddy's 80 and 443 are the only ports that should be public. Don't publish Postgres, the object store, the runner, or Caddy's admin API (:2019).

  3. Only trust your own repos

    Connect only repos you control. Review the buildCommand and dependencies of anything you deploy — the build and runtime run real code.

  4. Keep the terminal off

  5. Back up your data

    Back up the pgdata and objectdata volumes. See Backups & restore.

The complete threat model

This page is the plain-language overview. The full threat model — including the remaining known limitations (the runner container itself is privileged; Dockerfile apps share one network with internal services; no multi-admin RBAC) and how to report a vulnerability — is in SECURITY.md in the repository. Read it before exposing the box to anything you don't fully trust.

Related