Files
ouranos/docs/gitea.md
Robert Helewka b4d60f2f38 docs: rewrite README with structured overview and quick start guide
Replaces the minimal project description with a comprehensive README
including a component overview table, quick start instructions, common
Ansible operations, and links to detailed documentation. Aligns with
Red Panda Approval™ standards.
2026-03-03 12:49:06 +00:00

13 KiB

Gitea - Git with a Cup of Tea

Overview

Gitea is a lightweight, self-hosted Git service providing a GitHub-like web interface with repository management, issue tracking, pull requests, and code review capabilities. Deployed on Rosalind with PostgreSQL backend on Portia and Memcached caching.

Host: rosalind.incus
Role: Collaboration (PHP, Go, Node.js runtimes)
Container Port: 22083 (HTTP), 22022 (SSH), 22093 (Metrics)
External Access: https://gitea.ouranos.helu.ca/ (via HAProxy on Titania)
SSH Access: ssh -p 22022 git@gitea.ouranos.helu.ca (TCP passthrough via HAProxy)

Architecture

┌──────────┐      ┌────────────┐      ┌──────────┐      ┌───────────┐
│  Client  │─────▶│  HAProxy   │─────▶│  Gitea   │─────▶│PostgreSQL │
│          │      │ (Titania)  │      │(Rosalind)│      │ (Portia)  │
└──────────┘      └────────────┘      └──────────┘      └───────────┘
                                            │
                                            ▼
                                      ┌───────────┐
                                      │ Memcached │
                                      │ (Local)   │
                                      └───────────┘

Deployment

Playbook

cd ansible
ansible-playbook gitea/deploy.yml

Files

File Purpose
gitea/deploy.yml Main deployment playbook
gitea/app.ini.j2 Gitea configuration template

Deployment Steps

  1. Install Dependencies: git, git-lfs, curl, memcached
  2. Create System User: git:git with home directory
  3. Create Directories: Work dir, data, LFS storage, repository root, logs
  4. Download Gitea Binary: Latest release from GitHub (architecture-specific)
  5. Template Configuration: Apply app.ini.j2 with variables
  6. Create Systemd Service: Custom service unit for Gitea
  7. Start Service: Enable and start gitea.service
  8. Configure OAuth2: Register Casdoor as OpenID Connect provider

Configuration

Key Features

  • Git LFS Support: Large file storage enabled
  • SSH Server: Built-in SSH server on port 22022
  • Prometheus Metrics: Metrics endpoint on port 22094
  • Memcached Caching: Session and cache storage with gt_ prefix
  • Repository Settings: Push-to-create, all units enabled
  • Security: Argon2 password hashing, reverse proxy trusted

Storage Locations

Path Purpose Owner
/var/lib/gitea Working directory git:git
/var/lib/gitea/data Application data git:git
/var/lib/gitea/data/lfs Git LFS objects git:git
/mnt/dv Git repositories git:git
/var/log/gitea Application logs git:git
/etc/gitea Configuration files root:git

Logging

  • Console Output: Info level to systemd journal
  • File Logs: /var/log/gitea/gitea.log
  • Rotation: Daily rotation, 7-day retention
  • SSH Logs: Enabled for debugging

Access After Deployment

  1. Web Interface: https://gitea.ouranos.helu.ca/
  2. First-Time Setup: Create admin account on first visit
  3. Git Clone:
    git clone https://gitea.ouranos.helu.ca/username/repo.git
    
  4. SSH Clone:
    git clone git@gitea.ouranos.helu.ca:username/repo.git
    
    Note: SSH requires port 22022 configured in ~/.ssh/config

Monitoring

Alloy Configuration

File: ansible/alloy/rosalind/config.alloy.j2

  • Log Collection: /var/log/gitea/gitea.log → Loki
  • Metrics: Port 22094 → Prometheus (token-protected)
  • System Metrics: Process exporter tracks Gitea process

