Last active
March 19, 2026 11:14
-
-
Save emrul/f30f878443eb7a1624137980a2d1f975 to your computer and use it in GitHub Desktop.
OpenZiti Router Deploy Script
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 | |
| # | |
| # Ziti Router Deployment Script | |
| # | |
| # Usage: /bin/bash -c "$(curl -fsSL https://gitlab.com/.../deploy-router.sh)" - <router-name> | |
| # | |
| # This script automates the deployment of a Ziti router by: | |
| # 1. Accepting the router name as an argument | |
| # 2. Accepting a JWT token from the user | |
| # 3. Detecting the external IP address | |
| # 4. Generating an sslip.io address | |
| # 5. Creating a directory for the router | |
| # 6. Downloading the router compose file | |
| # 7. Running docker compose with the appropriate configuration | |
| set -e | |
| # Get router name from first argument and optional JWT from second argument | |
| ROUTER_NAME="$1" | |
| JWT_ARG="$2" | |
| # Colors for output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| NC='\033[0m' # No Color | |
| # Default values | |
| DEFAULT_PORT=3022 | |
| COMPOSE_URL="https://get.openziti.io/dist/docker-images/ziti-router/compose.yml" | |
| # Function to print colored messages | |
| print_info() { | |
| echo -e "${BLUE}ℹ${NC} $1" | |
| } | |
| print_success() { | |
| echo -e "${GREEN}✓${NC} $1" | |
| } | |
| print_warning() { | |
| echo -e "${YELLOW}⚠${NC} $1" | |
| } | |
| print_error() { | |
| echo -e "${RED}✗${NC} $1" | |
| } | |
| print_header() { | |
| echo "" | |
| echo -e "${BLUE}═══════════════════════════════════════════════${NC}" | |
| echo -e "${BLUE} Ziti Router Deployment${NC}" | |
| echo -e "${BLUE}═══════════════════════════════════════════════${NC}" | |
| echo "" | |
| } | |
| # Check if required commands are available | |
| check_requirements() { | |
| local missing_deps=() | |
| if ! command -v docker &> /dev/null; then | |
| missing_deps+=("docker") | |
| fi | |
| if ! command -v curl &> /dev/null; then | |
| missing_deps+=("curl") | |
| fi | |
| if [ ${#missing_deps[@]} -ne 0 ]; then | |
| print_error "Missing required dependencies: ${missing_deps[*]}" | |
| print_info "Please install the missing dependencies and try again." | |
| exit 1 | |
| fi | |
| } | |
| # Detect external IP address | |
| detect_external_ip() { | |
| local ip="" | |
| local services=( | |
| "https://api.ipify.org" | |
| "https://ifconfig.me" | |
| "https://icanhazip.com" | |
| "https://ipecho.net/plain" | |
| ) | |
| print_info "Detecting external IP address..." >&2 | |
| for service in "${services[@]}"; do | |
| ip=$(curl -s --max-time 5 "$service" 2>/dev/null || echo "") | |
| if [ -n "$ip" ] && [[ "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| print_success "Detected external IP: $ip" >&2 | |
| echo "$ip" | |
| return 0 | |
| fi | |
| done | |
| print_error "Failed to detect external IP address" >&2 | |
| return 1 | |
| } | |
| # Prompt for JWT token | |
| get_jwt_token() { | |
| echo "" >&2 | |
| print_info "Please paste your Ziti router enrollment JWT token below." >&2 | |
| print_info "Press ENTER when done." >&2 | |
| echo "" >&2 | |
| echo -n "JWT Token: " >&2 | |
| # Read the JWT token (hidden input) | |
| local jwt="" | |
| read -r -s jwt | |
| echo "" >&2 | |
| # Validate JWT (basic check - should start with "eyJ") | |
| if [[ ! "$jwt" =~ ^eyJ ]]; then | |
| print_error "Invalid JWT token format. JWT tokens should start with 'eyJ'." >&2 | |
| return 1 | |
| fi | |
| if [ ${#jwt} -lt 100 ]; then | |
| print_error "JWT token appears too short. Please verify and try again." >&2 | |
| return 1 | |
| fi | |
| print_success "JWT token received" >&2 | |
| echo "$jwt" | |
| } | |
| # Generate sslip.io address | |
| generate_sslip_address() { | |
| local ip="$1" | |
| local sslip_address="${ip//./-}.sslip.io" | |
| echo "$sslip_address" | |
| } | |
| # Confirm or override value | |
| confirm_or_override() { | |
| local prompt="$1" | |
| local default_value="$2" | |
| local value="" | |
| echo "" >&2 | |
| echo -e "${BLUE}${prompt}${NC} [${default_value}]: " >&2 | |
| read -r value | |
| if [ -z "$value" ]; then | |
| echo "$default_value" | |
| else | |
| echo "$value" | |
| fi | |
| } | |
| # Create temporary directory for JWT | |
| create_temp_jwt_file() { | |
| local jwt="$1" | |
| local temp_file=$(mktemp) | |
| echo "$jwt" > "$temp_file" | |
| echo "$temp_file" | |
| } | |
| # Main deployment function | |
| main() { | |
| print_header | |
| # Check if router name was provided | |
| if [ -z "$ROUTER_NAME" ]; then | |
| print_error "Router name is required" | |
| print_info "Usage: /bin/bash -c \"\$(curl -fsSL <script-url>)\" - <router-name>" | |
| exit 1 | |
| fi | |
| # Validate router name format (only letters, numbers, hyphens, and underscores) | |
| if [[ ! "$ROUTER_NAME" =~ ^[a-zA-Z0-9_-]+$ ]]; then | |
| print_error "Invalid router name: '$ROUTER_NAME'" | |
| print_info "Router names can only contain letters, numbers, hyphens (-), and underscores (_)" | |
| exit 1 | |
| fi | |
| print_info "Router name: $ROUTER_NAME" | |
| # Check requirements | |
| check_requirements | |
| # Get JWT token (from argument or prompt) | |
| if [ -n "$JWT_ARG" ]; then | |
| JWT="$JWT_ARG" | |
| print_success "JWT token received from argument" | |
| # Validate JWT (basic check - should start with "eyJ") | |
| if [[ ! "$JWT" =~ ^eyJ ]]; then | |
| print_error "Invalid JWT token format. JWT tokens should start with 'eyJ'." | |
| exit 1 | |
| fi | |
| if [ ${#JWT} -lt 100 ]; then | |
| print_error "JWT token appears too short. Please verify and try again." | |
| exit 1 | |
| fi | |
| else | |
| JWT=$(get_jwt_token) | |
| if [ $? -ne 0 ]; then | |
| exit 1 | |
| fi | |
| fi | |
| # Detect external IP | |
| EXTERNAL_IP=$(detect_external_ip) | |
| if [ $? -ne 0 ]; then | |
| EXTERNAL_IP="" | |
| fi | |
| # Generate sslip address | |
| if [ -n "$EXTERNAL_IP" ]; then | |
| SSLIP_ADDRESS=$(generate_sslip_address "$EXTERNAL_IP") | |
| print_success "Generated sslip.io address: $SSLIP_ADDRESS" | |
| else | |
| SSLIP_ADDRESS="" | |
| fi | |
| # Confirm or override advertised address | |
| if [ -n "$SSLIP_ADDRESS" ]; then | |
| ROUTER_ADDRESS=$(confirm_or_override "Router advertised address" "$SSLIP_ADDRESS") | |
| else | |
| print_warning "Could not detect external IP. Please enter the router's advertised address manually." | |
| echo -e "${BLUE}Router advertised address${NC}: " >&2 | |
| read -r ROUTER_ADDRESS | |
| if [ -z "$ROUTER_ADDRESS" ]; then | |
| print_error "Router advertised address is required." | |
| exit 1 | |
| fi | |
| fi | |
| # Confirm or override port | |
| ROUTER_PORT=$(confirm_or_override "Router port" "$DEFAULT_PORT") | |
| # Validate port number | |
| if ! [[ "$ROUTER_PORT" =~ ^[0-9]+$ ]] || [ "$ROUTER_PORT" -lt 1 ] || [ "$ROUTER_PORT" -gt 65535 ]; then | |
| print_error "Invalid port number: $ROUTER_PORT" | |
| exit 1 | |
| fi | |
| echo "" | |
| print_info "Configuration Summary:" | |
| echo " Router Name: $ROUTER_NAME" | |
| echo " Advertised Address: $ROUTER_ADDRESS" | |
| echo " Port: $ROUTER_PORT" | |
| echo "" | |
| echo -e "${YELLOW}Proceed with deployment? [y/N]:${NC} " >&2 | |
| read -r confirm | |
| if [[ ! "$confirm" =~ ^[Yy]$ ]]; then | |
| print_warning "Deployment cancelled." | |
| exit 0 | |
| fi | |
| # Create router directory | |
| print_info "Creating router directory: $ROUTER_NAME" | |
| if [ -d "$ROUTER_NAME" ]; then | |
| print_warning "Directory '$ROUTER_NAME' already exists" | |
| echo -e "${YELLOW}Overwrite existing directory? [y/N]:${NC} " >&2 | |
| read -r overwrite | |
| if [[ ! "$overwrite" =~ ^[Yy]$ ]]; then | |
| print_warning "Deployment cancelled." | |
| exit 0 | |
| fi | |
| fi | |
| mkdir -p "$ROUTER_NAME" | |
| cd "$ROUTER_NAME" | |
| print_success "Router directory created and navigated to: $(pwd)" | |
| # Download compose file | |
| print_info "Downloading Ziti router compose file..." | |
| if ! curl -fsSL "$COMPOSE_URL" -o docker-compose.yml; then | |
| print_error "Failed to download compose file from $COMPOSE_URL" | |
| cd .. | |
| rm -rf "$ROUTER_NAME" | |
| exit 1 | |
| fi | |
| print_success "Compose file downloaded as docker-compose.yml" | |
| # Run docker compose | |
| echo "" | |
| print_info "Starting Ziti router with Docker Compose..." | |
| echo "" | |
| export ZITI_ENROLL_TOKEN="$JWT" | |
| export ZITI_ROUTER_ADVERTISED_ADDRESS="$ROUTER_ADDRESS" | |
| export ZITI_ROUTER_PORT="$ROUTER_PORT" | |
| if docker compose up -d; then | |
| echo "" | |
| print_success "Ziti router deployed successfully!" | |
| echo "" | |
| print_info "Router Details:" | |
| echo " Name: $ROUTER_NAME" | |
| echo " Directory: $(pwd)" | |
| echo " Advertised Address: $ROUTER_ADDRESS" | |
| echo " Port: $ROUTER_PORT" | |
| echo "" | |
| print_info "Useful Commands (run from $ROUTER_NAME directory):" | |
| echo " View logs: docker compose logs -f" | |
| echo " Stop router: docker compose down" | |
| echo " Restart router: docker compose restart" | |
| echo "" | |
| else | |
| print_error "Failed to start router with Docker Compose" | |
| cd .. | |
| rm -rf "$ROUTER_NAME" | |
| exit 1 | |
| fi | |
| } | |
| # Run main function | |
| main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment