Security
Private by default, and careful with every change
These are the controls the StarlingTek platform actually has. Nothing on this page is a plan for later.
The admin panel
The web admin panel is off by default. When it's on, it's the most exposed part of the platform, so it gets the most checks.
- Password and authenticator code
- Signing in takes an argon2id-hashed password and a TOTP code from an authenticator app. Each code works once. Repeated failures lock the account and are rate-limited per IP.
- A fresh code for every change
- Deploying, rolling back, removing a site, changing alert channels or DNS: each needs the site or server name typed out and a fresh authenticator code, both checked on the server.
- An audit log
- Sign-ins, failures, rejected requests and every change are recorded with the time, target and client IP. Entries hold names, never secret values.
- Allowlisted actions
- The panel forwards a fixed list of operations to the same handlers
stkuses. Any route not on the list answers 404, even with a valid session. - No web terminal
- There is no shell in the browser. Server-wide settings, restores and anything not on the list stay an SSH step.
- Sessions and CSRF
- Server-side sessions, and a CSRF token, same-origin check and JSON body required on every change. The panel never holds the control plane's API token.
The server
Only what has to be public is public.
- Three open ports
- The firewall allows 22, 80 and 443 and nothing else. fail2ban watches SSH.
- Loopback everywhere else
- Site containers publish to
127.0.0.1only. The control plane's API listens on loopback behind a bearer token, and only webhooks and its health route are proxied publicly. - Fail-closed admin
- Disabled, the panel answers 403 to everything. Enabled with nobody enrolled, only setup with a one-time token works. It can also be limited to an IP allowlist, or left off the internet and reached over an SSH tunnel.
- Automatic HTTPS
- Caddy gets and renews Let's Encrypt certificates for every site, with expiry alerts at 21 and 7 days.
- Contained sites
- Containers run as non-root with dropped capabilities and
no-new-privileges. Each site's files live in their own directory. - Least-privilege GitHub access
- Private repositories get a read-only deploy key for that one repository, not an account-wide token. Webhooks are verified with an HMAC over the raw body.
- Secrets stay secret
- Secret environment values are masked in the panel and scrubbed from deploy logs and the audit log. Tokens for DigitalOcean databases are held in memory for minutes and never written to disk.
- This website
- A strict Content Security Policy with no inline scripts, no third-party assets, no trackers and no analytics.
Found a problem?
If you think you've found a security issue, email [email protected]. Every report is read.