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.
This commit is contained in:
386
docs/gitea.md
Normal file
386
docs/gitea.md
Normal file
@@ -0,0 +1,386 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user