Settings

Update application settings

Changed on
put/settings

Request

  • Base URL: /api (relative, and the document was published on a file host, not at the API’s origin)
  • URL: /api/settings
  • Auth: HTTP bearer

Request body

anonymous_telemetry_enabledboolean nullable

Admin preference for anonymous product telemetry (the events sent to the Temps maintainers by temps-telemetry; unrelated to Temps Cloud mirroring in cloud.telemetry_enabled and to OpenTelemetry ingest).

  • None (default) — the operator has not chosen; the built-in default applies (see temps_telemetry::DEFAULT_TELEMETRY_ENABLED).
  • Some(true) / Some(false) — an admin turned it on/off from Settings › Telemetry. Applied at runtime without a restart.

The TEMPS_TELEMETRY=0 environment variable is a host-level kill switch that wins over this value unconditionally. The dedicated PATCH /settings/telemetry endpoint is the only write path: the generic settings save restores the stored value under the row lock, so an older client round-tripping the whole document cannot flip it.

bunny_new_projectsboolean

Enable Bunny delivery by default only for projects created after this is set.

cloudflare_new_projectsboolean

Enable Cloudflare delivery by default for projects created after this is set.

console_force_httpsboolean nullable

Whether plain-HTTP requests to the console host (external_url) are redirected to HTTPS. Same tri-state contract as an environment's force_https:

  • None (default) — inherit the per-host heuristic: redirect only once the console hostname has actually completed TLS provisioning. An HTTP-only install, and an install whose TLS is terminated upstream, are both left alone.
  • Some(true) — always redirect. For operators who terminate TLS at Temps but have not provisioned the cert through Temps.
  • Some(false) — never redirect, even once a certificate exists.

Deliberately operator-set rather than inferred. Temps cannot tell "HTTPS terminated by an upstream CDN" apart from "plain HTTP" — both arrive as a plaintext connection, and X-Forwarded-Proto is not trustworthy from an arbitrary peer — so inferring true from an https:// external_url would 301 a CDN-fronted console into an infinite redirect loop with no way out but the global kill switch.

console_versionstring nullable

Binary version tag (e.g. "v0.1.0") of the console process (temps serve, role=all or role=console) that last started. Written on console startup; read by the standalone temps proxy to detect version skew during a rolling upgrade (ADR-017 Phase 3). None on installs that never ran a console build carrying this field.

This is informational state written by the binary itself — NOT an operator-tunable setting. It is intentionally absent from AppSettingsResponse and the PATCH path so an operator cannot accidentally overwrite the self-recorded value.

edge_targetstring nullable

Public edge target that generated DNS records point at when a managed domain opts into automatic record sync. An IPv4/IPv6 address produces an A/AAAA record; anything else is treated as a CNAME target. None disables DNS record sync regardless of per-domain opt-in.

external_urlstring nullable
insecure_tlsboolean

Skip TLS certificate verification on outbound HTTP clients built by the server (deployer, agent, remote service client). Strictly opt-in for operators running self-signed control plane / worker certs on a trusted internal network. Worker→control-plane traffic that traverses the public internet must keep this false — otherwise a MitM steals the join token.

internal_urlstring nullable

URL that service containers use to reach the Temps API from inside the Docker network (OTLP metrics ingest, agent callbacks, etc.). On Docker Desktop this defaults to http://host.docker.internal:<console_port>; on Linux it requires the host.docker.internal:host-gateway host mapping (which Temps adds to provisioned containers). Distinct from external_url, which is the public-facing address.

plugin_installation_reporting_enabledboolean

Share verified external-plugin installation counts with the official registry. Defaults to off; each plugin receives an unlinkable ID.

preview_domainstring
public_ingress_urlstring nullable

Base URL handed to third parties that call back into Temps: email open/click tracking, git provider webhooks, SES/SNS events, revenue webhooks, the Sentry DSN (ADR-051). None (the default) falls back to external_url, which is right whenever the console is publicly reachable. Set it when the console host is restricted (VPN, firewall, identity-aware proxy) so only this hostname has to be public: the proxy serves nothing but the public callback routes on it. Read it through [AppSettings::effective_public_ingress_url].

registry_mirror_prefixstring nullable

