Last active
May 30, 2026 05:48
-
-
Save shrijayan/1aaf72c3883d3de049bc2127f5a330c0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Exit on any error | |
| set -e | |
| # Help helper function | |
| usage() { | |
| echo "Usage: $0 [domain_name] [local_url]" | |
| echo "Example: $0 app.mydomain.com http://localhost:3000" | |
| } | |
| # Helper to run commands with root privileges | |
| run_as_root() { | |
| if [ "$EUID" -eq 0 ]; then | |
| "$@" | |
| else | |
| if command -v sudo &> /dev/null; then | |
| sudo "$@" | |
| else | |
| echo "Error: This script requires root privileges. Please run as root or install sudo." | |
| exit 1 | |
| fi | |
| fi | |
| } | |
| # Read arguments or prompt the user if they are missing | |
| DOMAIN=$1 | |
| LOCAL_URL=$2 | |
| if [ -z "$DOMAIN" ]; then | |
| read -p "Enter your custom domain name (e.g., app.example.com): " DOMAIN | |
| fi | |
| if [ -z "$LOCAL_URL" ]; then | |
| read -p "Enter your local URL (e.g., http://localhost:8080): " LOCAL_URL | |
| fi | |
| if [ -z "$DOMAIN" ] || [ -z "$LOCAL_URL" ]; then | |
| echo "Error: Both domain name and local URL are required." | |
| usage | |
| exit 1 | |
| fi | |
| echo "Target Domain: $DOMAIN" | |
| echo "Local Service: $LOCAL_URL" | |
| # 1. Install cloudflared if not present | |
| if ! command -v cloudflared &> /dev/null; then | |
| echo "cloudflared is not installed. Attempting installation..." | |
| # Detect OS | |
| if [[ "$OSTYPE" == "linux-gnu"* ]]; then | |
| # Check for Debian/Ubuntu | |
| if [ -f /etc/debian_version ]; then | |
| echo "Detected Debian/Ubuntu system..." | |
| curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb | |
| run_as_root dpkg -i cloudflared.deb | |
| rm cloudflared.deb | |
| else | |
| echo "Detected non-Debian Linux system. Installing static binary to /usr/local/bin..." | |
| curl -L --output cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 | |
| chmod +x cloudflared | |
| run_as_root mv cloudflared /usr/local/bin/ | |
| fi | |
| elif [[ "$OSTYPE" == "darwin"* ]]; then | |
| echo "Detected macOS..." | |
| if command -v brew &> /dev/null; then | |
| brew install cloudflare/cloudflare/cloudflared | |
| else | |
| echo "Homebrew not found. Downloading macOS binary manually..." | |
| curl -L --output cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-darwin-amd64.tgz | |
| tar -xzf cloudflared-darwin-amd64.tgz | |
| chmod +x cloudflared | |
| run_as_root mv cloudflared /usr/local/bin/ | |
| rm cloudflared-darwin-amd64.tgz | |
| fi | |
| else | |
| echo "Unsupported OS. Please install cloudflared manually before running this script." | |
| exit 1 | |
| fi | |
| else | |
| echo "cloudflared is already installed." | |
| fi | |
| # 2. Cloudflare Login (Only runs if certificate does not exist) | |
| USER_CONFIG_DIR="$HOME/.cloudflared" | |
| mkdir -p "$USER_CONFIG_DIR" | |
| if [ ! -f "$USER_CONFIG_DIR/cert.pem" ]; then | |
| echo "-----------------------------------------------------" | |
| echo "Requesting Cloudflare login..." | |
| echo "Please click the URL printed below to authorize your account." | |
| echo "-----------------------------------------------------" | |
| cloudflared tunnel login | |
| else | |
| echo "Existing login certificate found at $USER_CONFIG_DIR/cert.pem. Skipping login step." | |
| fi | |
| # 3. Create or Retrieve the Tunnel | |
| TUNNEL_NAME="tunnel-$(echo "$DOMAIN" | tr '.' '-')" | |
| echo "Checking if tunnel '$TUNNEL_NAME' already exists..." | |
| # List existing tunnels and extract the ID if found | |
| EXISTING_TUNNEL_ID=$(cloudflared tunnel list | grep -w "$TUNNEL_NAME" | awk '{print $1}' || true) | |
| if [ -n "$EXISTING_TUNNEL_ID" ]; then | |
| CRED_FILE="$USER_CONFIG_DIR/$EXISTING_TUNNEL_ID.json" | |
| if [ -f "$CRED_FILE" ]; then | |
| echo "Tunnel '$TUNNEL_NAME' already exists and credentials file is present locally." | |
| echo "Reusing Tunnel ID: $EXISTING_TUNNEL_ID" | |
| TUNNEL_ID=$EXISTING_TUNNEL_ID | |
| else | |
| echo "Tunnel '$TUNNEL_NAME' exists on Cloudflare, but credentials are missing locally." | |
| echo "Deleting the existing remote tunnel and creating a new one..." | |
| cloudflared tunnel delete -f "$TUNNEL_NAME" | |
| CREATE_OUTPUT=$(cloudflared tunnel create "$TUNNEL_NAME") | |
| TUNNEL_ID=$(echo "$CREATE_OUTPUT" | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | head -n 1) | |
| fi | |
| else | |
| echo "Creating new tunnel: $TUNNEL_NAME" | |
| CREATE_OUTPUT=$(cloudflared tunnel create "$TUNNEL_NAME") | |
| TUNNEL_ID=$(echo "$CREATE_OUTPUT" | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | head -n 1) | |
| fi | |
| if [ -z "$TUNNEL_ID" ]; then | |
| echo "Error: Could not retrieve or generate the Tunnel ID." | |
| exit 1 | |
| fi | |
| # 4. Set up system-wide configuration directories | |
| SYS_CONFIG_DIR="/etc/cloudflared" | |
| echo "Creating system configuration directory at $SYS_CONFIG_DIR..." | |
| run_as_root mkdir -p "$SYS_CONFIG_DIR" | |
| # Copy credentials file to system directory | |
| run_as_root cp "$USER_CONFIG_DIR/$TUNNEL_ID.json" "$SYS_CONFIG_DIR/" | |
| # Generate system-wide config.yml | |
| CONFIG_PATH="$SYS_CONFIG_DIR/config.yml" | |
| echo "Generating system configuration file at $CONFIG_PATH..." | |
| # Write the config securely | |
| cat <<EOF | run_as_root tee "$CONFIG_PATH" > /dev/null | |
| tunnel: $TUNNEL_ID | |
| credentials-file: $SYS_CONFIG_DIR/$TUNNEL_ID.json | |
| ingress: | |
| - hostname: $DOMAIN | |
| service: $LOCAL_URL | |
| - service: http_status:404 | |
| EOF | |
| # Remove redundant local configuration file to avoid conflicts | |
| if [ -f "$USER_CONFIG_DIR/config.yml" ]; then | |
| echo "Removing redundant local configuration file from $USER_CONFIG_DIR to prevent conflicts..." | |
| rm -f "$USER_CONFIG_DIR/config.yml" | |
| fi | |
| # 5. Route DNS | |
| echo "Routing DNS for $DOMAIN to point to the tunnel..." | |
| cloudflared tunnel route dns "$TUNNEL_NAME" "$DOMAIN" | |
| # 6. Systemd Service Installation (Linux background service) | |
| if command -v systemctl &> /dev/null; then | |
| echo "systemd detected. Configuring cloudflared as a system service..." | |
| # Clean up previous service configurations to prevent installation blocks | |
| if systemctl is-active --quiet cloudflared || systemctl is-enabled --quiet cloudflared &> /dev/null; then | |
| echo "Removing existing cloudflared service..." | |
| run_as_root cloudflared service uninstall || true | |
| fi | |
| # Install the service explicitly referencing the system configuration file | |
| run_as_root cloudflared --config "$CONFIG_PATH" service install | |
| # Enable and start the service | |
| echo "Enabling and starting the cloudflared service..." | |
| run_as_root systemctl daemon-reload | |
| run_as_root systemctl enable cloudflared | |
| run_as_root systemctl start cloudflared | |
| echo "-----------------------------------------------------" | |
| echo "Setup is complete." | |
| echo "The tunnel is now running in the background via systemd." | |
| echo "You can close this terminal or press Ctrl+C safely." | |
| echo "-----------------------------------------------------" | |
| echo "To check service status:" | |
| echo " systemctl status cloudflared" | |
| echo "To stop the service:" | |
| echo " systemctl stop cloudflared" | |
| echo "To start the service:" | |
| echo " systemctl start cloudflared" | |
| echo "-----------------------------------------------------" | |
| else | |
| echo "-----------------------------------------------------" | |
| echo "systemd was not detected on this system." | |
| echo "The system-wide configuration is saved at: $CONFIG_PATH" | |
| echo "You must manage this tunnel manually:" | |
| echo " cloudflared tunnel run $TUNNEL_NAME" | |
| echo "-----------------------------------------------------" | |
| fi |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
curl -sL "https://gist.github.com/shrijayan/1aaf72c3883d3de049bc2127f5a330c0/raw/setup_tunnel.sh?t=$(date +%s)" | bash -s --[domain-name] [localhost-url]