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:
2025-12-17 21:51:24 +01:00
parent 2fe194ba82
commit cf71fb3a8d
15 changed files with 1134 additions and 102 deletions

View File

@@ -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.

View File

@@ -20,16 +20,14 @@ gitea_home: "/var/lib/gitea"
# Network Configuration
gitea_http_port: 3000
gitea_ssh_port: 2222
# =================================================================
# Domain and Caddy Integration
# =================================================================
# Domain setup (follows rick-infra pattern)
gitea_subdomain: "git"
gitea_domain: "{{ caddy_domain | default('localhost') }}"
gitea_full_domain: "{{ gitea_subdomain }}.{{ gitea_domain }}"
gitea_http_domain: "git.jnss.me"
gitea_ssh_domain: "jnss.me"
# Caddy integration
caddy_sites_enabled_dir: "/etc/caddy/sites-enabled"
@@ -63,15 +61,34 @@ gitea_enable_lfs: true
gitea_disable_registration: false
gitea_require_signin: false
# SSH settings
gitea_start_ssh_server: true
# =================================================================
# SSH Mode Configuration
# =================================================================
# SSH Mode: 'passthrough' or 'dedicated'
# - passthrough (default): Use system SSH on port 22
# * More secure (single SSH daemon, smaller attack surface)
# * Standard Git URLs (no :2222 port number needed)
# * System fail2ban automatically protects Git operations
# * Recommended for production use
#
# - dedicated (fallback): Run Gitea's built-in SSH server on port 2222
# * Complete isolation from system SSH
# * Independent configuration and restarts
# * Requires opening port 2222 in firewall
# * Useful for debugging or when passthrough causes issues
gitea_ssh_mode: "passthrough"
# Dynamic SSH configuration based on mode
gitea_ssh_port: "{{ 22 if gitea_ssh_mode == 'passthrough' else 2222 }}"
gitea_start_ssh_server: "{{ false if gitea_ssh_mode == 'passthrough' else true }}"
# =================================================================
# Firewall Configuration
# =================================================================
# Firewall management
gitea_manage_firewall: true # Set to false if firewall is managed externally
# Firewall management (only opens port in dedicated mode)
gitea_manage_firewall: "{{ true if gitea_ssh_mode == 'dedicated' else false }}"
# =================================================================
# Infrastructure Dependencies (Read-only)
@@ -91,4 +108,4 @@ postgresql_port: 5432
# - Creates its own database and user
# - Deploys Caddy configuration to sites-enabled
# - Uses native Arch Linux Gitea package
# - Follows self-contained service pattern
# - Follows self-contained service pattern

View File

@@ -27,4 +27,11 @@
- name: restart fail2ban
systemd:
name: fail2ban
state: restarted
state: restarted
- name: restart sshd
systemd:
name: sshd
state: restarted
# Safety: only restart if not running locally
when: ansible_connection != 'local'

View File

