Headscale VPN Integration - Self-Hosted Tailscale Controler
Headscale VPN Integration
Self-Hosted Tailscale Control Server für sichere Server-zu-Client Verbindungen
1. Überblick & Architektur
Was ist Headscale?
Headscale ist eine Open-Source-Implementierung des Tailscale Control Servers. Es ermöglicht den Betrieb eines vollständig selbst gehosteten VPN-Netzwerks basierend auf WireGuard, ohne Abhängigkeit von Tailscale's Cloud-Diensten.
Anwendungsfall: n8n zu LiteLLM Verbindung
In unserer Infrastruktur verbinden wir einen Ubuntu Server (n8n Workflow-Automation) mit einem Windows Client (LiteLLM/Ollama LLM-Stack) über ein sicheres VPN-Netzwerk.
┌─────────────────────────────────────┐ ┌─────────────────────────────────────┐ │ Ubuntu Server (ssh2.matzka.cloud) │ │ Windows Client (Lokal) │ │ │ │ │ │ ┌─────────────┐ ┌──────────────┐ │ │ ┌──────────────┐ ┌─────────────┐ │ │ │ Headscale │ │ Traefik │ │ │ │ Tailscale │ │ Docker │ │ │ │ v0.27.1 │──│ (Reverse │ │ │ │ (Native) │ │ Stack: │ │ │ │ Port 8080 │ │ Proxy) │ │ │ │ │ │ │ │ │ └─────────────┘ └──────────────┘ │ │ └──────────────┘ │ ┌────────┐ │ │ │ │ │ │ │ │ │ │ Caddy │ │ │ │ ┌─────────────┐ │ │ │ │ │ │ :4000 │ │ │ │ │ Tailscale │ │ │ ◄─────VPN─────► │ │ └────────┘ │ │ │ │ (Client) │ │ │ │ │ │ ┌────────┐ │ │ │ │ 100.64.0.1 │ │ │ │ 100.64.0.3 │ │LiteLLM │ │ │ │ └─────────────┘ │ │ │ │ └────────┘ │ │ │ │ │ │ │ │ ┌────────┐ │ │ │ ┌─────────────┐ │ │ │ │ │ Ollama │ │ │ │ │ n8n │─────────┘ │ │ │ │ :11434 │ │ │ │ │ Workflows │ │ │ │ └────────┘ │ │ │ └─────────────┘ │ │ └─────────────┘ │ └─────────────────────────────────────┘ └─────────────────────────────────────┘ Datenfluss: n8n → http://llm-client:4000 → Tailnet VPN → Windows Host → Docker Caddy → LiteLLM → Ollama
Komponenten-Übersicht
| Komponente | Funktion | Standort |
|---|---|---|
| Headscale | VPN Control Server (koordiniert Verbindungen) | Ubuntu Server |
| Traefik | Reverse Proxy mit SSL-Terminierung | Ubuntu Server |
| Tailscale (Server) | VPN Client auf dem Server | Ubuntu Server |
| Tailscale (Client) | VPN Client (Native Windows) | Windows Client |
| Caddy | Reverse Proxy für Docker Services | Windows Client |
| LiteLLM | LLM API Gateway | Windows Client |
| Ollama | LLM Runtime (Llama 3.1 8B) | Windows Client |
Netzwerk-Adressen
| Host | Tailnet IP | Hostname |
|---|---|---|
| Ubuntu Server | 100.64.0.1 |
server2 |
| Windows Client | 100.64.0.3 |
llm-client |
2. Voraussetzungen
Server-Anforderungen
- Ubuntu 22.04+ oder Debian 12+
- Docker & Docker Compose installiert
- Traefik als Reverse Proxy konfiguriert
- Domain mit DNS-Eintrag (z.B.
vpn.matzka.cloud) - Ports: 443 (HTTPS via Traefik)
Client-Anforderungen
- Windows 10/11 oder Linux
- Tailscale Client installiert
- Ausgehende HTTPS-Verbindungen erlaubt
DNS-Eintrag erstellen
Bevor Sie beginnen, erstellen Sie einen DNS A-Record:
vpn.matzka.cloud → [Server-IP]
Überprüfen Sie den DNS-Eintrag:
dig +short vpn.matzka.cloud A # Erwartete Ausgabe: 188.245.52.235
3. Server-Installation (Headscale)
3.1 Verzeichnisstruktur erstellen
ssh root@ssh2.matzka.cloud
# Verzeichnisse anlegen
sudo mkdir -p /opt/headscale/{config,data,scripts}
cd /opt/headscale
3.2 Docker Compose Konfiguration
Erstellen Sie /opt/headscale/docker-compose.yml:
version: '3.8'
services:
headscale:
image: headscale/headscale:latest
container_name: headscale
restart: unless-stopped
volumes:
- ./config/config.yaml:/etc/headscale/config.yaml:ro
- ./data:/var/lib/headscale
- ./data/acls.yaml:/etc/headscale/acls.yaml:ro
command: serve
environment:
- TZ=Europe/Vienna
healthcheck:
test: ["CMD", "headscale", "health"]
interval: 30s
timeout: 10s
retries: 3
networks:
- frontend
labels:
# Traefik aktivieren
- "traefik.enable=true"
- "traefik.docker.network=frontend"
# HTTPS Router
- "traefik.http.routers.headscale.rule=Host(`vpn.matzka.cloud`)"
- "traefik.http.routers.headscale.entrypoints=websecure"
- "traefik.http.routers.headscale.tls=true"
- "traefik.http.routers.headscale.tls.certresolver=letsencrypt"
- "traefik.http.routers.headscale.service=headscale"
# HTTP Redirect
- "traefik.http.routers.headscale-http.rule=Host(`vpn.matzka.cloud`)"
- "traefik.http.routers.headscale-http.entrypoints=web"
- "traefik.http.routers.headscale-http.middlewares=redirect-to-https@docker"
# Service
- "traefik.http.services.headscale.loadbalancer.server.port=8080"
# Redirect Middleware
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true"
networks:
frontend:
external: true
3.3 Headscale Konfiguration
Erstellen Sie /opt/headscale/config/config.yaml:
# Headscale Configuration
# Docs: https://headscale.net/ref/configuration/
# Public URL (via Traefik)
server_url: https://vpn.matzka.cloud
# Listen Adressen (intern)
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 0.0.0.0:9090
# Database
database:
type: sqlite
sqlite:
path: /var/lib/headscale/db.sqlite
# IP-Bereiche für Tailnet
prefixes:
v4: 100.64.0.0/10
v6: fd7a:115c:a1e0::/48
# DNS-Konfiguration
dns:
magic_dns: true
base_domain: matzka.internal
nameservers:
global:
- 1.1.1.1
- 8.8.8.8
# ACL Policy
policy:
path: /etc/headscale/acls.yaml
mode: file
# Logging
log:
level: info
format: text
# DERP Server (für Relay-Verbindungen)
derp:
server:
enabled: false
urls:
- https://controlplane.tailscale.com/derpmap/default
auto_update_enabled: true
update_frequency: 24h
# Noise (WireGuard-basierte Verschlüsselung)
noise:
private_key_path: /var/lib/headscale/noise_private.key
# Unix Socket für CLI
unix_socket: /var/lib/headscale/headscale.sock
unix_socket_permission: "0770"
# TLS wird von Traefik terminiert
tls_cert_path: ""
tls_key_path: ""
# Ephemeral Nodes
ephemeral_node_inactivity_timeout: 30m
# Update Check
disable_check_updates: false
3.4 ACL-Konfiguration (Access Control Lists)
Erstellen Sie /opt/headscale/data/acls.yaml:
{
// Headscale ACL Policy
// Format: HuJSON (JSON mit Kommentaren)
// Gruppen definieren
"groups": {
"group:admins": ["admin@matzka.cloud"]
},
// Tag-Besitzer (muss user@ oder group: sein)
"tagOwners": {
"tag:n8n-server": ["group:admins"],
"tag:llm-client": ["group:admins"]
},
// Access Control Rules
"acls": [
// Erlaubt allen Traffic innerhalb des Tailnets
{
"action": "accept",
"src": ["*"],
"dst": ["*:*"]
}
],
// SSH-Regeln (optional)
"ssh": []
}
3.5 Headscale starten
# Container starten cd /opt/headscale docker compose up -d # Logs prüfen docker logs headscale # Erwartete Ausgabe: # INF Starting Headscale version=v0.27.1 # INF listening and serving HTTP on: 0.0.0.0:8080
3.6 User erstellen
# User (Namespace) erstellen docker exec headscale headscale users create matzka-cloud # User auflisten docker exec headscale headscale users list # Ausgabe: # ID | Name | Username | Email | Created # 1 | | matzka-cloud | | 2026-01-10 18:55:36
3.7 Tailscale auf Server installieren
# Tailscale installieren curl -fsSL https://tailscale.com/install.sh | sh # Pre-Auth Key für Server generieren (1 Stunde gültig) docker exec headscale headscale preauthkeys create \ --user 1 \ --expiration 1h \ --reusable=false # Ausgabe: <YOUR_PREAUTH_KEY> # Server mit Headscale verbinden tailscale up \ --login-server=https://vpn.matzka.cloud \ --authkey=<YOUR_PREAUTH_KEY> \ --accept-routes # Status prüfen tailscale status # Ausgabe: 100.64.0.1 server2 matzka-cloud linux -
4. Traefik Integration
Warum Traefik?
- Automatisches SSL: Let's Encrypt Zertifikate werden automatisch generiert
- Standard-Port 443: Funktioniert auch aus restriktiven Netzwerken
- Konsistenz: Alle Services nutzen denselben Reverse Proxy
Routing-Architektur
Internet
│
▼
┌─────────────────────────────────────────────┐
│ Traefik (Port 443) │
│ │
│ vpn.matzka.cloud → headscale:8080 │
│ n8n.matzka.cloud → n8n:5678 │
│ auth.matzka.cloud → authentik:9000 │
│ ... │
└─────────────────────────────────────────────┘
│
▼
┌─────────────────┐
│ Headscale │
│ Port 8080 │
└─────────────────┘
Traefik Labels erklärt
| Label | Funktion |
|---|---|
traefik.enable=true |
Aktiviert Traefik für diesen Container |
traefik.docker.network=frontend |
Verwendet das frontend-Netzwerk |
traefik.http.routers.headscale.rule |
Routing-Regel (Host-basiert) |
traefik.http.routers.headscale.tls.certresolver |
Let's Encrypt Zertifikat-Resolver |
traefik.http.services.headscale.loadbalancer.server.port |
Interner Port des Containers |
5. Client-Setup (Tailscale)
5.1 Pre-Auth Key generieren
Auf dem Server ausführen:
# Pre-Auth Key für Client generieren (7 Tage gültig) docker exec headscale headscale preauthkeys create \ --user 1 \ --expiration 168h \ --reusable=false # Ausgabe: <YOUR_PREAUTH_KEY>
5.2 Windows: Tailscale Installation
# PowerShell als Administrator # Download Tailscale $installerUrl = "https://pkgs.tailscale.com/stable/tailscale-setup-latest.exe" Invoke-WebRequest -Uri $installerUrl -OutFile "$env:TEMP\tailscale-setup.exe" # Installation Start-Process -FilePath "$env:TEMP\tailscale-setup.exe" -Args "/quiet /norestart" -Wait # Mit Headscale verbinden cd "C:\Program Files\Tailscale" .\tailscale.exe up ` --login-server=https://vpn.matzka.cloud ` --authkey=<YOUR_PREAUTH_KEY> ` --hostname=llm-client # Status prüfen .\tailscale.exe status .\tailscale.exe ip -4
5.3 Linux: Tailscale Installation
# Tailscale installieren curl -fsSL https://tailscale.com/install.sh | sh # Mit Headscale verbinden sudo tailscale up \ --login-server=https://vpn.matzka.cloud \ --authkey=<YOUR_PREAUTH_KEY> \ --hostname=llm-client \ --accept-routes # Status prüfen tailscale status tailscale ip -4
5.4 Server: /etc/hosts aktualisieren
Nach der Client-Verbindung die IP im Server eintragen:
# Client-IP ermitteln docker exec headscale headscale nodes list # /etc/hosts aktualisieren sudo nano /etc/hosts # Zeile hinzufügen: 100.64.0.3 llm-client litellm.matzka.cloud # Test ping llm-client -c 4
5.5 Windows Firewall konfigurieren
# PowerShell als Administrator
# Port 4000 (LiteLLM) erlauben
New-NetFirewallRule -DisplayName "Tailscale to LiteLLM" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 4000 `
-Action Allow `
-Profile Any
# ICMP (Ping) erlauben
New-NetFirewallRule -DisplayName "Tailscale ICMP" `
-Direction Inbound `
-Protocol ICMPv4 `
-Action Allow `
-Profile Any
# Regeln prüfen
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "*Tailscale*"}
6. Administration & Verwaltung
6.1 Nodes verwalten
# Alle Nodes auflisten docker exec headscale headscale nodes list # Beispiel-Ausgabe: # ID | Hostname | Name | User | IP addresses | Connected # 1 | server2 | server2 | matzka-cloud | 100.64.0.1 | online # 2 | llm-client | llm-client | matzka-cloud | 100.64.0.3 | online # Node umbenennen docker exec headscale headscale nodes rename -i 2 --name "windows-llm" # Node löschen docker exec headscale headscale nodes delete -i 2 --force # Node-Details anzeigen docker exec headscale headscale nodes show -i 1
6.2 Tags verwalten
# Tag zu Node hinzufügen docker exec headscale headscale nodes tag -i 1 -t tag:n8n-server docker exec headscale headscale nodes tag -i 2 -t tag:llm-client # Tags prüfen docker exec headscale headscale nodes list # Tags werden in der Ausgabe angezeigt
6.3 Pre-Auth Keys verwalten
# Alle Pre-Auth Keys auflisten docker exec headscale headscale preauthkeys list --user 1 # Neuen Key erstellen (verschiedene Optionen) # Standard (1 Stunde, einmalig) docker exec headscale headscale preauthkeys create --user 1 # 7 Tage gültig docker exec headscale headscale preauthkeys create --user 1 --expiration 168h # Wiederverwendbar (für mehrere Clients) docker exec headscale headscale preauthkeys create --user 1 --expiration 168h --reusable # Ephemeral (Node wird nach Disconnect gelöscht) docker exec headscale headscale preauthkeys create --user 1 --ephemeral # Key mit Tags docker exec headscale headscale preauthkeys create --user 1 --tags tag:llm-client # Key ablaufen lassen docker exec headscale headscale preauthkeys expire --user 1 <KEY>
6.4 User verwalten
# User auflisten docker exec headscale headscale users list # Neuen User erstellen docker exec headscale headscale users create development # User umbenennen docker exec headscale headscale users rename -i 1 --new-name production # User löschen (VORSICHT: Löscht alle Nodes!) docker exec headscale headscale users destroy --force <NAME>
6.5 API Keys (für externe Tools)
# API Key erstellen docker exec headscale headscale apikeys create --expiration 90d # API Keys auflisten docker exec headscale headscale apikeys list # API Key widerrufen docker exec headscale headscale apikeys expire <PREFIX>
6.6 Routes verwalten
# Alle Routes auflisten docker exec headscale headscale routes list # Route aktivieren docker exec headscale headscale routes enable -r <ROUTE_ID> # Route deaktivieren docker exec headscale headscale routes disable -r <ROUTE_ID>
7. ACL-Konfiguration
ACL-Grundlagen
Access Control Lists (ACLs) definieren, welche Nodes miteinander kommunizieren dürfen. Headscale verwendet das HuJSON-Format (JSON mit Kommentaren).
Restriktive ACL (Produktion)
{
// Gruppen
"groups": {
"group:admins": ["admin@matzka.cloud"]
},
// Tag-Besitzer
"tagOwners": {
"tag:n8n-server": ["group:admins"],
"tag:llm-client": ["group:admins"]
},
// Regeln
"acls": [
// n8n → LiteLLM nur auf Port 4000
{
"action": "accept",
"src": ["tag:n8n-server"],
"dst": ["tag:llm-client:4000"]
},
// ICMP für Monitoring
{
"action": "accept",
"src": ["tag:n8n-server"],
"dst": ["tag:llm-client:*"],
"proto": "icmp"
},
// Rückweg für ICMP
{
"action": "accept",
"src": ["tag:llm-client"],
"dst": ["tag:n8n-server:*"],
"proto": "icmp"
}
]
}
Permissive ACL (Entwicklung)
{
"acls": [
// Alles erlauben (nur für Entwicklung!)
{
"action": "accept",
"src": ["*"],
"dst": ["*:*"]
}
]
}
ACL-Syntax Referenz
| Element | Beispiel | Beschreibung |
|---|---|---|
| Wildcard | * |
Alle Nodes |
| Tag | tag:n8n-server |
Nodes mit diesem Tag |
| User | matzka-cloud |
Alle Nodes des Users |
| Gruppe | group:admins |
Alle Nodes der Gruppe |
| Port | tag:web:80,443 |
Spezifische Ports |
| Port-Range | tag:web:1000-2000 |
Port-Bereich |
| Alle Ports | tag:web:* |
Alle Ports |
ACL prüfen und anwenden
# ACL-Syntax prüfen docker exec headscale headscale policy check # Aktuelle ACL anzeigen docker exec headscale headscale policy get # ACL aus Datei laden docker exec headscale headscale policy set --file /etc/headscale/acls.yaml
8. n8n Integration
HTTP Request Node Konfiguration
Für LLM Chat Completions:
Method: POST
URL: http://llm-client:4000/v1/chat/completions
Authentication: Header Auth
Name: Authorization
Value: Bearer sk-your-api-key-here
Body Content Type: JSON
Body:
{
"model": "llama3.1",
"messages": [
{"role": "user", "content": "{{ $json.prompt }}"}
],
"max_tokens": 500
}
Für Embeddings:
Method: POST
URL: http://llm-client:4000/v1/embeddings
Authentication: Header Auth (wie oben)
Body:
{
"model": "nomic-embed-text",
"input": "{{ $json.text }}"
}
Verfügbare Modelle
| Modell | Typ | Verwendung |
|---|---|---|
llama3.1 |
Chat | Chat Completions, Text-Generierung |
nomic-embed-text |
Embedding | RAG, Vektorsuche |
Test-Request
curl -X POST http://llm-client:4000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-matzka-..." \
-d '{"model":"llama3.1","messages":[{"role":"user","content":"Hello"}],"max_tokens":50}'
9. Sicherheit
Implementierte Sicherheitsmaßnahmen
| Ebene | Maßnahme | Status |
|---|---|---|
| API-Authentifizierung | LiteLLM API-Key | Aktiv |
| VPN-Verschlüsselung | WireGuard (Tailscale) | Aktiv |
| Netzwerk-ACLs | Headscale ACLs | Aktiv |
| Firewall | Windows Firewall (nur VPN) | Aktiv |
| Keine öffentliche Exposition | Nur VPN-Zugriff | Gesichert |
API-Key Management
Key-Rotation:
# 1. Neuen Key generieren openssl rand -base64 48 # 2. In .env aktualisieren # 3. LiteLLM neu starten docker-compose restart litellm # 4. In n8n Workflows aktualisieren
Windows Firewall-Regeln
# Konfigurierte Regeln:
# - Port 4000/TCP - LiteLLM API
# - Port 11434/TCP - Ollama API
# - Port 80/TCP - Caddy HTTP
# - Port 443/TCP - Caddy HTTPS
# - ICMP - Ping
# Regeln anzeigen (PowerShell)
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "Docker -*"}
10. Performance
Erwartete Latenz
| Route | Latenz | Details |
|---|---|---|
| n8n → VPN | ~20-40ms | Über Tailscale/Headscale |
| VPN → Docker | <1ms | Lokal auf Windows |
| Docker → LLM | ~50-200ms | LLM Inference Zeit |
| Gesamt | ~100-250ms | Für erste Token |
Ressourcen-Nutzung
Windows Client:
- CPU: <5% (Tailscale minimal)
- RAM: +50MB (Tailscale Service)
- GPU: Unverändert (Ollama nutzt GPU)
Server:
- Headscale: ~50MB RAM, <1% CPU
Gemessene Werte (Ping-Test)
ping llm-client -c 4 # 64 bytes from llm-client (100.64.0.3): icmp_seq=1 ttl=128 time=87.3 ms # 64 bytes from llm-client (100.64.0.3): icmp_seq=2 ttl=128 time=20.4 ms # 64 bytes from llm-client (100.64.0.3): icmp_seq=3 ttl=128 time=20.2 ms # 64 bytes from llm-client (100.64.0.3): icmp_seq=4 ttl=128 time=19.8 ms # --- 0% packet loss, avg ~37ms
11. Troubleshooting
Lessons Learned: Docker Netzwerk-Isolation
Problem: Tailscale als Docker Container konnte nicht auf andere Docker Container zugreifen. Server konnte VPN-Verbindung herstellen (Ping OK), aber Port 4000 war "Connection refused".
Ursache: Docker bridge network isoliert Container. Tailscale Container hatte IP im Tailnet, aber andere Container (LiteLLM, Caddy) waren nur im Docker bridge network erreichbar.
Lösung: Umstellung auf native Windows Tailscale Installation: Tailscale läuft als Windows-Dienst (nicht in Docker), Windows Host ist direkt im Tailnet, Docker Ports sind vom Host aus erreichbar.
11.1 Headscale startet nicht
# Logs prüfen docker logs headscale # Häufige Fehler: # - "Invalid Owner" → ACL-Syntax prüfen (user@, group:, tag:) # - "database locked" → Nur ein Headscale-Prozess erlaubt # - "bind: address already in use" → Port bereits belegt # Konfiguration testen docker exec headscale headscale configtest
11.2 Client kann sich nicht verbinden
# Server-seitig prüfen docker exec headscale headscale nodes list # DNS prüfen dig +short vpn.matzka.cloud # HTTPS erreichbar? curl -I https://vpn.matzka.cloud # Pre-Auth Key gültig? docker exec headscale headscale preauthkeys list --user 1 # Neuen Key erstellen falls abgelaufen docker exec headscale headscale preauthkeys create --user 1 --expiration 168h
11.3 Ping funktioniert nicht
# Beide Nodes online?
docker exec headscale headscale nodes list
# Tailscale Status auf Server
tailscale status
# Tailscale Status auf Client
tailscale status # Linux
& "C:\Program Files\Tailscale\tailscale.exe" status # Windows
# Firewall prüfen (Windows)
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "*Tailscale*"}
# Firewall prüfen (Linux)
sudo ufw status
11.4 Port nicht erreichbar
# Vom Server testen nc -zv llm-client 4000 # Direkt mit IP testen nc -zv 100.64.0.3 4000 # Wenn IP funktioniert aber Hostname nicht: cat /etc/hosts | grep llm-client # Service auf Client läuft? # Windows: netstat -an | findstr 4000 # Linux: ss -tulpn | grep 4000 # Docker-Ports prüfen docker port <container_name>
11.5 Node wechselt IP-Adresse
# Wenn ein Node eine neue IP bekommt: # 1. Alten Node löschen docker exec headscale headscale nodes delete -i <ID> --force # 2. Neuen Pre-Auth Key erstellen docker exec headscale headscale preauthkeys create --user 1 --expiration 168h # 3. Client neu verbinden tailscale up --login-server=https://vpn.matzka.cloud --authkey=<NEW_KEY> # 4. /etc/hosts aktualisieren sudo sed -i 's/100.64.0.2/100.64.0.3/g' /etc/hosts
11.6 Headscale Logs analysieren
# Live-Logs docker logs -f headscale # Letzte 100 Zeilen docker logs --tail 100 headscale # Fehler filtern docker logs headscale 2>&1 | grep -E "(ERR|FTL|error)" # Verbindungsversuche docker logs headscale 2>&1 | grep -i "register"
12. Befehlsreferenz
Headscale CLI Übersicht
| Befehl | Beschreibung |
|---|---|
| User-Verwaltung | |
users list |
Alle User auflisten |
users create <name> |
Neuen User erstellen |
users rename -i <id> --new-name <name> |
User umbenennen |
users destroy <name> |
User löschen |
| Node-Verwaltung | |
nodes list |
Alle Nodes auflisten |
nodes show -i <id> |
Node-Details anzeigen |
nodes delete -i <id> |
Node löschen |
nodes rename -i <id> --name <name> |
Node umbenennen |
nodes tag -i <id> -t <tag> |
Tag zu Node hinzufügen |
| Pre-Auth Keys | |
preauthkeys list --user <id> |
Keys auflisten |
preauthkeys create --user <id> |
Neuen Key erstellen |
preauthkeys expire --user <id> <key> |
Key ablaufen lassen |
| Policy (ACL) | |
policy get |
Aktuelle Policy anzeigen |
policy check |
Policy-Syntax prüfen |
policy set --file <path> |
Policy aus Datei laden |
| Routes | |
routes list |
Alle Routes auflisten |
routes enable -r <id> |
Route aktivieren |
routes disable -r <id> |
Route deaktivieren |
| System | |
health |
Health-Check |
version |
Version anzeigen |
configtest |
Konfiguration testen |
Tailscale CLI Übersicht
| Befehl | Beschreibung |
|---|---|
tailscale up |
Verbindung herstellen |
tailscale down |
Verbindung trennen |
tailscale status |
Status anzeigen |
tailscale ip |
IP-Adresse anzeigen |
tailscale ping <host> |
Tailscale-spezifischer Ping |
tailscale netcheck |
Netzwerk-Diagnose |
tailscale debug |
Debug-Informationen |
Schnellreferenz: Neue Verbindung einrichten
# 1. Pre-Auth Key auf Server erstellen ssh root@ssh2.matzka.cloud docker exec headscale headscale preauthkeys create --user 1 --expiration 168h # 2. Auf Client verbinden # Windows: tailscale up --login-server=https://vpn.matzka.cloud --authkey=<KEY> --hostname=<NAME> # Linux: sudo tailscale up --login-server=https://vpn.matzka.cloud --authkey=<KEY> --hostname=<NAME> # 3. Node-Liste prüfen docker exec headscale headscale nodes list # 4. /etc/hosts auf Server aktualisieren echo "<TAILSCALE_IP> <HOSTNAME>" | sudo tee -a /etc/hosts # 5. Verbindung testen ping <HOSTNAME> nc -zv <HOSTNAME> <PORT>
Zusammenfassung
Erreichtes Ziel
- Stabile VPN-Verbindung zwischen Ubuntu Server und Windows Client
- Unabhängig von dynamischen IPs (stabile Tailnet-IPs)
- Verschlüsselte Verbindung via WireGuard
- Netzwerk-Zugriffskontrolle via ACLs
- 100% Self-Hosted (keine Cloud-Abhängigkeit)
Aktuelle Konfiguration
| Komponente | Wert |
|---|---|
| Headscale URL | https://vpn.matzka.cloud |
| Server IP | 100.64.0.1 (server2) |
| Client IP | 100.64.0.3 (llm-client) |
| LiteLLM Endpoint | http://llm-client:4000 |