Skip to content

Upgrading

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

Upgrading

v0.5.14 — OpenSSF Scorecard hardening (from 0.5.13)

Release notes: v0.5.14

Mostly CI/security-tooling — least-privilege GITHUB_TOKEN grants, real fuzz testing, hash-pinned dev/CI tooling, Sigstore-signed SBOMs. One real app-level fix: a malformed stored endpoint_url (found by the new fuzzer, not seen in production) is now blocked instead of crashing outbound push or startup preflight. Nothing to configure, no migration, no new env vars — bump the tag whenever convenient:

docker compose pull ssf-transmitter
docker compose up -d ssf-transmitter
docker compose logs ssf-transmitter --tail 50

v0.5.13 — Apple SCIM sync error handling (from 0.5.12)

Release notes: v0.5.13

One bug fix: POST /apple-scim/sync no longer 500s on a transient Apple API error while listing existing users — it now returns the same 502 Could not reach Apple Business Manager that an unreachable Authentik already produced. Nothing to configure, no migration. Bump the tag whenever convenient:

docker compose pull ssf-transmitter
docker compose up -d ssf-transmitter
docker compose logs ssf-transmitter --tail 50

v0.5.12 — Release pipeline hardening (from 0.5.11)

Release notes: v0.5.12

No app/ changes at all — this release only touches CI/release tooling (fixes to release.yml and docker-publish.yml found while cutting v0.5.11, the first release actually run through the new automation). Nothing to act on; the image content is identical to v0.5.11's except for a corrected SBOM (now covers both linux/amd64 and linux/arm64 instead of amd64 only). Upgrading is optional — bump the tag whenever convenient:

docker compose pull ssf-transmitter
docker compose up -d ssf-transmitter
docker compose logs ssf-transmitter --tail 50

v0.5.11 — Security audit fixes & release automation (from 0.5.10)

Release notes: v0.5.11

No config changes, no required env vars, no migration. This release is a set of internal bug fixes (an SSRF blocklist gap, a stream-write race condition, several Apple SCIM sync correctness fixes, a rate-limit sharing fix) plus new release-automation tooling that doesn't touch the running app. Bump the image tag and redeploy:

docker compose pull ssf-transmitter
docker compose up -d ssf-transmitter
docker compose logs ssf-transmitter --tail 50

Two things worth knowing, neither requiring action unless they apply to you:

  • If you've set APPLE_SCIM_UPDATE_MODE to anything other than the default patch_all: the sync loop that could previously retry the same no-op update forever under a narrow mode is fixed, and a new out_of_scope_diffs counter (plus a one-time WARNING log) now tells you when a field difference is permanently outside what that mode will write. See docs/Apple-SCIM-Sync.md.
  • If you script against the management API: PATCH /ssf/streams and PATCH /ssf/streams/{stream_id} now share one rate-limit counter instead of each getting its own — a script alternating between the two routes will hit 429 sooner than before (20/minute total, not 40).

v0.5.10 — Stream recovery hardening (from 0.5.8 or earlier)

Release notes: v0.5.10

What changed for operators

Area Change
Receiver tokens Encrypted at rest in SQLite (Fernet)
Reverse proxy SSF_FORWARDED_ALLOW_IPS default is now 127.0.0.1 (was *)
Management API In-app rate limits; failed auth attempts rate-limited per IP
Apple SCIM GET /apple-scim/status requires management Bearer token
Startup HTTPS required for SSF_ISSUER / SSF_BASE_URL; undecryptable receiver tokens pause streams
Logging Prefer SSF_LOG_LEVEL over LOG_LEVEL
Webhook auth Default is bearer; legacy HMAC installs must keep SSF_WEBHOOK_AUTH_MODE=hmac (see below)

Webhook auth: bearer vs HMAC

SSF_WEBHOOK_AUTH_MODE defaults to bearer in application code. New installs should use bearer with Authentik Header Mapping (Authorization: Bearer <SSF_WEBHOOK_TOKEN>).

