This is the default way to run Secrets.
This guide uses the latest Docker image (allisson/secrets).
-
AUTH_TOKEN_EXPIRATION_SECONDSdefault is14400(4 hours) -
RATE_LIMIT_ENABLEDdefault istrue(per authenticated client) -
RATE_LIMIT_TOKEN_ENABLEDdefault istrue(per IP onPOST /v1/token) -
CORS_ENABLEDdefault isfalse
These defaults were introduced in v0.5.0 with token-endpoint rate limiting added in v0.7.0 .
The Docker image uses security-hardened configuration:
-
Distroless base image: Google's
gcr.io/distroless/static-debian13(pinned by SHA256)-
No shell, package manager, or system utilities (minimal attack surface)
-
Regular security patches from Google Distroless team
-
Better CVE scanning support vs.
scratchbase📖 For vulnerability scanning instructions, see Security Scanning Guide
-
-
Non-root user: Runs as UID 65532 (
nonroot:nonroot) -
Static binary: No libc dependencies, compiled with
CGO_ENABLED=0 -
Read-only filesystem: Can run with
--read-onlyflag (no runtime writes) -
Image pinning: SHA256 digest pinning for immutability
-
Multi-architecture: Native support for
linux/amd64andlinux/arm64📖 For detailed multi-arch build instructions, see Multi-Architecture Build Guide
-
Build metadata: OCI labels with version, commit SHA, and build timestamp
The API exposes two health endpoints for container orchestration:
-
GET /health: Liveness probe (basic health check, < 10ms) -
GET /ready: Readiness probe (includes database connectivity check, < 100ms)
Quick example:
# Test liveness
curl http://localhost:8080/health
# Response: {"status":"healthy"}
# Test readiness
curl http://localhost:8080/ready
# Response: {"status":"ready","database":"ok"}
For complete health check documentation, including platform-specific configurations (Docker Compose, AWS ECS, Google Cloud Run), monitoring integration, and troubleshooting, see:
📖 Health Check Endpoints Guide
Quick reference for common platforms:
-
Docker Compose: Use healthcheck sidecar (distroless has no shell)
-
AWS ECS: Use ALB target group health checks with
/ready -
Google Cloud Run: Configure startup and liveness probes with
/healthand/ready -
Prometheus: Use Blackbox Exporter to monitor endpoints
Read-only filesystem example:
docker run --rm --name secrets-api \
--network secrets-net \
--env-file .env \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=10m \
-p 8080:8080 \
allisson/secrets server
Note: The
--tmpfs /tmpvolume is optional because the application doesn't write to the filesystem at runtime (embedded migrations, stateless binary). However, it's recommended for security hardening to support potential temporary file operations.
Use this minimal flow when you just want to get a working instance quickly:
docker pull allisson/secrets
docker network create secrets-net || true
docker run -d --name secrets-postgres --network secrets-net \
-e POSTGRES_USER=user \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=mydb \
postgres:16-alpine
# Generate KMS key and master key (KMS required in v0.19.0+)
KMS_KEY=$(openssl rand -base64 32)
# Create .env file
cat > .env <<EOF
DB_DRIVER=postgres
DB_CONNECTION_STRING=postgres://user:password@secrets-postgres:5432/mydb?sslmode=disable
KMS_PROVIDER=localsecrets
KMS_KEY_URI=base64key://$KMS_KEY
EOF
# Generate encrypted master key and append to .env
docker run --rm allisson/secrets create-master-key \
--id default \
--kms-provider localsecrets \
--kms-key-uri "base64key://$KMS_KEY" | grep -E "MASTER_KEYS|ACTIVE_MASTER_KEY_ID" >> .env
docker run --rm --network secrets-net --env-file .env allisson/secrets migrate
docker run --rm --network secrets-net --env-file .env allisson/secrets create-kek --algorithm aes-gcm
docker run --rm --name secrets-api --network secrets-net --env-file .env -p 8080:8080 \
allisson/secrets server
docker pull allisson/secrets
docker network create secrets-net
docker run -d --name secrets-postgres --network secrets-net \
-e POSTGRES_USER=user \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=mydb \
postgres:16-alpine
KMS mode is required in v0.19.0+. For local development, use the localsecrets provider:
# Generate a 32-byte base64 key for localsecrets
openssl rand -base64 32
# Create master key using localsecrets KMS provider
docker run --rm allisson/secrets create-master-key \
--id default \
--kms-provider localsecrets \
--kms-key-uri "base64key://YOUR_BASE64_KEY_HERE"
Copy the generated values into a local .env file.
cat > .env <<'EOF'
DB_DRIVER=postgres
DB_CONNECTION_STRING=postgres://user:password@secrets-postgres:5432/mydb?sslmode=disable
DB_MAX_OPEN_CONNECTIONS=25
DB_MAX_IDLE_CONNECTIONS=5
DB_CONN_MAX_LIFETIME_MINUTES=5
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
SERVER_SHUTDOWN_TIMEOUT_SECONDS=10
LOG_LEVEL=info
# KMS Configuration (required in v0.19.0+)
# For local development, use localsecrets provider
KMS_PROVIDER=localsecrets
KMS_KEY_URI=base64key://YOUR_BASE64_KEY_HERE
MASTER_KEYS=default:REPLACE_WITH_ENCRYPTED_MASTER_KEY_FROM_STEP_3
ACTIVE_MASTER_KEY_ID=default
AUTH_TOKEN_EXPIRATION_SECONDS=14400
RATE_LIMIT_ENABLED=true
RATE_LIMIT_REQUESTS_PER_SEC=10.0
RATE_LIMIT_BURST=20
RATE_LIMIT_TOKEN_ENABLED=true
RATE_LIMIT_TOKEN_REQUESTS_PER_SEC=5.0
RATE_LIMIT_TOKEN_BURST=10
METRICS_ENABLED=true
METRICS_NAMESPACE=secrets
METRICS_PORT=8081
EOF
docker run --rm --network secrets-net --env-file .env allisson/secrets migrate
docker run --rm --network secrets-net --env-file .env allisson/secrets create-kek --algorithm aes-gcm
docker run --rm --name secrets-api --network secrets-net --env-file .env -p 8080:8080 \
allisson/secrets server
Check the liveness endpoint:
curl http://localhost:8080/health
Expected:
{"status":"healthy"}
Check the readiness endpoint (includes database connectivity):
curl http://localhost:8080/ready
Expected (if database is connected):
{"status":"ready"}
Use the CLI command to create your first API client and policy set:
docker run --rm --network secrets-net --env-file .env allisson/secrets create-client \
--name bootstrap-admin \
--active \
--policies '[{"path":"*","capabilities":["read","write","delete","encrypt","decrypt","rotate"]}]' \
--format json
Save the returned client_id and one-time secret securely. The secret is shown only once.
curl -X POST http://localhost:8080/v1/token \
-H "Content-Type: application/json" \
-d '{"client_id":"<client-id>","client_secret":"<client-secret>"}'
Then:
curl -X POST http://localhost:8080/v1/secrets/app/prod/db-password \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"value":"c3VwZXItc2VjcmV0"}'
value is base64-encoded plaintext (super-secret).
For a full end-to-end check, run docs/getting-started/smoke-test.sh (usage in docs/getting-started/smoke-test.md).
For health check examples (Docker Compose sidecar, external monitoring), see the "Security Features" section above.
-
Docker Compose Examples - Complete Docker Compose setup