Add operational documentation

CloudBeaver database manager guide, Ecija intranet deployment,
Gitea-Coolify auto-deploy and integration docs, monitoring setup
with presentation, remote access guide, security architecture,
and Turbostarter deployment procedure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-02-18 15:17:18 +01:00
parent 1aa7ebcde3
commit 8b503a549c
9 changed files with 3817 additions and 0 deletions

329
docs/security.md Normal file
View File

@@ -0,0 +1,329 @@
# Security Configuration
Comprehensive security hardening for NUC server and OpenWrt router.
## Security Architecture
```
Internet
┌─────────────────────────────────────┐
│ OpenWrt Router (192.168.1.1) │
│ ├─ CrowdSec Bouncer (threat intel) │
│ ├─ Firewall (WAN: REJECT default) │
│ └─ SSH: key-only authentication │
└─────────────────────────────────────┘
│ Only allowed: WireGuard (51820/udp)
┌─────────────────────────────────────┐
│ NUC Server (192.168.1.3) │
│ ├─ CrowdSec (threat intelligence) │
│ ├─ fail2ban (brute force protect) │
│ ├─ SSH: key-only + 24h ban │
│ ├─ Unattended upgrades (auto) │
│ └─ Tailscale Funnel (HTTPS only) │
└─────────────────────────────────────┘
```
## External Attack Surface
| Port | Service | Protection |
|------|---------|------------|
| 51820/udp | WireGuard VPN | Cryptographic auth only |
| Tailscale Funnel | HTTPS services | Tailscale auth + TLS |
| Everything else | Blocked | Router firewall DROP |
**Not exposed to internet:**
- SSH (22)
- Router admin (80/443)
- Coolify (8000)
- All Docker services
---
## Router Security (OpenWrt)
### SSH Configuration
| Setting | Value |
|---------|-------|
| Password auth | Disabled |
| Root password auth | Disabled |
| Auth method | SSH key only |
| Port | 22 (LAN only) |
**Config:** `/etc/config/dropbear`
```bash
# Verify settings
uci get dropbear.@dropbear[0].PasswordAuth # off
uci get dropbear.@dropbear[0].RootPasswordAuth # off
```
### Firewall (fw4/nftables)
**WAN Zone Policy:**
- Input: REJECT
- Forward: REJECT
- Output: ACCEPT
**Allowed WAN Input:**
- DHCP (port 68)
- ICMPv6 (limited)
- WireGuard (51820/udp)
```bash
# View WAN input rules
ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1 "nft list chain inet fw4 input_wan"
```
### CrowdSec Firewall Bouncer
Blocks malicious IPs using threat intelligence from NUC CrowdSec.
| Setting | Value |
|---------|-------|
| API URL | http://192.168.1.3:8083/ |
| Update frequency | 10s |
| Action | DROP + log |
| Interfaces | wan, wan6 |
**Config:** `/etc/config/crowdsec`
```bash
# Check bouncer status
ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1 "/etc/init.d/crowdsec-firewall-bouncer status"
# View blocked IPs
ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1 "nft list set ip crowdsec crowdsec_blocklist"
# Check logs
ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1 "logread | grep crowdsec"
```
---
## NUC Security
### SSH Configuration
| Setting | Value |
|---------|-------|
| Password auth | Disabled |
| Auth method | SSH key only |
| Port | 22 |
**Config:** `/etc/ssh/sshd_config`
```bash
# Verify
grep "PasswordAuthentication" /etc/ssh/sshd_config
# PasswordAuthentication no
```
### fail2ban
Protects SSH from brute force attacks.
| Setting | Value |
|---------|-------|
| Max retries | 3 |
| Ban time | 24 hours |
| Find time | 10 minutes |
| Ignored IPs | LAN (192.168.1.0/24), Tailscale (100.0.0.0/8) |
**Config:** `/etc/fail2ban/jail.local`
```bash
# Check status
sudo fail2ban-client status sshd
# View banned IPs
sudo fail2ban-client status sshd | grep "Banned IP"
# Unban an IP
sudo fail2ban-client set sshd unbanip <IP>
```
### CrowdSec (Docker)
Central threat intelligence hub.
| Property | Value |
|----------|-------|
| Container | crowdsec-mwc4ocock400goww8s4k44o8 |
| API Port | 8083 |
| Dashboard | http://192.168.1.3:8083 |
```bash
# List registered bouncers
docker exec crowdsec-mwc4ocock400goww8s4k44o8 cscli bouncers list
# View decisions (blocked IPs)
docker exec crowdsec-mwc4ocock400goww8s4k44o8 cscli decisions list
# View alerts
docker exec crowdsec-mwc4ocock400goww8s4k44o8 cscli alerts list
```
### Unattended Upgrades
Automatic security and system updates.
| Setting | Value |
|---------|-------|
| Security updates | Enabled |
| Regular updates | Enabled |
| Auto-reboot | 4:00 AM if needed |
| Cleanup unused | Enabled |
**Config:** `/etc/apt/apt.conf.d/50unattended-upgrades-local`
```bash
# Check status
sudo systemctl status unattended-upgrades
# View logs
cat /var/log/unattended-upgrades/unattended-upgrades.log
# Manual dry-run
sudo unattended-upgrade --dry-run --debug
```
---
## Access Methods
### From LAN (Home Network)
| Service | Access |
|---------|--------|
| NUC SSH | `ssh nuc` or `ssh 192.168.1.3` |
| Router SSH | `ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1` |
| Router Admin | http://192.168.1.1 |
| Coolify | http://192.168.1.3:8000 |
### From Remote (Via Tailscale)
| Service | Access |
|---------|--------|
| NUC SSH | `ssh nuc-tailscale` |
| Full LAN | Via subnet router (192.168.1.0/24) |
| Grafana | https://nuc-tailscale.tail58f5ad.ts.net:3002 |
### From Remote (Via WireGuard)
```bash
# Connect
sudo wg-quick up ~/wireguard/home-vpn.conf
# Then access LAN normally
ssh 192.168.1.3
```
---
## SSH Keys
| Key | Location | Used For |
|-----|----------|----------|
| NUC/Router key | `~/.ssh/id_ed25519_nuc` | SSH to NUC and OpenWrt |
```bash
# Test NUC key auth
ssh -i ~/.ssh/id_ed25519_nuc -o BatchMode=yes alezmad@192.168.1.3 "echo OK"
# Test router key auth
ssh -i ~/.ssh/id_ed25519_nuc -o BatchMode=yes root@192.168.1.1 "echo OK"
```
---
## Security Checklist
### Router
- [x] SSH password auth disabled
- [x] LuCI not exposed on WAN
- [x] WAN input policy: REJECT
- [x] CrowdSec bouncer active
- [x] Only WireGuard port open (51820)
- [x] UPnP disabled
### NUC
- [x] SSH password auth disabled
- [x] fail2ban protecting SSH
- [x] CrowdSec running (Docker)
- [x] Unattended upgrades enabled
- [x] No services exposed to WAN directly
### Network
- [x] Tailscale for remote access
- [x] WireGuard as backup VPN
- [x] DuckDNS for dynamic IP
---
## Incident Response
### If Brute Force Detected
```bash
# Check fail2ban bans
sudo fail2ban-client status sshd
# Check CrowdSec alerts
docker exec crowdsec-mwc4ocock400goww8s4k44o8 cscli alerts list
# View auth logs
sudo tail -100 /var/log/auth.log | grep -i fail
```
### If Compromised IP Needs Blocking
```bash
# Add manual ban in CrowdSec (blocks on router too)
docker exec crowdsec-mwc4ocock400goww8s4k44o8 cscli decisions add --ip <IP> --duration 24h --reason "manual block"
# Or block directly on router
ssh -i ~/.ssh/id_ed25519_nuc root@192.168.1.1 "nft add element ip crowdsec crowdsec_blocklist { <IP> }"
```
### If Locked Out
1. **Physical access to NUC:** Connect monitor/keyboard
2. **Router:** Reset button (hold 10s) restores defaults
3. **Tailscale:** Still works if NUC is running
---
## Monitoring
| What | How |
|------|-----|
| SSH attempts | `sudo tail -f /var/log/auth.log` |
| fail2ban activity | `sudo fail2ban-client status sshd` |
| CrowdSec decisions | `docker exec crowdsec-... cscli decisions list` |
| Router firewall logs | `ssh root@192.168.1.1 "logread \| grep crowdsec"` |
| Blocked connections | `ssh root@192.168.1.1 "nft list set ip crowdsec crowdsec_blocklist"` |
---
## Regular Maintenance
### Weekly
- Check fail2ban status: `sudo fail2ban-client status`
- Review CrowdSec alerts: `docker exec crowdsec-... cscli alerts list`
### Monthly
- Verify unattended-upgrades working: `cat /var/log/unattended-upgrades/*.log`
- Check for OpenWrt updates: `opkg update && opkg list-upgradable`
- Review SSH auth logs for anomalies
### After Security Incident
1. Check all logs (auth, CrowdSec, fail2ban)
2. Rotate SSH keys if needed
3. Update CrowdSec scenarios
4. Review firewall rules