Skip to main content

Environment Variables

All environment variables used to configure Surface Security backend services.

Core Infrastructure

VariableDescriptionDefault
SERVER_ADDRAPI server bind address:8090 (Helm), :8080 (K8s manifests/Pulumi)
DEV_MODEEnable development mode (skips license check)Auto-detected from bind address
caution

The Go default for SERVER_ADDR is :8090, but Kubernetes base manifests and Pulumi override this to :8080. The Helm chart uses :8090. Ensure your ingress/service configuration targets the correct port for your deployment method.

Database: PostgreSQL

VariableDescriptionDefault
PG_HOSTPostgreSQL hostlocalhost
PG_PORTPostgreSQL port5432
PG_DATABASEPostgreSQL database namesurfacesec
PG_USERPostgreSQL usersurfacesec
PG_PASSWORDPostgreSQL password(required)
PG_MAX_CONNSMax connections per pod50 (API), 30 (Ingestion)
PG_MIN_CONNSMin idle connections per pod10 (API), 5 (Ingestion)

Database: ClickHouse

VariableDescriptionDefault
CH_HOSTSClickHouse hosts (comma-separated)localhost:9000
CH_DATABASEClickHouse database namesurfacesec
CH_USERClickHouse usersurfacesec
CH_PASSWORDClickHouse password(required)
CH_MAX_OPEN_CONNSMax open connections per pod30 (API), 40 (Ingestion)
CH_MAX_IDLE_CONNSMax idle connections per pod15 (API), 20 (Ingestion)

Streaming: Redpanda

VariableDescriptionDefault
KAFKA_BROKERSRedpanda broker endpoints (comma-separated)localhost:19092

Object Storage: MinIO

VariableDescriptionDefault
MINIO_ENDPOINTMinIO endpointlocalhost:9100
MINIO_ACCESS_KEYMinIO access keysurfacesec
MINIO_SECRET_KEYMinIO secret key(required)
MINIO_BUCKET_SCREENSHOTSBucket name for phishing screenshotssurfacesec-screenshots
MinIO Ports

In Docker Compose, MinIO is exposed on ports 9500 (API) and 9501 (Console). In Kubernetes, the standard ports 9000 (API) and 9001 (Console) are used.

Security

VariableDescriptionDefault
CERT_ENCRYPTION_KEYHex-encoded 32-byte key for mTLS CA private key encryptionAuto-generated in dev mode
SPIFFE_DOMAINSPIFFE trust domain for device certificate URI SANssurfacesec.local
EXTENSION_SIGNING_KEYBase64-encoded Ed25519 seed for signing extension manifests(empty)
ALLOWED_ORIGINSCORS allowed origins(none)
CERT_ENCRYPTION_KEY

The raw hex string is SHA256-hashed internally to derive the 32-byte ChaCha20-Poly1305 encryption key. Losing the original hex value means losing the ability to decrypt stored CA private keys. Generate with openssl rand -hex 32 and back up securely.

SPIFFE_DOMAIN

This value is embedded in device certificate URI SANs as spiffe://{domain}/device/{deviceID}. It must match the match_typed_subject_alt_names prefix configured in Envoy. If you change one, you must change both. Production deployments should set this to their own domain (e.g., surfacesec.yourcompany.com).

Licensing and Portal

VariableRequiredDescriptionDefault
SURFACE_LICENSE_KEYYes (production)Ed25519-signed license key (base64 JSON)(none)
SURFACE_PUBLIC_KEYYes (production)Ed25519 public key for license verification (PEM or base64)(none)
SURFACE_PUBLIC_KEY_FILEAlternativePath to file containing the public key(none)
SURFACE_PORTAL_URLNoPortal URL for heartbeats and sync; empty = offline modehttps://portal.surface-security.com
SURFACE_PORTAL_API_TOKENIf portal URL setBearer token for portal API authentication(none)
PORTAL_HEARTBEAT_INTERVAL_SECONDSNoSeconds between heartbeats to the portal21600 (6 hours; all deployed K8s/Helm configs override to 300s/5min)

Scaling

These variables control connection pool sizes and worker counts. Proper sizing is critical for multi-pod deployments.

VariableServiceDefaultDescription
PG_MAX_CONNSAPI50PostgreSQL pool size per pod
PG_MIN_CONNSAPI10Minimum idle PG connections
PG_MAX_CONNSIngestion30PostgreSQL pool size per pod
PG_MIN_CONNSIngestion5Minimum idle PG connections
CH_MAX_OPEN_CONNSAPI30ClickHouse pool size per pod
CH_MAX_IDLE_CONNSAPI15ClickHouse idle connections
CH_MAX_OPEN_CONNSIngestion40ClickHouse pool size per pod
CH_MAX_IDLE_CONNSIngestion20ClickHouse idle connections
NUM_WORKERSIngestion8Concurrent event processors
HEALTH_ADDRIngestion:9090Health HTTP server bind address
RATE_LIMIT_RPSAPI100Per-client rate limit (requests/second)

Scaling Reference

Use this table to size connection pools based on extension fleet size:

ExtensionsAPI PodsIngestion PodsTotal PG ConnsTotal CH Conns
1,0003315090
5,00055250150
10,000108500240
25,0001512750360
50,00020151,000450

Formula: total_db_connections = max_pods x pool_size_per_pod

Versioning

VariableDescriptionDefault
SURFACESEC_VERSIONApplication version reported by health endpoint and update controller1.0.0
IMAGE_REGISTRY_URLLocal registry for embedded update images(empty)
REGISTRY_USERNAMERegistry basic auth username(empty)
REGISTRY_PASSWORDRegistry basic auth password(empty)

Version resolution priority (checked in order at startup):

  1. SURFACESEC_VERSION environment variable
  2. BuildVersion compiled via -ldflags -X (from BUILD_VERSION build arg)
  3. Kubernetes deployment annotation
  4. /etc/surfacesec/version file
  5. Fallback "1.0.0"
VariableDescriptionDefault
SEARCH_BACKENDSearch backend: postgres or opensearchpostgres (Go binary default); docker-compose overrides to opensearch for dev
OPENSEARCH_URLOpenSearch endpoint URLhttp://opensearch:9200