Skip to content

Latest commit

 

History

History
113 lines (85 loc) · 4.2 KB

File metadata and controls

113 lines (85 loc) · 4.2 KB

Keycast Live Upgrade Notes

Use this when upgrading an existing Keycast deployment to the hardened runtime. This is not a blank install path.

What Changed

  • Containers now run as a non-root user and use a read-only root filesystem.
  • master.key is mounted from the host instead of being copied into the image.
  • ALLOWED_PUBKEYS is enforced by the API, not just the browser.
  • docker-compose.prod.yml can pull the published ghcr.io/marmot-protocol/keycast image instead of building Rust and Bun on the server.
  • The Nostr Rust stack moved to current crates.io releases.
  • Migration 0002_normalize_allowed_kinds_permissions.sql normalizes old allowed_kinds permission JSON from {"sign":[...]} to {"allowed_kinds":[...]}.

Before You Deploy

  1. Stop the running containers and make a cold backup of the database and key. SQLite runs in WAL mode, so prefer SQLite's backup command when sqlite3 is available:
mkdir -p backups
ts="$(date +%Y%m%d-%H%M%S)"
docker compose stop keycast-api keycast-signer keycast-web
sqlite3 database/keycast.db ".backup 'backups/keycast.${ts}.db'"
cp master.key "backups/master.${ts}.key"

If sqlite3 is not available on the host, copy the database sidecar files too when they exist:

mkdir -p backups
ts="$(date +%Y%m%d-%H%M%S)"
docker compose stop keycast-api keycast-signer keycast-web
cp database/keycast.db "backups/keycast.${ts}.db"
[ ! -f database/keycast.db-wal ] || cp database/keycast.db-wal "backups/keycast.${ts}.db-wal"
[ ! -f database/keycast.db-shm ] || cp database/keycast.db-shm "backups/keycast.${ts}.db-shm"
cp master.key "backups/master.${ts}.key"
  1. Do not generate a new master.key for an existing install. If the host file is missing but the old container still has /app/master.key, recover it before deploying:
docker cp keycast-api:/app/master.key ./master.key
chmod 600 master.key
  1. Set the server allowlist before starting the new API:
ALLOWED_PUBKEYS=hexpubkey1,hexpubkey2

Every admin pubkey that needs to use the app after the upgrade must be included.

  1. Run the preflight:
scripts/upgrade_preflight.sh
sudo scripts/upgrade_preflight.sh --fix-permissions

The second command is needed when the old root-running containers created root-owned database files. The preflight also checks that database/migrations/0002_normalize_allowed_kinds_permissions.sql is present in the checkout. The API and signer read migrations from the bind-mounted database/ directory at startup.

Deploy

docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
docker compose -f docker-compose.prod.yml ps

Production Compose pulls ghcr.io/marmot-protocol/keycast by default. If pull returns unauthorized, change the GitHub Packages visibility to public or log the deployment host in to GHCR before retrying.

The API and signer run SQLx migrations on startup. The new migration only normalizes old permission JSON. It does not rotate keys, change stored-key ciphertext, or invalidate existing bunker connection strings.

By default, production Compose tracks the moving master tag. To pin a specific build, set KEYCAST_IMAGE_TAG=sha-<commit> in .env, then run the same pull and up commands.

Verify

curl -f https://your-domain.example/health
curl -f https://your-domain.example/api/health
docker compose -f docker-compose.prod.yml logs --tail=100 keycast-api keycast-signer keycast-web

Then sign in with an allowlisted pubkey, open an existing team, inspect an existing policy, and test one existing NIP-46 authorization. Existing bunker connection strings should keep working because the stored keys, bunker keys, and connection secrets are unchanged.

Rollback

If you need to roll back code after migration 0002 has run, restore the database backup too. The old application may not understand the normalized allowed_kinds JSON.

docker compose -f docker-compose.prod.yml down
cp backups/keycast.YYYYMMDD-HHMMSS.db database/keycast.db
cp backups/master.YYYYMMDD-HHMMSS.key master.key
KEYCAST_IMAGE_TAG=sha-previous docker compose -f docker-compose.prod.yml up -d

Do not roll back with a different master.key; stored private keys and bunker keys will not decrypt.