Daemon — ssd

ssd is the SecretServer daemon — a lightweight background service that runs on your servers and provides local secret caching, certificate expiry monitoring, Certificate Transparency alerts, and secret rotation.

Overview

While the ss CLI is for interactive and scripted access, ssd is a persistent service that:

  • Caches secrets locally so processes can read them without a round-trip to the API
  • Exposes a Unix socket for fast, low-latency secret retrieval
  • Monitors certificate expiry and sends alerts before certs expire
  • Polls Certificate Transparency logs for your monitored domains
  • Executes secret rotation scripts on a schedule
  • Syncs secrets to environment files or directories for legacy applications
When to use ssd vs ss:

Use ss for one-off lookups and scripts. Use ssd when you want always-on monitoring, local caching for high-throughput services, or automatic rotation without cron hacks.

Install

ssd is included in the same release binary as the ss CLI.

# Install via the universal installer (installs both ss and ssd)
curl -sSL https://secretserver.io/install | sh

# Or via Homebrew (macOS / Linux)
brew install afterdark/tap/ss

# Verify
ssd --version

Binary locations

which ss    # /usr/local/bin/ss
which ssd   # /usr/local/bin/ssd

Configure

ssd reads from ~/.adkm/config.yaml (same file as the CLI). The [daemon] section controls daemon-specific behaviour.

# ~/.adkm/config.yaml

api_key: sk_live_...
api_url: https://api.secretserver.io   # or your self-hosted URL

daemon:
  socket: /var/run/ssd.sock      # Unix socket path
  cache_ttl: 300                 # Secret cache TTL in seconds (default: 300)
  poll_interval: 60              # Background poll interval in seconds (default: 60)
  log_file: /var/log/ssd.log    # Log file (default: stderr)
  log_level: info                # debug | info | warn | error

  # Certificate expiry alerts
  cert_warn_days: [30, 14, 7, 1]  # Alert when cert expires in N days

  # CT log monitoring (requires ss ct monitor add <domain> first)
  ct_poll_interval: 3600         # Check CT logs every hour

  # Secret rotation
  rotation:
    enabled: true
    scripts_dir: /etc/ssd/rotate.d/  # Directory of rotation scripts

Environment variables

SS_API_KEY=sk_live_...     # API key (overrides config file)
SS_API_URL=...            # API URL (overrides config file)
SSD_SOCKET=/var/run/ssd.sock
SSD_LOG_LEVEL=info

Running ssd

# Start the daemon (foreground)
ssd

# Start with verbose logging
ssd --log-level debug

# Start with a custom config file
ssd --config /etc/ssd/config.yaml

# Check daemon status (if already running)
ssd status

# Reload configuration without restart
ssd reload

# Stop the daemon
ssd stop

systemd service (Linux)

Install ssd as a systemd unit for automatic startup and restart.

# /etc/systemd/system/ssd.service

[Unit]
Description=SecretServer Daemon
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=ssd
Group=ssd
ExecStart=/usr/local/bin/ssd --config /etc/ssd/config.yaml
Restart=on-failure
RestartSec=5
Environment=SS_API_KEY=sk_live_...
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable ssd
sudo systemctl start ssd

# Check status and logs
sudo systemctl status ssd
sudo journalctl -u ssd -f

Features summary

FeatureConfig keyDefault
Local secret cachedaemon.cache_ttl300s
Unix socket APIdaemon.socket/var/run/ssd.sock
Background pollingdaemon.poll_interval60s
Cert expiry alertsdaemon.cert_warn_days[30,14,7,1]
CT log monitoringdaemon.ct_poll_interval3600s
Secret rotationdaemon.rotation.enabledfalse
Env file syncdaemon.env_sync.dirdisabled

Environment injection

ssd can write secrets to an env file that your application sources on startup, or keep it continuously up to date.

# In ~/.adkm/config.yaml:
daemon:
  env_sync:
    enabled: true
    dir: /etc/ssd/secrets/          # Write one file per secret here
    env_file: /etc/app/.env         # Or write a single .env file
    container: production           # Only sync secrets from this container
    interval: 300                   # Refresh every 5 minutes
# Application reads from the env file
# /etc/app/.env (auto-generated by ssd):
# POSTGRES_PASSWORD=s3cur3P@ssw0rd!
# STRIPE_SECRET_KEY=sk_live_...
# AWS_SECRET_ACCESS_KEY=...

source /etc/app/.env && exec myapp

Certificate expiry monitoring

ssd checks all certificates stored in SecretServer and sends alerts when expiry thresholds are crossed.

# In ~/.adkm/config.yaml:
daemon:
  cert_warn_days: [30, 14, 7, 1]    # Alert at 30, 14, 7, and 1 day before expiry

  alerts:
    email: ops@example.com           # Alert email
    webhook: https://hooks.slack.com/...  # Slack / Teams webhook
    pagerduty_key: abc123            # PagerDuty integration key

All certificates in the dashboard — including those discovered via ss discover ssl or imported via ss ct import — are included in expiry checks.

CT log monitoring

When domains are added to CT monitoring (via ss ct monitor add), ssd periodically polls Certificate Transparency logs and alerts when new certificates are issued.

# Add a domain to monitor
ss ct monitor add example.com
ss ct monitor add *.example.com

# ssd then polls every ct_poll_interval seconds and alerts on new issuances
# Configure in ~/.adkm/config.yaml:
daemon:
  ct_poll_interval: 3600    # every hour
  alerts:
    email: security@example.com

CT monitoring catches mis-issuance events (unexpected CAs issuing certs for your domain), shadow IT, and rogue wildcard certificates before they're used in attacks.

Secret rotation

Place shell scripts in daemon.rotation.scripts_dir. Each script is responsible for rotating one secret type. Scripts are executed on the configured schedule and must exit 0 on success.

# /etc/ssd/rotate.d/postgres-password.sh
#!/usr/bin/env bash
set -euo pipefail

NEW_PASS=$(openssl rand -base64 32)

# Update in the database
psql "host=db.internal user=admin" -c "ALTER USER app_user PASSWORD '$NEW_PASS'"

# Store the new value in SecretServer
ss secrets create --name "postgres-password" --value "$NEW_PASS" --update-existing
# In ~/.adkm/config.yaml:
daemon:
  rotation:
    enabled: true
    scripts_dir: /etc/ssd/rotate.d/
    schedule: "0 3 * * 0"   # Cron expression — every Sunday at 03:00
    on_failure: alert        # alert | retry | stop

Local Unix socket API

ssd exposes a local Unix socket at /var/run/ssd.sock that applications can query directly — no API key exposed in the process environment.

# Query via curl (using the socket)
curl --unix-socket /var/run/ssd.sock http://localhost/secret/production/postgres-password

# Response:
{ "value": "s3cur3P@ssw0rd!", "cached": true, "cached_at": "2026-02-17T03:00:00Z" }

# Force a cache refresh
curl --unix-socket /var/run/ssd.sock -X POST http://localhost/refresh/production/postgres-password

Client libraries (Python, Node.js, Go) can be configured to use the local socket instead of the remote API, eliminating network latency for hot paths.