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
This commit is contained in:
@@ -8,8 +8,10 @@ Self-contained Gitea Git service for rick-infra following the established archit
|
||||
- ✅ **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**: Automatically configures nftables for SSH access
|
||||
- ✅ **Firewall management**: Automatic nftables configuration per mode
|
||||
- ✅ **fail2ban protection**: Brute force protection for SSH authentication
|
||||
- ✅ **Production ready**: HTTPS, SSH access, LFS support
|
||||
|
||||
@@ -17,11 +19,11 @@ Self-contained Gitea Git service for rick-infra following the established archit
|
||||
|
||||
- **Dependencies**: PostgreSQL infrastructure role
|
||||
- **Database**: Self-managed gitea database and user
|
||||
- **Network**: HTTP on :3000 (localhost), SSH on :2222 (public)
|
||||
- **Web access**: https://git.domain.com (via Caddy reverse proxy)
|
||||
- **SSH access**: ssh://git@git.domain.com:2222
|
||||
- **Firewall**: Port 2222 automatically opened via nftables
|
||||
- **Security**: fail2ban monitors and blocks SSH brute force attempts
|
||||
- **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
|
||||
|
||||
@@ -31,11 +33,13 @@ Key variables (defaults in `defaults/main.yml`):
|
||||
# Service
|
||||
gitea_service_enabled: true
|
||||
gitea_http_port: 3000
|
||||
gitea_ssh_port: 2222
|
||||
|
||||
# Domain
|
||||
gitea_subdomain: "git"
|
||||
gitea_domain: "{{ caddy_domain }}"
|
||||
# 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"
|
||||
@@ -46,36 +50,108 @@ gitea_db_password: "{{ vault_gitea_db_password }}"
|
||||
gitea_app_name: "Gitea: Git with a cup of tea"
|
||||
gitea_disable_registration: false
|
||||
gitea_enable_lfs: true
|
||||
|
||||
# Firewall and Security
|
||||
gitea_manage_firewall: true # Automatically manage nftables rules
|
||||
```
|
||||
|
||||
## 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. **Deploy**: `ansible-playbook site.yml --tags gitea`
|
||||
3. **Access**: Visit https://git.yourdomain.com to set up admin account
|
||||
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
|
||||
|
||||
## Dependencies
|
||||
|
||||
- PostgreSQL infrastructure role (auto-included)
|
||||
- Caddy web server (for HTTPS access)
|
||||
- Vault password: `vault_gitea_db_password`
|
||||
|
||||
## SSH Access
|
||||
|
||||
Gitea provides Git repository access via SSH on port 2222:
|
||||
|
||||
```bash
|
||||
# Clone a repository
|
||||
git clone ssh://git@git.jnss.me:2222/username/repository.git
|
||||
|
||||
# Or add as remote
|
||||
git remote add origin ssh://git@git.jnss.me:2222/username/repository.git
|
||||
```
|
||||
|
||||
### SSH Key Setup
|
||||
## SSH Key Setup
|
||||
|
||||
1. **Generate SSH key** (if you don't have one):
|
||||
```bash
|
||||
@@ -95,40 +171,52 @@ git remote add origin ssh://git@git.jnss.me:2222/username/repository.git
|
||||
|
||||
4. **Test SSH connection**:
|
||||
```bash
|
||||
ssh -T -p 2222 git@git.jnss.me
|
||||
# Passthrough mode
|
||||
ssh -T git@jnss.me
|
||||
|
||||
# Dedicated mode
|
||||
ssh -T -p 2222 git@jnss.me
|
||||
```
|
||||
|
||||
## Firewall and Security
|
||||
|
||||
### Automatic Firewall Management
|
||||
|
||||
The Gitea role automatically manages firewall rules via nftables:
|
||||
Firewall configuration is mode-aware:
|
||||
|
||||
- **Port 2222** is opened automatically when Gitea is deployed
|
||||
- Firewall rules are stored in `/etc/nftables.d/gitea.nft`
|
||||
- Rules are integrated with the main security playbook configuration
|
||||
- To disable automatic firewall management, set `gitea_manage_firewall: false`
|
||||
**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
|
||||
|
||||
SSH brute force protection is automatically configured:
|
||||
Protection is mode-aware:
|
||||
|
||||
- **Jail**: `gitea-ssh` monitors Gitea SSH authentication attempts
|
||||
- **Max retries**: 5 failed attempts
|
||||
- **Find time**: 10 minutes (600 seconds)
|
||||
- **Ban time**: 1 hour (3600 seconds)
|
||||
- **Action**: IP banned via nftables
|
||||
**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
|
||||
# Check Gitea SSH jail status
|
||||
# Passthrough mode
|
||||
fail2ban-client status sshd
|
||||
|
||||
# Dedicated mode
|
||||
fail2ban-client status gitea-ssh
|
||||
|
||||
# View banned IPs
|
||||
fail2ban-client get gitea-ssh banned
|
||||
|
||||
# Unban an IP if needed
|
||||
fail2ban-client set gitea-ssh unbanip 203.0.113.100
|
||||
```
|
||||
|
||||
### Firewall Verification
|
||||
@@ -137,13 +225,20 @@ fail2ban-client set gitea-ssh unbanip 203.0.113.100
|
||||
# List active nftables rules
|
||||
nft list ruleset
|
||||
|
||||
# Check if Gitea SSH port is open
|
||||
# Check for Gitea SSH port (should be empty in passthrough)
|
||||
nft list ruleset | grep 2222
|
||||
|
||||
# Verify from external machine
|
||||
nc -zv git.jnss.me 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:
|
||||
@@ -151,9 +246,18 @@ This role follows rick-infra's self-contained service pattern:
|
||||
- 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 integrated CI/CD capabilities.
|
||||
Git repository management with flexible SSH modes and domain configuration.
|
||||
|
||||
Reference in New Issue
Block a user