152 lines
4.9 KiB
Bash
Executable File
152 lines
4.9 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# ============================================================
|
|
# Jefflix VPN Setup Script
|
|
# Run this on the Netcup RS 8000 server (ssh netcup)
|
|
# ============================================================
|
|
|
|
echo "========================================"
|
|
echo " Jefflix VPN Setup (Headscale/Tailscale)"
|
|
echo "========================================"
|
|
echo ""
|
|
|
|
# --- Phase 1: Backups ---
|
|
echo "[Phase 1] Creating backups..."
|
|
cp /root/cloudflared/config.yml /root/cloudflared/config.yml.backup-jefflix-vpn
|
|
cp /opt/apps/headscale-deploy/config/config.yaml /opt/apps/headscale-deploy/config/config.yaml.backup-jefflix-vpn
|
|
cp -r /root/traefik/config/ /root/traefik/config-backup-jefflix-vpn/ 2>/dev/null || true
|
|
echo " ✓ Backups created"
|
|
|
|
# --- Phase 1b: Create Headscale users ---
|
|
echo ""
|
|
echo "[Phase 1b] Creating Headscale users..."
|
|
docker exec headscale headscale users create server 2>/dev/null || echo " (user 'server' already exists)"
|
|
docker exec headscale headscale users create jefflix 2>/dev/null || echo " (user 'jefflix' already exists)"
|
|
echo " ✓ Users ready"
|
|
|
|
# --- Phase 2: Install Tailscale ---
|
|
echo ""
|
|
echo "[Phase 2] Installing Tailscale..."
|
|
if command -v tailscale &>/dev/null; then
|
|
echo " Tailscale already installed: $(tailscale version)"
|
|
else
|
|
curl -fsSL https://tailscale.com/install.sh | sh
|
|
echo " ✓ Tailscale installed"
|
|
fi
|
|
|
|
# Generate pre-auth key and join tailnet
|
|
echo ""
|
|
echo " Generating pre-auth key..."
|
|
PREAUTH_KEY=$(docker exec headscale headscale preauthkeys create --user server --reusable=false --expiration 1h 2>&1 | tail -1)
|
|
echo " Pre-auth key: $PREAUTH_KEY"
|
|
|
|
echo ""
|
|
echo " Joining tailnet..."
|
|
tailscale up \
|
|
--login-server=https://vpn.jeffemmett.com \
|
|
--authkey="$PREAUTH_KEY" \
|
|
--hostname=netcup-rs8000 \
|
|
--accept-dns=false
|
|
|
|
# Get the Tailscale IP
|
|
TAILSCALE_IP=$(tailscale ip -4)
|
|
echo " ✓ Joined tailnet with IP: $TAILSCALE_IP"
|
|
|
|
# --- Phase 3: Deploy CoreDNS ---
|
|
echo ""
|
|
echo "[Phase 3] Deploying CoreDNS for *.jefflix.lol..."
|
|
mkdir -p /opt/apps/jefflix-dns
|
|
|
|
# Write Corefile with the actual Tailscale IP
|
|
cat > /opt/apps/jefflix-dns/Corefile <<COREFILE_EOF
|
|
jefflix.lol {
|
|
template IN A {
|
|
answer "{{ .Name }} 60 IN A ${TAILSCALE_IP}"
|
|
}
|
|
log
|
|
}
|
|
COREFILE_EOF
|
|
|
|
cat > /opt/apps/jefflix-dns/docker-compose.yml <<COMPOSE_EOF
|
|
services:
|
|
coredns:
|
|
image: coredns/coredns:latest
|
|
container_name: jefflix-dns
|
|
restart: unless-stopped
|
|
command: -conf /etc/coredns/Corefile
|
|
volumes:
|
|
- ./Corefile:/etc/coredns/Corefile:ro
|
|
ports:
|
|
- "${TAILSCALE_IP}:53:53/udp"
|
|
- "${TAILSCALE_IP}:53:53/tcp"
|
|
cap_drop:
|
|
- ALL
|
|
cap_add:
|
|
- NET_BIND_SERVICE
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
COMPOSE_EOF
|
|
|
|
cd /opt/apps/jefflix-dns && docker compose up -d
|
|
echo " ✓ CoreDNS deployed"
|
|
|
|
# Test DNS
|
|
echo ""
|
|
echo " Testing DNS resolution..."
|
|
sleep 2
|
|
DIG_RESULT=$(dig +short @${TAILSCALE_IP} movies.jefflix.lol 2>/dev/null || echo "FAILED")
|
|
if [ "$DIG_RESULT" = "$TAILSCALE_IP" ]; then
|
|
echo " ✓ DNS test passed: movies.jefflix.lol -> $TAILSCALE_IP"
|
|
else
|
|
echo " ⚠ DNS test returned: $DIG_RESULT (expected $TAILSCALE_IP)"
|
|
echo " Check CoreDNS logs: docker logs jefflix-dns"
|
|
fi
|
|
|
|
# --- Phase 4: Configure Headscale split DNS ---
|
|
echo ""
|
|
echo "[Phase 4] Configuring Headscale split DNS..."
|
|
|
|
HEADSCALE_CONFIG="/opt/apps/headscale-deploy/config/config.yaml"
|
|
|
|
# Check if split DNS is already configured
|
|
if grep -q "jefflix.lol" "$HEADSCALE_CONFIG"; then
|
|
echo " Split DNS for jefflix.lol already in config, skipping"
|
|
else
|
|
# Add split DNS section to the nameservers block
|
|
# This uses sed to add the split DNS config after the global nameservers
|
|
sed -i '/nameservers:/,/^[^ ]/ {
|
|
/global:/,/^ [^ ]/ {
|
|
/- 1.0.0.1/a\ split:\n jefflix.lol:\n - '"${TAILSCALE_IP}"'
|
|
}
|
|
}' "$HEADSCALE_CONFIG"
|
|
echo " ✓ Split DNS added to Headscale config"
|
|
fi
|
|
|
|
# Restart Headscale
|
|
cd /opt/apps/headscale-deploy && docker compose restart headscale
|
|
echo " ✓ Headscale restarted"
|
|
sleep 3
|
|
|
|
# Verify Headscale is healthy
|
|
docker exec headscale headscale nodes list >/dev/null 2>&1 && echo " ✓ Headscale healthy" || echo " ⚠ Headscale may need attention"
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo " Setup Complete (Phases 1-4)"
|
|
echo "========================================"
|
|
echo ""
|
|
echo "Server Tailscale IP: $TAILSCALE_IP"
|
|
echo "CoreDNS: running on $TAILSCALE_IP:53"
|
|
echo "Split DNS: jefflix.lol -> $TAILSCALE_IP"
|
|
echo ""
|
|
echo "NEXT STEPS:"
|
|
echo " 1. Connect YOUR device to the tailnet and test:"
|
|
echo " tailscale up --login-server=https://vpn.jeffemmett.com"
|
|
echo " dig movies.jefflix.lol (should return $TAILSCALE_IP)"
|
|
echo " curl http://movies.jefflix.lol (should return Jellyfin)"
|
|
echo ""
|
|
echo " 2. Once confirmed working, run cutover.sh to remove public access"
|
|
echo " 3. Then onboard users with pre-auth keys"
|
|
echo ""
|