Upgrade & Backup
Move a self-hosted Solana Developer Platform to a new release and protect its data.
Upgrade to a new release, roll back, and back up the data that matters.
Upgrade
A release ships new images and an updated compose.yml.
-
Refresh the install files. Re-run the install script. It replaces
compose.ymlwith the new release's, verified against its checksums. It never touches.env, keeps an existing.env.example, and prints a link to the new release's template so you can check for new variables.Terminal curl -fsSL https://github.com/solana-foundation/solana-developer-platform/releases/latest/download/install.sh | bashTo install a specific release instead of the latest, set
INSTALL_VERSIONto its tag:Terminal curl -fsSL https://github.com/solana-foundation/solana-developer-platform/releases/latest/download/install.sh | INSTALL_VERSION=vX.Y.Z bash -
Pin the version. Set
SDP_VERSIONin.envto the same release tag, notlatest, so every service runs one known build. -
Pull and restart.
Terminal cd ~/sdp docker compose pull docker compose up -dsdp-migrateapplies any new database migrations before the API starts. -
Verify that the services are healthy, as in the Quickstart.
Roll back
To run the previous release again, re-run the install script with its tag in INSTALL_VERSION, set SDP_VERSION to that tag, and run docker compose up -d.
Migrations don't reverse. If the newer release applied any, restore a backup taken before the upgrade instead of only switching versions.
Backup
Two things hold your state:
- The Postgres database: all platform data. The bundled database lives in the
sdp-postgres-datavolume (sdp_sdp-postgres-dataindocker volume ls). Back up an externalDATABASE_URLwith your database provider's tools. - Your
.env: configuration and secrets you can't regenerate. Without the sameAPI_KEY_PEPPER, no existing API key matches. Without the sameCUSTODY_ENCRYPTION_KEY, SDP can't decrypt the custody secrets it stored, such as local wallet keys. Keep the file in a secret manager.
Redis is a cache and doesn't need a backup.
Back up the database
Take a logical dump with pg_dump inside the running container. Running it through sh -c lets it read POSTGRES_USER and POSTGRES_DB there, so custom values work:
cd ~/sdp
docker compose exec -T postgres \
sh -c 'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' > sdp-backup.sqlKeep dumps off the host, on a schedule that fits your recovery needs.
Restore the database
A plain pg_dump holds the full schema and the migration history, so restore it into an empty database and let the stack start on top. Restoring over an already migrated database collides with the schema sdp-migrate created.
cd ~/sdp
docker compose down # stop every service
docker volume rm sdp_sdp-postgres-data # discard the current database (destructive)
docker compose up -d postgres # start a fresh, empty Postgres
until docker compose exec -T postgres \
sh -c 'pg_isready -U "$POSTGRES_USER"' >/dev/null 2>&1; do sleep 1; done
docker compose exec -T postgres \
sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB"' < sdp-backup.sql
docker compose up -d # start the restOn that final up, sdp-migrate skips every migration the dump already records, so an older dump gets only the newer migrations.
Restore the matching .env too, so secrets such as CUSTODY_ENCRYPTION_KEY match the data they protect. Restore an external DATABASE_URL through your database provider instead of the bundled postgres service.