Security and Restore Safety
Secrets
kamal-backup redacts secrets in evidence and command failure output. It treats values from keys containing words such as password, secret, token, key, and credential as sensitive.
Do not put cloud credentials in clear Kamal environment. Use Kamal secrets for:
RESTIC_PASSWORD;AWS_ACCESS_KEY_ID;AWS_SECRET_ACCESS_KEY;- database passwords such as
DATABASE_PASSWORD,PGPASSWORD, orMYSQL_PWD.
Store a copy of RESTIC_PASSWORD outside the app repository and outside the S3 bucket. Restic repositories are encrypted with that password; without it, the backup data is not recoverable.
Subprocess execution
External tools are executed with argument arrays, not shell interpolation. The backup container does not need application source code.
Database backups
Database backups use database-native export tools:
- PostgreSQL:
pg_dump --format=custom --no-owner --no-privileges - MySQL/MariaDB:
mariadb-dumpormysqldumpwith transaction-safe defaults - SQLite:
sqlite3 <db> ".backup ..."
This is why the docs talk about database backups rather than raw database directories. kamal-backup is exporting application data with the tools Rails teams already use for dumps and restores.
Active Storage backups
File-backed Active Storage files are backed up from configured mounted paths with restic backup. In a Kamal accessory, mount the production storage volume read-only when possible so the backup container can read Active Storage files without being able to modify them.
SQLite is the exception when the live database is on that storage volume. Rails SQLite apps commonly use WAL mode, and live WAL backups need normal read-write access to the database, WAL, and shared-memory files. For the normal SQLite setup, mount the storage volume read-write and point the SQLite database path at the live database. If the backup accessory must have no write access to app storage, back up a writer-created WAL-less snapshot instead.
Deliberate restores
Restore commands are explicit and deliberate:
- operators must choose
restore local,restore production,drill local, ordrill production - destructive restore commands prompt for confirmation unless an explicit automation flag is passed
restore productionasks for typed confirmation and ignores the generic--yesshortcut- local restores refuse production-looking local targets
- production drills restore into scratch targets, not the live production database
- production-side commands can be run from the local gem with
-dor-c, but the destructive work still happens on the backup accessory with the same explicit command surface
Those checks are there to make restores deliberate. They also help when you need to explain to a reviewer that a restore drill cannot quietly point back at production by accident.