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.
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
- Install Dependencies: git, git-lfs, curl, memcached
- Create System User:
git:gitwith home directory - Create Directories: Work dir, data, LFS storage, repository root, logs
- Download Gitea Binary: Latest release from GitHub (architecture-specific)
- Template Configuration: Apply
app.ini.j2with variables - Create Systemd Service: Custom service unit for Gitea
- Start Service: Enable and start gitea.service
- 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
- Web Interface: https://gitea.ouranos.helu.ca/
- First-Time Setup: Create admin account on first visit
- Git Clone:
git clone https://gitea.ouranos.helu.ca/username/repo.git - SSH Clone:
Note: SSH requires port 22022 configured in
git clone git@gitea.ouranos.helu.ca:username/repo.git~/.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
clientIdin 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
clientSecretin 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
-
Deploy Casdoor first (if not already running):
ansible-playbook casdoor/deploy.yml -
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
- Official Documentation: https://docs.gitea.com/
- GitHub Repository: https://github.com/go-gitea/gitea
- Configuration Reference: https://docs.gitea.com/administration/config-cheat-sheet