Gitea Advanced Configuration and CI/CD

Gitea is a lightweight self-hosted Git platform that now includes Gitea Actions for CI/CD, making it a complete GitHub alternative. This guide covers advanced Gitea configuration including Actions runners, LDAP authentication, repository mirroring, webhook integration, and backup strategies.

Prerequisites

  • Gitea 1.19+ installed and running
  • Docker installed (for act runners)
  • Root or sudo access
  • Domain with SSL configured

If you need to install Gitea first:

# Download the latest binary
wget -O /usr/local/bin/gitea \
  https://dl.gitea.com/gitea/$(curl -s https://dl.gitea.com/gitea/version.json | \
  python3 -c "import sys,json; print(json.load(sys.stdin)['latest']['version'])")/gitea-*-linux-amd64

chmod +x /usr/local/bin/gitea

Gitea Actions Setup

Enable Gitea Actions in app.ini:

sudo nano /etc/gitea/app.ini
[actions]
ENABLED = true
DEFAULT_ACTIONS_URL = https://gitea.com  ; fallback for actions/checkout etc.
sudo systemctl restart gitea

In your Gitea web UI, go to Site Administration > Configuration and verify Actions is enabled. Repository owners must also enable Actions per-repo under Settings > Actions.

Running Act Runners

Gitea Actions uses act_runner to execute workflow jobs:

# Download act_runner
wget -O /usr/local/bin/act_runner \
  https://gitea.com/gitea/act_runner/releases/download/v0.2.10/act_runner-0.2.10-linux-amd64

chmod +x /usr/local/bin/act_runner

# Register the runner (get token from Site Admin > Runners)
act_runner register \
  --instance https://git.yourdomain.com \
  --token YOUR_RUNNER_TOKEN \
  --name my-runner \
  --labels ubuntu-latest:docker://node:18-bullseye

# Start the runner
act_runner daemon

Run as a systemd service:

sudo tee /etc/systemd/system/act_runner.service << 'EOF'
[Unit]
Description=Gitea Act Runner
After=network.target gitea.service

[Service]
Type=simple
User=gitea
WorkingDirectory=/var/lib/gitea
ExecStart=/usr/local/bin/act_runner daemon --config /etc/gitea/act_runner.yaml
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable --now act_runner

Example workflow file in your repository:

# .gitea/workflows/build.yaml
name: Build and Test
on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run tests
        run: |
          npm install
          npm test

Webhook Configuration

Gitea webhooks notify external services on repository events:

  1. Go to Repository > Settings > Webhooks > Add Webhook
  2. Select type (Gitea, Slack, Discord, etc.)
  3. Set the payload URL and secret

For custom webhooks, Gitea sends JSON payloads. Verify webhook delivery under Recent Deliveries.

CLI-based webhook testing:

# Send a test ping to your webhook endpoint
curl -X POST https://your-endpoint.com/webhook \
  -H "Content-Type: application/json" \
  -H "X-Gitea-Signature: sha256=..." \
  -d '{"action": "ping"}'

Add webhook secrets in app.ini for additional validation:

[webhook]
ALLOWED_HOST_LIST = *       ; restrict to specific hosts in production
SKIP_TLS_VERIFY = false

LDAP Authentication

Integrate Gitea with an LDAP/Active Directory server:

  1. Go to Site Administration > Authentication Sources > Add Authentication Source
  2. Select LDAP (via BindDN)

Key settings:

FieldExample Value
Hostldap.company.com
Port389 (or 636 for LDAPS)
Bind DNcn=gitea,ou=services,dc=company,dc=com
User Search Baseou=users,dc=company,dc=com
User Filter(&(objectClass=person)(uid=%s))
Username Attributeuid
Email Attributemail

For Active Directory:

User Filter: (&(objectCategory=person)(sAMAccountName=%s))
Username Attribute: sAMAccountName
Email Attribute: mail

Test the LDAP connection after saving:

# Test from the server
ldapsearch -x -H ldap://ldap.company.com \
  -D "cn=gitea,ou=services,dc=company,dc=com" \
  -W -b "ou=users,dc=company,dc=com" "(uid=testuser)"

Repository Mirroring

Mirror repositories from GitHub, GitLab, or other sources:

  1. Create a mirror: New Repository > Migration > Choose source
  2. For push mirrors: Repository > Settings > Mirror Settings

Configure auto-sync interval in app.ini:

[mirror]
DEFAULT_INTERVAL = 8h    ; sync every 8 hours
MIN_INTERVAL = 10m

Mirror via API:

# Create a pull mirror via API
curl -X POST https://git.yourdomain.com/api/v1/repos/migrate \
  -H "Authorization: token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clone_addr": "https://github.com/user/repo",
    "uid": 1,
    "repo_name": "mirrored-repo",
    "mirror": true,
    "mirror_interval": "8h0m0s"
  }'

Performance Tuning

# /etc/gitea/app.ini

[database]
DB_TYPE = postgres          ; prefer PostgreSQL over SQLite for production
MAX_OPEN_CONNS = 100
MAX_IDLE_CONNS = 50

[cache]
ADAPTER = redis
HOST = network=tcp,addr=127.0.0.1:6379,db=0,pool_size=100

[session]
PROVIDER = redis
PROVIDER_CONFIG = network=tcp,addr=127.0.0.1:6379,db=1

[queue]
TYPE = redis
CONN_STR = redis://127.0.0.1:6379/2

[server]
LFS_CONTENT_PATH = /var/lib/gitea/lfs   ; store LFS on fast storage

Backup and Restore

# Create a full backup (binary must be run as the gitea user)
sudo -u gitea gitea admin dump \
  --config /etc/gitea/app.ini \
  --file /backup/gitea-backup-$(date +%Y%m%d).zip

# What's included: database, config, repositories, LFS, attachments

# Restore from backup
sudo systemctl stop gitea
sudo -u gitea unzip gitea-backup-20240101.zip -d /tmp/gitea-restore
# Restore each component (database, repos, etc.) according to the dump structure
sudo systemctl start gitea

Automate with a cron job:

sudo crontab -u gitea -e
# Add:
# 0 2 * * * /usr/local/bin/gitea admin dump --config /etc/gitea/app.ini --file /backup/gitea-$(date +\%Y\%m\%d).zip

Troubleshooting

Actions not triggering:

# Check that the runner is connected
# Site Admin > Runners - verify runner status is "Online"
journalctl -u act_runner -f

# Ensure Actions is enabled for the repository
# Repo > Settings > Actions > Enable

Git operations slow over SSH:

# In app.ini, tune SSH settings
[server]
START_SSH_SERVER = true
SSH_LISTEN_PORT = 2222
# Or use system SSH with gitea shell

LDAP users can't log in:

# Test the LDAP bind from the server
ldapwhoami -H ldap://ldap.company.com \
  -D "cn=gitea,ou=services,dc=company,dc=com" -W

# Check Gitea logs
journalctl -u gitea -f | grep -i ldap

Database migration errors after upgrade:

# Run migrations manually
sudo -u gitea gitea migrate --config /etc/gitea/app.ini

Conclusion

Gitea's advanced features make it a capable self-hosted Git platform for teams of any size. With Gitea Actions providing native CI/CD, LDAP integration for enterprise authentication, and robust backup options, it can replace GitHub or GitLab in air-gapped or cost-sensitive environments. Keep Gitea updated and run regular backups to ensure data safety.