Prefix applied to Docker Hub base images generated for a build (e.g. autopack's FROM node:22-slim), turning them into {prefix}/node:22-slim. Unlike docker_registry above — which authenticates pulls to one named private registry a user's own image reference already points at — this rewrites Temps' own generated, otherwise-anonymous docker.io references, for operators whose internal registry is a path-prefixing reverse proxy rather than a registry-mirrors-compatible pull-through cache (which needs no rewriting at all — see docs/howto/configure-a-docker-registry-mirror). None/empty (the default) leaves every reference untouched.

require_mfa_for_adminsboolean

When true, any user holding the Admin role must have MFA enrolled (users.mfa_enabled = true) to complete a password login. Users without MFA enrolled are rejected with a typed error instructing them to enroll before retrying. This only gates the password-login path (AuthService::login) -- SSO/OIDC logins are handled by a separate code path (OidcService::resolve_user + oidc_handler) and are intentionally unaffected, since federating identity to a properly-hardened IdP is itself an acceptable alternative to local TOTP MFA. Modeled as a settings row (not an env var) per CLAUDE.md so an operator can flip it at runtime via the Settings API without restarting the binary.

setup_completeboolean

Set to true by temps setup (all modes) once initial configuration has been applied. The web onboarding wizard reads this from the server and skips itself when true, preventing the "Configure Base Domain" wall from appearing on installs that were already configured via the CLI.

trust_loopback_forwarded_ipboolean nullable

Allow the proxy to use forwarding headers from a loopback peer for client IP attribution. None means an older client did not send the field; the settings handler preserves the stored decision on PUT. This is the sole control surface — there is no CLI/env override.

trusted_private_networksstring[]

Private networks (CIDRs or single addresses) that user-configured outbound requests may reach: webhooks, notification channels, uptime checks, AI gateway providers, self-hosted git, importers. Empty by default, which keeps the SSRF guard blocking every private, loopback and CGNAT destination. Only private ranges are accepted, and cloud metadata endpoints stay blocked regardless. Published process-wide via url_validation::set_trusted_private_networks.

Example request

{
  "agent_sandbox": {
    "cpu_limit": 4,
    "default_provider": "claude_cli",
    "memory_limit_mb": 8192,
    "network_mode": "full",
    "runtime": "node",
    "sandbox_backend": "docker"
  },
  "ai_chat_limits": {
    "turn_timeout_secs": 900
  },
  "ai_config": {
    "config_repo_branch": "main"
  },
  "ai_workspace_file_limits": {
    "max_download_size_mb": 32,
    "max_file_size_mb": 16,
    "max_files_per_upload": 32,
    "max_image_preview_size_mb": 8,
    "max_text_preview_kb": 256,
    "max_upload_size_mb": 32,
    "max_workspace_entries": 5000,
    "max_workspace_size_mb": 256
  },
  "build_limits": {
    "cpu_limit_cores": 2,
    "max_concurrent": 2,
    "memory_limit_mb": 2048
  },
  "cloud": {
    "telemetry_bulk_anomaly_factor": 5,
    "telemetry_bulk_rate_limit_spans_per_sec": 5000,
    "telemetry_outbox_max_bytes": 536870912
  },
  "connection_limits": {
    "default_max_concurrent_connections": 200
  },
  "container_logs": {
    "cache_mb": 2048,
    "head_buffer_mb": 8,
    "max_file": 3,
    "max_size": "50m",
    "service_max_file": 3,
    "service_max_size": "20m"
  },
  "disk_space_alert": {
    "check_interval_seconds": 300,
    "threshold_percent": 80
  },
  "geo": {
    "refresh_interval_hours": 24,
    "stale_lookup_days": 30
  },
  "image_retention": {
    "default_hours": 336
  },
  "monitoring": {
    "retention_daily_years": 2,
    "retention_hourly_days": 90,
    "retention_raw_days": 7,
    "scrape_interval_secs": 30
  },
  "observability_compression": {
    "otel_spans_after_hours": 24,
    "proxy_logs_after_hours": 24
  },
  "observability_retention": {
    "container_logs_days": 30,
    "otel_logs_days": 90,
    "otel_metrics_days": 90,
    "otel_spans_days": 90,
    "proxy_logs_days": 30
  },
  "on_demand_tls": {
    "deployment_url_mode": "http",
    "hourly_cap": 10,
    "max_concurrent": 3,
    "zone": "1.2.3.4.sslip.io"
  },
  "preview_gateway": {
    "auto_upgrade": true,
    "container_name": "temps-preview-gateway",
    "enabled": true,
    "host_port": 8090,
    "image": "ghcr.io/gotempsh/temps-preview-gateway@sha256:02d5cdd382c3285d569032e84321d5ce8fc089372a3f08651119f6eda8cb1448"
  },
  "request_timeouts": {
    "max_request_timeout_seconds": 600
  },
  "self_update": {
    "channel": "stable",
    "enabled": true
  },
  "tenant_resource_ceilings": {
    "max_concurrent_connections": 200,
    "max_memory_limit_mb": 4096
  }
}

Response

Settings updated successfully

messagestring required

Changes