#!/usr/bin/env bash set -euo pipefail # === METADATA === SCRIPT_NAME="$(basename "$0")" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SKILL_ROOT="$(dirname "$SCRIPT_DIR")" # === CONFIGURATION === : "${DOMAIN:?DOMAIN required}" : "${CF_ACCOUNT_ID:?CF_ACCOUNT_ID required}" : "${NODE_NAME:=node-a}" : "${TUNNEL_NAME:=$NODE_NAME-tunnel}" : "${OUTPUT_DIR:=$SKILL_ROOT/outputs}" # === FUNCTIONS === log_info() { echo "[INFO] $(date -Iseconds) $*"; } log_warn() { echo "[WARN] $(date -Iseconds) $*" >&2; } log_error() { echo "[ERROR] $(date -Iseconds) $*" >&2; } die() { log_error "$@"; exit 1; } preflight() { [[ -d "$OUTPUT_DIR" ]] || mkdir -p "$OUTPUT_DIR" [[ -d "$HOME/.cloudflared" ]] || mkdir -p "$HOME/.cloudflared" } ensure_authenticated() { if [[ ! -f "$HOME/.cloudflared/cert.pem" ]]; then log_info "No cloudflared certificate found. Starting login..." log_info "A browser window will open for authentication." cloudflared tunnel login else log_info "Cloudflared already authenticated" fi } create_tunnel() { local creds="$HOME/.cloudflared/$TUNNEL_NAME.json" if [[ -f "$creds" ]]; then log_info "Tunnel credentials already exist - reusing existing tunnel" return 0 fi log_info "Creating Cloudflare tunnel: $TUNNEL_NAME" cloudflared tunnel create "$TUNNEL_NAME" if [[ ! -f "$creds" ]]; then die "Tunnel creation failed - credentials not found at $creds" fi log_info "Tunnel created successfully" } create_config() { local config="$HOME/.cloudflared/config-$TUNNEL_NAME.yml" if [[ -f "$config" ]]; then log_info "Tunnel config already exists at $config - skipping" return 0 fi cat > "$config" </dev/null; then log_info "DNS route created for ssh.$DOMAIN" else log_warn "DNS route creation returned error - may already exist" log_info "Verify DNS at: https://dash.cloudflare.com" fi } store_credentials_in_pass() { local creds="$HOME/.cloudflared/$TUNNEL_NAME.json" if command -v pass &>/dev/null && [[ -d "$HOME/.password-store" ]]; then log_info "Storing tunnel ID in pass..." local tunnel_id if command -v jq &>/dev/null; then tunnel_id=$(jq -r '.TunnelID' "$creds" 2>/dev/null || echo "unknown") else tunnel_id=$(grep -o '"TunnelID":"[^"]*"' "$creds" | cut -d'"' -f4 || echo "unknown") fi echo "$tunnel_id" | pass insert -f "infrastructure/cloudflare/tunnel-id" 2>/dev/null || \ log_warn "Could not store tunnel ID in pass" log_info "Tunnel ID stored in pass: infrastructure/cloudflare/tunnel-id" else log_warn "Pass not available - tunnel ID stored only in $creds" fi } install_service() { local config="$HOME/.cloudflared/config-$TUNNEL_NAME.yml" log_info "Attempting to install systemd service..." # Try user service first (doesn't require root) if systemctl --user daemon-reload 2>/dev/null; then # Create user service file local service_dir="$HOME/.config/systemd/user" mkdir -p "$service_dir" cat > "$service_dir/cloudflared-$TUNNEL_NAME.service" </dev/null && [[ -f "$creds" ]]; then tunnel_id=$(jq -r '.TunnelID' "$creds" 2>/dev/null || echo "unknown") elif [[ -f "$creds" ]]; then tunnel_id=$(grep -o '"TunnelID":"[^"]*"' "$creds" | cut -d'"' -f4 || echo "unknown") fi cat > "$manifest" <