From 12fd780af8f2e2997ef83cb4db15dfd389353a66 Mon Sep 17 00:00:00 2001 From: Marco Migozzi Date: Sat, 4 Apr 2026 13:37:20 +0200 Subject: [PATCH 1/2] feat: add named Cloudflare tunnel support Add named tunnel mode alongside existing quick tunnel, with systemd service and setup helper. Tunnel ID and hostname are configurable via CLOUDFLARED_TUNNEL_ID and CODEMAN_TUNNEL_HOSTNAME env vars. --- scripts/codeman-tunnel-named.service | 19 +++ scripts/tunnel.sh | 220 ++++++++++++++++++++++----- 2 files changed, 203 insertions(+), 36 deletions(-) create mode 100644 scripts/codeman-tunnel-named.service diff --git a/scripts/codeman-tunnel-named.service b/scripts/codeman-tunnel-named.service new file mode 100644 index 00000000..2602d588 --- /dev/null +++ b/scripts/codeman-tunnel-named.service @@ -0,0 +1,19 @@ +[Unit] +Description=Codeman Cloudflare Named Tunnel +After=network-online.target codeman-web.service +Wants=network-online.target + +[Service] +Type=simple +ExecStart=/usr/bin/cloudflared tunnel --config %h/.cloudflared/codeman.yml run codeman +Restart=always +RestartSec=5 +KillMode=process + +# Logging +StandardOutput=journal +StandardError=journal +SyslogIdentifier=codeman-tunnel-named + +[Install] +WantedBy=default.target diff --git a/scripts/tunnel.sh b/scripts/tunnel.sh index 32256f3a..8fc6597e 100755 --- a/scripts/tunnel.sh +++ b/scripts/tunnel.sh @@ -1,45 +1,193 @@ #!/usr/bin/env bash -# Quick Cloudflare Tunnel for Codeman -# Usage: ./scripts/tunnel.sh [start|stop|status|url] +# Cloudflare Tunnel manager for Codeman +# Usage: ./scripts/tunnel.sh [quick|named] [start|stop|status|url] +# +# Modes: +# quick — Quick tunnel with random trycloudflare.com URL (default) +# named — Named tunnel on codeman.marcomigozzi.it (requires setup, see below) +# +# First-time named tunnel setup: +# cloudflared tunnel login +# cloudflared tunnel create codeman +# cloudflared tunnel route dns codeman codeman.marcomigozzi.it +# ./scripts/tunnel.sh named setup # writes ~/.cloudflared/config.yml set -euo pipefail -SERVICE="codeman-tunnel" - -case "${1:-start}" in - start) - if ! systemctl --user is-active "$SERVICE" &>/dev/null; then - # Install service if not already - if ! systemctl --user cat "$SERVICE" &>/dev/null 2>&1; then - cp "$(dirname "$0")/codeman-tunnel.service" "$HOME/.config/systemd/user/" - systemctl --user daemon-reload - fi - systemctl --user start "$SERVICE" - echo "Tunnel starting... waiting for URL" - sleep 6 - fi - # Extract the tunnel URL from journal - URL=$(grep -oP 'https://[a-z0-9-]+\.trycloudflare\.com' "$HOME/.codeman/tunnel.log" 2>/dev/null | tail -1) - if [ -n "$URL" ]; then - echo "$URL" - else - echo "URL not ready yet, try: $0 url" - fi - ;; - stop) - systemctl --user stop "$SERVICE" - echo "Tunnel stopped" - ;; - status) - systemctl --user status "$SERVICE" --no-pager 2>&1 | head -10 - echo "" - echo "URL:" - grep -oP 'https://[a-z0-9-]+\.trycloudflare\.com' "$HOME/.codeman/tunnel.log" 2>/dev/null | tail -1 +QUICK_SERVICE="codeman-tunnel" +NAMED_SERVICE="codeman-tunnel-named" +TUNNEL_NAME="codeman" +TUNNEL_HOSTNAME="${CODEMAN_TUNNEL_HOSTNAME:-codeman.example.com}" +CODEMAN_PORT="3000" +LOG_FILE="$HOME/.codeman/tunnel.log" + +# ── helpers ────────────────────────────────────────────────────────────────── + +_require_cloudflared() { + if ! command -v cloudflared &>/dev/null; then + echo "Error: cloudflared not found. Install with: yay -S cloudflared" >&2 + exit 1 + fi +} + +_cloudflared_bin() { + command -v cloudflared +} + +_install_service() { + local svc_file="$1" + local svc_name="$2" + if ! systemctl --user cat "$svc_name" &>/dev/null 2>&1; then + cp "$(dirname "$0")/$svc_file" "$HOME/.config/systemd/user/" + systemctl --user daemon-reload + echo "Service $svc_name installed." + fi +} + +# ── named tunnel setup ─────────────────────────────────────────────────────── + +_named_setup() { + _require_cloudflared + + local creds_dir="$HOME/.cloudflared" + local config_file="$creds_dir/codeman.yml" + # Replace with your tunnel ID (from: cloudflared tunnel list) + local tunnel_id="${CLOUDFLARED_TUNNEL_ID:-YOUR_TUNNEL_ID_HERE}" + local creds_file="$creds_dir/$tunnel_id.json" + + if [ ! -f "$creds_file" ]; then + echo "Credentials not found: $creds_file" + echo "Run: cloudflared tunnel create $TUNNEL_NAME" + exit 1 + fi + + cat > "$config_file" </dev/null; then + _install_service "codeman-tunnel.service" "$QUICK_SERVICE" + systemctl --user start "$QUICK_SERVICE" + echo "Quick tunnel starting... waiting for URL" + sleep 6 + fi + local url + url=$(grep -oP 'https://[a-z0-9-]+\.trycloudflare\.com' "$LOG_FILE" 2>/dev/null | tail -1) + if [ -n "$url" ]; then + echo "$url" + else + echo "URL not ready yet, try: $0 quick url" + fi +} + +_quick_stop() { + systemctl --user stop "$QUICK_SERVICE" + echo "Quick tunnel stopped" +} + +_quick_status() { + systemctl --user status "$QUICK_SERVICE" --no-pager 2>&1 | head -10 + echo "" + echo "URL:" + grep -oP 'https://[a-z0-9-]+\.trycloudflare\.com' "$LOG_FILE" 2>/dev/null | tail -1 +} + +_quick_url() { + grep -oP 'https://[a-z0-9-]+\.trycloudflare\.com' "$LOG_FILE" 2>/dev/null | tail -1 +} + +# ── named mode ─────────────────────────────────────────────────────────────── + +_named_start() { + _require_cloudflared + if [ ! -f "$HOME/.cloudflared/codeman.yml" ]; then + echo "Config not found. Run: $0 named setup" + exit 1 + fi + if ! systemctl --user is-active "$NAMED_SERVICE" &>/dev/null; then + _install_service "codeman-tunnel-named.service" "$NAMED_SERVICE" + systemctl --user start "$NAMED_SERVICE" + echo "Named tunnel starting..." + sleep 3 + fi + echo "https://$TUNNEL_HOSTNAME" +} + +_named_stop() { + systemctl --user stop "$NAMED_SERVICE" + echo "Named tunnel stopped" +} + +_named_status() { + systemctl --user status "$NAMED_SERVICE" --no-pager 2>&1 | head -10 + echo "" + echo "URL: https://$TUNNEL_HOSTNAME" +} + +_named_enable() { + _install_service "codeman-tunnel-named.service" "$NAMED_SERVICE" + systemctl --user enable "$NAMED_SERVICE" + echo "Named tunnel enabled at boot." +} + +_named_disable() { + systemctl --user disable "$NAMED_SERVICE" + echo "Named tunnel disabled." +} + +# ── dispatch ───────────────────────────────────────────────────────────────── + +MODE="${1:-quick}" +CMD="${2:-start}" + +case "$MODE" in + quick) + case "$CMD" in + start) _quick_start ;; + stop) _quick_stop ;; + status) _quick_status ;; + url) _quick_url ;; + *) echo "Usage: $0 quick [start|stop|status|url]"; exit 1 ;; + esac ;; - url) - grep -oP 'https://[a-z0-9-]+\.trycloudflare\.com' "$HOME/.codeman/tunnel.log" 2>/dev/null | tail -1 + named) + case "$CMD" in + start) _named_start ;; + stop) _named_stop ;; + status) _named_status ;; + url) echo "https://$TUNNEL_HOSTNAME" ;; + setup) _named_setup ;; + enable) _named_enable ;; + disable) _named_disable ;; + *) echo "Usage: $0 named [start|stop|status|url|setup|enable|disable]"; exit 1 ;; + esac ;; + # backward compat: no mode prefix → quick tunnel + start) _quick_start ;; + stop) _quick_stop ;; + status) _quick_status ;; + url) _quick_url ;; *) - echo "Usage: $0 [start|stop|status|url]" + echo "Usage: $0 [quick|named] [start|stop|status|url]" + echo " $0 named setup # first-time named tunnel configuration" + echo " $0 named enable # start at boot" exit 1 ;; esac From f1a126efebd598d9c1c5255ff02a4808db6aba10 Mon Sep 17 00:00:00 2001 From: Marco Migozzi Date: Sat, 4 Apr 2026 13:41:28 +0200 Subject: [PATCH 2/2] feat: add named Cloudflare tunnel support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add named tunnel mode alongside existing quick tunnel, with systemd service and setup helper. All tunnel parameters are configurable via environment variables: CLOUDFLARED_TUNNEL_NAME — tunnel name (default: codeman) CLOUDFLARED_TUNNEL_ID — tunnel UUID (from: cloudflared tunnel list) CODEMAN_TUNNEL_HOSTNAME — public hostname Backward compatible: ./tunnel.sh [start|stop|status|url] still works. --- scripts/tunnel.sh | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/scripts/tunnel.sh b/scripts/tunnel.sh index 8fc6597e..3edb3eaa 100755 --- a/scripts/tunnel.sh +++ b/scripts/tunnel.sh @@ -4,18 +4,23 @@ # # Modes: # quick — Quick tunnel with random trycloudflare.com URL (default) -# named — Named tunnel on codeman.marcomigozzi.it (requires setup, see below) +# named — Named tunnel on a fixed hostname (requires setup, see below) +# +# Environment variables: +# CLOUDFLARED_TUNNEL_NAME — tunnel name (default: codeman) +# CLOUDFLARED_TUNNEL_ID — tunnel UUID (from: cloudflared tunnel list) +# CODEMAN_TUNNEL_HOSTNAME — public hostname (e.g. codeman.example.com) # # First-time named tunnel setup: # cloudflared tunnel login -# cloudflared tunnel create codeman -# cloudflared tunnel route dns codeman codeman.marcomigozzi.it -# ./scripts/tunnel.sh named setup # writes ~/.cloudflared/config.yml +# cloudflared tunnel create +# cloudflared tunnel route dns +# ./scripts/tunnel.sh named setup # writes ~/.cloudflared/.yml set -euo pipefail QUICK_SERVICE="codeman-tunnel" NAMED_SERVICE="codeman-tunnel-named" -TUNNEL_NAME="codeman" +TUNNEL_NAME="${CLOUDFLARED_TUNNEL_NAME:-codeman}" TUNNEL_HOSTNAME="${CODEMAN_TUNNEL_HOSTNAME:-codeman.example.com}" CODEMAN_PORT="3000" LOG_FILE="$HOME/.codeman/tunnel.log" @@ -43,13 +48,24 @@ _install_service() { fi } +_install_named_service() { + if ! systemctl --user cat "$NAMED_SERVICE" &>/dev/null 2>&1; then + # Generate service file with the configured tunnel name + sed "s/codeman\.yml/$TUNNEL_NAME.yml/g; s/run codeman/run $TUNNEL_NAME/g" \ + "$(dirname "$0")/codeman-tunnel-named.service" \ + > "$HOME/.config/systemd/user/codeman-tunnel-named.service" + systemctl --user daemon-reload + echo "Service $NAMED_SERVICE installed (tunnel: $TUNNEL_NAME)." + fi +} + # ── named tunnel setup ─────────────────────────────────────────────────────── _named_setup() { _require_cloudflared local creds_dir="$HOME/.cloudflared" - local config_file="$creds_dir/codeman.yml" + local config_file="$creds_dir/$TUNNEL_NAME.yml" # Replace with your tunnel ID (from: cloudflared tunnel list) local tunnel_id="${CLOUDFLARED_TUNNEL_ID:-YOUR_TUNNEL_ID_HERE}" local creds_file="$creds_dir/$tunnel_id.json" @@ -117,12 +133,12 @@ _quick_url() { _named_start() { _require_cloudflared - if [ ! -f "$HOME/.cloudflared/codeman.yml" ]; then + if [ ! -f "$HOME/.cloudflared/$TUNNEL_NAME.yml" ]; then echo "Config not found. Run: $0 named setup" exit 1 fi if ! systemctl --user is-active "$NAMED_SERVICE" &>/dev/null; then - _install_service "codeman-tunnel-named.service" "$NAMED_SERVICE" + _install_named_service systemctl --user start "$NAMED_SERVICE" echo "Named tunnel starting..." sleep 3 @@ -142,7 +158,7 @@ _named_status() { } _named_enable() { - _install_service "codeman-tunnel-named.service" "$NAMED_SERVICE" + _install_named_service systemctl --user enable "$NAMED_SERVICE" echo "Named tunnel enabled at boot." }