Implement modular nftables architecture and Gitea SSH firewall management
- Restructure security playbook with modular nftables loader - Base rules loaded first, service rules second, drop rule last - Add Gitea self-contained firewall management (port 2222) - Add fail2ban protection for Gitea SSH brute force attacks - Update documentation with new firewall architecture - Create comprehensive Gitea deployment and testing guide This enables self-contained service roles to manage their own firewall rules without modifying the central security playbook. Each service deploys rules to /etc/nftables.d/ which are loaded before the final drop rule, maintaining the defense-in-depth security model.
This commit is contained in:
541
docs/gitea-deployment-guide.md
Normal file
541
docs/gitea-deployment-guide.md
Normal file
@@ -0,0 +1,541 @@
|
|||||||
|
# Gitea Deployment and Testing Guide
|
||||||
|
|
||||||
|
Comprehensive guide for deploying and testing Gitea Git service with SSH access on rick-infra.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### 1. Prerequisites
|
||||||
|
|
||||||
|
Ensure you have the required vault variables set in your host_vars:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# host_vars/arch-vps/vault.yml (encrypted)
|
||||||
|
vault_gitea_db_password: "your_secure_password_here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Deploy Gitea Role
|
||||||
|
|
||||||
|
Run the rick-infra playbook with Gitea role:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy Gitea to arch-vps
|
||||||
|
ansible-playbook -i inventory/hosts.yml rick-infra.yml --limit arch-vps
|
||||||
|
|
||||||
|
# Or deploy only Gitea role
|
||||||
|
ansible-playbook -i inventory/hosts.yml rick-infra.yml --tags gitea --limit arch-vps
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Verify Deployment
|
||||||
|
|
||||||
|
Check that all services are running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH into the server
|
||||||
|
ssh root@arch-vps
|
||||||
|
|
||||||
|
# Check Gitea service status
|
||||||
|
systemctl status gitea
|
||||||
|
|
||||||
|
# Check if Gitea is listening on HTTP port
|
||||||
|
ss -tlnp | grep 3000
|
||||||
|
|
||||||
|
# Check if Gitea SSH is listening
|
||||||
|
ss -tlnp | grep 2222
|
||||||
|
|
||||||
|
# Verify firewall rules
|
||||||
|
nft list ruleset | grep 2222
|
||||||
|
|
||||||
|
# Check fail2ban status
|
||||||
|
fail2ban-client status gitea-ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected output:
|
||||||
|
- Gitea service: `active (running)`
|
||||||
|
- HTTP port 3000: listening on `127.0.0.1:3000`
|
||||||
|
- SSH port 2222: listening on `0.0.0.0:2222`
|
||||||
|
- nftables: Rule allowing `tcp dport 2222`
|
||||||
|
- fail2ban: `gitea-ssh` jail active
|
||||||
|
|
||||||
|
## Testing Guide
|
||||||
|
|
||||||
|
### Test 1: Web Interface Access
|
||||||
|
|
||||||
|
**Purpose**: Verify HTTPS access through Caddy reverse proxy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From your local machine
|
||||||
|
curl -I https://git.jnss.me
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected result**:
|
||||||
|
- HTTP/2 200 OK
|
||||||
|
- Redirects to login page
|
||||||
|
- Valid TLS certificate
|
||||||
|
|
||||||
|
**Action**: Open browser to `https://git.jnss.me` and verify web interface loads
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Test 2: Firewall Port Verification
|
||||||
|
|
||||||
|
**Purpose**: Confirm port 2222 is accessible from external networks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From your local machine (not from the server)
|
||||||
|
nc -zv git.jnss.me 2222
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected result**:
|
||||||
|
```
|
||||||
|
Connection to git.jnss.me 2222 port [tcp/*] succeeded!
|
||||||
|
```
|
||||||
|
|
||||||
|
**If this fails**: The firewall rule is not active or nftables service is not running.
|
||||||
|
|
||||||
|
**Troubleshooting**:
|
||||||
|
```bash
|
||||||
|
# On the server
|
||||||
|
ssh root@arch-vps
|
||||||
|
|
||||||
|
# Check if nftables service is running
|
||||||
|
systemctl status nftables
|
||||||
|
|
||||||
|
# List all firewall rules
|
||||||
|
nft list ruleset
|
||||||
|
|
||||||
|
# Verify Gitea rule file exists
|
||||||
|
cat /etc/nftables.d/gitea.nft
|
||||||
|
|
||||||
|
# Manually reload nftables
|
||||||
|
systemctl reload nftables
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Test 3: SSH Connection Test
|
||||||
|
|
||||||
|
**Purpose**: Verify Gitea SSH server accepts connections
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From your local machine
|
||||||
|
ssh -T -p 2222 git@git.jnss.me
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected result** (before adding SSH key):
|
||||||
|
```
|
||||||
|
Hi there, You've successfully authenticated, but Gitea does not provide shell access.
|
||||||
|
If this is unexpected, please log in with password and setup Gitea under another user.
|
||||||
|
```
|
||||||
|
|
||||||
|
**OR** (if authentication fails):
|
||||||
|
```
|
||||||
|
git@git.jnss.me: Permission denied (publickey).
|
||||||
|
```
|
||||||
|
|
||||||
|
This is normal - it means Gitea SSH server is responding, you just need to add your SSH key.
|
||||||
|
|
||||||
|
**If connection times out**: Port 2222 is blocked or Gitea SSH is not running.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Test 4: SSH Key Setup and Authentication
|
||||||
|
|
||||||
|
**Purpose**: Add SSH key to Gitea and test authentication
|
||||||
|
|
||||||
|
**Step 4.1**: Create Gitea admin account
|
||||||
|
1. Visit `https://git.jnss.me`
|
||||||
|
2. Click "Register" (if registration is enabled) or use initial admin setup
|
||||||
|
3. Create your user account
|
||||||
|
|
||||||
|
**Step 4.2**: Generate SSH key (if needed)
|
||||||
|
```bash
|
||||||
|
# On your local machine
|
||||||
|
ssh-keygen -t ed25519 -C "your_email@example.com"
|
||||||
|
|
||||||
|
# View your public key
|
||||||
|
cat ~/.ssh/id_ed25519.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 4.3**: Add SSH key to Gitea
|
||||||
|
1. Log into Gitea web interface
|
||||||
|
2. Click your profile → Settings
|
||||||
|
3. Click "SSH / GPG Keys" tab
|
||||||
|
4. Click "Add Key"
|
||||||
|
5. Paste your public key (`id_ed25519.pub` contents)
|
||||||
|
6. Give it a name and click "Add Key"
|
||||||
|
|
||||||
|
**Step 4.4**: Test SSH authentication
|
||||||
|
```bash
|
||||||
|
# From your local machine
|
||||||
|
ssh -T -p 2222 git@git.jnss.me
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected result**:
|
||||||
|
```
|
||||||
|
Hi there, <your_username>! You've successfully authenticated with the key named <key_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Test 5: Repository Operations
|
||||||
|
|
||||||
|
**Purpose**: Test actual Git operations over SSH
|
||||||
|
|
||||||
|
**Step 5.1**: Create a test repository in Gitea web interface
|
||||||
|
1. Click "+" → "New Repository"
|
||||||
|
2. Name: `test-repo`
|
||||||
|
3. Click "Create Repository"
|
||||||
|
|
||||||
|
**Step 5.2**: Clone the repository
|
||||||
|
```bash
|
||||||
|
# From your local machine
|
||||||
|
git clone ssh://git@git.jnss.me:2222/your_username/test-repo.git
|
||||||
|
cd test-repo
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected result**: Repository clones successfully
|
||||||
|
|
||||||
|
**Step 5.3**: Make a commit and push
|
||||||
|
```bash
|
||||||
|
# Create a test file
|
||||||
|
echo "# Test Repository" > README.md
|
||||||
|
|
||||||
|
# Commit and push
|
||||||
|
git add README.md
|
||||||
|
git commit -m "Initial commit"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected result**:
|
||||||
|
```
|
||||||
|
Enumerating objects: 3, done.
|
||||||
|
Counting objects: 100% (3/3), done.
|
||||||
|
Writing objects: 100% (3/3), 234 bytes | 234.00 KiB/s, done.
|
||||||
|
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
|
||||||
|
To ssh://git.jnss.me:2222/your_username/test-repo.git
|
||||||
|
* [new branch] main -> main
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 5.4**: Verify in web interface
|
||||||
|
1. Refresh Gitea web UI
|
||||||
|
2. Navigate to `test-repo`
|
||||||
|
3. Verify `README.md` appears
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Test 6: fail2ban Protection
|
||||||
|
|
||||||
|
**Purpose**: Verify SSH brute force protection is active
|
||||||
|
|
||||||
|
**Step 6.1**: Check fail2ban status
|
||||||
|
```bash
|
||||||
|
# On the server
|
||||||
|
ssh root@arch-vps
|
||||||
|
|
||||||
|
# Check gitea-ssh jail
|
||||||
|
fail2ban-client status gitea-ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected result**:
|
||||||
|
```
|
||||||
|
Status for the jail: gitea-ssh
|
||||||
|
|- Filter
|
||||||
|
| |- Currently failed: 0
|
||||||
|
| |- Total failed: 0
|
||||||
|
| `- File list: /var/lib/gitea/log/gitea.log
|
||||||
|
`- Actions
|
||||||
|
|- Currently banned: 0
|
||||||
|
|- Total banned: 0
|
||||||
|
`- Banned IP list:
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 6.2**: Simulate failed authentication (optional)
|
||||||
|
```bash
|
||||||
|
# From your local machine, try connecting with wrong key multiple times
|
||||||
|
ssh -T -p 2222 -i /path/to/wrong/key git@git.jnss.me
|
||||||
|
# Repeat this 5+ times quickly
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 6.3**: Check if IP was banned
|
||||||
|
```bash
|
||||||
|
# On the server
|
||||||
|
fail2ban-client status gitea-ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected result**: Your IP should appear in "Currently banned" list after 5 failed attempts.
|
||||||
|
|
||||||
|
**Step 6.4**: Unban yourself (if needed)
|
||||||
|
```bash
|
||||||
|
# On the server
|
||||||
|
fail2ban-client set gitea-ssh unbanip YOUR_IP_ADDRESS
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Test 7: Firewall Rule Persistence
|
||||||
|
|
||||||
|
**Purpose**: Verify firewall rules survive reboot
|
||||||
|
|
||||||
|
**Step 7.1**: Check current rules
|
||||||
|
```bash
|
||||||
|
# On the server
|
||||||
|
ssh root@arch-vps
|
||||||
|
nft list ruleset | grep 2222
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 7.2**: Reboot server
|
||||||
|
```bash
|
||||||
|
# On the server
|
||||||
|
reboot
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 7.3**: After reboot, verify rules are still active
|
||||||
|
```bash
|
||||||
|
# Wait for server to come back up, then SSH in
|
||||||
|
ssh root@arch-vps
|
||||||
|
|
||||||
|
# Check nftables rules again
|
||||||
|
nft list ruleset | grep 2222
|
||||||
|
|
||||||
|
# Verify Gitea SSH still accessible from outside
|
||||||
|
exit
|
||||||
|
|
||||||
|
# From local machine
|
||||||
|
ssh -T -p 2222 git@git.jnss.me
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected result**: Port 2222 rule persists after reboot, SSH access still works.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Issue: Connection timeout on port 2222
|
||||||
|
|
||||||
|
**Symptoms**: `ssh: connect to host git.jnss.me port 2222: Connection timed out`
|
||||||
|
|
||||||
|
**Diagnosis**:
|
||||||
|
```bash
|
||||||
|
# On server
|
||||||
|
systemctl status gitea # Check if Gitea is running
|
||||||
|
ss -tlnp | grep 2222 # Check if SSH is listening
|
||||||
|
nft list ruleset | grep 2222 # Check firewall rule
|
||||||
|
systemctl status nftables # Check firewall service
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
1. **Gitea not running**: `systemctl start gitea`
|
||||||
|
2. **Firewall rule missing**: Re-run Ansible playbook with Gitea role
|
||||||
|
3. **nftables not running**: `systemctl start nftables`
|
||||||
|
4. **Rule file missing**: Check `/etc/nftables.d/gitea.nft` exists
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Issue: Permission denied (publickey)
|
||||||
|
|
||||||
|
**Symptoms**: SSH connection succeeds but authentication fails
|
||||||
|
|
||||||
|
**Diagnosis**:
|
||||||
|
```bash
|
||||||
|
# Verbose SSH connection
|
||||||
|
ssh -vvv -T -p 2222 git@git.jnss.me
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
1. **SSH key not added to Gitea**: Add your public key in Gitea web UI
|
||||||
|
2. **Wrong SSH key used**: Specify correct key: `ssh -i ~/.ssh/id_ed25519 -T -p 2222 git@git.jnss.me`
|
||||||
|
3. **Key permissions wrong**: `chmod 600 ~/.ssh/id_ed25519`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Issue: fail2ban not protecting Gitea
|
||||||
|
|
||||||
|
**Symptoms**: `fail2ban-client status gitea-ssh` shows jail doesn't exist
|
||||||
|
|
||||||
|
**Diagnosis**:
|
||||||
|
```bash
|
||||||
|
# Check if filter exists
|
||||||
|
ls -la /etc/fail2ban/filter.d/gitea-ssh.conf
|
||||||
|
|
||||||
|
# Check if jail is configured
|
||||||
|
grep -A 10 "gitea-ssh" /etc/fail2ban/jail.local
|
||||||
|
|
||||||
|
# Check fail2ban logs
|
||||||
|
journalctl -u fail2ban | grep gitea
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
1. **Jail not configured**: Re-run Ansible playbook with Gitea role
|
||||||
|
2. **fail2ban not running**: `systemctl start fail2ban`
|
||||||
|
3. **Log file not found**: Check Gitea is logging to `/var/lib/gitea/log/gitea.log`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Issue: Git clone works but push fails
|
||||||
|
|
||||||
|
**Symptoms**: Can clone but `git push` gives permission error
|
||||||
|
|
||||||
|
**Diagnosis**:
|
||||||
|
- Check repository permissions in Gitea web UI
|
||||||
|
- Verify you have write access to the repository
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
1. **Not repository owner**: Ask owner to give you write access
|
||||||
|
2. **Repository is archived**: Unarchive in settings
|
||||||
|
3. **Branch protected**: Check branch protection rules
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verification Checklist
|
||||||
|
|
||||||
|
Use this checklist to verify your Gitea deployment:
|
||||||
|
|
||||||
|
- [ ] Gitea web interface accessible at `https://git.jnss.me`
|
||||||
|
- [ ] Port 2222 accessible from external network (`nc -zv git.jnss.me 2222`)
|
||||||
|
- [ ] SSH connection succeeds (`ssh -T -p 2222 git@git.jnss.me`)
|
||||||
|
- [ ] SSH key added to Gitea account
|
||||||
|
- [ ] SSH authentication works (shows username in response)
|
||||||
|
- [ ] Can clone repository via SSH
|
||||||
|
- [ ] Can push commits to repository
|
||||||
|
- [ ] nftables rule for port 2222 exists and is active
|
||||||
|
- [ ] fail2ban jail `gitea-ssh` is running
|
||||||
|
- [ ] Gitea service auto-starts on boot
|
||||||
|
- [ ] nftables rules persist after reboot
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Post-Deployment Configuration
|
||||||
|
|
||||||
|
### Disable Public Registration (Recommended)
|
||||||
|
|
||||||
|
If you don't want anyone to create accounts:
|
||||||
|
|
||||||
|
1. Edit `host_vars/arch-vps/main.yml` or `group_vars/production/main.yml`
|
||||||
|
2. Add:
|
||||||
|
```yaml
|
||||||
|
gitea_disable_registration: true
|
||||||
|
```
|
||||||
|
3. Re-run playbook:
|
||||||
|
```bash
|
||||||
|
ansible-playbook -i inventory/hosts.yml rick-infra.yml --tags gitea --limit arch-vps
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configure Email (Optional)
|
||||||
|
|
||||||
|
For password resets and notifications, configure SMTP:
|
||||||
|
|
||||||
|
1. Edit Gitea configuration directly:
|
||||||
|
```bash
|
||||||
|
ssh root@arch-vps
|
||||||
|
nano /etc/gitea/app.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Add mailer section:
|
||||||
|
```ini
|
||||||
|
[mailer]
|
||||||
|
ENABLED = true
|
||||||
|
FROM = gitea@jnss.me
|
||||||
|
PROTOCOL = smtps
|
||||||
|
SMTP_ADDR = smtp.example.com
|
||||||
|
SMTP_PORT = 465
|
||||||
|
USER = gitea@jnss.me
|
||||||
|
PASSWD = your_smtp_password
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Restart Gitea:
|
||||||
|
```bash
|
||||||
|
systemctl restart gitea
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enable Actions/CI (Optional)
|
||||||
|
|
||||||
|
Gitea Actions provides GitHub Actions-compatible CI/CD:
|
||||||
|
|
||||||
|
1. Edit `roles/gitea/templates/app.ini.j2`
|
||||||
|
2. Add Actions section
|
||||||
|
3. Re-run playbook
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## nftables Architecture
|
||||||
|
|
||||||
|
### Modular Firewall Design
|
||||||
|
|
||||||
|
Rick-infra uses a modular nftables architecture that allows services to self-manage their firewall rules:
|
||||||
|
|
||||||
|
**Load Order:**
|
||||||
|
1. **Base rules** (`/etc/nftables.conf`) - Infrastructure essentials (SSH, HTTP, HTTPS, ICMP)
|
||||||
|
2. **Service rules** (`/etc/nftables.d/[0-8]*.nft`) - Service-specific ports (e.g., `50-gitea.nft`)
|
||||||
|
3. **Drop rule** (`/etc/nftables.d/99-drop.nft`) - Final catch-all drop
|
||||||
|
|
||||||
|
**Key Files:**
|
||||||
|
- `/etc/nftables.conf` - Base infrastructure firewall rules
|
||||||
|
- `/etc/nftables-load.conf` - Loader script that orchestrates rule loading
|
||||||
|
- `/etc/nftables.d/50-gitea.nft` - Gitea SSH port (2222) rule
|
||||||
|
- `/etc/nftables.d/99-drop.nft` - Final drop rule (loaded last)
|
||||||
|
|
||||||
|
**How It Works:**
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ /etc/nftables-load.conf │
|
||||||
|
│ │
|
||||||
|
│ 1. include "/etc/nftables.conf" │
|
||||||
|
│ └─> Allow: SSH(22), HTTP(80), HTTPS(443) │
|
||||||
|
│ │
|
||||||
|
│ 2. include "/etc/nftables.d/[0-8]*.nft" │
|
||||||
|
│ └─> 50-gitea.nft: Allow SSH(2222) │
|
||||||
|
│ │
|
||||||
|
│ 3. include "/etc/nftables.d/99-drop.nft" │
|
||||||
|
│ └─> Drop all other traffic │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
This ensures service rules are evaluated **before** the drop rule, allowing each service role to be self-contained.
|
||||||
|
|
||||||
|
## Security Best Practices
|
||||||
|
|
||||||
|
1. **Use strong database password**: Ensure `vault_gitea_db_password` is strong
|
||||||
|
2. **Enable 2FA**: Enable two-factor authentication in Gitea settings
|
||||||
|
3. **Monitor fail2ban**: Regularly check banned IPs: `fail2ban-client status gitea-ssh`
|
||||||
|
4. **Keep updated**: Run security playbook regularly for system updates
|
||||||
|
5. **Review SSH keys**: Periodically audit SSH keys in Gitea user accounts
|
||||||
|
6. **Backup repositories**: Regular backups of `/var/lib/gitea/repositories`
|
||||||
|
7. **Monitor logs**: Check Gitea logs for suspicious activity: `journalctl -u gitea`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Service management
|
||||||
|
systemctl status gitea
|
||||||
|
systemctl restart gitea
|
||||||
|
journalctl -u gitea -f
|
||||||
|
|
||||||
|
# Firewall
|
||||||
|
nft list ruleset | grep 2222
|
||||||
|
systemctl restart nftables
|
||||||
|
cat /etc/nftables.d/50-gitea.nft
|
||||||
|
|
||||||
|
# fail2ban
|
||||||
|
fail2ban-client status gitea-ssh
|
||||||
|
fail2ban-client get gitea-ssh banned
|
||||||
|
fail2ban-client set gitea-ssh unbanip IP_ADDRESS
|
||||||
|
|
||||||
|
# Network
|
||||||
|
ss -tlnp | grep 2222
|
||||||
|
nc -zv git.jnss.me 2222
|
||||||
|
|
||||||
|
# SSH testing
|
||||||
|
ssh -T -p 2222 git@git.jnss.me
|
||||||
|
ssh -vvv -T -p 2222 git@git.jnss.me # Verbose mode
|
||||||
|
|
||||||
|
# Git operations
|
||||||
|
git clone ssh://git@git.jnss.me:2222/user/repo.git
|
||||||
|
git remote add origin ssh://git@git.jnss.me:2222/user/repo.git
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Rick-Infra Gitea Deployment Guide**
|
||||||
|
Self-contained Git service with automatic firewall and security management.
|
||||||
@@ -88,31 +88,42 @@ ssh root@your-vps "journalctl -u sshd | grep -i 'failed\|invalid'"
|
|||||||
|
|
||||||
### Firewall Configuration
|
### Firewall Configuration
|
||||||
|
|
||||||
#### nftables Firewall Rules
|
#### Modular nftables Architecture
|
||||||
|
|
||||||
|
Rick-infra uses a **modular firewall architecture** that enables self-contained service roles:
|
||||||
|
|
||||||
|
**Structure:**
|
||||||
|
```
|
||||||
|
/etc/nftables.conf Base infrastructure rules (SSH, HTTP, HTTPS)
|
||||||
|
/etc/nftables-load.conf Orchestration script (loads rules in order)
|
||||||
|
/etc/nftables.d/
|
||||||
|
├── 50-gitea.nft Service-specific rules (Gitea SSH port 2222)
|
||||||
|
└── 99-drop.nft Final drop rule (loaded last)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Load Order:**
|
||||||
|
1. Base infrastructure rules (always allowed)
|
||||||
|
2. Service-specific rules (00-98 prefix)
|
||||||
|
3. Final drop rule (99-drop.nft)
|
||||||
|
|
||||||
|
**Example: Current Ruleset**
|
||||||
```bash
|
```bash
|
||||||
# Deployed firewall configuration
|
|
||||||
table inet filter {
|
table inet filter {
|
||||||
chain input {
|
chain input {
|
||||||
type filter hook input priority 0; policy drop;
|
type filter hook input priority 0; policy drop;
|
||||||
|
|
||||||
# Allow loopback traffic
|
# Base infrastructure rules
|
||||||
iifname "lo" accept
|
iif "lo" accept
|
||||||
|
|
||||||
# Allow established connections
|
|
||||||
ct state established,related accept
|
ct state established,related accept
|
||||||
|
tcp dport 22 ct state new accept
|
||||||
# Allow SSH (rate limited)
|
tcp dport {80, 443} ct state new accept
|
||||||
tcp dport 22 ct state new limit rate 5/minute accept
|
|
||||||
|
|
||||||
# Allow HTTP/HTTPS
|
|
||||||
tcp dport {80, 443} accept
|
|
||||||
|
|
||||||
# Allow ICMP (rate limited)
|
|
||||||
icmp type echo-request limit rate 1/second accept
|
icmp type echo-request limit rate 1/second accept
|
||||||
|
|
||||||
# Log dropped packets
|
# Service-specific rules (loaded from /etc/nftables.d/)
|
||||||
log prefix "DROPPED: " drop
|
tcp dport 2222 ct state new accept comment "Gitea SSH (Port 2222)"
|
||||||
|
|
||||||
|
# Final drop rule (99-drop.nft)
|
||||||
|
counter drop comment "Drop all other traffic"
|
||||||
}
|
}
|
||||||
|
|
||||||
chain forward {
|
chain forward {
|
||||||
@@ -129,15 +140,38 @@ table inet filter {
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Check firewall status
|
# Check firewall status
|
||||||
ssh root@your-vps "nft list ruleset"
|
nft list ruleset
|
||||||
|
|
||||||
# Monitor dropped connections
|
# View service-specific rules
|
||||||
ssh root@your-vps "journalctl -k | grep DROPPED"
|
ls -la /etc/nftables.d/
|
||||||
|
cat /etc/nftables.d/50-gitea.nft
|
||||||
|
|
||||||
# Temporary rule addition (emergency access)
|
# Reload firewall (after manual changes)
|
||||||
ssh root@your-vps "nft add rule inet filter input tcp dport 8080 accept"
|
systemctl restart nftables
|
||||||
|
|
||||||
|
# Test configuration syntax
|
||||||
|
nft -c -f /etc/nftables-load.conf
|
||||||
|
|
||||||
|
# Add service rule (example for future services)
|
||||||
|
# Create /etc/nftables.d/60-newservice.nft with your rules
|
||||||
|
echo 'add rule inet filter input tcp dport 8080 accept comment "New Service"' > /etc/nftables.d/60-newservice.nft
|
||||||
|
systemctl restart nftables
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Adding New Service Ports
|
||||||
|
|
||||||
|
When deploying new services that need firewall access:
|
||||||
|
|
||||||
|
1. Create rule file: `/etc/nftables.d/XX-servicename.nft` (XX = 00-98)
|
||||||
|
2. Add rule: `add rule inet filter input tcp dport PORT accept comment "Service Name"`
|
||||||
|
3. Restart nftables: `systemctl restart nftables`
|
||||||
|
|
||||||
|
**Naming Convention:**
|
||||||
|
- `00-19`: Infrastructure services
|
||||||
|
- `20-79`: Application services
|
||||||
|
- `80-98`: Custom/temporary rules
|
||||||
|
- `99`: Drop rule (reserved)
|
||||||
|
|
||||||
### Intrusion Detection (fail2ban)
|
### Intrusion Detection (fail2ban)
|
||||||
|
|
||||||
#### fail2ban Configuration
|
#### fail2ban Configuration
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Now what?
|
# Now what?
|
||||||
|
|
||||||
- [ ] Redeploy on clean VPS to test playbook
|
- [x] Redeploy on clean VPS to test playbook
|
||||||
- [ ] Must set up mini-vps for sigvild and devigo
|
- [x] Must set up mini-vps for sigvild and devigo
|
||||||
|
|
||||||
- [ ] What gets served on jnss.me?
|
- [ ] What gets served on jnss.me?
|
||||||
- [ ] Backups
|
- [ ] Backups
|
||||||
|
|||||||
@@ -123,23 +123,37 @@
|
|||||||
name: nftables
|
name: nftables
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: Create nftables configuration
|
- name: Create nftables rules directory
|
||||||
|
file:
|
||||||
|
path: /etc/nftables.d
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Create base nftables configuration
|
||||||
copy:
|
copy:
|
||||||
content: |
|
content: |
|
||||||
#!/usr/sbin/nft -f
|
#!/usr/sbin/nft -f
|
||||||
|
|
||||||
# Main firewall table
|
# Flush existing rules for clean slate
|
||||||
|
flush ruleset
|
||||||
|
|
||||||
|
# Main firewall table - Rick-Infra Security
|
||||||
|
# Architecture: Base rules -> Service rules -> Drop rule
|
||||||
table inet filter {
|
table inet filter {
|
||||||
chain input {
|
chain input {
|
||||||
type filter hook input priority 0; policy drop;
|
type filter hook input priority 0; policy drop;
|
||||||
|
|
||||||
|
# ======================================
|
||||||
|
# Base Infrastructure Rules
|
||||||
|
# ======================================
|
||||||
|
|
||||||
# Allow loopback interface
|
# Allow loopback interface
|
||||||
iif "lo" accept
|
iif "lo" accept
|
||||||
|
|
||||||
# Allow established and related connections
|
# Allow established and related connections
|
||||||
ct state established,related accept
|
ct state established,related accept
|
||||||
|
|
||||||
# Allow SSH (port 22)
|
# Allow SSH (port 22) - Infrastructure access
|
||||||
tcp dport 22 ct state new accept
|
tcp dport 22 ct state new accept
|
||||||
|
|
||||||
# Allow HTTP and HTTPS for Caddy reverse proxy
|
# Allow HTTP and HTTPS for Caddy reverse proxy
|
||||||
@@ -148,9 +162,6 @@
|
|||||||
# Allow ping with rate limiting
|
# Allow ping with rate limiting
|
||||||
icmp type echo-request limit rate 1/second accept
|
icmp type echo-request limit rate 1/second accept
|
||||||
icmpv6 type echo-request limit rate 1/second accept
|
icmpv6 type echo-request limit rate 1/second accept
|
||||||
|
|
||||||
# Log and drop everything else
|
|
||||||
counter drop
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chain forward {
|
chain forward {
|
||||||
@@ -165,9 +176,43 @@
|
|||||||
mode: '0755'
|
mode: '0755'
|
||||||
backup: yes
|
backup: yes
|
||||||
register: nft_config_changed
|
register: nft_config_changed
|
||||||
|
|
||||||
|
- name: Create nftables drop rule (loaded last)
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
# Final drop rule - Rick-Infra Security
|
||||||
|
# This file is loaded LAST to drop all unmatched traffic
|
||||||
|
# Service-specific rules in /etc/nftables.d/ are loaded before this
|
||||||
|
|
||||||
|
add rule inet filter input counter drop comment "Drop all other traffic"
|
||||||
|
dest: /etc/nftables.d/99-drop.nft
|
||||||
|
mode: '0644'
|
||||||
|
backup: yes
|
||||||
|
register: nft_drop_changed
|
||||||
|
|
||||||
|
- name: Create nftables loader script
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
#!/usr/sbin/nft -f
|
||||||
|
|
||||||
|
# Rick-Infra nftables loader
|
||||||
|
# Loads rules in correct order: base -> services -> drop
|
||||||
|
|
||||||
|
# Load base infrastructure rules
|
||||||
|
include "/etc/nftables.conf"
|
||||||
|
|
||||||
|
# Load service-specific rules (00-98 range)
|
||||||
|
include "/etc/nftables.d/[0-8]*.nft"
|
||||||
|
|
||||||
|
# Load final drop rule (99-drop.nft)
|
||||||
|
include "/etc/nftables.d/99-drop.nft"
|
||||||
|
dest: /etc/nftables-load.conf
|
||||||
|
mode: '0755'
|
||||||
|
backup: yes
|
||||||
|
register: nft_loader_changed
|
||||||
|
|
||||||
- name: Test nftables configuration syntax
|
- name: Test nftables configuration syntax
|
||||||
command: nft -c -f /etc/nftables.conf
|
command: nft -c -f /etc/nftables-load.conf
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: false
|
failed_when: false
|
||||||
register: nft_test
|
register: nft_test
|
||||||
@@ -177,18 +222,31 @@
|
|||||||
msg: "nftables configuration test failed: {{ nft_test.stderr }}"
|
msg: "nftables configuration test failed: {{ nft_test.stderr }}"
|
||||||
when: nft_test.rc != 0
|
when: nft_test.rc != 0
|
||||||
|
|
||||||
|
- name: Update nftables systemd service to use loader
|
||||||
|
lineinfile:
|
||||||
|
path: /usr/lib/systemd/system/nftables.service
|
||||||
|
regexp: '^ExecStart='
|
||||||
|
line: 'ExecStart=/usr/sbin/nft -f /etc/nftables-load.conf'
|
||||||
|
backup: yes
|
||||||
|
register: nft_service_changed
|
||||||
|
|
||||||
|
- name: Reload systemd daemon if service changed
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
when: nft_service_changed.changed
|
||||||
|
|
||||||
- name: Flush existing nftables rules before applying new configuration
|
- name: Flush existing nftables rules before applying new configuration
|
||||||
command: nft flush ruleset
|
command: nft flush ruleset
|
||||||
failed_when: false
|
failed_when: false
|
||||||
changed_when: false
|
changed_when: false
|
||||||
when: nft_config_changed.changed
|
when: nft_config_changed.changed or nft_drop_changed.changed or nft_loader_changed.changed
|
||||||
|
|
||||||
- name: Enable and start nftables service
|
- name: Enable and start nftables service
|
||||||
systemd:
|
systemd:
|
||||||
name: nftables
|
name: nftables
|
||||||
enabled: yes
|
enabled: yes
|
||||||
state: restarted
|
state: restarted
|
||||||
when: nft_config_changed.changed
|
when: nft_config_changed.changed or nft_drop_changed.changed or nft_loader_changed.changed or nft_service_changed.changed
|
||||||
|
|
||||||
- name: Wait for nftables to be active
|
- name: Wait for nftables to be active
|
||||||
pause:
|
pause:
|
||||||
|
|||||||
@@ -25,13 +25,13 @@
|
|||||||
# name: authentik
|
# name: authentik
|
||||||
# tags: ['authentik', 'sso', 'auth']
|
# tags: ['authentik', 'sso', 'auth']
|
||||||
|
|
||||||
# - name: Deploy Gitea
|
- name: Deploy Gitea
|
||||||
# include_role:
|
|
||||||
# name: gitea
|
|
||||||
# tags: ['gitea', 'git', 'development']
|
|
||||||
|
|
||||||
- name: Deploy Nextcloud
|
|
||||||
include_role:
|
include_role:
|
||||||
name: nextcloud
|
name: gitea
|
||||||
tags: ['nextcloud', 'cloud', 'storage']
|
tags: ['gitea', 'git', 'development']
|
||||||
|
|
||||||
|
# - name: Deploy Nextcloud
|
||||||
|
# include_role:
|
||||||
|
# name: nextcloud
|
||||||
|
# tags: ['nextcloud', 'cloud', 'storage']
|
||||||
|
|
||||||
|
|||||||
@@ -9,15 +9,19 @@ Self-contained Gitea Git service for rick-infra following the established archit
|
|||||||
- ✅ **PostgreSQL integration**: Uses shared PostgreSQL infrastructure
|
- ✅ **PostgreSQL integration**: Uses shared PostgreSQL infrastructure
|
||||||
- ✅ **Caddy integration**: Deploys reverse proxy configuration
|
- ✅ **Caddy integration**: Deploys reverse proxy configuration
|
||||||
- ✅ **Security hardened**: SystemD restrictions and secure defaults
|
- ✅ **Security hardened**: SystemD restrictions and secure defaults
|
||||||
|
- ✅ **Firewall management**: Automatically configures nftables for SSH access
|
||||||
|
- ✅ **fail2ban protection**: Brute force protection for SSH authentication
|
||||||
- ✅ **Production ready**: HTTPS, SSH access, LFS support
|
- ✅ **Production ready**: HTTPS, SSH access, LFS support
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
- **Dependencies**: PostgreSQL infrastructure role
|
- **Dependencies**: PostgreSQL infrastructure role
|
||||||
- **Database**: Self-managed gitea database and user
|
- **Database**: Self-managed gitea database and user
|
||||||
- **Network**: HTTP on :3000, SSH on :2222 (localhost)
|
- **Network**: HTTP on :3000 (localhost), SSH on :2222 (public)
|
||||||
- **Web access**: https://git.domain.com (via Caddy)
|
- **Web access**: https://git.domain.com (via Caddy reverse proxy)
|
||||||
- **SSH access**: ssh://git@git.domain.com:2222
|
- **SSH access**: ssh://git@git.domain.com:2222
|
||||||
|
- **Firewall**: Port 2222 automatically opened via nftables
|
||||||
|
- **Security**: fail2ban monitors and blocks SSH brute force attempts
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
@@ -42,6 +46,9 @@ gitea_db_password: "{{ vault_gitea_db_password }}"
|
|||||||
gitea_app_name: "Gitea: Git with a cup of tea"
|
gitea_app_name: "Gitea: Git with a cup of tea"
|
||||||
gitea_disable_registration: false
|
gitea_disable_registration: false
|
||||||
gitea_enable_lfs: true
|
gitea_enable_lfs: true
|
||||||
|
|
||||||
|
# Firewall and Security
|
||||||
|
gitea_manage_firewall: true # Automatically manage nftables rules
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -56,12 +63,94 @@ gitea_enable_lfs: true
|
|||||||
- Caddy web server (for HTTPS access)
|
- Caddy web server (for HTTPS access)
|
||||||
- Vault password: `vault_gitea_db_password`
|
- 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
|
||||||
|
|
||||||
|
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
|
||||||
|
ssh -T -p 2222 git@git.jnss.me
|
||||||
|
```
|
||||||
|
|
||||||
|
## Firewall and Security
|
||||||
|
|
||||||
|
### Automatic Firewall Management
|
||||||
|
|
||||||
|
The Gitea role automatically manages firewall rules via nftables:
|
||||||
|
|
||||||
|
- **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`
|
||||||
|
|
||||||
|
### fail2ban Protection
|
||||||
|
|
||||||
|
SSH brute force protection is automatically configured:
|
||||||
|
|
||||||
|
- **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
|
||||||
|
|
||||||
|
Check fail2ban status:
|
||||||
|
```bash
|
||||||
|
# Check Gitea SSH jail status
|
||||||
|
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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List active nftables rules
|
||||||
|
nft list ruleset
|
||||||
|
|
||||||
|
# Check if Gitea SSH port is open
|
||||||
|
nft list ruleset | grep 2222
|
||||||
|
|
||||||
|
# Verify from external machine
|
||||||
|
nc -zv git.jnss.me 2222
|
||||||
|
```
|
||||||
|
|
||||||
## Self-Contained Design
|
## Self-Contained Design
|
||||||
|
|
||||||
This role follows rick-infra's self-contained service pattern:
|
This role follows rick-infra's self-contained service pattern:
|
||||||
- Creates its own database and user via PostgreSQL infrastructure
|
- Creates its own database and user via PostgreSQL infrastructure
|
||||||
- Manages its own configuration and data
|
- Manages its own configuration and data
|
||||||
- Deploys its own Caddy reverse proxy config
|
- Deploys its own Caddy reverse proxy config
|
||||||
|
- Manages its own firewall rules and security (nftables, fail2ban)
|
||||||
- Independent lifecycle from other services
|
- Independent lifecycle from other services
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -66,6 +66,13 @@ gitea_require_signin: false
|
|||||||
# SSH settings
|
# SSH settings
|
||||||
gitea_start_ssh_server: true
|
gitea_start_ssh_server: true
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Firewall Configuration
|
||||||
|
# =================================================================
|
||||||
|
|
||||||
|
# Firewall management
|
||||||
|
gitea_manage_firewall: true # Set to false if firewall is managed externally
|
||||||
|
|
||||||
# =================================================================
|
# =================================================================
|
||||||
# Infrastructure Dependencies (Read-only)
|
# Infrastructure Dependencies (Read-only)
|
||||||
# =================================================================
|
# =================================================================
|
||||||
|
|||||||
@@ -15,4 +15,16 @@
|
|||||||
systemd:
|
systemd:
|
||||||
name: caddy
|
name: caddy
|
||||||
state: reloaded
|
state: reloaded
|
||||||
when: caddy_service_enabled | default(false)
|
when: caddy_service_enabled | default(false)
|
||||||
|
|
||||||
|
- name: reload nftables
|
||||||
|
systemd:
|
||||||
|
name: nftables
|
||||||
|
state: reloaded
|
||||||
|
# Safety: only reload if service is active
|
||||||
|
when: ansible_connection != 'local'
|
||||||
|
|
||||||
|
- name: restart fail2ban
|
||||||
|
systemd:
|
||||||
|
name: fail2ban
|
||||||
|
state: restarted
|
||||||
75
roles/gitea/tasks/fail2ban.yml
Normal file
75
roles/gitea/tasks/fail2ban.yml
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
---
|
||||||
|
# Gitea fail2ban Configuration - Rick-Infra
|
||||||
|
# Protects Gitea SSH from brute force attacks
|
||||||
|
# Integrates with system fail2ban service
|
||||||
|
|
||||||
|
- name: Install fail2ban
|
||||||
|
pacman:
|
||||||
|
name: fail2ban
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create Gitea fail2ban filter
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
# Fail2ban filter for Gitea SSH authentication failures
|
||||||
|
# Rick-Infra: Gitea role
|
||||||
|
|
||||||
|
[Definition]
|
||||||
|
# Match failed authentication attempts in Gitea logs
|
||||||
|
failregex = .*(Failed authentication attempt|authentication failed|Invalid user|Failed login attempt).*from\s+<HOST>
|
||||||
|
.*level=warning.*msg=.*authentication.*failed.*ip=<HOST>
|
||||||
|
|
||||||
|
ignoreregex =
|
||||||
|
dest: /etc/fail2ban/filter.d/gitea-ssh.conf
|
||||||
|
mode: '0644'
|
||||||
|
backup: yes
|
||||||
|
notify: restart fail2ban
|
||||||
|
|
||||||
|
- name: Ensure fail2ban jail.local exists
|
||||||
|
file:
|
||||||
|
path: /etc/fail2ban/jail.local
|
||||||
|
state: touch
|
||||||
|
mode: '0644'
|
||||||
|
modification_time: preserve
|
||||||
|
access_time: preserve
|
||||||
|
|
||||||
|
- name: Add Gitea SSH jail to fail2ban
|
||||||
|
blockinfile:
|
||||||
|
path: /etc/fail2ban/jail.local
|
||||||
|
marker: "# {mark} ANSIBLE MANAGED BLOCK - Gitea SSH"
|
||||||
|
block: |
|
||||||
|
# Gitea SSH Protection - Rick-Infra
|
||||||
|
[gitea-ssh]
|
||||||
|
enabled = true
|
||||||
|
port = {{ gitea_ssh_port }}
|
||||||
|
filter = gitea-ssh
|
||||||
|
logpath = {{ gitea_home }}/log/gitea.log
|
||||||
|
maxretry = 5
|
||||||
|
findtime = 600
|
||||||
|
bantime = 3600
|
||||||
|
banaction = nftables
|
||||||
|
backup: yes
|
||||||
|
notify: restart fail2ban
|
||||||
|
|
||||||
|
- name: Enable and start fail2ban service
|
||||||
|
systemd:
|
||||||
|
name: fail2ban
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Add fail2ban restart handler
|
||||||
|
meta: flush_handlers
|
||||||
|
|
||||||
|
- name: Display fail2ban status for Gitea
|
||||||
|
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
|
||||||
|
|
||||||
|
Check status: fail2ban-client status gitea-ssh
|
||||||
|
|
||||||
|
# Rick-Infra: Self-contained fail2ban protection per role
|
||||||
51
roles/gitea/tasks/firewall.yml
Normal file
51
roles/gitea/tasks/firewall.yml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
# Gitea Firewall Configuration - Rick-Infra
|
||||||
|
# Self-contained firewall management for Gitea SSH access
|
||||||
|
# Opens port 2222 for Gitea's SSH server
|
||||||
|
|
||||||
|
- name: Install nftables (if not present)
|
||||||
|
pacman:
|
||||||
|
name: nftables
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create nftables rules directory
|
||||||
|
file:
|
||||||
|
path: /etc/nftables.d
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Deploy Gitea nftables rules
|
||||||
|
template:
|
||||||
|
src: gitea.nft.j2
|
||||||
|
dest: /etc/nftables.d/50-gitea.nft
|
||||||
|
mode: '0644'
|
||||||
|
notify: reload nftables
|
||||||
|
register: gitea_nft_deployed
|
||||||
|
|
||||||
|
- name: Validate nftables loader configuration
|
||||||
|
command: nft -c -f /etc/nftables-load.conf
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: nft_validation
|
||||||
|
|
||||||
|
- name: Display nftables validation results
|
||||||
|
debug:
|
||||||
|
msg: "{{ 'nftables configuration valid' if nft_validation.rc == 0 else 'nftables validation failed: ' + nft_validation.stderr }}"
|
||||||
|
when: nft_validation is defined
|
||||||
|
|
||||||
|
- name: Enable and start nftables service
|
||||||
|
systemd:
|
||||||
|
name: nftables
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Display Gitea firewall status
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
🔥 Gitea firewall configuration deployed
|
||||||
|
📍 Rule file: /etc/nftables.d/50-gitea.nft
|
||||||
|
🔓 Port opened: {{ gitea_ssh_port }} (Gitea SSH)
|
||||||
|
|
||||||
|
⚠️ Note: nftables will reload automatically via handler
|
||||||
|
|
||||||
|
# Rick-Infra: Self-contained firewall management per role
|
||||||
@@ -16,6 +16,18 @@
|
|||||||
name: gitea
|
name: gitea
|
||||||
state: present
|
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)
|
||||||
|
|
||||||
|
# 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: Install Git
|
- name: Install Git
|
||||||
pacman:
|
pacman:
|
||||||
name: git
|
name: git
|
||||||
|
|||||||
11
roles/gitea/templates/gitea.nft.j2
Normal file
11
roles/gitea/templates/gitea.nft.j2
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Gitea SSH Firewall Rules - Rick-Infra
|
||||||
|
# Generated by Ansible Gitea role
|
||||||
|
# Allows incoming SSH connections on port {{ gitea_ssh_port }}
|
||||||
|
#
|
||||||
|
# This file is loaded BEFORE the final drop rule (99-drop.nft)
|
||||||
|
# Filename: 50-gitea.nft (ensures proper load order)
|
||||||
|
|
||||||
|
# Add Gitea SSH port to the input chain
|
||||||
|
add rule inet filter input tcp dport {{ gitea_ssh_port }} ct state new accept comment "Gitea SSH (Port {{ gitea_ssh_port }})"
|
||||||
|
|
||||||
|
# Rick-Infra: Self-contained firewall rule for Gitea SSH access
|
||||||
Reference in New Issue
Block a user