Metrics Endpoint

  • URL: http://rosalind.incus:22083/metrics
  • Authentication: Bearer token required (vault_gitea_metrics_token)
  • Note: Metrics are exposed on the main web port, not a separate metrics port

Required Vault Secrets

Add to ansible/inventory/group_vars/all/vault.yml:

1. Database Password

vault_gitea_db_password: "YourSecurePassword123!"

Requirements:

  • Minimum 12 characters recommended
  • Used by PostgreSQL authentication

2. Secret Key (Session Encryption)

vault_gitea_secret_key: "RandomString64CharactersLongForSessionCookieEncryptionSecurity123"

Requirements:

  • Length: Recommended 64+ characters
  • Format: Base64 or hex string
  • Generation:
    openssl rand -base64 48
    

3. LFS JWT Secret

vault_gitea_lfs_jwt_secret: "AnotherRandomString64CharsForLFSJWTTokenSigning1234567890ABC"

Requirements:

  • Length: Recommended 64+ characters
  • Purpose: Signs JWT tokens for Git LFS authentication
  • Generation:
    openssl rand -base64 48
    

4. Metrics Token

vault_gitea_metrics_token: "RandomTokenForPrometheusMetricsAccess123"

Requirements:

  • Length: 32+ characters recommended
  • Purpose: Bearer token for Prometheus scraping
  • Generation:
    openssl rand -hex 32
    

5. OAuth Client ID

vault_gitea_oauth_client_id: "gitea-oauth-client"

Requirements:

  • Purpose: Client ID for Casdoor OAuth2 application
  • Source: Must match clientId in Casdoor application configuration

6. OAuth Client Secret

vault_gitea_oauth_client_secret: "YourRandomOAuthSecret123!"

Requirements:

  • Length: 32+ characters recommended
  • Purpose: Client secret for Casdoor OAuth2 authentication
  • Generation:
    openssl rand -base64 32
    
  • Source: Must match clientSecret in Casdoor application configuration

Host Variables

File: ansible/inventory/host_vars/rosalind.incus.yml

# Gitea User and Directories
gitea_user: git
gitea_group: git
gitea_work_dir: /var/lib/gitea
gitea_data_dir: /var/lib/gitea/data
gitea_lfs_dir: /var/lib/gitea/data/lfs
gitea_repo_root: /mnt/dv
gitea_config_file: /etc/gitea/app.ini

# Ports
gitea_web_port: 22083
gitea_ssh_port: 22022
gitea_metrics_port: 22094

# Network
gitea_domain: ouranos.helu.ca
gitea_root_url: https://gitea.ouranos.helu.ca/

# Database Configuration
gitea_db_type: postgres
gitea_db_host: portia.incus
gitea_db_port: 5432
gitea_db_name: gitea
gitea_db_user: gitea
gitea_db_password: "{{vault_gitea_db_password}}"
gitea_db_ssl_mode: disable

# Features
gitea_lfs_enabled: true
gitea_metrics_enabled: true

# Service Settings
gitea_disable_registration: true  # Use Casdoor SSO
gitea_require_signin_view: false

# Security (vault secrets)
gitea_secret_key: "{{vault_gitea_secret_key}}"
gitea_lfs_jwt_secret: "{{vault_gitea_lfs_jwt_secret}}"
gitea_metrics_token: "{{vault_gitea_metrics_token}}"

# OAuth2 (Casdoor SSO)
gitea_oauth_enabled: true
gitea_oauth_name: "casdoor"
gitea_oauth_display_name: "Sign in with Casdoor"
gitea_oauth_client_id: "{{vault_gitea_oauth_client_id}}"
gitea_oauth_client_secret: "{{vault_gitea_oauth_client_secret}}"
gitea_oauth_auth_url: "https://id.ouranos.helu.ca/login/oauth/authorize"
gitea_oauth_token_url: "http://titania.incus:22081/api/login/oauth/access_token"
gitea_oauth_userinfo_url: "http://titania.incus:22081/api/userinfo"
gitea_oauth_scopes: "openid profile email"

OAuth2 / Casdoor SSO