@@ -1,7 +1,7 @@
---
# Gitea fail2ban Configuration - Rick-Infra
# Protects Gitea SSH from brute force attacks
# Integrates with system fail2ban service
# Mode-aware: Only protects dedicated mode (port 2222)
# In passthrough mode, system 'sshd' jail protects port 22
- name: Install fail2ban
pacman:
@@ -13,6 +13,7 @@
content: |
# Fail2ban filter for Gitea SSH authentication failures
# Rick-Infra: Gitea role
# Only used in dedicated mode (port {{ gitea_ssh_port }})
[Definition]
# Match failed authentication attempts in Gitea logs
@@ -33,14 +34,17 @@
modification_time: preserve
access_time: preserve
- name: Add Gitea SSH jail to fail2ban
- name: Add Gitea SSH jail to fail2ban (mode-aware)
blockinfile:
path: /etc/fail2ban/jail.local
marker: "# {mark} ANSIBLE MANAGED BLOCK - Gitea SSH"
block: |
# Gitea SSH Protection - Rick-Infra
# Mode: {{ gitea_ssh_mode }}
# - dedicated: Monitors Gitea logs on port {{ gitea_ssh_port }}
# - passthrough: Disabled (system 'sshd' jail protects port 22)
[gitea-ssh]
enabled = true
enabled = {{ 'true' if gitea_ssh_mode == 'dedicated' else 'false' }}
port = {{ gitea_ssh_port }}
filter = gitea-ssh
logpath = {{ gitea_home }}/log/gitea.log
@@ -57,19 +61,61 @@
enabled: yes
state: started
- name: Add fail2ban restart handler
- name: Flush handlers to ensure fail2ban restarts
meta: flush_handlers
- name: Display fail2ban status for Gitea
- name: Wait for fail2ban to be ready
pause:
seconds: 2
- name: Verify gitea-ssh jail status (dedicated mode only)
command: fail2ban-client status gitea-ssh
register: gitea_jail_verify
changed_when: false
failed_when: false
when: gitea_ssh_mode == 'dedicated'
- name: Verify sshd jail status (passthrough mode)
command: fail2ban-client status sshd
register: sshd_jail_verify
changed_when: false
failed_when: false
when: gitea_ssh_mode == 'passthrough'
- name: Display fail2ban configuration status
debug:
msg: |
🛡️ fail2ban configured for Gitea SSH
📍 Filter: /etc/fail2ban/filter.d/gitea-ssh.conf
📍 Jail: gitea-ssh (in /etc/fail2ban/jail.local)
🔒 Protection: Port {{ gitea_ssh_port }}
⏱️ Ban time: 1 hour (3600 seconds)
🔢 Max retries: 5 attempts in 10 minutes
🛡️ fail2ban Protection for Gitea SSH
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📍 Mode: {{ gitea_ssh_mode | upper }}
Check status: fail2ban-client status gitea-ssh
{% if gitea_ssh_mode == 'dedicated' %}
📍 Jail: gitea-ssh
📍 Port: {{ gitea_ssh_port }}
📍 Status: {{ 'Active ✅' if gitea_jail_verify.rc == 0 else 'Not Active ⚠️' }}
📍 Filter: /etc/fail2ban/filter.d/gitea-ssh.conf
📍 Logfile: {{ gitea_home }}/log/gitea.log
Protection Settings:
• Max retries: 5 attempts
• Find time: 10 minutes (600 seconds)
• Ban time: 1 hour (3600 seconds)
Check status:
fail2ban-client status gitea-ssh
{% else %}
📍 Jail: sshd (system jail)
📍 Port: 22
📍 Status: {{ 'Active ✅' if sshd_jail_verify.rc == 0 else 'Not Active ⚠️' }}
📍 Coverage: All SSH traffic including Gitea Git operations
Note: In passthrough mode, the system 'sshd' jail automatically
protects all SSH traffic on port 22, including Gitea Git
operations. No separate gitea-ssh jail is needed.
Check status:
fail2ban-client status sshd
{% endif %}
# Rick-Infra: Self-contained fail2ban protection per role

View File

@@ -16,23 +16,30 @@
name: gitea
state: present
# Firewall configuration - self-managed by Gitea role
- name: Configure firewall for Gitea SSH
import_tasks: firewall.yml
tags: ['firewall']
when: gitea_manage_firewall | default(true)
# SSH Mode Configuration - Conditional based on gitea_ssh_mode
# Mode determines how Git SSH operations are handled
# fail2ban protection - self-managed by Gitea role
- name: Configure fail2ban for Gitea SSH
import_tasks: fail2ban.yml
tags: ['fail2ban', 'security']
when: gitea_manage_firewall | default(true)
- name: Configure SSH passthrough mode (default)
import_tasks: ssh_passthrough.yml
when: gitea_ssh_mode == "passthrough"
tags: ['ssh', 'passthrough']
- name: Configure SSH dedicated mode (fallback)
import_tasks: ssh_dedicated.yml
when: gitea_ssh_mode == "dedicated"
tags: ['ssh', 'dedicated']
- name: Install Git
pacman:
name: git
state: present
- name: Create Gitea group
group:
name: "{{ gitea_group }}"
system: yes
state: present
- name: Create Gitea user and group
user:
name: "{{ gitea_user }}"
@@ -156,8 +163,8 @@
msg: |
✅ Gitea Git service deployed successfully!
🌐 Web Interface: https://{{ gitea_full_domain }}
🔗 SSH Clone: ssh://git@{{ gitea_full_domain }}:{{ gitea_ssh_port }}
🌐 Web Interface: https://{{ gitea_http_domain }}
🔗 SSH Clone: ssh://git@{{ gitea_ssh_domain }}:{{ gitea_ssh_port }}
📦 Local HTTP: http://127.0.0.1:{{ gitea_http_port }}
🗄️ Database: {{ gitea_db_name }} (self-managed)

View File

