Guides
Backups and encryption
Skiff backs up your databases and volumes every day and encrypts the secrets it stores. This page covers what that protects, what it doesn't, and the two things to set up yourself.
What gets backed up
- Databases: Postgres, MySQL, MongoDB and Redis, daily. Skiff keeps the last 10 on your server.
- Volumes:daily, keeping the last 3 on your server. Previews aren't backed up, because they use empty copies of their project's volumes.
- Skiff itself: its database and settings, sealed with your recovery key. See self-hosting.
You can also take a backup at any time. For a database, open Backupson it. For a volume, open the project's Settings and use the backups button beside the volume.
Your app pauses briefly while a volume is copied, so files like SQLite databases stay consistent. Requests wait during the pause. Volumes over 1 GB are copied while the app runs, because the pause would be too long, and are labelled copied while running. If your app writes constantly, check that those copies restore cleanly. A backup is skipped when it could fill the disk.
Add an offsite bucket
- 1
Create a private bucket
Any S3-compatible storage works. Keep it private, because database and volume backups are stored there unencrypted. - 2
Add it in Settings
Enter the endpoint, bucket and keys in the offsite section. New backups are copied there, and the bucket keeps up to 30 per database or volume.
Restoring
A restore returns the database or volume to exactly what's in the backup. Anything created after it is removed, including new tables and files. Before every restore, Skiff backs up the current data, so you can undo it. That backup is listed as before restore. If it can't be taken, the restore doesn't run.
- Postgres restores in one transaction, so a failure changes nothing. Other connections are closed first, so your apps will reconnect.
- MySQL and MongoDBcan't do this in one step, so a failure partway can leave them incomplete. If that happens, restore the before restore backup.
- Redis stops briefly. The file is checked first, so a damaged backup causes no downtime.
- Volumes unpack while your app keeps running, and it restarts for a moment when the files are swapped. If the swap fails, the original files go back. If the backup is no longer on your server, Skiff fetches it from your bucket.
After moving to a new server, managed databases load their newest offsite backup on their own. Volumes don't: redeploy the app, then restore the volume from its backups.
What's encrypted
These are encrypted in Skiff's database with a key derived from your recovery key:
- Environment variables, including shared and preview ones
- Database passwords, and bucket and offsite keys
- Registry passwords
- Alert URLs, and log drain URLs and headers
- Two-factor secrets
Login sessions and invite links are stored as hashes, so they can't be read back. Passwords and API tokens are hashed too.
What this protects against
It protects a copy of the database file on its own, such as one left in a stray backup or on an old disk. It doesn't protect against someone with root on your server, or anyone who copies all of ~/.skiff, because the key is kept there too. Your apps also receive their secrets as ordinary environment variables while they run.
These aren't encrypted: database and volume backups, the GitHub and email settings files in ~/.skiff, and any data your apps store themselves.
Save your recovery key
Find it in the dashboard under Server, in the control-plane backup section, and keep it somewhere off the server, such as a password manager.
recovery.keygoes missing or doesn't match, the panel refuses to start rather than create a new one. Put the original file back to fix it.Downgrading
Older versions can't read encrypted secrets, so going back to a version before v0.6.0 will break them. When the upgrade converts your secrets, Skiff first writes a sealed copy of the old database to ~/.skiff/pre-encryption-*.skiffbackup and keeps it for 14 days. skiff server restore can read it.