Deployment overview
Two things in the SuperFile family can run on infrastructure you control today.
| What | Tier | How |
|---|---|---|
| SuperDRM — the key and licence server behind every protected open | Any customer, on any plan; the software is the same we run | Docker Compose, Kubernetes (Helm) or systemd, documented on this site |
| The SuperSecure packaging and viewing pipeline with customer-held keys | Institutional | Scoped and installed with you; the licence server below is its core |
The rest of this section is the operator's manual for SuperDRM: what it is made of, how to install it, configure it, protect its keys and run it.
#What you are deploying
SuperDRM is four stateless services and one database. Every service is a container image built for linux/arm64 and linux/amd64, every setting is an environment variable, and the only durable state is Postgres plus the key-encryption key (KEK). That is what makes it portable: the same images run on a laptop, a single VM, Kubernetes, or a customer's own network.
| Service | Image | Port | State | Needs |
|---|---|---|---|---|
| api — Key Protect + License Service | ghcr.io/shanesupers/superdrm-api | 8770 | Postgres, KEK | Outbound HTTPS to the Widevine cloud service, unless you run Clear Key / FairPlay only |
| console — operator console | ghcr.io/shanesupers/superdrm-console | 8771 | none | api + admin token; put behind your own auth before exposing |
| docs — this documentation, password-gated | ghcr.io/shanesupers/superdrm-docs | 8772 | none | api (live status only) |
| live — real-time operations console | ghcr.io/shanesupers/superdrm-live | 8773 | demo clip cache | api + admin token; ffmpeg and gpac are in the image |
| ksm — FairPlay Key Security Module sidecar (optional) | built from ksm-sidecar/ | 8781 | Apple certificate + provisioning data | Apple's FPS Server SDK |
| postgres | postgres:16 | 5432 | the data | a volume, backups |
Runtime: Node 24, non-root, health checks on /health (api) and /healthz (docs, live).
#Topologies
#1. Single VM with Docker Compose (recommended first production host)
git clone https://github.com/shanesupers/superdrm && cd superdrm/deploy/compose
DOMAIN=drm.example.com ./install.sh # pulls images, generates secrets, starts, creates tenant "default"
DOMAIN=drm.example.com PROFILE=edge ./install.sh # + Caddy with automatic TLS (ports 80/443 open)
DOMAIN=drm.example.com PROFILE=tunnel TUNNEL_TOKEN=… ./install.sh # + cloudflared, no open ports
BUILD=1 DOMAIN=… ./install.sh # build the images from this checkout instead of pullinginstall.sh writes .env (every variable; see .env.example), secrets/kek.hex (back it up offline: every content key is sealed under it), secrets/docs.password and secrets/demo-tenant.json (the first tenant's API key and token secret, shown once). Ports bind to 127.0.0.1 by default; the edge and tunnel profiles are the two ways to expose the four hostnames.
Sizing: 2 vCPU / 4 GB handles thousands of licences per minute (a licence is one Postgres insert and one signed HTTPS call). Postgres grows about 200 bytes per licence row.
#2. Kubernetes with Helm
helm upgrade --install superdrm deploy/helm/superdrm \
--set domain=drm.example.com \
--set secrets.adminToken=$(openssl rand -hex 32) --set secrets.docsSessionSecret=$(openssl rand -hex 32) \
--set secrets.docsPasswordHash='scrypt$…' --set postgres.password=$(openssl rand -hex 24) \
--set secrets.kekHex=$(openssl rand -hex 32) # local vault; prefer the pkcs11 / aws-kms values belowThe chart gives you: Deployments for api (HPA 2–10, PodDisruptionBudget, rolling with zero unavailable), console, docs and live; an optional in-cluster Postgres StatefulSet or postgres.externalUrl; a pre-install/pre-upgrade migration Job; Ingress with TLS (cert-manager annotation by default; the console is not exposed unless ingress.exposeConsole=true); vault.provider=pkcs11 with a hostPath/CSI mount of your HSM vendor's PKCS#11 client, or vault.provider=aws-kms with an IRSA role on the ServiceAccount; ksm.enabled for the FairPlay sidecar; secrets.existingSecret to bring your own Secret.
#3. Bare metal or VM with systemd
ops/install.sh plus the four ops/superdrm-*.service user units, with env files under ~/.config/superdrm/. Postgres via DATABASE_URL, or the embedded PGlite for a single node. See Operations & migration.
#Database
Postgres 16 is the production database. The api talks plain SQL through one thin adapter; migrations are the files in db/migrations, applied by the api at boot, by npm run migrate, or by the Helm hook Job. The whole test suite runs against real Postgres and against embedded PGlite.
PGlite is for development, tests and single-node staging only: one process, one directory, no replication, no concurrent writers.
Backups: pg_dump nightly (Compose: docker compose exec postgres pg_dump -U superdrm superdrm | gzip > backup.sql.gz), plus the KEK material kept separately and offline. A database backup without the KEK is ciphertext; a KEK without the database is nothing. Restore drill: new stack → superdrm import the bundle or psql < backup → superdrm verify-kek.
#TLS and exposure
Only the api's licence routes must be reachable by players; everything else can stay private. Choose one: the Compose edge profile (Caddy, Let's Encrypt), the tunnel profile (cloudflared, no inbound ports), your Kubernetes Ingress, or your own load balancer. The api sets no cookies and licence routes are CORS-open by design; put a WAF or rate limit in front of /v1/*/license/* in public deployments.
#Upgrades
Images are tagged by git SHA and by version. Migrations are additive and idempotent; the api applies pending ones at boot (or the Helm hook does). Upgrade = pull the new tag, restart api first, then the others. Roll back by pointing the tag back; schema changes never drop columns in a release that a previous version still reads.
#Vault per platform
| Platform | Provider | Notes |
|---|---|---|
| Laptop / dev | local | KEK file, software only |
| Compose on a VM | local + offline backup, or pkcs11 with a USB HSM (YubiHSM 2) mounted into the container, or aws-kms with instance credentials | |
| Kubernetes on AWS | aws-kms via IRSA | keys never leave KMS |
| Kubernetes elsewhere | pkcs11 via the HSM vendor's client mounted with vault.pkcs11.hostPath / extraVolumes | Luna, CloudHSM, Thales |
| IBM Cloud (Sovereign tier) | pkcs11 against Hyper Protect Crypto Services' PKCS#11 (GREP11) client | FIPS 140-2 Level 4 |
Details and the key ceremony: Hardware key vault.
#Hosting tiers we operate and offer
| Tier | Where | Key protection | Fit |
|---|---|---|---|
| Standard | Our own cluster behind a tunnel | Software KEK or a YubiHSM 2 via pkcs11 | Staging, internal tenants; no SLA |
| Protected | Two cloud regions behind a load balancer, managed Postgres | AWS KMS (FIPS 140-3 Level 3 HSMs); FairPlay KSM inside a Nitro Enclave | Production for hosted tenants |
| Sovereign | IBM Cloud: Hyper Protect Crypto Services (FIPS 140-2 Level 4, Keep-Your-Own-Key) + Hyper Protect Virtual Servers | KEK and Apple secret never exist outside a Level 4 HSM; the licence service runs in an attested enclave | Banks and governments that require Level 4 and KYOK |
| On-premises | Your network | Your HSM or KMS | Institutional customers; On-premises install |
The code is identical across tiers: SUPERDRM_VAULT is the only switch.
Updated September 2026