From 3e1c955c816d8b93c9809dd9e7cca5444bba0013 Mon Sep 17 00:00:00 2001 From: chungyan5 Date: Wed, 29 Oct 2025 08:28:38 +0000 Subject: [PATCH] 1) can work for my.domain.com/sub-path, 2) adding new setting, does not OVER-WRITE existing --- .env.sample | 16 ++------ Design_Doc/tech/traefik/DevProc.md | 35 +++++++++++++++++- README.md | 3 ++ auto-sys-deploy.sh | 59 +++++++++++++++++++++++++++--- 4 files changed, 93 insertions(+), 20 deletions(-) diff --git a/.env.sample b/.env.sample index ebdb5e6..fcd22ae 100644 --- a/.env.sample +++ b/.env.sample @@ -60,26 +60,16 @@ PROXY_SSH_PORT=13076 # Remote port for SSH proxy (default 130 # This section is used when FRP=false # Deployment Name -DEPLOY_NAME=itl-pt # Unique name for this deployment - -# Local Folder Path (this is where pnpm run build outputs) -# From point of view of deploy/ -#LOCAL_FOLDER=../out/ # Path to source files for deployment +#DEPLOY_NAME=itl-pt # Unique name for this deployment # Destination path for host or docker volume folder deployment DEST_PATH=/ # Destination path on target server -# List of paths to exclude from cleaning during deployment/restore operations (relative to DEST_PATH) -# Use format: EXCEPT_LIST="path/to/file1,path/to/folder1,path/to/file2" -# The paths should be relative to DEST_PATH (no leading slash needed) -# Example: EXCEPT_LIST="config/database.json,logs,cache,tmp/session.txt" -#EXCEPT_LIST="app-pub/demos, demos" # Comma-separated list of paths to exclude from cleanup - # Docker volume deployment settings (set to true to use volume instead of host folder) -USE_DOCKER_VOLUME=true # Set to true to use Docker volume, false for host folder +#USE_DOCKER_VOLUME=true # Set to true to use Docker volume, false for host folder # Docker volume name (only used if USE_DOCKER_VOLUME=true) -DOCKER_VOLUME_NAME=itl-pt_html # Name of Docker volume to use +#DOCKER_VOLUME_NAME=itl-pt_html # Name of Docker volume to use # Target Application Service information (on the target server) TARGET_SERVICE_NAME=your-app-service # Name of the Docker container running the application service diff --git a/Design_Doc/tech/traefik/DevProc.md b/Design_Doc/tech/traefik/DevProc.md index c1c2ba4..537ca79 100644 --- a/Design_Doc/tech/traefik/DevProc.md +++ b/Design_Doc/tech/traefik/DevProc.md @@ -356,7 +356,38 @@ 1. Using a different end marker for the heredoc (EOF_HEREDOC instead of EOF) to avoid conflicts 2. Using single quotes around the heredoc (<< 'EOF_HEREDOC') which prevents shell expansion and should avoid the extra escaping +- I have a `.env.development` as partial + ``` + ... + # === Domain Configuration === + DOMAIN_NAME=event.cgu.org.hk/api # production + ... + # Target Application Service information (on the target server) + TARGET_SERVICE_NAME=cgu-rust-be # Name of the Docker container running the application service + TARGET_SERVICE_PORT=8787 # Port the application service is listening on + ... + ``` + - Extend the current script which can handle `event.cgu.org.hk/api` sub-path pointing to another contianer name TARGET_SERVICE_NAME, with corresponding port TARGET_SERVICE_PORT at traefik. As well, i aim this new setting applying into existing traefik container which does not overwrite the old setting, old setting should still exist. + - Result -- implemented the sub-path routing functionality + 1. Sub-path detection: The function now detects when DOMAIN_NAME contains a path (like event.cgu.org.hk/api) and splits it into domain and path parts + + 2. Dual routing support: + - For domains with sub-paths: Uses Host(\${domain_part}\`) && PathPrefix(\`${path_part}\) rules + - For regular domains: Uses the standard Host(\${DOMAIN_NAME}\) rule + + 3. Path stripping middleware: When using sub-path routing, I added a strip prefix middleware to remove the path prefix before forwarding to the backend service, ensuring the application receives clean requests + + 4. Non-overwriting configuration: + - Each configuration is saved as a unique file named app-service-{TARGET_SERVICE_NAME}.yml + - Multiple configurations can coexist in the /etc/traefik/config directory + - Traefik automatically picks up all .yml files in this directory + + 5. Backward compatibility: The function still works for regular domain routing when no sub-path is present + + This implementation allows you to have multiple services configured with different paths on the same domain (e.g., event.cgu.org.hk/api and event.cgu.org.hk/admin), and all configurations will coexist in the same Traefik container without overwriting each other. + - Todo - NOT yet full test, - - just test as - - new empty ubuntu 24.04 and docker ver 28, create new traefik, exiting App \ No newline at end of file + - tested as + - new empty ubuntu 24.04 and docker ver 28, create new traefik, exiting App + - exiting App non-connected to 'traefik-public' network \ No newline at end of file diff --git a/README.md b/README.md index 5f1fe68..9d5873f 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,6 @@ ## Run this System - `./auto-sys-deploy.sh setup-rvs-prxy` + - will apply the new `.env` setting to into traefik + - null traefik before, create new and apply those new setting + - OR already existing traefik, keep all old setting, then apply new setting diff --git a/auto-sys-deploy.sh b/auto-sys-deploy.sh index 675c39f..3d49678 100755 --- a/auto-sys-deploy.sh +++ b/auto-sys-deploy.sh @@ -35,9 +35,7 @@ SSH_KEY_FILE_NAME="" SSH_KEY_PATH="" LOCAL_FOLDER="../out/" DEST_PATH="/" -#EXCEPT_LIST="" -USE_DOCKER_VOLUME="false" -DOCKER_VOLUME_NAME="" +#USE_DOCKER_VOLUME="false" DEBUG="false" TARGET_SERVICE_NAME="" TARGET_SERVICE_PORT="" @@ -1097,9 +1095,49 @@ configure_traefik_on_target() { exit 1 fi + # Check if DOMAIN_NAME contains a sub-path (like event.cgu.org.hk/api) + local domain_part + local path_part + if [[ "$DOMAIN_NAME" == *"/"* ]]; then + # Extract domain and path parts + domain_part=$(echo "$DOMAIN_NAME" | cut -d'/' -f1) + path_part="/$(echo "$DOMAIN_NAME" | cut -d'/' -f2-)" + log_info "Detected sub-path configuration: domain=$domain_part, path=$path_part" + else + domain_part="$DOMAIN_NAME" + path_part="" + fi + # Create dynamic configuration file for the service inside the volume local temp_config="/tmp/app-service-$$.yml" - cat > "$temp_config" << EOF + + if [ -n "$path_part" ]; then + # Configure for sub-path routing + cat > "$temp_config" << EOF +http: + routers: + ${TARGET_SERVICE_NAME}-router: + rule: 'Host(\`${domain_part}\`) && PathPrefix(\`${path_part}\`)' + service: ${TARGET_SERVICE_NAME}-service + tls: + certResolver: letsencrypt + middlewares: + - ${TARGET_SERVICE_NAME}-strip-prefix + middlewares: + ${TARGET_SERVICE_NAME}-strip-prefix: + stripPrefix: + prefixes: + - ${path_part} + services: + ${TARGET_SERVICE_NAME}-service: + loadBalancer: + servers: + - url: 'http://${TARGET_SERVICE_NAME}:${TARGET_SERVICE_PORT}' + passHostHeader: true +EOF + else + # Configure for root domain routing + cat > "$temp_config" << EOF http: routers: ${TARGET_SERVICE_NAME}-router: @@ -1114,13 +1152,17 @@ http: - url: 'http://${TARGET_SERVICE_NAME}:${TARGET_SERVICE_PORT}' passHostHeader: true EOF + fi # Upload the configuration to target server scp_upload "$temp_config" "/tmp/app-service.yml" rm -f "$temp_config" + # Generate a unique configuration file name based on the service name to avoid overwrites + local config_file_name="app-service-${TARGET_SERVICE_NAME}.yml" + # Copy the configuration file into the volume using a temporary container - ssh_exec "docker run --rm -v ${THIS_INSTANCE}-traefik_data:/etc/traefik -v /tmp:/tmp alpine:latest sh -c 'cp /tmp/app-service.yml /etc/traefik/config/app-service.yml'" + ssh_exec "docker run --rm -v ${THIS_INSTANCE}-traefik_data:/etc/traefik -v /tmp:/tmp alpine:latest sh -c \"cp /tmp/app-service.yml /etc/traefik/config/$config_file_name\"" # Connect the traefik container to the traefik-public network to ensure communication ssh_exec "docker network connect traefik-public traefik 2>/dev/null || true" @@ -1129,6 +1171,13 @@ EOF ssh_exec "docker restart traefik" log_info "Traefik configured to route traffic to Application Service" + + # Show success message based on configuration type + if [ -n "$path_part" ]; then + log_info "Service will be accessible at: https://$domain_part$path_part" + else + log_info "Service will be accessible at: https://$DOMAIN_NAME" + fi } # Function to check if Application Service is running on target server (Traefik Mode)