Gitea integrates with Casdoor for Single Sign-On using OpenID Connect.

Architecture

┌──────────┐      ┌────────────┐      ┌──────────┐      ┌──────────┐
│  Browser │─────▶│  HAProxy   │─────▶│  Gitea   │─────▶│ Casdoor  │
│          │      │ (Titania)  │      │(Rosalind)│      │(Titania) │
└──────────┘      └────────────┘      └──────────┘      └──────────┘
     │                                      │                 │
     │  1. Click "Sign in with Casdoor"     │                 │
     │◀─────────────────────────────────────│                 │
     │  2. Redirect to Casdoor login        │                 │
     │─────────────────────────────────────────────────────▶│
     │  3. User authenticates               │                 │
     │◀─────────────────────────────────────────────────────│
     │  4. Redirect back with auth code     │                 │
     │─────────────────────────────────────▶│                 │
     │                                      │  5. Exchange code for token
     │                                      │────────────────▶│
     │                                      │◀────────────────│
     │  6. User logged into Gitea           │                 │
     │◀─────────────────────────────────────│                 │

Casdoor Application Configuration

A Gitea application is defined in ansible/casdoor/init_data.json.j2:

Setting Value
Name app-gitea
Client ID vault_gitea_oauth_client_id
Redirect URI https://gitea.ouranos.helu.ca/user/oauth2/casdoor/callback
Grant Types authorization_code, refresh_token

URL Strategy

URL Type Address Used By
Auth URL https://id.ouranos.helu.ca/... User's browser (external)
Token URL http://titania.incus:22081/... Gitea server (internal)
Userinfo URL http://titania.incus:22081/... Gitea server (internal)
Discovery URL http://titania.incus:22081/.well-known/openid-configuration Gitea server (internal)

The auth URL uses the external HAProxy address because it runs in the user's browser. Token/userinfo URLs use internal addresses for server-to-server communication.

User Auto-Registration

With ENABLE_AUTO_REGISTRATION = true in [oauth2_client], users who authenticate via Casdoor are automatically created in Gitea. Account linking uses auto mode to match by email address.

Deployment Order

  1. Deploy Casdoor first (if not already running):

    ansible-playbook casdoor/deploy.yml
    
  2. Deploy Gitea (registers OAuth provider):

    ansible-playbook gitea/deploy.yml
    

Verify OAuth Configuration

# List authentication sources
ssh rosalind.incus "sudo -u git /usr/local/bin/gitea admin auth list --config /etc/gitea/app.ini"

# Should show: casdoor (OpenID Connect)

Database Setup

Gitea requires a PostgreSQL database on Portia. This is automatically created by the postgresql/deploy.yml playbook.

Database Details:

  • Name: gitea
  • User: gitea
  • Owner: gitea
  • Extensions: None required

Integration with Other Services

HAProxy Routing

Backend Configuration (titania.incus.yml):

- subdomain: "gitea"
  backend_host: "rosalind.incus"
  backend_port: 22083
  health_path: "/api/healthz"
  timeout_server: 120s

Memcached Integration

  • Host: localhost:11211
  • Session Prefix: N/A (Memcache adapter doesn't require prefix)
  • Cache Prefix: N/A

Prometheus Monitoring

  • Scrape Target: rosalind.incus:22094
  • Job Name: gitea
  • Authentication: Bearer token

Troubleshooting

Service Status

ssh rosalind.incus
sudo systemctl status gitea

View Logs

# Application logs
sudo tail -f /var/log/gitea/gitea.log

# Systemd journal
sudo journalctl -u gitea -f

Test Database Connection

psql -h portia.incus -U gitea -d gitea

Check Memcached

echo "stats" | nc localhost 11211

Verify Metrics Endpoint

curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:22094/metrics

Version Information

  • Installation Method: Binary download from GitHub releases
  • Version Selection: Latest stable release (dynamic)
  • Update Process: Re-run deployment playbook to fetch latest binary
  • Architecture: linux-amd64

References