# Gitea Stack - Self-Hosted Git Server ## Overview Gitea acts as the central Git server with integrated CI/CD capabilities through Gitea Actions, handling: - Git repository hosting - User and organization management - Pull requests and code reviews - Issue tracking - Gitea Actions for CI/CD (runner runs on development machine) - API for automation ## Services - **git.michaelschiemer.de** - Gitea Web Interface - **git.michaelschiemer.de:2222** - SSH for Git operations - **MySQL 8.0** - Database backend - **Redis 7** - Cache, session, and queue storage ## Prerequisites 1. **Traefik Stack Running** ```bash cd ../traefik docker compose up -d ``` 2. **DNS Configuration** Point `git.michaelschiemer.de` to your server IP (94.16.110.151) 3. **SSH Port Availability** Ensure port 2222 is open in your firewall for Git SSH operations ## Configuration ### 1. Create Environment File ```bash cp .env.example .env ``` ### 2. Generate Strong Passwords ```bash # MySQL root password openssl rand -base64 32 # MySQL gitea password openssl rand -base64 32 # Redis password openssl rand -base64 32 ``` Update `.env` with generated passwords: ```env MYSQL_ROOT_PASSWORD= MYSQL_PASSWORD= REDIS_PASSWORD= ``` ### 3. Adjust Configuration (Optional) Edit `.env` for: - Domain customization - User registration settings - Database configuration ## Deployment ### Initial Setup ```bash # Deploy stack docker compose up -d # Check logs docker compose logs -f # Wait for MySQL initialization (30-60 seconds) docker compose logs mysql | grep "ready for connections" # Verify services are healthy docker compose ps ``` ### First Time Configuration 1. **Access Gitea**: https://git.michaelschiemer.de 2. **Initial Setup Wizard**: - Database settings are pre-configured via environment variables - Set up admin account: - Username: `admin` (or your preference) - Email: `kontakt@michaelschiemer.de` - Password: Strong password - Server and third-party settings: Use defaults - Click "Install Gitea" 3. **Verify SSH Access**: ```bash # Test SSH connection (replace 'git' with your username after setup) ssh -T -p 2222 git@git.michaelschiemer.de ``` ## Usage ### Creating a Repository 1. Log in to https://git.michaelschiemer.de 2. Click "+" → "New Repository" 3. Fill in repository details 4. Clone via HTTPS or SSH: ```bash # HTTPS git clone https://git.michaelschiemer.de/username/repo.git # SSH git clone ssh://git@git.michaelschiemer.de:2222/username/repo.git ``` ### Gitea Actions Gitea Actions (GitHub Actions compatible) are enabled by default. To use them: 1. **Create `.gitea/workflows/` directory** in your repository 2. **Add workflow YAML files** (e.g., `deploy.yml`) 3. **Register a Runner** (see Runner setup section below) **Note**: The Gitea Actions Runner should run on your **development machine**, not on the production server. See Stack 9 documentation for runner setup. ### User Management **Disable Registration** (Default): - Set `DISABLE_REGISTRATION=true` in `.env` (already default) - Create users via Admin Panel **Enable Registration**: - Set `DISABLE_REGISTRATION=false` in `.env` - Restart: `docker compose restart gitea` ### Organizations and Teams 1. Navigate to Organizations 2. Create organization 3. Add repositories to organization 4. Manage teams and permissions ## API Access Gitea provides a comprehensive API: ```bash # Generate API token # Settings → Applications → Generate New Token # Example: List repositories curl -H "Authorization: token YOUR_TOKEN" \ https://git.michaelschiemer.de/api/v1/user/repos ``` **API Documentation**: https://git.michaelschiemer.de/api/swagger ## Backup & Recovery ### Manual Backup ```bash # Backup script (run on production server) #!/bin/bash BACKUP_DIR="/backups/gitea" DATE=$(date +%Y%m%d_%H%M%S) # Create backup directory mkdir -p $BACKUP_DIR # Backup Gitea data docker run --rm \ -v gitea-data:/data \ -v $BACKUP_DIR:/backup \ alpine tar czf /backup/gitea-data-$DATE.tar.gz -C /data . # Backup MySQL database docker exec gitea-mysql mysqldump \ -u root -p$MYSQL_ROOT_PASSWORD \ --all-databases \ --single-transaction \ --quick \ --lock-tables=false \ > $BACKUP_DIR/gitea-mysql-$DATE.sql # Backup Redis data docker run --rm \ -v gitea-redis-data:/data \ -v $BACKUP_DIR:/backup \ alpine tar czf /backup/gitea-redis-$DATE.tar.gz -C /data . echo "Backup completed: $BACKUP_DIR/*-$DATE.*" ``` ### Restore from Backup ```bash # Stop services docker compose down # Restore Gitea data docker run --rm \ -v gitea-data:/data \ -v /backups/gitea:/backup \ alpine tar xzf /backup/gitea-data-YYYYMMDD_HHMMSS.tar.gz -C /data # Restore MySQL cat /backups/gitea/gitea-mysql-YYYYMMDD_HHMMSS.sql | \ docker exec -i gitea-mysql mysql -u root -p$MYSQL_ROOT_PASSWORD # Restore Redis docker run --rm \ -v gitea-redis-data:/data \ -v /backups/gitea:/backup \ alpine tar xzf /backup/gitea-redis-YYYYMMDD_HHMMSS.tar.gz -C /data # Start services docker compose up -d ``` ### Automated Backups Add to crontab on production server: ```bash # Daily backup at 2 AM 0 2 * * * /path/to/backup-gitea.sh # Keep only last 7 days 0 3 * * * find /backups/gitea -type f -mtime +7 -delete ``` ## Monitoring ### Health Checks ```bash # Check service health docker compose ps # Gitea health endpoint curl -f https://git.michaelschiemer.de/api/healthz # MySQL health docker exec gitea-mysql mysqladmin ping -h localhost -u root -p$MYSQL_ROOT_PASSWORD # Redis health docker exec gitea-redis redis-cli -a $REDIS_PASSWORD ping ``` ### Logs ```bash # All services docker compose logs -f # Gitea only docker compose logs -f gitea # MySQL only docker compose logs -f mysql # Redis only docker compose logs -f redis # MySQL slow queries docker exec gitea-mysql tail -f /var/log/mysql/slow-queries.log ``` ### Resource Usage ```bash # Container stats docker stats gitea gitea-mysql gitea-redis # Disk usage docker system df -v | grep gitea ``` ## Troubleshooting ### Gitea Not Starting ```bash # Check logs docker compose logs gitea # Common issues: # 1. MySQL not ready - wait 30-60 seconds # 2. Database connection failed - check MYSQL_PASSWORD in .env # 3. Redis connection failed - check REDIS_PASSWORD ``` ### SSH Not Working ```bash # Verify port 2222 is open sudo ufw status | grep 2222 # Open if needed sudo ufw allow 2222/tcp # Test SSH connection ssh -T -p 2222 git@git.michaelschiemer.de # Check Gitea SSH settings # Admin Panel → Configuration → Server and Other Services → SSH Server Domain ``` ### Database Connection Issues ```bash # Verify MySQL is running and healthy docker compose ps mysql # Test database connection docker exec gitea-mysql mysql -u gitea -p$MYSQL_PASSWORD -e "SELECT 1;" # Check MySQL logs docker compose logs mysql | grep -i error ``` ### Redis Connection Issues ```bash # Verify Redis is running docker compose ps redis # Test Redis connection docker exec gitea-redis redis-cli -a $REDIS_PASSWORD ping # Check Redis logs docker compose logs redis ``` ### Performance Issues ```bash # Check MySQL slow queries docker exec gitea-mysql tail -100 /var/log/mysql/slow-queries.log # Analyze MySQL performance docker exec gitea-mysql mysql -u root -p$MYSQL_ROOT_PASSWORD \ -e "SHOW PROCESSLIST;" # Check Redis memory usage docker exec gitea-redis redis-cli -a $REDIS_PASSWORD INFO memory ``` ### Reset Admin Password ```bash # Connect to Gitea container docker exec -it gitea bash # Change admin password gitea admin user change-password --username admin --password new-password ``` ## Security ### Security Best Practices 1. **Disable User Registration**: Set `DISABLE_REGISTRATION=true` 2. **Strong Passwords**: Use generated passwords for all services 3. **Regular Updates**: Keep Gitea, MySQL, and Redis updated 4. **SSH Keys**: Prefer SSH keys over HTTPS for Git operations 5. **2FA**: Enable two-factor authentication for admin accounts 6. **API Token Security**: Rotate tokens regularly 7. **Firewall**: Only expose ports 80, 443, and 2222 ### Update Stack ```bash # Pull latest images docker compose pull # Recreate containers docker compose up -d # Verify docker compose ps ``` ### Security Headers Security headers are applied via Traefik's `default-chain@file` middleware: - HSTS - Content-Type Nosniff - XSS Protection - Frame Deny - CSP ## Integration with Other Stacks ### Docker Registry (Stack 3) Gitea Actions can push built images to the private Docker Registry: ```yaml # .gitea/workflows/deploy.yml - name: Push to Registry run: | docker login registry.michaelschiemer.de -u ${{ secrets.REGISTRY_USER }} -p ${{ secrets.REGISTRY_PASS }} docker push registry.michaelschiemer.de/myapp:latest ``` ### Application Stack (Stack 4) Deploy applications via Gitea Actions + Ansible: ```yaml - name: Deploy to Production run: | ansible-playbook -i inventory/production deploy.yml ``` ## Performance Tuning ### MySQL Optimization Adjust `mysql/conf.d/gitea.cnf`: - `innodb_buffer_pool_size`: Increase for more RAM - `max_connections`: Increase for more concurrent users - `slow_query_log`: Monitor slow queries ### Redis Optimization ```bash # Add to docker-compose.yml redis command: # --maxmemory 512mb --maxmemory-policy allkeys-lru ``` ### Gitea Configuration Edit via Admin Panel → Configuration or `app.ini`: - Enable caching for static assets - Adjust session timeout - Configure queue workers for Actions ## Additional Resources - **Gitea Documentation**: https://docs.gitea.io/ - **Gitea Actions**: https://docs.gitea.io/en-us/usage/actions/overview/ - **API Documentation**: https://git.michaelschiemer.de/api/swagger - **MySQL Tuning**: https://dev.mysql.com/doc/refman/8.0/en/optimization.html