Skip to the content.

Overview

Borg UI uses SQLite as its database. The database file is stored outside the container on your host machine, ensuring data persists across container rebuilds, updates, and restarts.


How It Works

Database Location

Inside Container:

/app/data/borg.db

On Host Machine:

./data/borg.db

Docker Volume Mount

The docker-compose.yml file mounts the host directory to the container:

volumes:
  - ./data:/app/data:rw

This means:


Configuration

Database URL

In .env or docker-compose.yml:

DATABASE_URL=sqlite:////app/data/borg.db

Note the 4 slashes: sqlite:////


Verifying Persistence

Test 1: Check Database File Exists

# On your host machine
ls -lh ./data/borg.db

# Should show something like:
# -rw-r--r--  1 user  staff   256K Jan 14 10:30 ./data/borg.db

Test 2: Create Test Data

# 1. Start the application
docker-compose up -d

# 2. Login and create some data (user, SSH key, repository, etc.)

# 3. Stop the container
docker-compose down

# 4. Check database file still exists
ls -lh ./data/borg.db

# 5. Restart the container
docker-compose up -d

# 6. Login - your data should still be there!

Test 3: Rebuild Container

# 1. Make sure you have data in the application

# 2. Rebuild from scratch
docker-compose down
docker-compose build --no-cache
docker-compose up -d

# 3. Login - your data should still be there!

Backing Up the Database

Manual Backup

# Stop the application first (recommended)
docker-compose down

# Copy the database file
cp ./data/borg.db ./data/borg-backup-$(date +%Y%m%d).db

# Or create a compressed backup
tar -czf borg-backup-$(date +%Y%m%d).tar.gz ./data/

# Restart
docker-compose up -d

Automated Backup Script

Create backup-db.sh:

#!/bin/bash
BACKUP_DIR="./backups/db"
mkdir -p "$BACKUP_DIR"

# Create backup with timestamp
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
cp ./data/borg.db "$BACKUP_DIR/borg-$TIMESTAMP.db"

# Keep only last 7 days of backups
find "$BACKUP_DIR" -name "borg-*.db" -mtime +7 -delete

echo "✅ Database backed up to: $BACKUP_DIR/borg-$TIMESTAMP.db"

Run it:

chmod +x backup-db.sh
./backup-db.sh

Backup with Cron

# Edit crontab
crontab -e

# Add daily backup at 2 AM
0 2 * * * cd /path/to/borg-ui && ./backup-db.sh

Restoring the Database

From Backup

# 1. Stop the application
docker-compose down

# 2. Replace the database file
cp ./data/borg-backup-20250114.db ./data/borg.db

# 3. Restart
docker-compose up -d

From Another Server

# 1. Copy database from old server
scp user@old-server:/path/to/borg-ui/data/borg.db ./data/

# 2. Start the application
docker-compose up -d

Troubleshooting

Database File Not Found

If you see errors about missing database:

# Check if data directory exists
ls -la ./data/

# If it doesn't exist, create it
mkdir -p ./data
chmod 755 ./data

# Restart container
docker-compose restart

The application will automatically create a new database file on first run.

Database Locked Error

If you see “database is locked”:

# Check if multiple processes are accessing the database
docker-compose ps

# Stop all containers
docker-compose down

# Check for lingering processes
ps aux | grep borg

# Restart
docker-compose up -d

Permissions Issues

If you get permission denied errors:

# Fix ownership (run on host)
sudo chown -R $USER:$USER ./data/

# Fix permissions
chmod 644 ./data/borg.db
chmod 755 ./data/

Database Corrupted

If database becomes corrupted:

# 1. Stop the application
docker-compose down

# 2. Check integrity
sqlite3 ./data/borg.db "PRAGMA integrity_check;"

# If corrupted, restore from backup
cp ./data/borg-backup-YYYYMMDD.db ./data/borg.db

# Or start fresh (⚠️ loses all data!)
rm ./data/borg.db

# 3. Restart
docker-compose up -d

Migrating to New Machine

Export Data

On old machine:

# 1. Stop the application
docker-compose down

# 2. Create archive
tar -czf borg-data-export.tar.gz \
  ./data/ \
  ./config/ \
  ./backups/ \
  .env

# 3. Transfer to new machine
scp borg-data-export.tar.gz user@new-machine:/path/to/destination/

Import Data

On new machine:

# 1. Clone repository
git clone https://github.com/karanhudia/borg-ui.git
cd borg-ui

# 2. Extract backup
tar -xzf /path/to/borg-data-export.tar.gz

# 3. Start the application
docker-compose up -d

Why SQLite?

Advantages:

Perfect For:

When to Consider PostgreSQL:


Database Size Management

Check Database Size

# On host
du -h ./data/borg.db

# Or inside container
docker exec borg-web-ui du -h /app/data/borg.db

Vacuum Database (Optimize)

SQLite can accumulate free space. Vacuum to reclaim it:

# Stop application first
docker-compose down

# Vacuum the database
sqlite3 ./data/borg.db "VACUUM;"

# Restart
docker-compose up -d

Typical Sizes

Archives Jobs Size
10 5 ~100 KB
100 20 ~1 MB
1000 50 ~10 MB
10000 100 ~100 MB

Summary

Database persists automatically - stored in ./data/borg.dbSurvives container rebuilds - volume mounted to host ✅ Easy to backup - just copy one file ✅ Simple to migrate - transfer data directory ✅ Zero configuration - works out of the box

No action needed - it just works! 🎉