← All articles
TutorialConfiguration

Paperclip Backup and Restore

Paperclip stores everything in a data directory — your database, secrets, and agent workspace files. Backing it up is straightforward once you know what to include.

Deploy on Railway →

What to back up

Paperclip's data lives in the directory set by PAPERCLIP_DATA_DIR (default: ~/.paperclip/instances/default). The critical pieces are:

| Path | Contents | Critical? | |---|---|---| | data/db/ | SQLite database (all issues, agents, comments) | Yes — required | | secrets/master.key | Encryption key for agent API keys | Yes — losing this = losing all secrets | | data/storage/ | File attachments uploaded through Paperclip | Yes if you use attachments | | workspaces/ | Agent workspace files | Nice to have |

The entire data directory is safe to back up. Nothing in it is regenerated from elsewhere.

Manual backup

Stop Paperclip first for a consistent database snapshot:

sudo systemctl stop paperclip

# Backup everything
tar -czf ~/paperclip-backup-$(date +%Y%m%d-%H%M).tar.gz \
  /opt/paperclip/data \
  /opt/paperclip/secrets

sudo systemctl start paperclip

echo "Backup complete: ~/paperclip-backup-$(date +%Y%m%d).tar.gz"

Live backup (without stopping Paperclip)

SQLite supports hot backups using its .backup command. For Paperclip, this looks like:

# Create a live backup of just the database
sqlite3 /opt/paperclip/data/db/paperclip.db ".backup /tmp/paperclip-db-backup.db"

# Then archive it
tar -czf ~/paperclip-db-backup-$(date +%Y%m%d).tar.gz /tmp/paperclip-db-backup.db
rm /tmp/paperclip-db-backup.db

This creates a consistent snapshot without taking Paperclip offline. Always include the secrets/master.key separately.

Automated daily backups with cron

# Create a backup script
sudo tee /opt/paperclip/backup.sh << 'EOF'
#!/bin/bash
BACKUP_DIR=/opt/paperclip/backups
DATA_DIR=/opt/paperclip/data
SECRETS_DIR=/opt/paperclip/secrets
DB_PATH=$DATA_DIR/db/paperclip.db
DATE=$(date +%Y%m%d-%H%M)

mkdir -p $BACKUP_DIR

# Live database backup
sqlite3 $DB_PATH ".backup $BACKUP_DIR/paperclip-db-$DATE.db"

# Secrets backup
cp $SECRETS_DIR/master.key $BACKUP_DIR/master-key-$DATE.key

# Compress
tar -czf $BACKUP_DIR/paperclip-backup-$DATE.tar.gz \
  $BACKUP_DIR/paperclip-db-$DATE.db \
  $BACKUP_DIR/master-key-$DATE.key

# Clean up intermediate files
rm $BACKUP_DIR/paperclip-db-$DATE.db
rm $BACKUP_DIR/master-key-$DATE.key

# Keep only last 7 days of backups
find $BACKUP_DIR -name "paperclip-backup-*.tar.gz" -mtime +7 -delete

echo "Backup complete: $BACKUP_DIR/paperclip-backup-$DATE.tar.gz"
EOF

sudo chmod +x /opt/paperclip/backup.sh
sudo chown deploy:deploy /opt/paperclip/backup.sh

Add to crontab (runs daily at 2am):

crontab -e
# Add this line:
0 2 * * * /opt/paperclip/backup.sh >> /var/log/paperclip-backup.log 2>&1

Offsite backup

Copy backups to a remote location. Using rclone with S3:

# Install rclone
curl https://rclone.org/install.sh | sudo bash

# Configure (follow prompts)
rclone config

# Copy backups to S3
rclone copy /opt/paperclip/backups s3:your-bucket/paperclip-backups

# Add to backup script:
rclone copy /opt/paperclip/backups s3:your-bucket/paperclip-backups --max-age 8d

Or use rsync to a remote server:

rsync -avz /opt/paperclip/backups/ backup-user@backup-server:/backups/paperclip/

Restoring from backup

Full restore on the same server

# Stop Paperclip
sudo systemctl stop paperclip

# Extract backup
tar -xzf paperclip-backup-20250115-0200.tar.gz -C /tmp/

# Restore database
cp /tmp/opt/paperclip/data/db/paperclip.db /opt/paperclip/data/db/paperclip.db

# Restore secrets
cp /tmp/opt/paperclip/secrets/master.key /opt/paperclip/secrets/master.key
chmod 600 /opt/paperclip/secrets/master.key

# Restart
sudo systemctl start paperclip
sudo systemctl status paperclip

Restore on a new server

  1. Set up a fresh Paperclip instance following the deployment guide for your platform
  2. Stop Paperclip on the new server
  3. Copy the backup to the new server:
scp paperclip-backup-20250115.tar.gz deploy@new-server:/tmp/
  1. On the new server:
sudo systemctl stop paperclip

tar -xzf /tmp/paperclip-backup-20250115.tar.gz -C /tmp/

# Restore data
sudo cp -r /tmp/opt/paperclip/data/db/ /opt/paperclip/data/
sudo cp /tmp/opt/paperclip/secrets/master.key /opt/paperclip/secrets/
sudo chown -R deploy:deploy /opt/paperclip/

sudo systemctl start paperclip

Docker Compose backup

# Backup the named volume
docker run --rm \
  -v paperclip_paperclip_data:/data \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/paperclip-backup-$(date +%Y%m%d).tar.gz /data

# Restore
docker compose down
docker run --rm \
  -v paperclip_paperclip_data:/data \
  -v $(pwd)/backups:/backup \
  alpine tar xzf /backup/paperclip-backup-20250115.tar.gz -C /
docker compose up -d

Verifying a backup

Test your backups work before you need them:

# Check the backup is readable
tar -tzf paperclip-backup-20250115.tar.gz | head -20

# Test database integrity
sqlite3 /path/to/restored/paperclip.db "PRAGMA integrity_check;"
# Should output: ok

What's not backed up

  • Active agent runs in progress — in-progress heartbeats will need to be restarted
  • Claude Code conversation history — stored in Claude's own memory, not Paperclip
  • npm packages / binaries — reinstalled via npm during setup

The Paperclip database + secrets master key is everything you need for a full restore.

Ready to deploy?

Affiliate disclosure: this link may earn us a commission at no extra cost to you.

This is an independent guide. Paperclip Hosting is not affiliated with the official Paperclip project. Guide steps are based on real deployments and are subject to change as the software evolves.