refactor(deployment): Remove WireGuard VPN dependency and restore public service access
Remove WireGuard integration from production deployment to simplify infrastructure: - Remove docker-compose-direct-access.yml (VPN-bound services) - Remove VPN-only middlewares from Grafana, Prometheus, Portainer - Remove WireGuard middleware definitions from Traefik - Remove WireGuard IPs (10.8.0.0/24) from Traefik forwarded headers All monitoring services now publicly accessible via subdomains: - grafana.michaelschiemer.de (with Grafana native auth) - prometheus.michaelschiemer.de (with Basic Auth) - portainer.michaelschiemer.de (with Portainer native auth) All services use Let's Encrypt SSL certificates via Traefik.
This commit is contained in:
206
deployment/scripts/cleanup-old-wireguard.sh
Executable file
206
deployment/scripts/cleanup-old-wireguard.sh
Executable file
@@ -0,0 +1,206 @@
|
||||
#!/bin/bash
|
||||
# Cleanup Old WireGuard Docker Setup
|
||||
# Purpose: Remove old WireGuard Docker stack and CoreDNS before migrating to host-based setup
|
||||
# WARNING: This will stop and remove the old VPN setup!
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# Configuration
|
||||
# ========================================
|
||||
|
||||
DEPLOYMENT_DIR="/home/michael/dev/michaelschiemer/deployment"
|
||||
WIREGUARD_STACK_DIR="${DEPLOYMENT_DIR}/stacks/wireguard"
|
||||
COREDNS_STACK_DIR="${DEPLOYMENT_DIR}/stacks/coredns"
|
||||
ARCHIVE_DIR="${DEPLOYMENT_DIR}/wireguard-docker-archive-$(date +%Y%m%d)"
|
||||
|
||||
# ========================================
|
||||
# Pre-flight Checks
|
||||
# ========================================
|
||||
|
||||
print_info "WireGuard Docker Setup Cleanup Script"
|
||||
echo ""
|
||||
print_warning "This script will:"
|
||||
echo " - Stop WireGuard Docker container"
|
||||
echo " - Stop CoreDNS container (if exists)"
|
||||
echo " - Archive old configuration"
|
||||
echo " - Remove Docker stacks"
|
||||
echo ""
|
||||
print_warning "VPN access will be lost until new host-based setup is deployed!"
|
||||
echo ""
|
||||
read -p "Continue? (type 'yes' to proceed): " -r
|
||||
if [[ ! $REPLY == "yes" ]]; then
|
||||
print_info "Aborted by user"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ========================================
|
||||
# Stop Docker Containers
|
||||
# ========================================
|
||||
|
||||
print_info "Stopping WireGuard Docker container..."
|
||||
if [ -d "$WIREGUARD_STACK_DIR" ]; then
|
||||
cd "$WIREGUARD_STACK_DIR"
|
||||
if [ -f "docker-compose.yml" ]; then
|
||||
docker-compose down || print_warning "WireGuard container already stopped or not found"
|
||||
fi
|
||||
else
|
||||
print_warning "WireGuard stack directory not found: $WIREGUARD_STACK_DIR"
|
||||
fi
|
||||
|
||||
print_info "Stopping CoreDNS Docker container (if exists)..."
|
||||
if [ -d "$COREDNS_STACK_DIR" ]; then
|
||||
cd "$COREDNS_STACK_DIR"
|
||||
if [ -f "docker-compose.yml" ]; then
|
||||
docker-compose down || print_warning "CoreDNS container already stopped or not found"
|
||||
fi
|
||||
else
|
||||
print_info "CoreDNS stack directory not found (may not have existed)"
|
||||
fi
|
||||
|
||||
# ========================================
|
||||
# Archive Old Configuration
|
||||
# ========================================
|
||||
|
||||
print_info "Creating archive of old configuration..."
|
||||
mkdir -p "$ARCHIVE_DIR"
|
||||
|
||||
# Archive WireGuard stack
|
||||
if [ -d "$WIREGUARD_STACK_DIR" ]; then
|
||||
print_info "Archiving WireGuard stack..."
|
||||
cp -r "$WIREGUARD_STACK_DIR" "$ARCHIVE_DIR/wireguard-stack"
|
||||
print_success "WireGuard stack archived to: $ARCHIVE_DIR/wireguard-stack"
|
||||
fi
|
||||
|
||||
# Archive CoreDNS stack
|
||||
if [ -d "$COREDNS_STACK_DIR" ]; then
|
||||
print_info "Archiving CoreDNS stack..."
|
||||
cp -r "$COREDNS_STACK_DIR" "$ARCHIVE_DIR/coredns-stack"
|
||||
print_success "CoreDNS stack archived to: $ARCHIVE_DIR/coredns-stack"
|
||||
fi
|
||||
|
||||
# Archive old Ansible files
|
||||
print_info "Archiving old Ansible playbooks..."
|
||||
if [ -d "${DEPLOYMENT_DIR}/wireguard-old" ]; then
|
||||
cp -r "${DEPLOYMENT_DIR}/wireguard-old" "$ARCHIVE_DIR/ansible-old"
|
||||
fi
|
||||
|
||||
# Archive nftables templates
|
||||
if [ -f "${DEPLOYMENT_DIR}/ansible/templates/wireguard-nftables.nft.j2" ]; then
|
||||
mkdir -p "$ARCHIVE_DIR/ansible-templates"
|
||||
cp "${DEPLOYMENT_DIR}/ansible/templates/wireguard-nftables.nft.j2" "$ARCHIVE_DIR/ansible-templates/"
|
||||
fi
|
||||
|
||||
# Create archive summary
|
||||
cat > "$ARCHIVE_DIR/ARCHIVE_INFO.txt" <<EOF
|
||||
WireGuard Docker Setup Archive
|
||||
Created: $(date)
|
||||
|
||||
This archive contains the old WireGuard Docker-based setup that was replaced
|
||||
with a host-based WireGuard configuration.
|
||||
|
||||
Contents:
|
||||
- wireguard-stack/: Docker Compose stack for WireGuard
|
||||
- coredns-stack/: Docker Compose stack for CoreDNS (if existed)
|
||||
- ansible-old/: Old Ansible playbooks and configs
|
||||
- ansible-templates/: Old nftables templates
|
||||
|
||||
To restore old setup (NOT RECOMMENDED):
|
||||
1. Stop new host-based WireGuard: systemctl stop wg-quick@wg0
|
||||
2. Copy stacks back: cp -r wireguard-stack ../stacks/
|
||||
3. Start container: cd ../stacks/wireguard && docker-compose up -d
|
||||
|
||||
For new host-based setup, see:
|
||||
- deployment/wireguard/README.md
|
||||
- deployment/ansible/playbooks/setup-wireguard-host.yml
|
||||
EOF
|
||||
|
||||
print_success "Archive created at: $ARCHIVE_DIR"
|
||||
|
||||
# ========================================
|
||||
# Remove Docker Stacks
|
||||
# ========================================
|
||||
|
||||
print_info "Removing old Docker stacks..."
|
||||
|
||||
read -p "Remove WireGuard Docker stack directory? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
if [ -d "$WIREGUARD_STACK_DIR" ]; then
|
||||
rm -rf "$WIREGUARD_STACK_DIR"
|
||||
print_success "WireGuard Docker stack removed"
|
||||
fi
|
||||
fi
|
||||
|
||||
read -p "Remove CoreDNS Docker stack directory? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
if [ -d "$COREDNS_STACK_DIR" ]; then
|
||||
rm -rf "$COREDNS_STACK_DIR"
|
||||
print_success "CoreDNS Docker stack removed"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ========================================
|
||||
# Clean up Docker Resources
|
||||
# ========================================
|
||||
|
||||
print_info "Cleaning up Docker resources..."
|
||||
|
||||
# Remove WireGuard network
|
||||
docker network rm wireguard-net 2>/dev/null || print_info "WireGuard network already removed"
|
||||
|
||||
# Remove unused volumes
|
||||
print_info "Removing unused Docker volumes..."
|
||||
docker volume prune -f || print_warning "Could not prune volumes"
|
||||
|
||||
# ========================================
|
||||
# Summary
|
||||
# ========================================
|
||||
|
||||
echo ""
|
||||
print_success "=========================================="
|
||||
print_success "Cleanup Complete!"
|
||||
print_success "=========================================="
|
||||
echo ""
|
||||
echo "Archive Location: $ARCHIVE_DIR"
|
||||
echo ""
|
||||
print_info "Next Steps:"
|
||||
echo " 1. Deploy host-based WireGuard:"
|
||||
echo " cd ${DEPLOYMENT_DIR}/ansible"
|
||||
echo " ansible-playbook playbooks/setup-wireguard-host.yml"
|
||||
echo ""
|
||||
echo " 2. Generate client configs:"
|
||||
echo " cd ${DEPLOYMENT_DIR}/scripts"
|
||||
echo " sudo ./generate-client-config.sh <device-name>"
|
||||
echo ""
|
||||
echo " 3. Verify new setup:"
|
||||
echo " sudo wg show wg0"
|
||||
echo " sudo systemctl status wg-quick@wg0"
|
||||
echo ""
|
||||
print_warning "Old Docker-based VPN is now inactive!"
|
||||
print_info "VPN access will be restored after deploying host-based setup"
|
||||
echo ""
|
||||
282
deployment/scripts/generate-client-config.sh
Executable file
282
deployment/scripts/generate-client-config.sh
Executable file
@@ -0,0 +1,282 @@
|
||||
#!/bin/bash
|
||||
# WireGuard Client Configuration Generator
|
||||
# Purpose: Generate client configs with QR codes for easy mobile import
|
||||
# Usage: ./generate-client-config.sh <client-name>
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ========================================
|
||||
# Configuration
|
||||
# ========================================
|
||||
|
||||
WG_CONFIG_DIR="/etc/wireguard"
|
||||
CLIENT_CONFIG_DIR="$(dirname "$0")/../wireguard/configs"
|
||||
WG_INTERFACE="wg0"
|
||||
WG_SERVER_CONFIG="${WG_CONFIG_DIR}/${WG_INTERFACE}.conf"
|
||||
WG_NETWORK="10.8.0.0/24"
|
||||
WG_SERVER_IP="10.8.0.1"
|
||||
WG_PORT="51820"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ========================================
|
||||
# Helper Functions
|
||||
# ========================================
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
check_root() {
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
print_error "This script must be run as root (for server config modifications)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_dependencies() {
|
||||
local deps=("wg" "wg-quick" "qrencode")
|
||||
local missing=()
|
||||
|
||||
for dep in "${deps[@]}"; do
|
||||
if ! command -v "$dep" &> /dev/null; then
|
||||
missing+=("$dep")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing[@]} -ne 0 ]; then
|
||||
print_error "Missing dependencies: ${missing[*]}"
|
||||
print_info "Install with: apt install wireguard wireguard-tools qrencode"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
get_next_client_ip() {
|
||||
# Find highest used IP in last octet and add 1
|
||||
if [ ! -f "$WG_SERVER_CONFIG" ]; then
|
||||
echo "10.8.0.2"
|
||||
return
|
||||
fi
|
||||
|
||||
local last_octet=$(grep -oP 'AllowedIPs\s*=\s*10\.8\.0\.\K\d+' "$WG_SERVER_CONFIG" 2>/dev/null | sort -n | tail -1)
|
||||
|
||||
if [ -z "$last_octet" ]; then
|
||||
echo "10.8.0.2"
|
||||
else
|
||||
echo "10.8.0.$((last_octet + 1))"
|
||||
fi
|
||||
}
|
||||
|
||||
get_server_public_key() {
|
||||
if [ ! -f "${WG_CONFIG_DIR}/server_public.key" ]; then
|
||||
print_error "Server public key not found at ${WG_CONFIG_DIR}/server_public.key"
|
||||
print_info "Run the Ansible playbook first: ansible-playbook setup-wireguard-host.yml"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat "${WG_CONFIG_DIR}/server_public.key"
|
||||
}
|
||||
|
||||
get_server_endpoint() {
|
||||
# Try to detect public IP
|
||||
local public_ip
|
||||
public_ip=$(curl -s -4 ifconfig.me 2>/dev/null || curl -s -4 icanhazip.com 2>/dev/null || echo "YOUR_SERVER_IP")
|
||||
|
||||
echo "${public_ip}:${WG_PORT}"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# Main Script
|
||||
# ========================================
|
||||
|
||||
main() {
|
||||
print_info "WireGuard Client Configuration Generator"
|
||||
echo ""
|
||||
|
||||
# Validate input
|
||||
if [ $# -ne 1 ]; then
|
||||
print_error "Usage: $0 <client-name>"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
echo " $0 michael-laptop"
|
||||
echo " $0 iphone"
|
||||
echo " $0 office-desktop"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local client_name="$1"
|
||||
|
||||
# Validate client name (alphanumeric + dash/underscore only)
|
||||
if ! [[ "$client_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
||||
print_error "Client name must contain only alphanumeric characters, dashes, and underscores"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Pre-flight checks
|
||||
check_root
|
||||
check_dependencies
|
||||
|
||||
# Create client config directory
|
||||
mkdir -p "$CLIENT_CONFIG_DIR"
|
||||
|
||||
# Check if client already exists
|
||||
if [ -f "${CLIENT_CONFIG_DIR}/${client_name}.conf" ]; then
|
||||
print_warning "Client config for '${client_name}' already exists"
|
||||
read -p "Regenerate? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
print_info "Aborted"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
print_info "Generating configuration for client: ${client_name}"
|
||||
echo ""
|
||||
|
||||
# Generate client keys
|
||||
print_info "Generating client keys..."
|
||||
local client_private_key=$(wg genkey)
|
||||
local client_public_key=$(echo "$client_private_key" | wg pubkey)
|
||||
local client_preshared_key=$(wg genpsk)
|
||||
|
||||
# Get server information
|
||||
print_info "Reading server configuration..."
|
||||
local server_public_key=$(get_server_public_key)
|
||||
local server_endpoint=$(get_server_endpoint)
|
||||
|
||||
# Assign client IP
|
||||
local client_ip=$(get_next_client_ip)
|
||||
print_info "Assigned client IP: ${client_ip}"
|
||||
|
||||
# Create client config file
|
||||
print_info "Creating client configuration file..."
|
||||
cat > "${CLIENT_CONFIG_DIR}/${client_name}.conf" <<EOF
|
||||
[Interface]
|
||||
# Client: ${client_name}
|
||||
# Generated: $(date)
|
||||
PrivateKey = ${client_private_key}
|
||||
Address = ${client_ip}/32
|
||||
|
||||
# DNS: Use Cloudflare/Quad9 (change if needed)
|
||||
DNS = 1.1.1.1, 9.9.9.9
|
||||
|
||||
[Peer]
|
||||
# Server
|
||||
PublicKey = ${server_public_key}
|
||||
PresharedKey = ${client_preshared_key}
|
||||
Endpoint = ${server_endpoint}
|
||||
|
||||
# Route only VPN network through tunnel (split-tunnel)
|
||||
AllowedIPs = ${WG_NETWORK}
|
||||
|
||||
# Keep connection alive (NAT traversal)
|
||||
PersistentKeepalive = 25
|
||||
EOF
|
||||
|
||||
chmod 600 "${CLIENT_CONFIG_DIR}/${client_name}.conf"
|
||||
|
||||
# Add peer to server configuration
|
||||
print_info "Adding peer to server configuration..."
|
||||
|
||||
# Check if peer already exists in server config
|
||||
if grep -q "# ${client_name}" "$WG_SERVER_CONFIG" 2>/dev/null; then
|
||||
print_info "Removing old peer entry..."
|
||||
# Remove old peer entry (from comment to next empty line or end of file)
|
||||
sed -i "/# ${client_name}/,/^$/d" "$WG_SERVER_CONFIG"
|
||||
fi
|
||||
|
||||
# Append new peer
|
||||
cat >> "$WG_SERVER_CONFIG" <<EOF
|
||||
|
||||
[Peer]
|
||||
# ${client_name}
|
||||
PublicKey = ${client_public_key}
|
||||
PresharedKey = ${client_preshared_key}
|
||||
AllowedIPs = ${client_ip}/32
|
||||
PersistentKeepalive = 25
|
||||
EOF
|
||||
|
||||
# Reload WireGuard to apply changes
|
||||
print_info "Reloading WireGuard configuration..."
|
||||
systemctl reload wg-quick@${WG_INTERFACE}
|
||||
|
||||
# Verify peer is active
|
||||
sleep 1
|
||||
if wg show ${WG_INTERFACE} | grep -q "$client_public_key"; then
|
||||
print_success "Peer successfully added to server"
|
||||
else
|
||||
print_warning "Peer added to config but not yet active (will activate when client connects)"
|
||||
fi
|
||||
|
||||
# Generate QR code for mobile devices
|
||||
print_info "Generating QR code for mobile import..."
|
||||
qrencode -t ansiutf8 < "${CLIENT_CONFIG_DIR}/${client_name}.conf" > "${CLIENT_CONFIG_DIR}/${client_name}.qr.txt"
|
||||
qrencode -t png -o "${CLIENT_CONFIG_DIR}/${client_name}.qr.png" < "${CLIENT_CONFIG_DIR}/${client_name}.conf"
|
||||
|
||||
# Display success summary
|
||||
echo ""
|
||||
print_success "=========================================="
|
||||
print_success "Client Configuration Created!"
|
||||
print_success "=========================================="
|
||||
echo ""
|
||||
echo "Client Name: ${client_name}"
|
||||
echo "Client IP: ${client_ip}"
|
||||
echo "Config File: ${CLIENT_CONFIG_DIR}/${client_name}.conf"
|
||||
echo "QR Code (text): ${CLIENT_CONFIG_DIR}/${client_name}.qr.txt"
|
||||
echo "QR Code (PNG): ${CLIENT_CONFIG_DIR}/${client_name}.qr.png"
|
||||
echo ""
|
||||
echo "Server Endpoint: ${server_endpoint}"
|
||||
echo "VPN Network: ${WG_NETWORK}"
|
||||
echo ""
|
||||
print_info "=========================================="
|
||||
print_info "Import Instructions:"
|
||||
print_info "=========================================="
|
||||
echo ""
|
||||
echo "Desktop (Linux/macOS):"
|
||||
echo " sudo cp ${CLIENT_CONFIG_DIR}/${client_name}.conf /etc/wireguard/"
|
||||
echo " sudo wg-quick up ${client_name}"
|
||||
echo ""
|
||||
echo "Desktop (Windows):"
|
||||
echo " 1. Open WireGuard GUI"
|
||||
echo " 2. Click 'Import tunnel(s) from file'"
|
||||
echo " 3. Select: ${CLIENT_CONFIG_DIR}/${client_name}.conf"
|
||||
echo ""
|
||||
echo "Mobile (iOS/Android):"
|
||||
echo " 1. Open WireGuard app"
|
||||
echo " 2. Tap '+' > 'Create from QR code'"
|
||||
echo " 3. Scan QR code below or from: ${CLIENT_CONFIG_DIR}/${client_name}.qr.png"
|
||||
echo ""
|
||||
print_info "QR Code (scan with phone):"
|
||||
echo ""
|
||||
cat "${CLIENT_CONFIG_DIR}/${client_name}.qr.txt"
|
||||
echo ""
|
||||
print_info "=========================================="
|
||||
print_info "Verify Connection:"
|
||||
print_info "=========================================="
|
||||
echo ""
|
||||
echo "After connecting:"
|
||||
echo " ping ${WG_SERVER_IP}"
|
||||
echo " curl -k https://${WG_SERVER_IP}:8080 # Traefik Dashboard"
|
||||
echo ""
|
||||
print_success "Configuration complete! Client is ready to connect."
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
307
deployment/scripts/manual-wireguard-setup.sh
Executable file
307
deployment/scripts/manual-wireguard-setup.sh
Executable file
@@ -0,0 +1,307 @@
|
||||
#!/bin/bash
|
||||
# Manual WireGuard Setup Script
|
||||
# Purpose: Step-by-step WireGuard installation and configuration
|
||||
# This script shows what needs to be done - review before executing!
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
print_step() {
|
||||
echo -e "${BLUE}[STEP]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# Configuration
|
||||
# ========================================
|
||||
|
||||
WG_INTERFACE="wg0"
|
||||
WG_NETWORK="10.8.0.0/24"
|
||||
WG_SERVER_IP="10.8.0.1"
|
||||
WG_PORT="51820"
|
||||
WG_CONFIG_DIR="/etc/wireguard"
|
||||
WAN_INTERFACE="eth0" # ANPASSEN an dein System!
|
||||
|
||||
# ========================================
|
||||
# Pre-flight Checks
|
||||
# ========================================
|
||||
|
||||
print_step "Pre-flight Checks"
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
print_error "This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if WireGuard is installed
|
||||
if ! command -v wg &> /dev/null; then
|
||||
print_error "WireGuard is not installed"
|
||||
echo "Install with: apt update && apt install -y wireguard wireguard-tools qrencode nftables"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_success "Pre-flight checks passed"
|
||||
|
||||
# ========================================
|
||||
# Step 1: Create WireGuard Directory
|
||||
# ========================================
|
||||
|
||||
print_step "Creating WireGuard directory"
|
||||
|
||||
mkdir -p ${WG_CONFIG_DIR}
|
||||
chmod 700 ${WG_CONFIG_DIR}
|
||||
|
||||
print_success "Directory created: ${WG_CONFIG_DIR}"
|
||||
|
||||
# ========================================
|
||||
# Step 2: Generate Server Keys
|
||||
# ========================================
|
||||
|
||||
print_step "Generating server keys"
|
||||
|
||||
cd ${WG_CONFIG_DIR}
|
||||
|
||||
if [ ! -f server_private.key ]; then
|
||||
wg genkey | tee server_private.key | wg pubkey > server_public.key
|
||||
chmod 600 server_private.key
|
||||
chmod 644 server_public.key
|
||||
print_success "Server keys generated"
|
||||
else
|
||||
print_warning "Server keys already exist - skipping generation"
|
||||
fi
|
||||
|
||||
SERVER_PRIVATE_KEY=$(cat server_private.key)
|
||||
SERVER_PUBLIC_KEY=$(cat server_public.key)
|
||||
|
||||
echo ""
|
||||
echo "Server Public Key: ${SERVER_PUBLIC_KEY}"
|
||||
echo ""
|
||||
|
||||
# ========================================
|
||||
# Step 3: Create WireGuard Configuration
|
||||
# ========================================
|
||||
|
||||
print_step "Creating WireGuard configuration"
|
||||
|
||||
cat > ${WG_CONFIG_DIR}/${WG_INTERFACE}.conf <<EOF
|
||||
[Interface]
|
||||
# Server Configuration
|
||||
PrivateKey = ${SERVER_PRIVATE_KEY}
|
||||
Address = ${WG_SERVER_IP}/24
|
||||
ListenPort = ${WG_PORT}
|
||||
|
||||
# Enable IP forwarding
|
||||
PostUp = sysctl -w net.ipv4.ip_forward=1
|
||||
|
||||
# NAT Configuration with nftables
|
||||
PostUp = nft add table inet wireguard
|
||||
PostUp = nft add chain inet wireguard postrouting { type nat hook postrouting priority srcnat\; }
|
||||
PostUp = nft add rule inet wireguard postrouting oifname "${WAN_INTERFACE}" ip saddr ${WG_NETWORK} masquerade
|
||||
|
||||
# Cleanup on shutdown
|
||||
PostDown = nft delete table inet wireguard
|
||||
|
||||
# Peers will be added here via generate-client-config.sh
|
||||
EOF
|
||||
|
||||
chmod 600 ${WG_CONFIG_DIR}/${WG_INTERFACE}.conf
|
||||
|
||||
print_success "Configuration created: ${WG_CONFIG_DIR}/${WG_INTERFACE}.conf"
|
||||
|
||||
# ========================================
|
||||
# Step 4: Create nftables Firewall Rules
|
||||
# ========================================
|
||||
|
||||
print_step "Creating nftables firewall rules"
|
||||
|
||||
cat > /etc/nftables.d/wireguard.nft <<'EOF'
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
# WireGuard Host-based Firewall Configuration
|
||||
# Purpose: Secure VPN access with admin service protection
|
||||
|
||||
table inet wireguard_firewall {
|
||||
# Define sets for efficient rule matching
|
||||
set vpn_network {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
elements = { 10.8.0.0/24 }
|
||||
}
|
||||
|
||||
set admin_service_ports {
|
||||
type inet_service
|
||||
elements = {
|
||||
8080, # Traefik Dashboard
|
||||
9090, # Prometheus
|
||||
3001, # Grafana
|
||||
9000, # Portainer
|
||||
8001, # Redis Insight
|
||||
}
|
||||
}
|
||||
|
||||
set public_service_ports {
|
||||
type inet_service
|
||||
elements = {
|
||||
80, # HTTP
|
||||
443, # HTTPS
|
||||
22, # SSH
|
||||
}
|
||||
}
|
||||
|
||||
# Input chain - Control incoming connections
|
||||
chain input {
|
||||
type filter hook input priority filter; policy drop;
|
||||
|
||||
# Allow established/related connections
|
||||
ct state established,related accept
|
||||
|
||||
# Allow loopback
|
||||
iif lo accept
|
||||
|
||||
# Allow ICMP (ping)
|
||||
ip protocol icmp accept
|
||||
ip6 nexthdr icmpv6 accept
|
||||
|
||||
# Allow WireGuard port
|
||||
udp dport 51820 accept
|
||||
|
||||
# Allow VPN network to access admin services
|
||||
ip saddr @vpn_network tcp dport @admin_service_ports accept
|
||||
|
||||
# Allow public access to public services
|
||||
tcp dport @public_service_ports accept
|
||||
|
||||
# Block public access to admin services (with logging)
|
||||
tcp dport @admin_service_ports counter log prefix "BLOCKED_ADMIN_SERVICE: " drop
|
||||
|
||||
# Rate limit SSH to prevent brute force
|
||||
tcp dport 22 ct state new limit rate 10/minute accept
|
||||
|
||||
# Drop everything else
|
||||
counter log prefix "BLOCKED_INPUT: " drop
|
||||
}
|
||||
|
||||
# Forward chain - Control packet forwarding
|
||||
chain forward {
|
||||
type filter hook forward priority filter; policy drop;
|
||||
|
||||
# Allow established/related connections
|
||||
ct state established,related accept
|
||||
|
||||
# Allow VPN network to forward
|
||||
ip saddr @vpn_network accept
|
||||
|
||||
# Drop everything else
|
||||
counter log prefix "BLOCKED_FORWARD: " drop
|
||||
}
|
||||
|
||||
# Output chain - Allow all outgoing by default
|
||||
chain output {
|
||||
type filter hook output priority filter; policy accept;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
chmod 755 /etc/nftables.d/wireguard.nft
|
||||
|
||||
print_success "Firewall rules created: /etc/nftables.d/wireguard.nft"
|
||||
|
||||
# ========================================
|
||||
# Step 5: Enable IP Forwarding
|
||||
# ========================================
|
||||
|
||||
print_step "Enabling IP forwarding"
|
||||
|
||||
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-wireguard.conf
|
||||
sysctl -p /etc/sysctl.d/99-wireguard.conf
|
||||
|
||||
print_success "IP forwarding enabled"
|
||||
|
||||
# ========================================
|
||||
# Step 6: Apply nftables Rules
|
||||
# ========================================
|
||||
|
||||
print_step "Applying nftables firewall rules"
|
||||
|
||||
if [ -f /etc/nftables.d/wireguard.nft ]; then
|
||||
nft -f /etc/nftables.d/wireguard.nft
|
||||
print_success "Firewall rules applied"
|
||||
else
|
||||
print_error "Firewall rules file not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ========================================
|
||||
# Step 7: Enable and Start WireGuard
|
||||
# ========================================
|
||||
|
||||
print_step "Enabling and starting WireGuard service"
|
||||
|
||||
systemctl enable wg-quick@${WG_INTERFACE}
|
||||
systemctl start wg-quick@${WG_INTERFACE}
|
||||
|
||||
print_success "WireGuard service enabled and started"
|
||||
|
||||
# ========================================
|
||||
# Step 8: Verify Installation
|
||||
# ========================================
|
||||
|
||||
print_step "Verifying installation"
|
||||
|
||||
echo ""
|
||||
echo "WireGuard Status:"
|
||||
wg show ${WG_INTERFACE}
|
||||
|
||||
echo ""
|
||||
echo "Service Status:"
|
||||
systemctl status wg-quick@${WG_INTERFACE} --no-pager
|
||||
|
||||
echo ""
|
||||
echo "nftables Rules:"
|
||||
nft list table inet wireguard_firewall
|
||||
|
||||
# ========================================
|
||||
# Summary
|
||||
# ========================================
|
||||
|
||||
echo ""
|
||||
print_success "=========================================="
|
||||
print_success "WireGuard Installation Complete!"
|
||||
print_success "=========================================="
|
||||
echo ""
|
||||
echo "Server IP: ${WG_SERVER_IP}"
|
||||
echo "Listen Port: ${WG_PORT}"
|
||||
echo "VPN Network: ${WG_NETWORK}"
|
||||
echo "Interface: ${WG_INTERFACE}"
|
||||
echo ""
|
||||
print_step "Next Steps:"
|
||||
echo " 1. Generate client configs:"
|
||||
echo " cd /home/michael/dev/michaelschiemer/deployment/scripts"
|
||||
echo " sudo ./generate-client-config.sh <client-name>"
|
||||
echo ""
|
||||
echo " 2. Import client config on your device"
|
||||
echo ""
|
||||
echo " 3. Connect and test access to admin services:"
|
||||
echo " - Traefik Dashboard: https://10.8.0.1:8080"
|
||||
echo " - Prometheus: http://10.8.0.1:9090"
|
||||
echo " - Grafana: https://10.8.0.1:3001"
|
||||
echo " - Portainer: http://10.8.0.1:9000"
|
||||
echo " - Redis Insight: http://10.8.0.1:8001"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user