Skip to main content

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

gitea dump
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
--type
string
default:"zip"
Archive format: zip, tar, tar.gz, tar.xz, tar.bz2, tar.lz4, tar.sz, or tar.zst
--database
string
Database SQL syntax for export: sqlite3, mysql, postgres, mssql. Use this to export to a different database format than currently configured.
--verbose
boolean
default:"false"
Show detailed progress during backup
--quiet
boolean
default:"false"
Only show warnings and errors

Selective Backup

You can exclude specific components from the backup:
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:
  1. Database - All database tables and data
  2. Repositories - Git repositories and their data
  3. Configuration - app.ini configuration file
  4. Custom Files - Templates, logos, and customizations
  5. Data Directory - User avatars, attachments, etc.
  6. LFS Objects - Git LFS files (if enabled)
  7. Attachments - Issue and comment attachments
  8. Packages - Package registry data (if enabled)
  9. 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

1

Stop Gitea

sudo systemctl stop gitea
2

Extract Backup

unzip gitea-dump-1234567890.zip -d /tmp/gitea-restore
3

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
4

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
5

Fix Permissions

sudo chown -R git:git /path/to/gitea/data
sudo chown -R git:git /path/to/gitea/custom
6

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:
backup.sh
#!/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:
  1. Database restore: 5-30 minutes depending on size
  2. Repository restore: Depends on repository count and size
  3. Configuration: 1-5 minutes
  4. 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

Build docs developers (and LLMs) love