Skip to content

Deployment

github-actions[bot] edited this page Sep 30, 2026 · 8 revisions

Deployment

SSF Transmitter runs as a single Docker container next to Authentik. TLS terminates at your reverse proxy; the container listens on port 8000 internally.

Image

Published to two registries, built for both linux/amd64 and linux/arm64 (e.g. Synology DS220+/DS920+ vs. Apple Silicon/ARM NAS):

ghcr.io/solarssk/ssf-transmitter:0.5.14     # pinned release
ghcr.io/solarssk/ssf-transmitter:latest      # tracks main

docker.io/solarssk/ssf-transmitter:0.5.14   # same image, Docker Hub
docker.io/solarssk/ssf-transmitter:latest

GHCR's package is private — docker pull ghcr.io/... requires docker login ghcr.io first with a GitHub PAT (read:packages). The Docker Hub image is public, so docker.io/solarssk/ssf-transmitter needs no login at all; use it if you'd rather not manage a GitHub PAT just to pull images. Both are built from the same source in the same CI run.

Minimal compose service

See docker-compose.snippet.yml in the repository root.

ssf-transmitter:
  image: ghcr.io/solarssk/ssf-transmitter:0.5.14
  container_name: authentik-ssf
  restart: unless-stopped
  env_file:
    - stack.env
  ports:
    - "127.0.0.1:${SSF_HOST_PORT:-62107}:${SSF_CONTAINER_PORT:-8000}"
  environment:
    SSF_ISSUER: "${SSF_ISSUER:?required}"
    SSF_BASE_URL: "${SSF_BASE_URL:?required}"
    SSF_ROOT_PATH: "${SSF_ROOT_PATH:-/shared-signals}"
    SSF_CONTAINER_PORT: "${SSF_CONTAINER_PORT:-8000}"
    SSF_LOG_LEVEL: "${SSF_LOG_LEVEL:-INFO}"
    SSF_WEBHOOK_AUTH_MODE: "${SSF_WEBHOOK_AUTH_MODE:-bearer}"
    SSF_WEBHOOK_TOKEN: "${SSF_WEBHOOK_TOKEN:?required}"
    SSF_MANAGEMENT_TOKEN: "${SSF_MANAGEMENT_TOKEN:?required}"
    SSF_FORWARDED_ALLOW_IPS: "${SSF_FORWARDED_ALLOW_IPS:-127.0.0.1}"
  volumes:
    - ./ssf-keys:/app/keys
    - ./ssf-data:/app/data
  networks:
    - authentik_network

Swap image: to docker.io/solarssk/ssf-transmitter:0.5.14 to pull from Docker Hub instead — skips the docker login GHCR needs.

Set SSF_FORWARDED_ALLOW_IPS to your reverse proxy Docker subnet when using Nginx Proxy Manager or similar. See Configuration.

stack.env minimum

SSF_ISSUER=https://idp.example.com/shared-signals
SSF_BASE_URL=https://idp.example.com/shared-signals
SSF_ROOT_PATH=/shared-signals
SSF_MANAGEMENT_TOKEN=<openssl rand -hex 32>
SSF_WEBHOOK_AUTH_MODE=bearer
SSF_WEBHOOK_TOKEN=<openssl rand -hex 32>
SSF_LOG_LEVEL=INFO
SSF_FORWARDED_ALLOW_IPS=172.16.3.0/24

Reverse proxy (Nginx Proxy Manager)

Add a location block on your IdP hostname:

location ^~ /shared-signals/ {
    limit_req zone=ssf_api burst=10 nodelay;
    proxy_pass http://127.0.0.1:62107/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Rate-limit zone (in http block):

limit_req_zone $binary_remote_addr zone=ssf_api:10m rate=30r/m;

Match SSF_FORWARDED_ALLOW_IPS to the Docker bridge subnet NPM uses.

Authentik webhook

Create a Generic Webhook notification transport:

Field Value
URL http://authentik-ssf:8000/webhook/authentik
Header Authorization: Bearer <SSF_WEBHOOK_TOKEN>
Events authentik.core.auth.logout, authentik.core.user.write

Use the Docker service name (authentik-ssf) so traffic stays on the internal network.

If you are upgrading an older deployment that still uses X-Authentik-Signature, keep SSF_WEBHOOK_AUTH_MODE=hmac and SSF_WEBHOOK_SECRET in stack.env until you intentionally migrate the transport to bearer auth.

Register stream with receiver

After the container is healthy, register the SSF stream with your receiver (e.g. Apple Business Manager) using:

  • SSF Config URL: https://idp.example.com/shared-signals/.well-known/ssf-configuration
  • Management API: POST /ssf/streams with Authorization: Bearer <SSF_MANAGEMENT_TOKEN>

One active stream is supported; creating a new stream replaces the previous one.

A stream is the receiver-side registration stored in SQLite: receiver URL, receiver bearer token, requested events, and status (enabled, paused, disabled).

Synology step-by-step

See synology-authentik-compose.md for a full Authentik stack integration guide.

Upgrading

See Upgrading.md — especially if you are moving from 0.5.8 to 0.5.9+.

Clone this wiki locally