Security Overview
Temps is self-hosted, which means every layer of security runs on your own infrastructure. This page covers the protections Temps applies automatically, the ones you switch on (IP rules, Attack Mode, security headers), and a hardening checklist.
In this section:
- Authentication — login methods, MFA, step-up verification and API keys
- Authorization — instance, team and API-key roles and scopes
- Teams — grouping users and granting project access
- Data protection — what is encrypted or hashed, and the encryption key
- Data ownership and privacy — where data lives, telemetry and GDPR
- Attack Mode — proof-of-work bot protection, security headers and IP rules
- Audit logging — audit event types, retention and queries
- Production checklist — what to check before going live
For a non-technical overview, see Security and trust.
Transport Security
Automatic SSL/TLS
Temps issues and renews Let's Encrypt certificates automatically for every custom domain — no certificate management required. Modern TLS versions (1.2 and 1.3) are supported. A Strict-Transport-Security header (max-age=31536000; includeSubDomains by default) is added once you enable security headers. You can attach unlimited custom domains per project. Point your domain to your Temps server and SSL is configured automatically.
Cluster mutual TLS (multi-node)
In a multi-node cluster on the current release (v0.1.0-beta.56), calls from the control plane to worker agents are plain HTTP authorized by a per-node bearer token, so keep the agent port on a private network. Mutual TLS is off and has no dashboard or CLI switch on this release; from the next release, fresh clusters require it. With mTLS on, the control plane runs a per-cluster CA — its private key stays encrypted at rest and never leaves the control plane — and signs a per-node certificate for each worker. Each node generates its own key pair locally, and joins can pin the CA fingerprint with --ca-fingerprint to prevent CA substitution. Worker heartbeats still use the control plane's public HTTPS certificate plus the node token. Upgraded clusters keep their existing setting until you re-enroll their workers. Node certificate renewal is not automatic yet; follow the documented rotation procedure after suspected key exposure or an ownership change.
Access Control
Control Plane Admin Surface
The Temps control plane can split its HTTP surface across two listeners so admin/management routes bind to a private interface while public ingest endpoints stay reachable. See the Admin Listener guide for configuration, deployment recipes (SSH tunnel, Tailscale, reverse proxy), and the route classification.
Worker-Node Enrollment
Worker nodes join a multi-node cluster with a token. Settings → Worker Nodes generates one shared join token; for per-node control, mint single-use enrollment tokens through the API: short-lived (1 h default, 24 h max), optionally bound to a specific node name, and stored only as a SHA-256 hash (the plaintext is shown once at mint time). Expired, revoked, or exhausted tokens are rejected outright with no fallback to the legacy shared token, and the registration endpoint is rate-limited per-IP. See Multi-node → Securing node enrollment.
IP Access Control
- 1
Go to Settings → Security → IP Access Control
- 2
Click Add Rule
- 3
Enter the IP address or CIDR range and choose Block
- 4
Save — block rules take effect within about 30 seconds
Temps has one instance-wide IP access list, enforced by the proxy before requests reach any app. Block rules return 403 Forbidden to an IP or CIDR range, which is useful for cutting off abusive clients quickly. Rules apply to every project on the instance and take effect within about 30 seconds, when the proxy next refreshes its list. Only block rules are enforced: the form also accepts Allow rules, but the proxy ignores them in v0.1.0-beta.56, so an allow list does not restrict access. Manage them under Settings → Security → IP Access Control or with bunx @temps-sdk/cli ip-access; see IP access control for details.
Per-project and per-environment IP allow and deny lists (a request firewall) are part of Temps Premium. To keep the console itself off the public internet, use the Admin Listener instead.
OIDC SSO Security
OIDC SSO is free. SAML 2.0, requiring SSO for every user with password login turned off, SCIM provisioning and custom roles are part of Temps Premium.
The OIDC SSO login flow generates a server-side state token, a nonce, and a PKCE code challenge before redirecting to the identity provider, and validates all three when the IdP calls back (temps-auth/src/oidc_service.rs:539-556,678-701). The redirect_uri is pinned to the console's own callback route and validated before the authorize URL is built (oidc_service.rs:976-987). Requests to the IdP's issuer are blocked from resolving to private, link-local, or CGNAT IP ranges — re-checked at connect time to close off DNS-rebinding — so issuer discovery can't be abused to reach internal services or cloud metadata endpoints (oidc_service.rs:1018-1213, BlocklistResolver at :92-113). Callback failures return a short opaque error code to the browser instead of the IdP's raw error text, so failure detail never leaks into the URL bar, browser history, or Referer header (oidc_handler.rs:150-256). The per-provider trust_idp_email flag defaults to false; enabling it bypasses the email_verified verification gate but not the underlying record, and every bypass is logged (oidc_service.rs::resolve_user, migration m20260526_000002_add_trust_idp_email_to_oidc_providers).
Bot Protection
Attack Mode
- 1
Go to your project
- 2
Open Settings → Security
- 3
Toggle Enable Attack Mode in the Attack Mode card
- 4
Click Save Attack Mode Settings
Attack Mode serves a proof-of-work challenge to every visitor while it is on. The visitor's browser solves it in a few seconds and the result is valid for 24 hours. It does not switch on by itself: enable it per project or per environment when you see bot pressure or an application-layer request flood, and turn it off afterwards. It does not absorb volumetric network DDoS; put a CDN or your provider's DDoS protection in front for that.
Application Security
Security Headers
Temps can add four headers to your apps' responses: Content-Security-Policy, X-Frame-Options, Strict-Transport-Security and Referrer-Policy. Headers are off until you enable them in Settings → Security (instance-wide) or in a project's security settings. In a project, choose a preset (Strict, Moderate, Permissive), set values yourself (Custom), or turn them off; the instance-wide default sends X-Frame-Options: SAMEORIGIN. A project setting replaces the instance-wide one. Permissions-Policy, X-Content-Type-Options and X-XSS-Protection are not sent, and environment-level header settings are ignored in v0.1.0-beta.56, so set those in your app. See Security headers for the exact value of every preset.
Control-plane protections
The Temps API and console itself:
- Input Validation — All inputs validated at the API layer
- SQL Injection Prevention — Parameterized queries throughout
- XSS Protection — Output encoding on all rendered content
- OIDC Login CSRF Protection — The OIDC login flow uses a
stateparameter to protect against CSRF
Hardening checklist
Work through these in order on a new instance. The production checklist covers the wider go-live list.
- Keep the console private. Bind the admin listener to a private interface, VPN or Tailscale address, so the console and management API are unreachable from the internet while your apps and public ingest stay public. See Admin Listener and Secure your VPS with Tailscale.
- Lock down the server. Open only ports 22, 80 and 443 to the internet (see firewall rules), use SSH keys, and keep the OS patched. Temps does not manage the host for you; the VPS security checklist has the commands for Ubuntu 24.04 and Debian 12.
- Turn on MFA (TOTP) for every Admin account, or sign in through OIDC SSO with MFA enforced at your identity provider. See Authentication.
- Give people the least access they need. Use the User instance role for non-admins and grant project access through teams. See Authorization.
- Scope API keys. One key per integration, Custom role with only the scopes it needs, and an expiry for CI keys. Revoke unused keys.
- Mark sensitive variables as secrets. All environment variable values are encrypted at rest; secrets are also write-only, so the API never returns them.
- Protect the encryption key. Back up
~/.temps/encryption_keyseparately from the database. See Data protection. - Enable security headers and use Attack Mode or the IP block list when an app comes under bot pressure.
- Back up to S3 on a schedule, and test a restore. See Backups.
- Review the audit log for
LOGIN_FAILUREandPERMISSION_DENIEDevents. - Keep Temps updated. See Upgrade Temps.
Compliance
Data Privacy
Because Temps is self-hosted, you control all data:
- Your analytics, recordings, errors, logs and credentials stay on your own infrastructure. The binary sends anonymous product telemetry to
telemetry.temps.shunless you setTEMPS_TELEMETRY=0 - Export your data at any time via API or database access
- Delete data at any time; Temps does not retain copies
GDPR & Privacy
- Data Minimization — Temps collects only what is necessary to operate the platform
- User Consent — Temps analytics sets first-party cookies; integrate your own consent management where your jurisdiction requires it
- Right to Access & Deletion — All data is in your PostgreSQL database, so you can export or delete it directly
See Data ownership and privacy for what is stored where, and Data protection for encryption. A tamper-evident audit log and compliance and access-review reports are part of Temps Premium.
Reporting Security Issues
If you discover a security vulnerability in Temps, please report it privately:
- Do not post publicly until a fix is available
- Email david@temps.sh with a description of the issue
- Allow reasonable time for a fix before any public disclosure
We follow coordinated disclosure and aim to respond within 48 hours. The full policy, including what to put in a report and the disclosure timeline, is in SECURITY.md.