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:
279
docs/architecture.md
Normal file
279
docs/architecture.md
Normal 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).
|
||||
Reference in New Issue
Block a user