Procedures for backing up and restoring Bitwarden Server databases
Regular database backups are critical for disaster recovery and data protection. This guide covers backup strategies, automated backups, and restoration procedures for Bitwarden Server.
Bitwarden Server stores all critical data in a SQL Server database (or PostgreSQL/MySQL for alternative deployments). Your backup strategy should account for:
Vault data (ciphers, collections, organizations)
User accounts and authentication data
Organizational configurations
Attachments and Send files (stored separately)
Event logs and audit data
Backups must include both the database and file storage (attachments, Send files). A database backup alone is incomplete.
Bitwarden provides an automated backup script for SQL Server deployments:Location:util/MsSql/backup-db.sql and util/MsSql/backup-db.shBackup Script Overview:
-- Database nameDECLARE @DatabaseName varchar(100)SET @DatabaseName = 'vault'-- Check recovery model and adjust if neededIF EXISTS ( SELECT 1 FROM sys.databases WHERE name = @DatabaseName AND recovery_model = 1) AND NOT EXISTS ( SELECT 1 FROM msdb.dbo.backupset WHERE database_name = @DatabaseName AND type = 'L')BEGIN EXEC('ALTER DATABASE [' + @DatabaseName + '] SET RECOVERY SIMPLE')END-- Create backup fileDECLARE @BackupFile varchar(100)SET @BackupFile = '/etc/bitwarden/mssql/backups/' + 'vault' + '_FULL_$(now).BAK'DECLARE @BackupCommand NVARCHAR(1000)SET @BackupCommand = 'BACKUP DATABASE [' + @DatabaseName + '] TO DISK = ''' + @BackupFile + ''' WITH INIT, NAME= ''' + @DatabaseName + ' full backup for $(now)' + ''', NOSKIP, NOFORMAT'EXEC(@BackupCommand)
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "${SA_PASSWORD}" -C -Q "RESTORE DATABASE vault FROM DISK = '/etc/bitwarden/mssql/backups/vault_FULL_20260310_143022.BAK' WITH REPLACE, MOVE 'vault' TO '/var/opt/mssql/data/vault.mdf',MOVE 'vault_log' TO '/var/opt/mssql/data/vault_log.ldf'"
4
Verify Restore
Check database integrity:
USE vault;DBCC CHECKDB;SELECT COUNT(*) FROM [dbo].[User];
For point-in-time recovery, you need transaction log backups:
-- Set database to FULL recovery modelALTER DATABASE vault SET RECOVERY FULL;-- Create full backupBACKUP DATABASE vault TO DISK = '/backups/vault_full.bak';-- Create transaction log backups every hourBACKUP LOG vault TO DISK = '/backups/vault_log.trn';
Restore to specific time:
-- Restore full backupRESTORE DATABASE vault FROM DISK = '/backups/vault_full.bak'WITH NORECOVERY, REPLACE;-- Restore transaction log to specific pointRESTORE LOG vault FROM DISK = '/backups/vault_log.trn'WITH STOPAT = '2026-03-10 14:30:00', RECOVERY;