Repository navigation
Upgrading
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 50Release 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 50Release 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 50Release 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 50Two things worth knowing, neither requiring action unless they apply to you:
-
If you've set
APPLE_SCIM_UPDATE_MODEto anything other than the defaultpatch_all: the sync loop that could previously retry the same no-op update forever under a narrow mode is fixed, and a newout_of_scope_diffscounter (plus a one-timeWARNINGlog) 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/streamsandPATCH /ssf/streams/{stream_id}now share one rate-limit counter instead of each getting its own — a script alternating between the two routes will hit429sooner than before (20/minute total, not 40).
Release notes: v0.5.10
| 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) |
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.
-
Backup volumes:
-
/app/keys(signing key) -
/app/data(SQLite — stream + SCIM tokens)
-
-
Update image tag:
(or
image: ghcr.io/solarssk/ssf-transmitter:0.5.10
docker.io/solarssk/ssf-transmitter:0.5.10— same image, public, no login; see Deployment.md#image) -
Set proxy trust (if behind NPM/Caddy/Traefik):
SSF_FORWARDED_ALLOW_IPS=172.16.3.0/24 # your proxy subnet
-
Do not add
SSF_TOKEN_ENCRYPTION_KEYon an existing install unless you will re-register the stream. -
Do not rotate
SSF_MANAGEMENT_TOKENwithout a plan to re-register the stream. - Pull and redeploy:
docker compose pull ssf-transmitter docker compose up -d ssf-transmitter docker compose logs ssf-transmitter --tail 50
-
Verify startup logs show
preflight OK. -
Check stream status:
Expect
curl -s -H "Authorization: Bearer $SSF_MANAGEMENT_TOKEN" \ https://idp.example.com/shared-signals/ssf/status"status": "enabled".
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.
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>"
}
}| 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 |
- Set all required variables per Configuration.md.
- Optionally set
SSF_TOKEN_ENCRYPTION_KEYbefore firstPOST /ssf/streams. - Set
SSF_FORWARDED_ALLOW_IPSif behind a reverse proxy. - Register stream with ABM.
docker compose pull ssf-transmitter
docker compose up -d ssf-transmitter
docker compose logs ssf-transmitter --tail 50Pin to a version tag (0.5.11) in production; use :latest only if you accept automatic updates on redeploy.
- Stop container.
- Restore
/app/keysand/app/datafrom backup if needed. - Deploy previous image tag (e.g.
0.5.8). - If you upgraded DB format or encryption on 0.5.9+ installs, test rollback in a lab first.