This template allows deploying a forgejo en either Scaleway or Hetzner (untested) without much knowledge about them. It DOES require knowledge about Terragrunt and ansible. A wizard of sorts is provided but it will not guarantee success without some knowledge about the underlying technology.
9.8 KiB
9.8 KiB
Operations Guide - Forgejo Self-Hosting
Complete guide for day-to-day operations and maintenance.
Table of Contents
- Daily Operations
- Backup & Recovery
- Updates & Upgrades
- Monitoring
- Troubleshooting
- Security Operations
- Scaling
- Disaster Recovery
Daily Operations
Health Checks
# Quick health check
make health
# Full status
make status
# View recent logs
make logs | tail -100
User Management
# SSH into server
make ssh
# List users
docker exec --user git forgejo forgejo admin user list
# Create user
docker exec --user git forgejo forgejo admin user create \
--username newuser \
--password 'SecureP@ssw0rd' \
--email user@example.com
# Change user password
docker exec --user git forgejo forgejo admin user change-password \
--username user \
--password 'NewP@ssw0rd'
# Make user admin
docker exec --user git forgejo forgejo admin user change-admin \
--username user \
--admin
Repository Management
# Sync mirrors
docker exec --user git forgejo forgejo admin repo-sync-releases
# Rebuild indexes
docker exec --user git forgejo forgejo admin regenerate hooks
docker exec --user git forgejo forgejo admin regenerate keys
Backup & Recovery
Manual Backup
# Create immediate backup
make backup
# Backup with S3 upload
make backup-to-s3
# Verify backup
make ssh
ls -lh /opt/forgejo/backups/
Automated Backups
Backups run automatically at 2 AM daily.
Check backup status:
make ssh
tail -f /var/log/forgejo-backup.log
Modify schedule:
# In inventory or vars
forgejo_backup_schedule: "0 3 * * *" # 3 AM daily
Restore from Backup
# List available backups
make ssh
ls /opt/forgejo/backups/
# Restore (timestamp format: 20240115T120000)
make restore
# Enter backup timestamp when prompted
# Force restore without confirmation
make restore-force
# Restore from S3
make restore-from-s3
Backup Verification
# Test restore in separate environment
make ssh
cd /opt/forgejo/backups
# Verify database backup
gunzip -c database-TIMESTAMP.sql.gz | head -100
# Verify repositories backup
tar -tzf repositories-TIMESTAMP.tar.gz | head -20
Updates & Upgrades
Update Forgejo
# Standard update (includes backup)
make update
# Update without backup (not recommended)
make update-no-backup
Update process:
- Creates pre-update backup
- Stops Forgejo service
- Pulls new Docker image
- Starts service
- Runs database migrations
- Verifies health
Update System Packages
make ssh
sudo apt update
sudo apt upgrade -y
sudo reboot # If kernel updated
Update Infrastructure
# Review changes
make terraform-plan PROVIDER=scaleway
# Apply updates
make terraform-apply PROVIDER=scaleway
Monitoring
Log Management
# Forgejo logs
make logs
# Follow logs (real-time)
make logs | tail -f
# Nginx access logs
make logs-nginx
# System logs
make ssh
sudo journalctl -u forgejo -f
# Docker logs
docker logs forgejo --tail 100 -f
Performance Monitoring
# Check resource usage
make ssh
# CPU and memory
htop
# Disk usage
df -h
du -sh /opt/forgejo/*
# Docker stats
docker stats forgejo
# PostgreSQL status
sudo systemctl status postgresql
Database Monitoring
make ssh
# Connect to PostgreSQL
sudo -u postgres psql forgejo
# Check database size
SELECT pg_size_pretty(pg_database_size('forgejo'));
# Check table sizes
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
LIMIT 10;
# Active connections
SELECT count(*) FROM pg_stat_activity;
Troubleshooting
Service Won't Start
# Check Docker status
make ssh
docker ps -a
docker logs forgejo
# Check system resources
free -h
df -h
# Restart service
make restart
# Full rebuild if needed
docker compose down
docker compose up -d
Database Connection Issues
make ssh
# Check PostgreSQL
sudo systemctl status postgresql
# Check connections
sudo -u postgres psql -c "SELECT * FROM pg_stat_activity;"
# Restart PostgreSQL
sudo systemctl restart postgresql
# Check logs
sudo tail -f /var/log/postgresql/postgresql-16-main.log
SSL Certificate Issues
make ssh
# Check certificate status
sudo certbot certificates
# Renew manually
sudo certbot renew --force-renewal
# Check Nginx configuration
sudo nginx -t
sudo systemctl restart nginx
# Check certificate files
sudo ls -la /etc/letsencrypt/live/git.yourdomain.com/
Performance Issues
# Check slow queries
make ssh
sudo -u postgres psql forgejo
# Enable slow query logging
ALTER SYSTEM SET log_min_duration_statement = 1000;
SELECT pg_reload_conf();
# View slow queries
sudo tail -f /var/log/postgresql/postgresql-16-main.log
# Vacuum database
sudo -u postgres vacuumdb --analyze forgejo
Disk Space Issues
make ssh
# Check space
df -h
# Find large directories
du -h /opt/forgejo | sort -rh | head -20
# Clean Docker
docker system prune -a
# Clean old backups
find /opt/forgejo/backups -type f -mtime +30 -delete
# Clean logs
sudo journalctl --vacuum-time=7d
Security Operations
Security Audit
make ssh
# Check for security updates
sudo apt update
sudo apt list --upgradable
# Review firewall rules
sudo ufw status verbose
# Check open ports
sudo netstat -tulpn
# Review SSH configuration
cat /etc/ssh/sshd_config
# Check failed login attempts
sudo grep "Failed password" /var/log/auth.log | tail -20
Rotate Secrets
# Generate new secrets
openssl rand -base64 48
# Update vault
make ansible-vault-edit
# Redeploy with new secrets
make deploy
SSL Certificate Renewal
# Auto-renewal is configured, but to force:
make ssh
sudo certbot renew --force-renewal
sudo systemctl reload nginx
Security Updates
# Enable automatic security updates (already configured)
make ssh
sudo cat /etc/apt/apt.conf.d/50unattended-upgrades
# Check update history
sudo cat /var/log/unattended-upgrades/unattended-upgrades.log
Scaling
Vertical Scaling (More Resources)
# Update instance type
vim terraform/scaleway/compute/terraform.tfvars
# Change: instance_type = "DEV1-L" # 8GB RAM
make terraform-apply PROVIDER=scaleway
# Service restarts automatically
Database Optimization
make ssh
sudo -u postgres psql forgejo
# Optimize settings
ALTER SYSTEM SET shared_buffers = '512MB';
ALTER SYSTEM SET effective_cache_size = '2GB';
ALTER SYSTEM SET maintenance_work_mem = '256MB';
SELECT pg_reload_conf();
Add Storage Volume
# In inventory
forgejo_use_external_volume: true
forgejo_volume_device: /dev/sdb
# Redeploy
make deploy-tags TAGS=volume
Disaster Recovery
Complete Failure Recovery
# 1. Create new infrastructure
make terraform-apply PROVIDER=scaleway
# 2. Update inventory with new IP
vim ansible/inventory/production/hosts.yml
# 3. Update DNS records
# Point domain to new IP
# 4. Deploy with restore
# First, copy backup timestamp
make ssh
ls /opt/forgejo/backups/ # Note timestamp
# Then restore
make restore
# Enter timestamp when prompted
# 5. Verify
make health
Backup Storage Migration
# Copy backups to new location
make ssh
rsync -avz /opt/forgejo/backups/ /new/backup/location/
# Update backup configuration
vim ansible/playbooks/vars/main.yml
# forgejo_backup_path: /new/backup/location
make deploy-tags TAGS=backup
Database Recovery from Corruption
make ssh
# Stop Forgejo
docker compose down
# Backup corrupted database
sudo -u postgres pg_dump forgejo > /tmp/forgejo-corrupted.sql
# Drop and recreate
sudo -u postgres dropdb forgejo
sudo -u postgres createdb forgejo
# Restore from latest backup
gunzip -c /opt/forgejo/backups/database-TIMESTAMP.sql.gz | \
sudo -u postgres psql forgejo
# Restart Forgejo
docker compose up -d
Best Practices
Daily Checklist
- Check service health:
make health - Review logs for errors:
make logs | grep -i error - Verify backups ran:
ls -lt /opt/forgejo/backups/ | head -5 - Check disk space:
df -h
Weekly Checklist
- Review security logs:
sudo grep "Failed" /var/log/auth.log - Check for updates:
sudo apt update && apt list --upgradable - Test backup restore (in dev environment)
- Review performance metrics
- Check SSL certificate expiry
Monthly Checklist
- Full security audit
- Review and update firewall rules
- Rotate secrets if needed
- Review and optimize database
- Update documentation
- Test disaster recovery procedures
Emergency Contacts
Keep these handy:
# Quick recovery commands
make health # Check status
make restart # Restart service
make logs # View logs
make backup # Create backup
make restore # Restore from backup
make ssh # SSH access
# Emergency rollback
make update # Includes backup
# If issues: make restore # Roll back
Useful Scripts
Health Check Script
#!/bin/bash
# Save as: health-check.sh
echo "=== Forgejo Health Check ==="
echo "Date: $(date)"
echo ""
echo "1. Service Status:"
docker ps | grep forgejo
echo ""
echo "2. Disk Space:"
df -h | grep -E "Filesystem|/dev/vda1|/dev/sda1"
echo ""
echo "3. Memory Usage:"
free -h
echo ""
echo "4. Latest Backup:"
ls -lth /opt/forgejo/backups/*.tar.gz | head -1
echo ""
echo "5. HTTP Status:"
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000
Remember: Always test procedures in a development environment first!