# Security

> What a Resta server exposes, how credentials work, how SQL is sandboxed, and how to hand out database tokens safely.

Source: https://resta.dev/docs/security · Updated 2026-11-01

**A Resta server exposes one port, the gateway's, and every request through it needs a credential: a dashboard session, an API key, or a database token.** Postgres, the node's admin port and the operator routes stay on the internal Docker network.

## Credentials

| Credential | Who uses it | Scope | Stored as |
|---|---|---|---|
| Account password | You, in the dashboard | Everything | Argon2id hash |
| Session | The dashboard, after sign-in | Everything; 14 days | SHA-256 hash |
| API key (`blk_...`) | Your backend | Everything | SHA-256 hash; shown once |
| Database token (JWT) | Your apps | One database or all; `rw` or `ro`; up to 30 days | Not stored |

The account, its sessions and API keys can do everything. Treat API keys like a root password: keep them on servers, rotate them, and revoke unused ones (the dashboard shows when each was last used).

## Giving apps access

Mint database tokens from your backend, for the one database a user needs, read-only where possible, with a short lifetime. Tokens are signed with an Ed25519 key that never leaves the server; the node checks the signature on every request. Individual tokens cannot be revoked, so prefer short lifetimes and refresh them.

To invalidate every token at once, delete the signing key from the `keys` volume and restart the API. A new key is generated, and every token issued before is rejected.

## SQL sandboxing

Anyone with a token can run SQL, so the node parses every statement with the engine's own parser before running it and blocks anything that could reach outside the database file: `ATTACH`, `VACUUM INTO`, extensions, raw page access, and most pragmas. Per-statement and per-request time limits, a size limit per database and a response size limit bound what one query can consume. See [SQL support and limits](https://resta.dev/docs/sql).

## Network

- The gateway is the only published service. On Coolify, Coolify's proxy is in front of it.
- `/admin/*` returns `404` at the gateway; operator routes are reachable only inside the stack.
- The node's admin port (8081) is not routed.
- Containers run as a non-root user.

## Login protection

Sign-in and setup are rate limited to 10 attempts per minute per client address and per email. Unknown emails and wrong passwords return the same error, after the same amount of work.

## Reporting a vulnerability

Contact details will be published with the open-source release. Until then, please do not file security issues publicly.