If your deployment still uses HMAC (X-Authentik-Signature + SSF_WEBHOOK_SECRET), you must explicitly set in stack.env:

SSF_WEBHOOK_AUTH_MODE=hmac
SSF_WEBHOOK_SECRET=<your existing secret>

Without this, an upgrade can silently switch to bearer mode and Authentik webhooks will return 401 until you migrate the transport to bearer or restore hmac in env.

To migrate to bearer: set SSF_WEBHOOK_AUTH_MODE=bearer, add SSF_WEBHOOK_TOKEN, and update the Authentik Generic Webhook Header Mapping. See Deployment.md.

Use this when you already have a working stream and Apple Business Manager is connected.

  1. Backup volumes:
    • /app/keys (signing key)
    • /app/data (SQLite — stream + SCIM tokens)
  2. Update image tag:
    image: ghcr.io/solarssk/ssf-transmitter:0.5.10
    (or docker.io/solarssk/ssf-transmitter:0.5.10 — same image, public, no login; see Deployment.md#image)
  3. Set proxy trust (if behind NPM/Caddy/Traefik):
    SSF_FORWARDED_ALLOW_IPS=172.16.3.0/24   # your proxy subnet
  4. Do not add SSF_TOKEN_ENCRYPTION_KEY on an existing install unless you will re-register the stream.
  5. Do not rotate SSF_MANAGEMENT_TOKEN without a plan to re-register the stream.
  6. Pull and redeploy:
    docker compose pull ssf-transmitter
    docker compose up -d ssf-transmitter
    docker compose logs ssf-transmitter --tail 50
  7. Verify startup logs show preflight OK.
  8. Check stream status:
    curl -s -H "Authorization: Bearer $SSF_MANAGEMENT_TOKEN" \
      https://idp.example.com/shared-signals/ssf/status
    Expect "status": "enabled".

What is a “stream”?

A stream is the SSF receiver configuration stored in SQLite (/app/data/ssf.db): receiver URL, bearer token, events, and status. “Already connected to ABM” means you already have a stream — not a fresh install.

If stream is paused after upgrade

Startup pauses streams when the stored receiver token cannot be decrypted (e.g. after key rotation). Logs contain:

undecryptable endpoint tokens and were paused

Fix: Re-register the stream via management API with a new delivery.endpoint_url_token from your receiver, then set status: enabled.

You cannot re-enable a paused stream with an undecryptable token without supplying a replacement token (by design since v0.5.9, still enforced in v0.5.10).

Minimal recovery PATCH (include the current delivery.endpoint_url; the PATCH schema still requires it):

{
  "status": "enabled",
  "delivery": {
    "endpoint_url": "https://receiver.example.com/sets",
    "endpoint_url_token": "<new receiver token>"
  }
}

Optional hardening after upgrade

Variable When
SSF_ALLOWED_RECEIVER_HOSTS Restrict stream registration to known receiver hostnames
SSF_PII_PEPPER Dedicated secret for log pseudonymisation
SSF_TOKEN_ENCRYPTION_KEY New installs only, or planned migration with stream re-registration

Fresh install (no existing stream)

  1. Set all required variables per Configuration.md.
  2. Optionally set SSF_TOKEN_ENCRYPTION_KEY before first POST /ssf/streams.
  3. Set SSF_FORWARDED_ALLOW_IPS if behind a reverse proxy.
  4. Register stream with ABM.

General upgrade procedure

docker compose pull ssf-transmitter
docker compose up -d ssf-transmitter
docker compose logs ssf-transmitter --tail 50

Pin to a version tag (0.5.11) in production; use :latest only if you accept automatic updates on redeploy.

Rolling back

  1. Stop container.
  2. Restore /app/keys and /app/data from backup if needed.
  3. Deploy previous image tag (e.g. 0.5.8).
  4. If you upgraded DB format or encryption on 0.5.9+ installs, test rollback in a lab first.

Clone this wiki locally