Initial commit - NUC server configuration and docs

- CLAUDE.md: Server instructions and service reference
- docs/: Persistent documentation (architecture, guides)
- .artifacts/: Session-generated notes
- playwriter-browser/: Remote browser container config

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-02-01 20:49:20 +00:00
commit 390eda1595
25 changed files with 3664 additions and 0 deletions

279
docs/architecture.md Normal file
View File

@@ -0,0 +1,279 @@
# NUC Infrastructure Architecture
**Date:** 2026-02-01
**Context:** Secure self-hosted infrastructure with Tailscale Funnel for public access and Tailscale mesh for private admin access. Designed to bypass Spanish ISP blocks and handle dynamic IPs.
---
## Architecture Diagram
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ INTERNET │
└─────────────────────────────────────────────────────────────────────────────┘
│ │
│ Public Traffic │ Admin Traffic
▼ ▼
┌───────────────────────────────┐ ┌─────────────────────────────────────┐
│ whyrating.com │ │ TAILSCALE MESH │
│ │ │ │ (encrypted, private) │
│ ▼ │ │ │
│ ┌─────────────────────┐ │ │ ┌───────────┐ ┌───────────┐ │
│ │ Namecheap DNS │ │ │ │ Your Mac │◄──►│ NUC │ │
│ │ (301 redirect) │ │ │ │100.x.x.2 │ │100.x.x.1 │ │
│ └──────────┬──────────┘ │ │ └───────────┘ └───────────┘ │
│ │ │ │ ▲ ▲ │
│ ▼ │ │ │ Anywhere │ │
│ ┌─────────────────────┐ │ │ │ in world │ │
│ │ Tailscale Funnel │ │ └─────────┴────────────────┴─────────┘
│ │ nuc-tailscale.ts.net│◄─────┼────────────────────────┘
│ └──────────┬──────────┘ │
│ │ HTTPS/443 │
└─────────────┼─────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ NUC SERVER │
│ 192.168.1.3 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ SECURITY LAYER │ │
│ │ ┌─────────────┐ │ │
│ │ │ CrowdSec │ ← Blocks malicious IPs, DDoS protection │ │
│ │ │ :8083 │ │ │
│ │ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ COOLIFY (Docker Orchestrator) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ TRAEFIK (Reverse Proxy) │ │ │
│ │ │ Routes by domain │ │ │
│ │ └───────────┬─────────────────┬─────────────────┬─────────────┘ │ │
│ │ │ │ │ │ │
│ │ ▼ ▼ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ PUBLIC WEBSITES │ │ │
│ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
│ │ │ │Homepage │ │ App A │ │ App B │ │ App C │ │ │ │
│ │ │ │ :3000 │ │ :3001 │ │ :3002 │ │ :3003 │ │ │ │
│ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │
│ │ │ (internal ports only, not exposed) │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ PRIVATE SERVICES (Tailscale only) │ │ │
│ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
│ │ │ │Coolify │ │ Gitea │ │ MinIO │ │Postgres │ │ │ │
│ │ │ │ :8000 │ │ :3030 │ │ :9001 │ │ :5432 │ │ │ │
│ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │
│ │ │ │ │ │
│ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
│ │ │ │Authentik│ │ n8n │ │Vaultwrdn│ │ Outline │ │ │ │
│ │ │ │ :9090 │ │ :5678 │ │ :8222 │ │ :3080 │ │ │ │
│ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## Traffic Flows
### Public Website Access
```
User → whyrating.com → Namecheap 301 → nuc-tailscale.ts.net → Tailscale Funnel
→ CrowdSec → Traefik → Container (internal port)
```
### Admin Access (Remote)
```
Your Mac → Tailscale mesh (encrypted) → NUC Tailscale IP (100.x.x.x)
→ Direct access to any port (8000, 22, etc.)
```
### Admin Access (Home Network)
```
Your Mac → Local network → 192.168.1.3 → Any port
```
---
## Component Summary
| Component | Port | Access | Purpose |
|-----------|------|--------|---------|
| **Tailscale Funnel** | 443 | Public | Single internet entry point |
| **CrowdSec** | 8083 | Private | DDoS/attack protection |
| **Traefik** | 80/443 | Internal | Routes domains to containers |
| **Homepage** | 3000 | Via Funnel | Public dashboard |
| **Coolify** | 8000 | Tailscale only | Container management |
| **Databases** | various | Tailscale only | Data storage |
---
## Security Layers
```
┌─────────────────────────────────────────────────────────┐
│ Layer 1: TAILSCALE FUNNEL │
│ • Only entry point from internet │
│ • HTTPS termination │
│ • No open ports on router │
├─────────────────────────────────────────────────────────┤
│ Layer 2: CROWDSEC │
│ • Crowdsourced threat intelligence │
│ • Blocks known malicious IPs │
│ • DDoS mitigation │
├─────────────────────────────────────────────────────────┤
│ Layer 3: TRAEFIK │
│ • Domain-based routing │
│ • Only forwards to valid services │
│ • Rate limiting (configurable) │
├─────────────────────────────────────────────────────────┤
│ Layer 4: DOCKER NETWORK ISOLATION │
│ • Containers can't access each other unless configured │
│ • Databases on separate network from public apps │
├─────────────────────────────────────────────────────────┤
│ Layer 5: TAILSCALE MESH (Admin) │
│ • All admin traffic encrypted │
│ • No admin ports exposed to internet │
│ • Device authentication required │
└─────────────────────────────────────────────────────────┘
```
---
## Dynamic IP Handling
```
ISP Changes IP
┌─────────────┐ auto-update ┌──────────────────────┐
│ NUC detects │ ────────────────► │ Tailscale Coord │
│ new IP │ │ Server │
└─────────────┘ └──────────┬───────────┘
┌──────────────────────────────────────┘
│ broadcasts new location
┌─────────────────────────────────────────────────────────┐
│ UNCHANGED │
│ • Tailscale IP: 100.x.x.x (stable) │
│ • Funnel URL: nuc-tailscale.tail58f5ad.ts.net (stable)│
│ • whyrating.com redirect (stable) │
│ • All tunnels auto-reconnect (~10-30 sec) │
└─────────────────────────────────────────────────────────┘
```
**Key Point:** Your ISP can change your public IP anytime - Tailscale handles this automatically. No DDNS needed.
---
## Access Reference
| From | To | Method |
|------|----|--------|
| **Public users** | Websites | `whyrating.com` or `.ts.net` URL |
| **You (remote)** | NUC admin | `ssh nuc-tailscale` or `http://100.x.x.x:8000` |
| **You (home)** | NUC admin | `ssh nuc` or `http://192.168.1.3:8000` |
| **You (remote)** | Router | SSH jump: `ssh -J nuc-tailscale root@192.168.1.1` |
---
## URLs
| Service | Public URL | Private URL (Tailscale) |
|---------|------------|-------------------------|
| Main site | `whyrating.com` | - |
| Direct Funnel | `nuc-tailscale.tail58f5ad.ts.net` | - |
| Coolify | - | `http://nuc-tailscale:8000` |
| Homepage | Via Funnel :3000 | `http://nuc-tailscale:3000` |
| Gitea | - | `http://nuc-tailscale:3030` |
---
## What's NOT Exposed to Internet
- SSH (22)
- Coolify (8000)
- Databases (5432, 3306)
- MinIO (9000/9001)
- Authentik (9090)
- Router admin (192.168.1.1)
- Any direct ports on router
---
## Coolify Deployment Best Practices
### For Public Apps:
```yaml
services:
myapp:
image: myapp:latest
# NO ports: section - Traefik routes internally
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`myapp.whyrating.com`)"
networks:
- coolify
```
### For Private Apps:
```yaml
services:
mydb:
image: postgres:16
# No traefik labels
# No exposed ports
networks:
- internal # Separate from coolify network
```
---
## Quick Commands
```bash
# Check Tailscale status
tailscale status
# Check Funnel status
ssh nuc "tailscale funnel status"
# Access Coolify remotely
open http://nuc-tailscale:8000
# SSH to NUC from anywhere
ssh nuc-tailscale
# Check CrowdSec decisions
ssh nuc "docker exec crowdsec-* cscli decisions list"
```
---
## Related Documents
- `.artifacts/2026-02-01_19-11_domain-pre-purchase-check-guide.md` - Domain checking before purchase
- `.artifacts/domain-check.sh` - Script to check domains for blocks
- `CLAUDE.md` - Full NUC server documentation
---
## Why This Architecture?
1. **Spanish ISP Blocks** - Cloudflare shared IPs are blocked during LaLiga matches. Tailscale Funnel uses different infrastructure.
2. **Dynamic IP** - No need for DDNS or port forwarding. Tailscale handles IP changes automatically.
3. **Security** - Zero ports exposed on router. All admin via encrypted Tailscale mesh.
4. **Simplicity** - Single entry point (Funnel), single orchestrator (Coolify), single security layer (CrowdSec).