Security
The model
- One identity provider. id is the only place that handles passkeys. Panels are OIDC clients with
their own host-only cookies; there is no cookie shared across the domain, so a user's site on
*.pages.xvii.network never receives a panel's session.
- Short tokens. Access tokens are JWTs that live 15 minutes, verified by services with id's keys.
Refresh tokens rotate; reusing an old one revokes the whole family. API tokens are stored as SHA-256 and
can be narrowed to services, a project and a lifetime.
- Roles everywhere. Team roles and protected environments are enforced by each service on the
resources it owns. Services call each other with client credentials, never with a person's token.
- Same-origin panels. Requests carrying a cookie are refused unless they come from the panel's own
origin.
- Everything is logged. Every change through any API records who, what, team and IP.
Where secrets live
| Secret |
Where |
Protected by |
| env values |
env's database |
per-set data keys sealed with env's master key |
| app secrets, registry passwords, database passwords |
apps' database |
apps' seal key |
| Cloudflare tokens, DNSSEC keys |
domains' database |
domains' seal key |
| AI accounts and keys |
ai's database |
sealed, never returned by the API |
| backup repository passwords |
backups' database and the recovery kit |
sealed |
| the instance's DNS token |
/etc/xvii/instance.env |
root only |
The seal keys live in each service's data folder. Back them up with the databases, and protect the backups
like the instance itself.
User content on its own domain
Sites, apps and tunnels serve content anyone can write. Panels check Sec-Fetch-Site and Origin so that
content can't act on a panel. A separate registrable domain for user content is planned for extra
separation.
Hardening the servers
- Keep SSH key-only and limit who has root. Root on the control plane is root on the platform.
- Open only what is needed: 22, 80 and 443 on the control plane; 7443 from the control plane to relay
nodes; 53 (UDP and TCP) on name servers; mail ports on the mail edge.
- Keep the operating system updated; xvii updates itself service by service.
- Don't run unrelated internet-facing software on the control plane.
- Put teams that don't trust each other on separate nodes, or run their containers with gVisor.
The Docker socket
ai runs a helper container through Docker on the control plane, and nodes drive Docker as root. Access to a
Docker socket is root on that machine: never mount it into an app container.