@@ -0,0 +1,74 @@
---
# Gitea Dedicated SSH Server Configuration - Rick-Infra
# Configures Gitea to run its own SSH server on port 2222
# This is the fallback mode when passthrough is not desired
- name: Configure firewall for Gitea SSH (dedicated mode)
import_tasks: firewall.yml
tags: ['firewall']
- name: Configure fail2ban for Gitea SSH (dedicated mode)
import_tasks: fail2ban.yml
tags: ['fail2ban', 'security']
- name: Wait for fail2ban to be ready
pause:
seconds: 2
- name: Verify gitea-ssh jail is active
command: fail2ban-client status gitea-ssh
register: gitea_jail_status
changed_when: false
failed_when: false
- name: Display fail2ban protection status
debug:
msg: |
🛡️ Gitea SSH fail2ban protection:
{% if gitea_jail_status.rc == 0 %}
✅ gitea-ssh jail is ACTIVE
{{ gitea_jail_status.stdout }}
{% else %}
⚠️ WARNING: gitea-ssh jail not active!
This is a security risk - port {{ gitea_ssh_port }} is vulnerable to brute force attacks.
{% endif %}
- name: Fail if gitea-ssh jail is not running (security critical)
fail:
msg: |
SECURITY ERROR: gitea-ssh fail2ban jail is not active!
Port {{ gitea_ssh_port }} is exposed but not protected.
Check fail2ban configuration and logs.
when: gitea_jail_status.rc != 0
- name: Remove SSH passthrough configuration if present
blockinfile:
path: /etc/ssh/sshd_config
marker: "# {mark} ANSIBLE MANAGED BLOCK - Gitea SSH Passthrough"
state: absent
backup: yes
register: sshd_config_cleaned
notify: restart sshd
- name: Remove AuthorizedKeysCommand script if present
file:
path: /usr/local/bin/gitea-keys
state: absent
- name: Display dedicated mode configuration
debug:
msg: |
🔧 Gitea SSH Mode: DEDICATED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📍 SSH Server: Gitea built-in (port {{ gitea_ssh_port }})
🔗 Clone URL: ssh://git@{{ gitea_ssh_domain }}:{{ gitea_ssh_port }}/user/repo.git
🔥 Firewall: Port {{ gitea_ssh_port }} opened (nftables)
🛡️ fail2ban: gitea-ssh jail protecting port {{ gitea_ssh_port }}
Test connection:
ssh -T -p {{ gitea_ssh_port }} git@{{ gitea_ssh_domain }}
Clone repository:
git clone ssh://git@{{ gitea_ssh_domain }}:{{ gitea_ssh_port }}/username/repo.git
# Rick-Infra: Self-contained dedicated SSH mode with full security

View File

@@ -0,0 +1,128 @@
---
# Gitea SSH Passthrough Configuration - Rick-Infra
# Configures system SSH to handle Gitea Git authentication
# This is the default mode: more secure, standard Git URLs
- name: Ensure OpenSSH server is installed
pacman:
name: openssh
state: present
- name: Create Gitea AuthorizedKeysCommand script
template:
src: gitea-keys.sh.j2
dest: /usr/local/bin/gitea-keys
mode: '0755'
owner: root
group: root
register: gitea_keys_script
- name: Configure SSH for Gitea passthrough
blockinfile:
path: /etc/ssh/sshd_config
marker: "# {mark} ANSIBLE MANAGED BLOCK - Gitea SSH Passthrough"
block: |
# Gitea SSH Passthrough - Rick-Infra
# System SSH delegates git user authentication to Gitea
# This allows standard Git URLs: git@{{ gitea_ssh_domain }}:user/repo.git
Match User {{ gitea_user }}
AuthorizedKeysCommandUser {{ gitea_user }}
AuthorizedKeysCommand /usr/local/bin/gitea-keys %u %t %k
AllowTcpForwarding no
AllowAgentForwarding no
X11Forwarding no
PermitTTY no
backup: yes
validate: '/usr/bin/sshd -t -f %s'
register: sshd_config_changed
notify: restart sshd
- name: Verify SSH configuration syntax
command: sshd -t
changed_when: false
register: sshd_test
- name: Display SSH validation result
debug:
msg: |
{% if sshd_test.rc == 0 %}
✅ SSH configuration is valid
{% else %}
⚠️ SSH configuration test failed:
{{ sshd_test.stderr }}
{% endif %}
- name: Fail if SSH configuration is invalid
fail:
msg: "SSH configuration test failed. Rolling back changes."
when: sshd_test.rc != 0
- name: Remove Gitea firewall rule (passthrough uses port 22)
file:
path: /etc/nftables.d/50-gitea.nft
state: absent
notify: reload nftables
register: firewall_cleaned
- name: Reload nftables if firewall rule was removed
systemd:
name: nftables
state: reloaded
when: firewall_cleaned.changed
- name: Configure fail2ban for passthrough mode
import_tasks: fail2ban.yml
tags: ['fail2ban', 'security']
- name: Flush handlers to ensure sshd restarts if needed
meta: flush_handlers
- name: Wait for SSH service to be available after restart
wait_for:
port: 22
host: "{{ ansible_host | default('127.0.0.1') }}"
timeout: 30
delegate_to: localhost
become: false
when: sshd_config_changed.changed
- name: Test SSH connection after configuration
ping:
when: sshd_config_changed.changed
- name: Verify passthrough is working
command: sudo -u {{ gitea_user }} /usr/local/bin/gitea-keys ssh-rsa test
register: gitea_keys_test
changed_when: false
failed_when: false
- name: Display passthrough mode configuration
debug:
msg: |
🔧 Gitea SSH Mode: PASSTHROUGH (Default)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📍 SSH Server: System SSH (port 22)
🔗 Clone URL: git@{{ gitea_ssh_domain }}:user/repo.git
🔥 Firewall: Port 2222 closed (not needed)
🛡️ fail2ban: System 'sshd' jail protects all SSH traffic
🔑 AuthorizedKeysCommand: /usr/local/bin/gitea-keys
How it works:
1. User connects: ssh git@{{ gitea_ssh_domain }}
2. System SSH checks: /usr/local/bin/gitea-keys
3. Script queries Gitea database for SSH key
4. If authorized, Gitea handles Git operation
Test connection:
ssh -T git@{{ gitea_ssh_domain }}
Clone repository:
git clone git@{{ gitea_ssh_domain }}:username/repo.git
Benefits:
✅ Standard Git URLs (no :2222 port number)
✅ Single SSH daemon (smaller attack surface)
✅ System fail2ban protects everything
✅ One port to manage and monitor
# Rick-Infra: Self-contained SSH passthrough mode with enhanced security

