Files
rick-infra/roles/gitea/README.md
Joakim cf71fb3a8d Implement SSH passthrough mode and refactor Gitea domain configuration
Major Changes:
- Add dual SSH mode system (passthrough default, dedicated fallback)
- Refactor domain configuration to use direct specification pattern
- Fix critical fail2ban security gap in dedicated mode
- Separate HTTP and SSH domains for cleaner Git URLs
2025-12-17 21:51:24 +01:00

264 lines
7.1 KiB
Markdown

# Gitea Git Service Role
Self-contained Gitea Git service for rick-infra following the established architectural patterns.
## Features
-**Self-contained**: Manages its own database and configuration
-**Native Arch installation**: Uses pacman packages
-**PostgreSQL integration**: Uses shared PostgreSQL infrastructure
-**Caddy integration**: Deploys reverse proxy configuration
-**Dual SSH modes**: Passthrough (default) or dedicated SSH server
-**Flexible domains**: Separate HTTP and SSH domains
-**Security hardened**: SystemD restrictions and secure defaults
-**Firewall management**: Automatic nftables configuration per mode
-**fail2ban protection**: Brute force protection for SSH authentication
-**Production ready**: HTTPS, SSH access, LFS support
## Architecture
- **Dependencies**: PostgreSQL infrastructure role
- **Database**: Self-managed gitea database and user
- **Network**: HTTP on :3000 (localhost), SSH via system SSH (port 22) or dedicated (port 2222)
- **Web access**: https://git.jnss.me (via Caddy reverse proxy)
- **SSH access**: git@jnss.me:user/repo.git (passthrough mode, default)
- **Firewall**: Managed per SSH mode (no extra ports in passthrough)
- **Security**: fail2ban protects SSH authentication (system or dedicated jail)
## Configuration
Key variables (defaults in `defaults/main.yml`):
```yaml
# Service
gitea_service_enabled: true
gitea_http_port: 3000
# Domain Configuration
gitea_http_domain: "git.jnss.me" # Web interface
gitea_ssh_domain: "jnss.me" # SSH/Git operations
# SSH Mode
gitea_ssh_mode: "passthrough" # or "dedicated"
# Database (self-managed)
gitea_db_name: "gitea"
gitea_db_user: "gitea"
gitea_db_password: "{{ vault_gitea_db_password }}"
# Application
gitea_app_name: "Gitea: Git with a cup of tea"
gitea_disable_registration: false
gitea_enable_lfs: true
```
## Domain Configuration
Gitea uses **separate domains** for HTTP and SSH access, providing flexibility and cleaner URLs:
### HTTP Domain (`gitea_http_domain`)
- **Purpose**: Web interface access
- **Default**: `git.jnss.me`
- **Example**: `https://git.jnss.me`
- **Used for**: Browsing repos, managing settings, viewing commits
### SSH Domain (`gitea_ssh_domain`)
- **Purpose**: Git clone/push/pull operations
- **Default**: `jnss.me` (root domain)
- **Example**: `git@jnss.me:user/repo.git`
- **Used for**: Git operations over SSH
**Why Separate Domains?**
- ✅ Cleaner SSH URLs (no redundant "git" subdomain)
- ✅ Flexibility to use completely different domains
- ✅ Matches industry standards (GitHub, GitLab use root domain for SSH)
- ✅ Professional appearance
**Configuration Examples:**
```yaml
# Standard setup (recommended)
gitea_http_domain: "git.jnss.me"
gitea_ssh_domain: "jnss.me"
# Result: git@jnss.me:user/repo.git
# Same domain for both
gitea_http_domain: "git.jnss.me"
gitea_ssh_domain: "git.jnss.me"
# Result: git@git.jnss.me:user/repo.git
# Completely custom
gitea_http_domain: "code.jnss.me"
gitea_ssh_domain: "git.example.com"
# Result: git@git.example.com:user/repo.git
```
## SSH Modes
### Passthrough Mode (Default - Recommended)
System SSH handles Git operations via AuthorizedKeysCommand:
```bash
# Clone repository (standard Git URL, no port number)
git clone git@jnss.me:username/repository.git
# Add as remote
git remote add origin git@jnss.me:username/repository.git
# Test SSH connection
ssh -T git@jnss.me
```
**Features:**
- ✅ Standard Git URLs (no :2222 port)
- ✅ Single SSH daemon (smaller attack surface)
- ✅ System fail2ban protects everything
- ✅ Port 22 only (no extra firewall rules)
- ✅ Matches GitHub/GitLab pattern
### Dedicated Mode (Fallback)
Gitea runs its own SSH server on port 2222:
```bash
# Clone repository (with port number)
git clone ssh://git@jnss.me:2222/username/repository.git
# Add as remote
git remote add origin ssh://git@jnss.me:2222/username/repository.git
# Test SSH connection
ssh -T -p 2222 git@jnss.me
```
**Features:**
- ✅ Complete isolation from system SSH
- ✅ Independent configuration
- ⚠️ Requires port 2222 open in firewall
- ⚠️ Non-standard URLs (requires :2222)
**To switch modes:**
```yaml
# host_vars/arch-vps/main.yml
gitea_ssh_mode: "dedicated" # or "passthrough"
```
Then re-run the playbook.
## Usage
1. **Add vault password**: Set `vault_gitea_db_password` in host_vars vault
2. **Configure domains** (optional): Override `gitea_http_domain` and `gitea_ssh_domain` in host_vars
3. **Deploy**: `ansible-playbook site.yml --tags gitea`
4. **Access**: Visit https://git.jnss.me to set up admin account
## SSH Key Setup
1. **Generate SSH key** (if you don't have one):
```bash
ssh-keygen -t ed25519 -C "your_email@example.com"
```
2. **Copy your public key**:
```bash
cat ~/.ssh/id_ed25519.pub
```
3. **Add to Gitea**:
- Log into Gitea web interface
- Go to Settings → SSH/GPG Keys
- Click "Add Key"
- Paste your public key
4. **Test SSH connection**:
```bash
# Passthrough mode
ssh -T git@jnss.me
# Dedicated mode
ssh -T -p 2222 git@jnss.me
```
## Firewall and Security
### Automatic Firewall Management
Firewall configuration is mode-aware:
**Passthrough Mode:**
- No extra firewall rules needed (uses port 22)
- System SSH already configured in security playbook
**Dedicated Mode:**
- Port 2222 automatically opened via nftables
- Firewall rules stored in `/etc/nftables.d/50-gitea.nft`
- Rules integrated with main security playbook
- Automatically removed when switching to passthrough
### fail2ban Protection
Protection is mode-aware:
**Passthrough Mode:**
- System `sshd` jail protects all SSH traffic (port 22)
- Covers admin SSH + Git operations automatically
- No separate Gitea jail needed
**Dedicated Mode:**
- `gitea-ssh` jail monitors Gitea logs (port 2222)
- Max retries: 5 failed attempts
- Find time: 10 minutes (600 seconds)
- Ban time: 1 hour (3600 seconds)
- Action: IP banned via nftables
Check fail2ban status:
```bash
# Passthrough mode
fail2ban-client status sshd
# Dedicated mode
fail2ban-client status gitea-ssh
```
### Firewall Verification
```bash
# List active nftables rules
nft list ruleset
# Check for Gitea SSH port (should be empty in passthrough)
nft list ruleset | grep 2222
# Verify SSH connectivity
nc -zv jnss.me 22 # Passthrough
nc -zv jnss.me 2222 # Dedicated
```
## Dependencies
- PostgreSQL infrastructure role (auto-included)
- Caddy web server (for HTTPS access)
- Vault password: `vault_gitea_db_password`
## Self-Contained Design
This role follows rick-infra's self-contained service pattern:
- Creates its own database and user via PostgreSQL infrastructure
- Manages its own configuration and data
- Deploys its own Caddy reverse proxy config
- Manages its own firewall rules and security (nftables, fail2ban)
- Flexible domain configuration (not tied to infrastructure variables)
- Independent lifecycle from other services
## Migration Guide
See `docs/gitea-ssh-migration-guide.md` for:
- Switching between SSH modes
- Updating Git remote URLs
- Bulk migration scripts
- Troubleshooting
---
**Rick-Infra Gitea Service**
Git repository management with flexible SSH modes and domain configuration.