Overview
Gitea provides built-in commands for backing up and restoring your entire installation, including repositories, database, configuration, and attachments.
Backup
The dump command creates a compressed archive containing all Gitea data.
Basic Backup
This creates a file named gitea-dump-{timestamp}.zip in the current directory.
Specify Output File
gitea dump --file my-backup.zip
Backup to stdout
gitea dump --file - > backup.zip
Backup Options
The dump command supports extensive customization options (see cmd/dump.go:27-97):
--file
string
default: "gitea-dump-{time}.zip"
Output file name. Use - for stdout.
--tempdir
string
default: "system temp dir"
Temporary directory for building the archive
Archive format: zip, tar, tar.gz, tar.xz, tar.bz2, tar.lz4, tar.sz, or tar.zst
Database SQL syntax for export: sqlite3, mysql, postgres, mssql.
Use this to export to a different database format than currently configured.
Show detailed progress during backup
Only show warnings and errors
Selective Backup
You can exclude specific components from the backup:
Skip Repositories
Skip Database
Skip Logs
Skip Custom Directory
Skip LFS Data
Skip Attachments
Skip Packages
Skip Search Index
gitea dump --skip-repository
Combine Multiple Options
gitea dump \
--file /backup/gitea- $( date +%Y%m%d ) .tar.gz \
--type tar.gz \
--tempdir /tmp/gitea-backup \
--skip-log \
--skip-index \
--verbose
What’s Included in a Backup
A complete Gitea backup includes:
Database - All database tables and data
Repositories - Git repositories and their data
Configuration - app.ini configuration file
Custom Files - Templates, logos, and customizations
Data Directory - User avatars, attachments, etc.
LFS Objects - Git LFS files (if enabled)
Attachments - Issue and comment attachments
Packages - Package registry data (if enabled)
Logs - Application logs (optional)
The backup structure (from cmd/dump.go:164-324):
gitea-dump.zip
├── app.ini # Configuration file
├── gitea-db.sql # Database dump
├── repos/ # All repositories
├── custom/ # Custom templates and assets
├── data/
│ ├── lfs/ # LFS objects
│ ├── attachments/ # File attachments
│ ├── packages/ # Package data
│ └── ... # Other app data
└── log/ # Log files (optional)
Restore
Restoring from a backup involves extracting the archive and placing files in the correct locations.
Complete Restore
Stop Gitea
sudo systemctl stop gitea
Extract Backup
unzip gitea-dump-1234567890.zip -d /tmp/gitea-restore
Restore Database
# Drop existing database
sudo -u postgres psql -c "DROP DATABASE gitea;"
sudo -u postgres psql -c "CREATE DATABASE gitea;"
# Restore from backup
sudo -u postgres psql gitea < /tmp/gitea-restore/gitea-db.sql
Restore Files
# Restore repositories
rm -rf /path/to/gitea/data/gitea-repositories
cp -r /tmp/gitea-restore/repos /path/to/gitea/data/gitea-repositories
# Restore data directory
cp -r /tmp/gitea-restore/data/ * /path/to/gitea/data/
# Restore custom directory (if present)
cp -r /tmp/gitea-restore/custom/ * /path/to/gitea/custom/
# Restore configuration
cp /tmp/gitea-restore/app.ini /path/to/gitea/custom/conf/app.ini
Fix Permissions
sudo chown -R git:git /path/to/gitea/data
sudo chown -R git:git /path/to/gitea/custom
Start Gitea
sudo systemctl start gitea
Repository-Level Restore
Restore a single repository using the restore-repo command (see cmd/restore_repo.go):
gitea restore-repo \
--repo_dir /path/to/backup/repos/owner/repo.git \
--owner_name target-owner \
--repo_name target-repo
Selective Repository Restore
Restore specific repository components:
gitea restore-repo \
--repo_dir /backup/repos/owner/repo.git \
--owner_name owner \
--repo_name repo \
--units "issues,labels,milestones,pull_requests,comments"
Available units:
wiki
issues
labels
releases
release_assets
milestones
pull_requests
comments
Validation Before Restore
gitea restore-repo \
--repo_dir /backup/repos/owner/repo.git \
--owner_name owner \
--repo_name repo \
--validation
This performs a sanity check on the backup data before attempting restoration.
Automated Backup
Create a backup script for automated backups:
#!/bin/bash
# Configuration
BACKUP_DIR = "/backup/gitea"
RETENTION_DAYS = 30
DATESTAMP = $( date +%Y%m%d-%H%M%S )
# Create backup directory
mkdir -p " $BACKUP_DIR "
# Run backup
/usr/local/bin/gitea dump \
--file " $BACKUP_DIR /gitea- $DATESTAMP .zip" \
--tempdir /tmp/gitea-backup \
--skip-log \
--verbose
# Check if backup succeeded
if [ $? -eq 0 ]; then
echo "Backup completed successfully: gitea- $DATESTAMP .zip"
# Remove old backups
find " $BACKUP_DIR " -name "gitea-*.zip" -mtime + $RETENTION_DAYS -delete
echo "Removed backups older than $RETENTION_DAYS days"
else
echo "Backup failed!" >&2
exit 1
fi
Schedule with Cron
# Daily backup at 2 AM
0 2 * * * /usr/local/bin/gitea-backup.sh >> /var/log/gitea-backup.log 2>&1
Schedule with systemd Timer
Create /etc/systemd/system/gitea-backup.service:
[Unit]
Description =Gitea Backup
After =network.target
[Service]
Type =oneshot
User =git
ExecStart =/usr/local/bin/gitea dump --file /backup/gitea/gitea-%Y%m%d.zip
Create /etc/systemd/system/gitea-backup.timer:
[Unit]
Description =Gitea Backup Timer
[Timer]
OnCalendar =daily
Persistent =true
[Install]
WantedBy =timers.target
Enable the timer:
sudo systemctl enable gitea-backup.timer
sudo systemctl start gitea-backup.timer
Database-Only Backup
For quick database backups without repositories:
pg_dump -h localhost -U gitea gitea > gitea-db- $( date +%Y%m%d ) .sql
Disaster Recovery
Backup Verification
Regularly verify your backups:
# Extract to temporary location
unzip -t gitea-dump-20240101.zip
# Or restore to a test instance
Off-Site Backup
Copy backups to remote storage:
# Using rsync
rsync -avz /backup/gitea/ user@backup-server:/gitea-backups/
# Using rclone to cloud storage
rclone sync /backup/gitea/ remote:gitea-backups/
Recovery Time Objective (RTO)
Plan for recovery:
Database restore : 5-30 minutes depending on size
Repository restore : Depends on repository count and size
Configuration : 1-5 minutes
Total downtime : Plan for 30-60 minutes for most installations
Best Practices
Regular Backups : Daily backups for production systems
Test Restores : Regularly test your backup restoration process
Multiple Locations : Store backups in multiple locations (on-site and off-site)
Encryption : Encrypt backups containing sensitive data
Retention Policy : Define how long to keep backups (e.g., 30 days)
Monitoring : Alert on backup failures
Documentation : Document your backup and restore procedures
Separate Database Backups : Consider additional database-specific backups
Troubleshooting
Backup Fails with “Permission Denied”
# Ensure Gitea has write access to backup directory
sudo chown git:git /backup/gitea
sudo chmod 755 /backup/gitea
Backup File Too Large
# Use compression
gitea dump --type tar.gz --file backup.tar.gz
# Or exclude large optional data
gitea dump --skip-log --skip-index
Database Restore Fails
# Check database encoding
# PostgreSQL: should be UTF8
# MySQL: should be utf8mb4
# Verify SQL file integrity
head -n 50 gitea-db.sql