View File

@@ -11,14 +11,17 @@ DEFAULT_BRANCH = {{ gitea_default_branch }}
[server]
PROTOCOL = http
DOMAIN = {{ gitea_full_domain }}
DOMAIN = {{ gitea_http_domain }}
HTTP_PORT = {{ gitea_http_port }}
ROOT_URL = https://{{ gitea_full_domain }}/
ROOT_URL = https://{{ gitea_http_domain }}/
DISABLE_SSH = false
# SSH Mode: {{ gitea_ssh_mode }}
START_SSH_SERVER = {{ gitea_start_ssh_server | lower }}
SSH_DOMAIN = {{ gitea_full_domain }}
SSH_DOMAIN = {{ gitea_ssh_domain }}
SSH_PORT = {{ gitea_ssh_port }}
{% if gitea_ssh_mode == 'dedicated' %}
SSH_LISTEN_PORT = {{ gitea_ssh_port }}
{% endif %}
LOCAL_ROOT_URL = http://127.0.0.1:{{ gitea_http_port }}/
APP_DATA_PATH = {{ gitea_home }}/data
@@ -47,7 +50,7 @@ DISABLE_REGISTRATION = {{ gitea_disable_registration | lower }}
REQUIRE_SIGNIN_VIEW = {{ gitea_require_signin | lower }}
DEFAULT_KEEP_EMAIL_PRIVATE = true
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
NO_REPLY_ADDRESS = noreply.{{ gitea_domain }}
NO_REPLY_ADDRESS = noreply@{{ gitea_http_domain }}
[log]
MODE = console
@@ -63,4 +66,4 @@ CONTENT_PATH = {{ gitea_home }}/data/lfs
[git]
PATH = /usr/bin/git
# Rick-Infra: Simplified Gitea configuration for self-contained service
# Rick-Infra: Simplified Gitea configuration for self-contained service

View File

@@ -0,0 +1,28 @@
#!/bin/bash
# Gitea SSH Keys AuthorizedKeysCommand - Rick-Infra
# Generated by Ansible Gitea role
#
# This script is called by OpenSSH's AuthorizedKeysCommand to query
# Gitea's database for SSH public keys when the 'git' user connects.
#
# Called by SSH with parameters:
# %u = username (should be "git")
# %t = key type (ssh-rsa, ssh-ed25519, ecdsa-sha2-nistp256, etc.)
# %k = base64 encoded public key content
#
# The script returns authorized_keys format entries that include
# forced commands to execute Gitea's Git server.
set -euo pipefail
# Gitea keys command queries the database and returns authorized_keys format
# If the key is found, it returns a line like:
# command="/usr/bin/gitea serv key-123",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAA...
exec /usr/bin/gitea keys \
--config /etc/gitea/app.ini \
--username "$1" \
--type "$2" \
--content "$3"
# Rick-Infra: AuthorizedKeysCommand for Gitea SSH passthrough mode

View File

@@ -2,7 +2,7 @@
# Generated by Ansible Gitea role
# Deployed to {{ caddy_sites_enabled_dir }}/gitea.caddy
{{ gitea_full_domain }} {
{{ gitea_http_domain }} {
# Reverse proxy to Gitea
reverse_proxy 127.0.0.1:{{ gitea_http_port }}
@@ -29,4 +29,4 @@
}
}
# Rick-Infra: Self-contained Gitea service with Caddy reverse proxy
# Rick-Infra: Self-contained Gitea service with Caddy reverse proxy