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.
387 lines
13 KiB
Markdown
387 lines
13 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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**:
|
|
```bash
|
|
git clone https://gitea.ouranos.helu.ca/username/repo.git
|
|
```
|
|
4. **SSH Clone**:
|
|
```bash
|
|
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
|
|
```yaml
|
|
vault_gitea_db_password: "YourSecurePassword123!"
|
|
```
|
|
**Requirements:**
|
|
- Minimum 12 characters recommended
|
|
- Used by PostgreSQL authentication
|
|
|
|
### 2. Secret Key (Session Encryption)
|
|
```yaml
|
|
vault_gitea_secret_key: "RandomString64CharactersLongForSessionCookieEncryptionSecurity123"
|
|
```
|
|
**Requirements:**
|
|
- **Length**: Recommended 64+ characters
|
|
- **Format**: Base64 or hex string
|
|
- **Generation**:
|
|
```bash
|
|
openssl rand -base64 48
|
|
```
|
|
|
|
### 3. LFS JWT Secret
|
|
```yaml
|
|
vault_gitea_lfs_jwt_secret: "AnotherRandomString64CharsForLFSJWTTokenSigning1234567890ABC"
|
|
```
|
|
**Requirements:**
|
|
- **Length**: Recommended 64+ characters
|
|
- **Purpose**: Signs JWT tokens for Git LFS authentication
|
|
- **Generation**:
|
|
```bash
|
|
openssl rand -base64 48
|
|
```
|
|
|
|
### 4. Metrics Token
|
|
```yaml
|
|
vault_gitea_metrics_token: "RandomTokenForPrometheusMetricsAccess123"
|
|
```
|
|
**Requirements:**
|
|
- **Length**: 32+ characters recommended
|
|
- **Purpose**: Bearer token for Prometheus scraping
|
|
- **Generation**:
|
|
```bash
|
|
openssl rand -hex 32
|
|
```
|
|
|
|
### 5. OAuth Client ID
|
|
```yaml
|
|
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
|
|
```yaml
|
|
vault_gitea_oauth_client_secret: "YourRandomOAuthSecret123!"
|
|
```
|
|
**Requirements:**
|
|
- **Length**: 32+ characters recommended
|
|
- **Purpose**: Client secret for Casdoor OAuth2 authentication
|
|
- **Generation**:
|
|
```bash
|
|
openssl rand -base64 32
|
|
```
|
|
- **Source**: Must match `clientSecret` in Casdoor application configuration
|
|
|
|
## Host Variables
|
|
|
|
**File:** `ansible/inventory/host_vars/rosalind.incus.yml`
|
|
|
|
```yaml
|
|
# 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):
|
|
```bash
|
|
ansible-playbook casdoor/deploy.yml
|
|
```
|
|
|
|
2. **Deploy Gitea** (registers OAuth provider):
|
|
```bash
|
|
ansible-playbook gitea/deploy.yml
|
|
```
|
|
|
|
### Verify OAuth Configuration
|
|
|
|
```bash
|
|
# 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`):
|
|
```yaml
|
|
- 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
|
|
```bash
|
|
ssh rosalind.incus
|
|
sudo systemctl status gitea
|
|
```
|
|
|
|
### View Logs
|
|
```bash
|
|
# Application logs
|
|
sudo tail -f /var/log/gitea/gitea.log
|
|
|
|
# Systemd journal
|
|
sudo journalctl -u gitea -f
|
|
```
|
|
|
|
### Test Database Connection
|
|
```bash
|
|
psql -h portia.incus -U gitea -d gitea
|
|
```
|
|
|
|
### Check Memcached
|
|
```bash
|
|
echo "stats" | nc localhost 11211
|
|
```
|
|
|
|
### Verify Metrics Endpoint
|
|
```bash
|
|
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
|