Files
michaelschiemer/deployment/stacks/gitea/README.md

9.7 KiB

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

    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

cp .env.example .env

2. Generate Strong Passwords

# 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:

MYSQL_ROOT_PASSWORD=<generated-password-1>
MYSQL_PASSWORD=<generated-password-2>
REDIS_PASSWORD=<generated-password-3>

3. Adjust Configuration (Optional)

Edit .env for:

  • Domain customization
  • User registration settings
  • Database configuration

Deployment

Initial Setup

# 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:

    # 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:
    # 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:

# 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

# 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

# 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:

# 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

# 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

# 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

# Container stats
docker stats gitea gitea-mysql gitea-redis

# Disk usage
docker system df -v | grep gitea

Troubleshooting

Gitea Not Starting

# 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

# 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

# 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

# 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

# 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

# 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

# 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:

# .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:

- 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

# 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