Some checks failed
Test / test (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
245 lines
7.5 KiB
Bash
Executable File
245 lines
7.5 KiB
Bash
Executable File
#!/bin/bash
|
|
source ~/.bashrc
|
|
# Configure Cloudflare Tunnel Authentication and Setup on VM 100
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
|
|
# Load environment variables
|
|
if [ -f "$PROJECT_ROOT/.env" ]; then
|
|
set -a
|
|
source <(grep -v '^#' "$PROJECT_ROOT/.env" | grep -v '^$' | sed 's/#.*$//' | grep '=')
|
|
set +a
|
|
fi
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log_info() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
VM_USER="${VM_USER:-ubuntu}"
|
|
SSH_KEY="${SSH_KEY:-$HOME/.ssh/id_ed25519_proxmox}"
|
|
VMID=100
|
|
VM_NAME="cloudflare-tunnel"
|
|
TUNNEL_NAME="${CLOUDFLARE_TUNNEL_NAME:-azure-stack-hci}"
|
|
|
|
# Import helper library
|
|
if [ -f "$PROJECT_ROOT/scripts/lib/proxmox_vm_helpers.sh" ]; then
|
|
source "$PROJECT_ROOT/scripts/lib/proxmox_vm_helpers.sh"
|
|
else
|
|
log_error "Helper library not found"
|
|
exit 1
|
|
fi
|
|
|
|
main() {
|
|
log_info "Configuring Cloudflare Tunnel on VM $VMID ($VM_NAME)"
|
|
echo ""
|
|
|
|
# Get IP using guest agent
|
|
local ip
|
|
ip="$(get_vm_ip_or_warn "$VMID" "$VM_NAME" || true)"
|
|
|
|
if [[ -z "$ip" ]]; then
|
|
log_error "Cannot get IP for VM $VMID. Ensure SSH is working and QEMU Guest Agent is installed."
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Using IP: $ip"
|
|
echo ""
|
|
|
|
# Check if cloudflared is installed
|
|
log_info "Checking cloudflared installation..."
|
|
if ! ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "${VM_USER}@${ip}" "command -v cloudflared" &>/dev/null; then
|
|
log_warn "cloudflared not found. Installing..."
|
|
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "${VM_USER}@${ip}" <<'EOF'
|
|
set -e
|
|
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /tmp/cloudflared
|
|
sudo mv /tmp/cloudflared /usr/local/bin/cloudflared
|
|
sudo chmod +x /usr/local/bin/cloudflared
|
|
cloudflared --version
|
|
EOF
|
|
log_info "cloudflared installed"
|
|
else
|
|
log_info "cloudflared is installed"
|
|
fi
|
|
|
|
# Create cloudflared user and directories
|
|
log_info "Setting up cloudflared user and directories..."
|
|
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "${VM_USER}@${ip}" <<'EOF'
|
|
set -e
|
|
sudo useradd -r -s /bin/false cloudflared 2>/dev/null || true
|
|
sudo mkdir -p /etc/cloudflared
|
|
sudo chown cloudflared:cloudflared /etc/cloudflared
|
|
EOF
|
|
|
|
# Authenticate cloudflared (interactive)
|
|
log_info "Authenticating with Cloudflare..."
|
|
log_warn "This requires interactive browser authentication."
|
|
log_info "A browser window will open for authentication."
|
|
echo ""
|
|
|
|
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no -t "${VM_USER}@${ip}" <<EOF
|
|
set -e
|
|
cd /tmp
|
|
cloudflared tunnel login
|
|
EOF
|
|
|
|
# Create tunnel
|
|
log_info "Creating tunnel: $TUNNEL_NAME..."
|
|
local tunnel_id
|
|
tunnel_id=$(ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "${VM_USER}@${ip}" "cloudflared tunnel create $TUNNEL_NAME 2>&1 | grep -oP '(?<=Created tunnel )[a-f0-9-]+' || cloudflared tunnel list | grep '$TUNNEL_NAME' | awk '{print \$1}'" || true)
|
|
|
|
if [[ -z "$tunnel_id" ]]; then
|
|
log_error "Failed to create or find tunnel. Please check Cloudflare dashboard."
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Tunnel ID: $tunnel_id"
|
|
|
|
# Get service IPs
|
|
local git_ip prometheus_ip grafana_ip proxmox_ml110_ip proxmox_r630_ip
|
|
git_ip="192.168.1.121" # VM 102
|
|
prometheus_ip="192.168.1.82" # VM 103
|
|
grafana_ip="192.168.1.82" # VM 103
|
|
proxmox_ml110_ip="192.168.1.206"
|
|
proxmox_r630_ip="192.168.1.49"
|
|
|
|
# Create tunnel configuration
|
|
log_info "Creating tunnel configuration..."
|
|
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "${VM_USER}@${ip}" "sudo tee /etc/cloudflared/config.yml" <<EOF
|
|
tunnel: $tunnel_id
|
|
credentials-file: /etc/cloudflared/$tunnel_id.json
|
|
|
|
ingress:
|
|
# Grafana Dashboard
|
|
- hostname: grafana.yourdomain.com
|
|
service: http://$grafana_ip:3000
|
|
originRequest:
|
|
noHappyEyeballs: true
|
|
tcpKeepAlive: 30
|
|
|
|
# Prometheus
|
|
- hostname: prometheus.yourdomain.com
|
|
service: http://$prometheus_ip:9090
|
|
originRequest:
|
|
noHappyEyeballs: true
|
|
tcpKeepAlive: 30
|
|
|
|
# Git Server (Gitea)
|
|
- hostname: git.yourdomain.com
|
|
service: http://$git_ip:3000
|
|
originRequest:
|
|
noHappyEyeballs: true
|
|
tcpKeepAlive: 30
|
|
|
|
# Proxmox ML110
|
|
- hostname: proxmox-ml110.yourdomain.com
|
|
service: https://$proxmox_ml110_ip:8006
|
|
originRequest:
|
|
noHappyEyeballs: true
|
|
tcpKeepAlive: 30
|
|
connectTimeout: 10s
|
|
tlsTimeout: 10s
|
|
httpHostHeader: proxmox-ml110.yourdomain.com
|
|
|
|
# Proxmox R630
|
|
- hostname: proxmox-r630.yourdomain.com
|
|
service: https://$proxmox_r630_ip:8006
|
|
originRequest:
|
|
noHappyEyeballs: true
|
|
tcpKeepAlive: 30
|
|
connectTimeout: 10s
|
|
tlsTimeout: 10s
|
|
httpHostHeader: proxmox-r630.yourdomain.com
|
|
|
|
# Catch-all (must be last)
|
|
- service: http_status:404
|
|
EOF
|
|
|
|
# Move credentials file to proper location
|
|
log_info "Setting up credentials file..."
|
|
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "${VM_USER}@${ip}" <<EOF
|
|
set -e
|
|
if [ -f ~/.cloudflared/$tunnel_id.json ]; then
|
|
sudo mv ~/.cloudflared/$tunnel_id.json /etc/cloudflared/$tunnel_id.json
|
|
sudo chown cloudflared:cloudflared /etc/cloudflared/$tunnel_id.json
|
|
sudo chmod 600 /etc/cloudflared/$tunnel_id.json
|
|
fi
|
|
EOF
|
|
|
|
# Create systemd service
|
|
log_info "Creating systemd service..."
|
|
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "${VM_USER}@${ip}" "sudo tee /etc/systemd/system/cloudflared.service" <<'EOF'
|
|
[Unit]
|
|
Description=Cloudflare Tunnel
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=cloudflared
|
|
ExecStart=/usr/local/bin/cloudflared tunnel --config /etc/cloudflared/config.yml run
|
|
Restart=on-failure
|
|
RestartSec=5s
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
# Enable and start service
|
|
log_info "Enabling and starting cloudflared service..."
|
|
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "${VM_USER}@${ip}" <<'EOF'
|
|
set -e
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable cloudflared
|
|
sudo systemctl start cloudflared
|
|
sleep 3
|
|
sudo systemctl status cloudflared --no-pager || true
|
|
EOF
|
|
|
|
# Verify service
|
|
log_info "Verifying tunnel status..."
|
|
sleep 5
|
|
if ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "${VM_USER}@${ip}" "sudo systemctl is-active --quiet cloudflared"; then
|
|
log_info "✓ Cloudflare Tunnel is running!"
|
|
echo ""
|
|
log_info "Tunnel Configuration:"
|
|
log_info " Tunnel Name: $TUNNEL_NAME"
|
|
log_info " Tunnel ID: $tunnel_id"
|
|
log_info " Config: /etc/cloudflared/config.yml"
|
|
echo ""
|
|
log_warn "Next steps:"
|
|
log_info "1. Configure DNS records in Cloudflare Dashboard:"
|
|
log_info " - grafana.yourdomain.com → CNAME to $tunnel_id.cfargotunnel.com"
|
|
log_info " - prometheus.yourdomain.com → CNAME to $tunnel_id.cfargotunnel.com"
|
|
log_info " - git.yourdomain.com → CNAME to $tunnel_id.cfargotunnel.com"
|
|
log_info " - proxmox-ml110.yourdomain.com → CNAME to $tunnel_id.cfargotunnel.com"
|
|
log_info " - proxmox-r630.yourdomain.com → CNAME to $tunnel_id.cfargotunnel.com"
|
|
echo ""
|
|
log_info "2. Configure Zero Trust policies in Cloudflare Dashboard"
|
|
log_info "3. View logs: ssh ${VM_USER}@${ip} 'sudo journalctl -u cloudflared -f'"
|
|
else
|
|
log_error "Tunnel service failed to start. Check logs:"
|
|
log_info " ssh ${VM_USER}@${ip} 'sudo journalctl -u cloudflared'"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
main "$@"
|
|
|