1) dynamic to add ENTRYPOINTS, 2) fixed the bug by manage cmd to remove sub-domain / domain
This commit is contained in:
parent
d825a46ded
commit
20c55e0c4b
File diff suppressed because it is too large
Load Diff
@ -241,6 +241,116 @@ Select configurations to remove (enter numbers separated by space, or 'q' to qui
|
|||||||
- Domain removal does not require Traefik restart (dynamic config removal)
|
- Domain removal does not require Traefik restart (dynamic config removal)
|
||||||
- All changes are permanent and cannot be undone - make sure you want to remove before confirming
|
- All changes are permanent and cannot be undone - make sure you want to remove before confirming
|
||||||
|
|
||||||
|
### Step 6: Configure Extra Traefik Entrypoints (QUIC, Custom Ports, etc.)
|
||||||
|
|
||||||
|
Beyond the default entrypoints (`web` on :80, `websecure` on :443), you can add extra entrypoints such as HTTP/3 QUIC (UDP 443) or other custom protocols. Entrypoints are defined via command-line arguments to the Traefik container, so the container must be recreated to apply them.
|
||||||
|
|
||||||
|
**Configuration Variable:**
|
||||||
|
- `EXTRA_ENTRYPOINTS` in `.env.rvs-prxy` (global proxy config) or per-domain `.env-<domain>` files
|
||||||
|
- Format: `name=:port/protocol,name2=:port` (comma-separated)
|
||||||
|
- Protocol defaults to `tcp` if omitted; use `/udp` for UDP entrypoints
|
||||||
|
- Example: `quic=:443/udp` creates entrypoint `quic` listening on UDP port 443
|
||||||
|
- Example: `quic=:443/udp, mqtt=:1883` adds both QUIC and a custom TCP entrypoint on port 1883
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Scenario A: First-Time Setup (Traefik Not Yet Created)
|
||||||
|
|
||||||
|
The wizard asks for extra entrypoints during the Traefik configuration step. You can also pre-configure them:
|
||||||
|
|
||||||
|
1. Create `.env.rvs-prxy` with the entrypoints setting:
|
||||||
|
```bash
|
||||||
|
EXTRA_ENTRYPOINTS="quic=:443/udp"
|
||||||
|
```
|
||||||
|
2. Run the script as usual:
|
||||||
|
```bash
|
||||||
|
curl -s "https://www.ivantito.com/app-pub/demos/test/deploy-rvs-prxy.sh" | bash
|
||||||
|
```
|
||||||
|
3. **What happens:**
|
||||||
|
- The docker-compose.yml generated by the script includes the extra entrypoints in the `command:` section and their port mappings in the `ports:` section
|
||||||
|
- The Traefik container starts with `--entrypoints.quic.address=:443/udp` and `-p 443:443/udp`
|
||||||
|
- Both TCP and UDP on port 443 are now mapped (QUIC shares port 443 with HTTPS)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Scenario B: Running Traefik — Add New Extra Entrypoints
|
||||||
|
|
||||||
|
To add a new entrypoint (e.g., QUIC) to a Traefik container that is already running:
|
||||||
|
|
||||||
|
1. Set `EXTRA_ENTRYPOINTS` in `.env.rvs-prxy` (proxy config) or in the per-domain `.env-<domain>` file:
|
||||||
|
```bash
|
||||||
|
EXTRA_ENTRYPOINTS="quic=:443/udp"
|
||||||
|
```
|
||||||
|
If the variable already has values, add the new one with a comma:
|
||||||
|
```bash
|
||||||
|
EXTRA_ENTRYPOINTS="quic=:443/udp, mqtt=:1883"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Run the script:
|
||||||
|
```bash
|
||||||
|
curl -s "https://www.ivantito.com/app-pub/demos/test/deploy-rvs-prxy.sh" | bash
|
||||||
|
```
|
||||||
|
The script detects the running Traefik container and checks if `EXTRA_ENTRYPOINTS` has changed.
|
||||||
|
|
||||||
|
3. **What happens:**
|
||||||
|
- The script calls `parse_extra_entrypoints()` which parses the variable
|
||||||
|
- It inspects the current Traefik container's command-line args
|
||||||
|
- If any extra entrypoints are missing from the running container, the script:
|
||||||
|
1. Stops and removes the current Traefik container (data in `traefik_data` volume is preserved)
|
||||||
|
2. Recreates the container with all standard entrypoints plus the new extra entrypoints and their port mappings
|
||||||
|
- Brief downtime (~5 seconds) while the container is recreated
|
||||||
|
- Existing domain routing and port exposure configurations remain intact (they are stored in the volume)
|
||||||
|
|
||||||
|
4. **Expected output** (proxy setup mode — `deploy-rvs-prxy.sh`):
|
||||||
|
```
|
||||||
|
[INFO] Extra entrypoints changed, recreating Traefik container to apply...
|
||||||
|
[INFO] Updating Traefik container...
|
||||||
|
[INFO] Traefik container recreated with new entry points
|
||||||
|
```
|
||||||
|
**Expected output** (domain setup mode — `.env-p2prly1-ivantito-com`):
|
||||||
|
```
|
||||||
|
[INFO] Loading domain config from .env-p2prly1-ivantito-com
|
||||||
|
[INFO] Detected running Traefik reverse proxy
|
||||||
|
[INFO] Extra entrypoints changed, recreating Traefik container to apply...
|
||||||
|
[INFO] Checking if Application Service is running locally...
|
||||||
|
...
|
||||||
|
[INFO] Traefik configured to route traffic to Application Service
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Verify the new entrypoint is active:**
|
||||||
|
```bash
|
||||||
|
# Check container args for entrypoint definitions
|
||||||
|
docker inspect traefik --format '{{range .Config.Cmd}}{{println .}}{{end}}' | grep entrypoints
|
||||||
|
# Should show: --entrypoints.quic.address=:443/udp
|
||||||
|
|
||||||
|
# Check port mappings (TCP and UDP on 443)
|
||||||
|
docker port traefik
|
||||||
|
# Should show: 443/tcp → 0.0.0.0:443 and 443/udp → 0.0.0.0:443
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Scenario C: Running Traefik — Remove an Extra Entrypoint
|
||||||
|
|
||||||
|
1. Edit `.env.rvs-prxy` and remove the entrypoint from `EXTRA_ENTRYPOINTS`
|
||||||
|
2. Run the script to trigger the recreation with the updated entrypoints (same as Scenario B steps 2-4)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Scenario D: Running Traefik — Add/Remove During Port Exposure Setup
|
||||||
|
|
||||||
|
When you use port exposure (`--manage` or `.env-port-<port>`), the `add_traefik_entry_point()` and `manage_configurations()` functions automatically preserve all `EXTRA_ENTRYPOINTS`. Extra entrypoints are re-injected whenever the Traefik container is recreated for port operations, so they are never lost.
|
||||||
|
|
||||||
|
**No additional steps needed** — extra entrypoints configured in `.env.rvs-prxy` are automatically preserved across all port management operations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Important Notes:**
|
||||||
|
- Recreating the Traefik container causes ~5 seconds of downtime
|
||||||
|
- The `traefik_data` volume (config files, SSL certificates, ACME data) is preserved across recreations
|
||||||
|
- `EXTRA_ENTRYPOINTS` adds entrypoints to the Traefik container's command-line args. When a domain config also has a UDP port in `LOCAL_SERVICE_PORT` (e.g., `80,4443/udp`), the script automatically creates a Traefik UDP router in the domain config, so no manual routing setup is needed for that UDP port
|
||||||
|
- For port-mapped entrypoints (like port-exposure), existing `--manage` flows already handle adding/removing
|
||||||
|
|
||||||
## Run this System
|
## Run this System
|
||||||
|
|
||||||
### Using with curl (Remote Execution)
|
### Using with curl (Remote Execution)
|
||||||
@ -400,6 +510,8 @@ When the FRP reverse proxy is already running, you can add new domains:
|
|||||||
- **Configuration Files:**
|
- **Configuration Files:**
|
||||||
- `.env.rvs-prxy` - Reverse proxy instance configuration (contains `INSTANCE_NAME`, `FRP_SERVER_ADDR`, etc.)
|
- `.env.rvs-prxy` - Reverse proxy instance configuration (contains `INSTANCE_NAME`, `FRP_SERVER_ADDR`, etc.)
|
||||||
- `.env-<domain>` - Domain-specific configuration (contains `DOMAIN_NAME`, `LOCAL_SERVICE_NAME`, `LOCAL_SERVICE_PORT`)
|
- `.env-<domain>` - Domain-specific configuration (contains `DOMAIN_NAME`, `LOCAL_SERVICE_NAME`, `LOCAL_SERVICE_PORT`)
|
||||||
|
- `LOCAL_SERVICE_PORT` supports comma-separated ports with protocol: `80` or `80,4443/udp`
|
||||||
|
- First TCP port is used for HTTPS routing; additional UDP ports get automatic Traefik UDP router config
|
||||||
|
|
||||||
- **What Happens:**
|
- **What Happens:**
|
||||||
- A new TCP proxy is added to frpc.toml for the domain's service
|
- A new TCP proxy is added to frpc.toml for the domain's service
|
||||||
@ -428,6 +540,9 @@ If environment variables are not set, the script will prompt for:
|
|||||||
|
|
||||||
#### Traefik Container (Traefik Mode)
|
#### Traefik Container (Traefik Mode)
|
||||||
|
|
||||||
|
**Entrypoints:**
|
||||||
|
Default entrypoints are `web` (:80) and `websecure` (:443). See **[Step 6: Configure Extra Traefik Entrypoints](#step-6-configure-extra-traefik-entrypoints-quic-custom-ports-etc)** for a complete guide on adding/removing extra entrypoints (QUIC, custom ports, etc.) during both first-time setup and on a running Traefik container.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Start/run container
|
# Start/run container
|
||||||
docker run -d --name traefik --restart=unless-stopped \
|
docker run -d --name traefik --restart=unless-stopped \
|
||||||
@ -453,8 +568,11 @@ docker inspect traefik
|
|||||||
# Remove container
|
# Remove container
|
||||||
docker rm -f traefik
|
docker rm -f traefik
|
||||||
|
|
||||||
# Access Traefik Dashboard
|
# Access Traefik Dashboard (port from DASHBOARD_PORT, default 18080)
|
||||||
http://localhost:8080
|
http://localhost:${DASHBOARD_PORT:-18080}/dashboard/
|
||||||
|
|
||||||
|
# Check docker-compose.yml used to create the container (preserved after each run)
|
||||||
|
cat /tmp/docker-compose.yml
|
||||||
|
|
||||||
# Complete removal (including data)
|
# Complete removal (including data)
|
||||||
docker rm -f traefik
|
docker rm -f traefik
|
||||||
|
|||||||
@ -109,13 +109,15 @@
|
|||||||
**Required Variables (only 3):**
|
**Required Variables (only 3):**
|
||||||
- `DOMAIN_NAME` - Domain name for reverse proxy routing (e.g., `app.example.com`)
|
- `DOMAIN_NAME` - Domain name for reverse proxy routing (e.g., `app.example.com`)
|
||||||
- `LOCAL_SERVICE_NAME` - Name of the local Docker application container
|
- `LOCAL_SERVICE_NAME` - Name of the local Docker application container
|
||||||
- `LOCAL_SERVICE_PORT` - Port number of the local application service
|
- `LOCAL_SERVICE_PORT` - Port(s) of the local application service, comma-separated with optional protocol suffix (e.g., `80` or `80,4443/udp`)
|
||||||
|
|
||||||
**Example `.env-app-example-com`:**
|
**Example `.env-app-example-com`:**
|
||||||
```bash
|
```bash
|
||||||
DOMAIN_NAME="app.example.com"
|
DOMAIN_NAME="app.example.com"
|
||||||
LOCAL_SERVICE_NAME="my-app-container"
|
LOCAL_SERVICE_NAME="my-app-container"
|
||||||
LOCAL_SERVICE_PORT="3000"
|
LOCAL_SERVICE_PORT="3000" # Single port (TCP)
|
||||||
|
# LOCAL_SERVICE_PORT="80,4443/udp" # Multiple ports (TCP + UDP)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Reverse Proxy Instance Configuration (`.env.rvs-prxy`):**
|
**Reverse Proxy Instance Configuration (`.env.rvs-prxy`):**
|
||||||
@ -127,6 +129,7 @@ LOCAL_SERVICE_PORT="3000"
|
|||||||
- `INSTANCE_NAME` - Container name for Traefik instance (default: `traefik`)
|
- `INSTANCE_NAME` - Container name for Traefik instance (default: `traefik`)
|
||||||
- `DOCKER_NETWORK` - Docker network name for container connectivity (default: `traefik-public`)
|
- `DOCKER_NETWORK` - Docker network name for container connectivity (default: `traefik-public`)
|
||||||
- `DASHBOARD_PORT` - Traefik dashboard port exposed on localhost (default: `18080`)
|
- `DASHBOARD_PORT` - Traefik dashboard port exposed on localhost (default: `18080`)
|
||||||
|
- `EXTRA_ENTRYPOINTS` - Additional Traefik entrypoints beyond defaults (web/websecure), format: `name=:port/protocol,name2=:port`, e.g., `quic=:443/udp` for HTTP/3 QUIC support (default: empty). Can be set in `.env.rvs-prxy` or per-domain `.env-<domain>` files
|
||||||
- `TRAEFIK_VER` - Traefik version (default: `v3.6.9`)
|
- `TRAEFIK_VER` - Traefik version (default: `v3.6.9`)
|
||||||
- `LETSENCRYPT_EMAIL` - Email for Let's Encrypt certificates
|
- `LETSENCRYPT_EMAIL` - Email for Let's Encrypt certificates
|
||||||
- `RESTART_TRAEFIK` - Whether to restart Traefik after config update (`true`/`false`, default: `false`)
|
- `RESTART_TRAEFIK` - Whether to restart Traefik after config update (`true`/`false`, default: `false`)
|
||||||
@ -146,7 +149,7 @@ LOCAL_SERVICE_PORT="3000"
|
|||||||
**Required Variables:**
|
**Required Variables:**
|
||||||
- `DOMAIN_NAME` - Domain name for reverse proxy routing (e.g., `app.example.com`, `sub.domain.org.hk`)
|
- `DOMAIN_NAME` - Domain name for reverse proxy routing (e.g., `app.example.com`, `sub.domain.org.hk`)
|
||||||
- `LOCAL_SERVICE_NAME` - Name of the local Docker application container
|
- `LOCAL_SERVICE_NAME` - Name of the local Docker application container
|
||||||
- `LOCAL_SERVICE_PORT` - Port number of the local application service
|
- `LOCAL_SERVICE_PORT` - Port(s) of the local application service, comma-separated with optional protocol suffix (e.g., `80` or `80,4443/udp`)
|
||||||
|
|
||||||
**Port-Based Routing Configuration (`.env-port-<port>`):**
|
**Port-Based Routing Configuration (`.env-port-<port>`):**
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
|||||||
# Before Starting Any Work
|
# Before Starting Any Work
|
||||||
- Please read the following documents carefully **before taking any actions** on this project: `README.md`, `Design_Doc/Spec.md`, `Design_Doc/Operations.md` and `Design_Doc/Tech_Desc.md`. You may skip the `Design_Doc/Tech_Desc.md` -> "AI Prompt" section and its sub-sections when reading. These files provide essential background information and project understanding. Only after reviewing them should you proceed with the following tasks.
|
|
||||||
|
- Please read the following documents carefully **before taking any actions** on this project: `README.md`, `Design_Doc/Spec.md`, `Design_Doc/Operations.md` and `Design_Doc/Tech_Desc.md`. These files provide essential background information and project understanding. Only after reviewing them should you proceed with the following tasks.
|
||||||
|
|
||||||
# Your Current Tasks
|
# Your Current Tasks
|
||||||
- Listing the specific tasks for this session.
|
- Listing the specific tasks for this session.
|
||||||
@ -10,6 +11,7 @@ Whenever you finish making code changes, please take a few minutes to update the
|
|||||||
This keeps everything clear and up-to-date for everyone on the team.
|
This keeps everything clear and up-to-date for everyone on the team.
|
||||||
|
|
||||||
## Which files might need an update?
|
## Which files might need an update?
|
||||||
|
|
||||||
Only touch the files that your changes actually affect. The most common ones are:
|
Only touch the files that your changes actually affect. The most common ones are:
|
||||||
|
|
||||||
- `README.md`
|
- `README.md`
|
||||||
@ -18,45 +20,11 @@ Only touch the files that your changes actually affect. The most common ones are
|
|||||||
- `Design_Doc/Tech_Desc.md`
|
- `Design_Doc/Tech_Desc.md`
|
||||||
|
|
||||||
## How should you update them?
|
## How should you update them?
|
||||||
|
|
||||||
Just follow the style and purpose each file already has.
|
Just follow the style and purpose each file already has.
|
||||||
(You can check the "Documentation Overview" part in `README.md` if you're not sure.)
|
(You can check the "Documentation Overview" part in `README.md` if you're not sure.)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚠️ CRITICAL RULE for `Design_Doc/Tech_Desc.md` - The "AI Prompt" Section
|
BACKUP before you touch the above mentioned documents:
|
||||||
|
- you make a doc. backup folder `Design_Doc/bck/` if not exist, then before any your touch of documents, such as: `Design_Doc/Tech_Desc.md`, you copy that current version into eg. `Design_Doc/bck/Design_Doc/Tech_Desc_YYYYMMDDHHMMSS.md`. The other document files as same approach by keeping the path and file name with Date and Time at file name into backup folder.
|
||||||
**The "AI Prompt" section at the end of `Design_Doc/Tech_Desc.md` must NEVER be modified, deleted, or rewritten by you.**
|
|
||||||
|
|
||||||
### What is the "AI Prompt" section?
|
|
||||||
- It is the section that starts with `# AI Prompt` (level-1 heading)
|
|
||||||
- It is always located at the **very end** of `Design_Doc/Tech_Desc.md`
|
|
||||||
- It contains sub-sections like `## AI Prompt habit as a reminder`, `## Script Code`, `## Doc.`
|
|
||||||
- It contains **task history and instructions from previous sessions** written by the user
|
|
||||||
|
|
||||||
### Why must you NOT touch it?
|
|
||||||
- This section is **written and maintained by the user only**
|
|
||||||
- It contains **accumulated task history** that the user wants to preserve
|
|
||||||
- It is **not documentation** about the project - it is a **working log of tasks**
|
|
||||||
- Other team members (including the user) will update this section manually when needed
|
|
||||||
|
|
||||||
### What you MUST do:
|
|
||||||
✅ **Leave the "AI Prompt" section completely unchanged**
|
|
||||||
✅ **Keep the exact content** that is currently there (do not revert, do not update, do not clean up)
|
|
||||||
✅ **Only edit the technical documentation sections** that come BEFORE the "AI Prompt" section
|
|
||||||
✅ **Ensure "AI Prompt" stays at the end** of the file (do not move it)
|
|
||||||
|
|
||||||
### What you MUST NOT do:
|
|
||||||
❌ **Do NOT delete** the "AI Prompt" section
|
|
||||||
❌ **Do NOT modify** any words, sentences, or formatting inside "AI Prompt"
|
|
||||||
❌ **Do NOT revert** it to an older version
|
|
||||||
❌ **Do NOT clean up** or reorganize its content
|
|
||||||
❌ **Do NOT add** new task results to it (the user does this manually)
|
|
||||||
❌ **Do NOT remove** task history from it
|
|
||||||
|
|
||||||
### Simple rule to remember:
|
|
||||||
> **Everything before `# AI Prompt` = Your responsibility to update**
|
|
||||||
> **Everything from `# AI Prompt` to the end = User's responsibility, DO NOT TOUCH**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Thank you so much for helping keep the documents accurate and the task history preserved — it makes a big difference to the whole team!
|
|
||||||
@ -34,6 +34,12 @@ INSTANCE_NAME="traefik" # Default container name, can be overridden in .env.rvs
|
|||||||
DOCKER_NETWORK="${DOCKER_NETWORK}" # Default Docker network name, can be overridden in .env.rvs-prxy
|
DOCKER_NETWORK="${DOCKER_NETWORK}" # Default Docker network name, can be overridden in .env.rvs-prxy
|
||||||
DASHBOARD_PORT="18080" # Default dashboard port, can be overridden in .env.rvs-prxy
|
DASHBOARD_PORT="18080" # Default dashboard port, can be overridden in .env.rvs-prxy
|
||||||
|
|
||||||
|
# Extra entrypoints beyond default web (:80/tcp) and websecure (:443/tcp)
|
||||||
|
# Format: comma-separated list of name=address
|
||||||
|
# Example: "quic=:443/udp, custom-tcp=:8888"
|
||||||
|
# Address format: :port or :port/protocol (default protocol: tcp)
|
||||||
|
EXTRA_ENTRYPOINTS=""
|
||||||
|
|
||||||
# Target server variables (for Traefik mode - now running locally)
|
# Target server variables (for Traefik mode - now running locally)
|
||||||
LOCAL_SERVICE_NAME=""
|
LOCAL_SERVICE_NAME=""
|
||||||
LOCAL_SERVICE_PORT=""
|
LOCAL_SERVICE_PORT=""
|
||||||
@ -411,14 +417,16 @@ interactive_setup_wizard() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Get service port
|
# Get service port(s)
|
||||||
echo -e "Enter your application's internal port:" >&2
|
echo -e "Enter your application's internal port(s):" >&2
|
||||||
|
echo -e " Single port: 80" >&2
|
||||||
|
echo -e " Multiple: 80,4443/udp (comma-separated, protocol defaults to tcp)" >&2
|
||||||
while [ -z "$LOCAL_SERVICE_PORT" ]; do
|
while [ -z "$LOCAL_SERVICE_PORT" ]; do
|
||||||
LOCAL_SERVICE_PORT=$(read_terminal "Service port (default: 3000): " "3000")
|
LOCAL_SERVICE_PORT=$(read_terminal "Service port (default: 3000): " "3000")
|
||||||
if [ -z "$LOCAL_SERVICE_PORT" ]; then
|
if [ -z "$LOCAL_SERVICE_PORT" ]; then
|
||||||
LOCAL_SERVICE_PORT="3000"
|
LOCAL_SERVICE_PORT="3000"
|
||||||
elif ! [[ "$LOCAL_SERVICE_PORT" =~ ^[0-9]+$ ]] || [ "$LOCAL_SERVICE_PORT" -lt 1 ] || [ "$LOCAL_SERVICE_PORT" -gt 65535 ]; then
|
elif ! [[ "$LOCAL_SERVICE_PORT" =~ ^[0-9]+(/tcp|/udp)?(,[0-9]+(/tcp|/udp)?)*$ ]]; then
|
||||||
echo -e "${RED}Invalid port. Please enter a number between 1 and 65535.${NC}" >&2
|
echo -e "${RED}Invalid format. Use comma-separated port/protocol, e.g. 80 or 80,4443/udp${NC}" >&2
|
||||||
LOCAL_SERVICE_PORT=""
|
LOCAL_SERVICE_PORT=""
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@ -578,6 +586,16 @@ interactive_setup_wizard() {
|
|||||||
save_to_env "LETSENCRYPT_EMAIL" "$LETSENCRYPT_EMAIL" ".env.rvs-prxy"
|
save_to_env "LETSENCRYPT_EMAIL" "$LETSENCRYPT_EMAIL" ".env.rvs-prxy"
|
||||||
echo "" >&2
|
echo "" >&2
|
||||||
|
|
||||||
|
# Extra entrypoints (e.g., QUIC)
|
||||||
|
echo -e "Extra Traefik entrypoints (optional):" >&2
|
||||||
|
echo -e " Format: name=:port/protocol (comma-separated)" >&2
|
||||||
|
echo -e " Example: quic=:443/udp enables HTTP/3 QUIC on port 443/udp" >&2
|
||||||
|
EXTRA_ENTRYPOINTS=$(read_terminal "Extra entrypoints (leave empty for none): " "")
|
||||||
|
if [ -n "$EXTRA_ENTRYPOINTS" ]; then
|
||||||
|
save_to_env "EXTRA_ENTRYPOINTS" "$EXTRA_ENTRYPOINTS" ".env.rvs-prxy"
|
||||||
|
fi
|
||||||
|
echo "" >&2
|
||||||
|
|
||||||
# Optional: Debug mode
|
# Optional: Debug mode
|
||||||
DEBUG_MODE=$(read_terminal "Enable debug mode? (y/N): " "n")
|
DEBUG_MODE=$(read_terminal "Enable debug mode? (y/N): " "n")
|
||||||
if [[ "$DEBUG_MODE" =~ ^[Yy]$ ]]; then
|
if [[ "$DEBUG_MODE" =~ ^[Yy]$ ]]; then
|
||||||
@ -1433,6 +1451,63 @@ local_volume_copy() {
|
|||||||
docker run --rm -v "$volume:$dest" -v "$(dirname "$source"):/tmp/source:ro" alpine:latest cp -r "/tmp/source/$(basename "$source")" "$dest/"
|
docker run --rm -v "$volume:$dest" -v "$(dirname "$source"):/tmp/source:ro" alpine:latest cp -r "/tmp/source/$(basename "$source")" "$dest/"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Function to parse EXTRA_ENTRYPOINTS variable and produce entrypoint args and port mappings
|
||||||
|
# Globals read: EXTRA_ENTRYPOINTS
|
||||||
|
# Globals set: EXTRA_ENTRYPOINT_ARGS (array of --entrypoints.NAME.address=ADDRESS)
|
||||||
|
# EXTRA_PORT_MAPPINGS (array of port mappings for docker-compose/docker-run)
|
||||||
|
# EXTRA_COMPOSE_ENTRYPOINTS (string of YAML command entries for compose)
|
||||||
|
# EXTRA_COMPOSE_PORTS (string of YAML port entries for compose)
|
||||||
|
parse_extra_entrypoints() {
|
||||||
|
EXTRA_ENTRYPOINT_ARGS=()
|
||||||
|
EXTRA_PORT_MAPPINGS=()
|
||||||
|
EXTRA_COMPOSE_ENTRYPOINTS=""
|
||||||
|
EXTRA_COMPOSE_PORTS=""
|
||||||
|
|
||||||
|
if [ -z "$EXTRA_ENTRYPOINTS" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local saved_ifs="$IFS"
|
||||||
|
IFS=','
|
||||||
|
for entry in $EXTRA_ENTRYPOINTS; do
|
||||||
|
IFS="$saved_ifs"
|
||||||
|
entry=$(echo "$entry" | xargs)
|
||||||
|
local name="${entry%%=*}"
|
||||||
|
local address="${entry#*=}"
|
||||||
|
address=$(echo "$address" | xargs)
|
||||||
|
|
||||||
|
# Determine port and protocol from address
|
||||||
|
local port="${address#:}"
|
||||||
|
local protocol="tcp"
|
||||||
|
if [[ "$port" == *"/"* ]]; then
|
||||||
|
protocol="${port#*/}"
|
||||||
|
port="${port%%/*}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build entrypoint arg
|
||||||
|
EXTRA_ENTRYPOINT_ARGS+=("--entrypoints.${name}.address=${address}")
|
||||||
|
|
||||||
|
# Build port mapping
|
||||||
|
if [ "$protocol" = "udp" ]; then
|
||||||
|
EXTRA_PORT_MAPPINGS+=("${port}:${port}/udp")
|
||||||
|
else
|
||||||
|
EXTRA_PORT_MAPPINGS+=("${port}:${port}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build compose YAML strings (with real newlines for heredoc expansion)
|
||||||
|
EXTRA_COMPOSE_ENTRYPOINTS="${EXTRA_COMPOSE_ENTRYPOINTS} - '--entrypoints.${name}.address=${address}'
|
||||||
|
"
|
||||||
|
if [ "$protocol" = "udp" ]; then
|
||||||
|
EXTRA_COMPOSE_PORTS="${EXTRA_COMPOSE_PORTS} - '${port}:${port}/udp'
|
||||||
|
"
|
||||||
|
else
|
||||||
|
EXTRA_COMPOSE_PORTS="${EXTRA_COMPOSE_PORTS} - '${port}:${port}'
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS="$saved_ifs"
|
||||||
|
}
|
||||||
|
|
||||||
# Function to check if Traefik container exists locally (Traefik Mode)
|
# Function to check if Traefik container exists locally (Traefik Mode)
|
||||||
check_traefik_container() {
|
check_traefik_container() {
|
||||||
log_info "Checking if Traefik container exists locally..."
|
log_info "Checking if Traefik container exists locally..."
|
||||||
@ -1464,8 +1539,33 @@ create_traefik_container_local() {
|
|||||||
|
|
||||||
if [ -n "$container_exists" ] && [ "$container_exists" = "$TRAEFIK_CONTAINER_NAME" ]; then
|
if [ -n "$container_exists" ] && [ "$container_exists" = "$TRAEFIK_CONTAINER_NAME" ]; then
|
||||||
log_info "Traefik container '$TRAEFIK_CONTAINER_NAME' already exists locally"
|
log_info "Traefik container '$TRAEFIK_CONTAINER_NAME' already exists locally"
|
||||||
# Only update the config files in the volume, don't recreate the container
|
|
||||||
log_info "Updating configuration in existing Traefik container..."
|
# Parse extra entrypoints and check if container needs recreation
|
||||||
|
parse_extra_entrypoints
|
||||||
|
if [ ${#EXTRA_ENTRYPOINT_ARGS[@]} -gt 0 ]; then
|
||||||
|
# Check if entrypoints are already in the container
|
||||||
|
local current_cmd
|
||||||
|
current_cmd=$(docker inspect traefik --format='{{json .Config.Cmd}}' 2>/dev/null || echo "[]")
|
||||||
|
local needs_recreate=false
|
||||||
|
for ep_arg in "${EXTRA_ENTRYPOINT_ARGS[@]}"; do
|
||||||
|
if ! echo "$current_cmd" | grep -qF -- "${ep_arg}"; then
|
||||||
|
needs_recreate=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$needs_recreate" = true ]; then
|
||||||
|
log_info "Extra entrypoints changed, recreating Traefik container to apply..."
|
||||||
|
# Re-enter the creation path by removing the container reference
|
||||||
|
docker stop traefik 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
docker rm traefik 2>/dev/null || true
|
||||||
|
container_exists=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$container_exists" ] && [ "$container_exists" = "$TRAEFIK_CONTAINER_NAME" ]; then
|
||||||
|
log_info "Traefik container '$TRAEFIK_CONTAINER_NAME' exists, updating configuration..."
|
||||||
|
|
||||||
# Use specified Traefik version or default to v3.6.9
|
# Use specified Traefik version or default to v3.6.9
|
||||||
local TRAEFIK_VER="${TRAEFIK_VER:-v3.6.9}"
|
local TRAEFIK_VER="${TRAEFIK_VER:-v3.6.9}"
|
||||||
@ -1575,6 +1675,9 @@ EOF_HEREDOC
|
|||||||
docker run --rm -v "$TRAEFIK_VOLUME_NAME:/etc/traefik" -v "/tmp:/tmp" alpine:latest sh -c 'mkdir -p /etc/traefik/config /etc/traefik/acme && cp /tmp/traefik.yml /etc/traefik/config/traefik.yml && touch /etc/traefik/acme/acme.json && chmod 600 /etc/traefik/acme/acme.json'
|
docker run --rm -v "$TRAEFIK_VOLUME_NAME:/etc/traefik" -v "/tmp:/tmp" alpine:latest sh -c 'mkdir -p /etc/traefik/config /etc/traefik/acme && cp /tmp/traefik.yml /etc/traefik/config/traefik.yml && touch /etc/traefik/acme/acme.json && chmod 600 /etc/traefik/acme/acme.json'
|
||||||
rm -f "$temp_config"
|
rm -f "$temp_config"
|
||||||
|
|
||||||
|
# Parse extra entrypoints for dynamic entrypoint/port configuration
|
||||||
|
parse_extra_entrypoints
|
||||||
|
|
||||||
# Determine Docker version to decide if we need the version field
|
# Determine Docker version to decide if we need the version field
|
||||||
local compose_version_field
|
local compose_version_field
|
||||||
docker_version=$(docker --version | sed 's/Docker version //' | sed 's/,.*//')
|
docker_version=$(docker --version | sed 's/Docker version //' | sed 's/,.*//')
|
||||||
@ -1607,7 +1710,7 @@ services:
|
|||||||
- '--providers.docker.exposedbydefault=false'
|
- '--providers.docker.exposedbydefault=false'
|
||||||
- '--entrypoints.web.address=:80'
|
- '--entrypoints.web.address=:80'
|
||||||
- '--entrypoints.websecure.address=:443'
|
- '--entrypoints.websecure.address=:443'
|
||||||
- '--certificatesresolvers.letsencrypt.acme.httpchallenge=true'
|
${EXTRA_COMPOSE_ENTRYPOINTS} - '--certificatesresolvers.letsencrypt.acme.httpchallenge=true'
|
||||||
- '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web'
|
- '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web'
|
||||||
- '--certificatesresolvers.letsencrypt.acme.email=$LETSENCRYPT_EMAIL'
|
- '--certificatesresolvers.letsencrypt.acme.email=$LETSENCRYPT_EMAIL'
|
||||||
- '--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json'
|
- '--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json'
|
||||||
@ -1616,7 +1719,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '80:80'
|
- '80:80'
|
||||||
- '443:443'
|
- '443:443'
|
||||||
- "127.0.0.1:${DASHBOARD_PORT}:8080" # Bind dashboard to localhost only for security
|
${EXTRA_COMPOSE_PORTS} - "127.0.0.1:${DASHBOARD_PORT}:8080" # Bind dashboard to localhost only for security
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
- $TRAEFIK_VOLUME_NAME:/etc/traefik
|
- $TRAEFIK_VOLUME_NAME:/etc/traefik
|
||||||
@ -1650,7 +1753,7 @@ services:
|
|||||||
- '--providers.docker.exposedbydefault=false'
|
- '--providers.docker.exposedbydefault=false'
|
||||||
- '--entrypoints.web.address=:80'
|
- '--entrypoints.web.address=:80'
|
||||||
- '--entrypoints.websecure.address=:443'
|
- '--entrypoints.websecure.address=:443'
|
||||||
- '--certificatesresolvers.letsencrypt.acme.httpchallenge=true'
|
${EXTRA_COMPOSE_ENTRYPOINTS} - '--certificatesresolvers.letsencrypt.acme.httpchallenge=true'
|
||||||
- '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web'
|
- '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web'
|
||||||
- '--certificatesresolvers.letsencrypt.acme.email=$LETSENCRYPT_EMAIL'
|
- '--certificatesresolvers.letsencrypt.acme.email=$LETSENCRYPT_EMAIL'
|
||||||
- '--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json'
|
- '--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json'
|
||||||
@ -1659,7 +1762,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '80:80'
|
- '80:80'
|
||||||
- '443:443'
|
- '443:443'
|
||||||
- "127.0.0.1:${DASHBOARD_PORT}:8080" # Bind dashboard to localhost only for security
|
${EXTRA_COMPOSE_PORTS} - "127.0.0.1:${DASHBOARD_PORT}:8080" # Bind dashboard to localhost only for security
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
- $TRAEFIK_VOLUME_NAME:/etc/traefik
|
- $TRAEFIK_VOLUME_NAME:/etc/traefik
|
||||||
@ -1693,9 +1796,12 @@ EOF
|
|||||||
|
|
||||||
# Start Traefik container using appropriate command
|
# Start Traefik container using appropriate command
|
||||||
$compose_cmd -f "$temp_compose" up -d
|
$compose_cmd -f "$temp_compose" up -d
|
||||||
|
cp "$temp_compose" /tmp/docker-compose.yml
|
||||||
rm -f "$temp_compose"
|
rm -f "$temp_compose"
|
||||||
|
|
||||||
log_info "Traefik container '$TRAEFIK_CONTAINER_NAME' is running locally using image: $TRAEFIK_IMAGE with volume: $TRAEFIK_VOLUME_NAME"
|
log_info "Traefik container '$TRAEFIK_CONTAINER_NAME' is running locally using image: $TRAEFIK_IMAGE with volume: $TRAEFIK_VOLUME_NAME"
|
||||||
|
log_info "Docker compose file saved to /tmp/docker-compose.yml for reference"
|
||||||
|
log_info "Traefik dashboard: http://localhost:${DASHBOARD_PORT}/dashboard/"
|
||||||
|
|
||||||
# Wait a bit for the container to start
|
# Wait a bit for the container to start
|
||||||
sleep 3
|
sleep 3
|
||||||
@ -1707,6 +1813,38 @@ EOF
|
|||||||
configure_traefik_local() {
|
configure_traefik_local() {
|
||||||
log_info "Configuring Traefik locally to connect to Application Service..."
|
log_info "Configuring Traefik locally to connect to Application Service..."
|
||||||
|
|
||||||
|
# Parse LOCAL_SERVICE_PORT for multi-port support
|
||||||
|
# Format: comma-separated port/protocol entries (protocol defaults to tcp)
|
||||||
|
# Example: "80,4443/udp" → two ports: 80/tcp and 4443/udp
|
||||||
|
local service_ports=()
|
||||||
|
local service_protocols=()
|
||||||
|
local first_tcp_port=""
|
||||||
|
local saved_ifs="$IFS"
|
||||||
|
local entry port protocol
|
||||||
|
IFS=','
|
||||||
|
for entry in $LOCAL_SERVICE_PORT; do
|
||||||
|
IFS="$saved_ifs"
|
||||||
|
entry=$(echo "$entry" | xargs)
|
||||||
|
port="$entry"
|
||||||
|
protocol="tcp"
|
||||||
|
if [[ "$port" == *"/"* ]]; then
|
||||||
|
protocol="${port#*/}"
|
||||||
|
port="${port%%/*}"
|
||||||
|
fi
|
||||||
|
service_ports+=("$port")
|
||||||
|
service_protocols+=("$protocol")
|
||||||
|
if [ -z "$first_tcp_port" ] && [ "$protocol" = "tcp" ]; then
|
||||||
|
first_tcp_port="$port"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS="$saved_ifs"
|
||||||
|
|
||||||
|
if [ -z "$first_tcp_port" ]; then
|
||||||
|
log_error "No TCP port found in LOCAL_SERVICE_PORT ($LOCAL_SERVICE_PORT)"
|
||||||
|
log_error "At least one TCP port is required for HTTP routing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Check if the target service is running
|
# Check if the target service is running
|
||||||
local service_running
|
local service_running
|
||||||
service_running=$(docker ps --filter name="$LOCAL_SERVICE_NAME" --format '{{.Names}}' 2>/dev/null || true)
|
service_running=$(docker ps --filter name="$LOCAL_SERVICE_NAME" --format '{{.Names}}' 2>/dev/null || true)
|
||||||
@ -1785,7 +1923,7 @@ http:
|
|||||||
${LOCAL_SERVICE_NAME}-service:
|
${LOCAL_SERVICE_NAME}-service:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
servers:
|
servers:
|
||||||
- url: 'http://${LOCAL_SERVICE_NAME}:${LOCAL_SERVICE_PORT}'
|
- url: 'http://${LOCAL_SERVICE_NAME}:${first_tcp_port}'
|
||||||
passHostHeader: true
|
passHostHeader: true
|
||||||
EOF
|
EOF
|
||||||
else
|
else
|
||||||
@ -1811,11 +1949,71 @@ http:
|
|||||||
${LOCAL_SERVICE_NAME}-service:
|
${LOCAL_SERVICE_NAME}-service:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
servers:
|
servers:
|
||||||
- url: 'http://${LOCAL_SERVICE_NAME}:${LOCAL_SERVICE_PORT}'
|
- url: 'http://${LOCAL_SERVICE_NAME}:${first_tcp_port}'
|
||||||
passHostHeader: true
|
passHostHeader: true
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Generate UDP/TCP router config for non-HTTP service ports (e.g., UDP relay ports)
|
||||||
|
local udp_routers_added=false
|
||||||
|
if [ ${#service_ports[@]} -gt 1 ]; then
|
||||||
|
parse_extra_entrypoints
|
||||||
|
|
||||||
|
local udp_ep_ports=()
|
||||||
|
local udp_ep_names=()
|
||||||
|
for ep_arg in "${EXTRA_ENTRYPOINT_ARGS[@]}"; do
|
||||||
|
local ep_name="${ep_arg#--entrypoints.}"
|
||||||
|
ep_name="${ep_name%%.address=*}"
|
||||||
|
local ep_addr="${ep_arg#*=}"
|
||||||
|
if [[ "$ep_addr" == *"/udp" ]]; then
|
||||||
|
local ep_port="${ep_addr#:}"
|
||||||
|
ep_port="${ep_port%/udp}"
|
||||||
|
udp_ep_ports+=("$ep_port")
|
||||||
|
udp_ep_names+=("$ep_name")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for i in "${!service_ports[@]}"; do
|
||||||
|
if [ "${service_protocols[$i]}" = "udp" ]; then
|
||||||
|
local container_port="${service_ports[$i]}"
|
||||||
|
local matching_ep=""
|
||||||
|
|
||||||
|
for j in "${!udp_ep_ports[@]}"; do
|
||||||
|
if [ "${udp_ep_ports[$j]}" = "$container_port" ]; then
|
||||||
|
matching_ep="${udp_ep_names[$j]}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$matching_ep" ] && [ ${#udp_ep_names[@]} -gt 0 ]; then
|
||||||
|
matching_ep="${udp_ep_names[0]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$matching_ep" ]; then
|
||||||
|
cat >> "$temp_config" << EOF
|
||||||
|
|
||||||
|
udp:
|
||||||
|
routers:
|
||||||
|
${LOCAL_SERVICE_NAME}-${matching_ep}:
|
||||||
|
entryPoints:
|
||||||
|
- ${matching_ep}
|
||||||
|
service: ${LOCAL_SERVICE_NAME}-udp
|
||||||
|
services:
|
||||||
|
${LOCAL_SERVICE_NAME}-udp:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- address: "${LOCAL_SERVICE_NAME}:${container_port}"
|
||||||
|
EOF
|
||||||
|
udp_routers_added=true
|
||||||
|
log_info "Added UDP routing: entrypoint '${matching_ep}' → ${LOCAL_SERVICE_NAME}:${container_port}"
|
||||||
|
else
|
||||||
|
log_warn "UDP port ${container_port} in LOCAL_SERVICE_PORT has no matching EXTRA_ENTRYPOINTS entry"
|
||||||
|
log_warn "Add e.g. EXTRA_ENTRYPOINTS=\"myudp=:${container_port}/udp\" to your .env file"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
# Generate a unique configuration file name based on the domain and service name to avoid conflicts
|
# Generate a unique configuration file name based on the domain and service name to avoid conflicts
|
||||||
# Use the domain (without path) and service name to create a unique identifier
|
# Use the domain (without path) and service name to create a unique identifier
|
||||||
local domain_base=$(echo "$DOMAIN_NAME" | cut -d'/' -f1)
|
local domain_base=$(echo "$DOMAIN_NAME" | cut -d'/' -f1)
|
||||||
@ -2517,6 +2715,19 @@ add_traefik_entry_point() {
|
|||||||
log_info "Updating Traefik container with new entry point '${entry_point_name}'..."
|
log_info "Updating Traefik container with new entry point '${entry_point_name}'..."
|
||||||
log_info "Using Let's Encrypt email: ${letsencrypt_email}"
|
log_info "Using Let's Encrypt email: ${letsencrypt_email}"
|
||||||
|
|
||||||
|
# Parse extra entrypoints from config to include them in the recreation
|
||||||
|
parse_extra_entrypoints
|
||||||
|
|
||||||
|
# Build extra entrypoint args and port mappings
|
||||||
|
local extra_ep_args=""
|
||||||
|
local extra_port_maps=""
|
||||||
|
for ep_arg in "${EXTRA_ENTRYPOINT_ARGS[@]}"; do
|
||||||
|
extra_ep_args="${extra_ep_args} ${ep_arg}"
|
||||||
|
done
|
||||||
|
for pm in "${EXTRA_PORT_MAPPINGS[@]}"; do
|
||||||
|
extra_port_maps="${extra_port_maps} -p ${pm}"
|
||||||
|
done
|
||||||
|
|
||||||
# Stop current container
|
# Stop current container
|
||||||
log_info "Stopping Traefik container..."
|
log_info "Stopping Traefik container..."
|
||||||
docker stop traefik 2>/dev/null || true
|
docker stop traefik 2>/dev/null || true
|
||||||
@ -2525,7 +2736,7 @@ add_traefik_entry_point() {
|
|||||||
# Remove old container (keep volume)
|
# Remove old container (keep volume)
|
||||||
docker rm traefik 2>/dev/null || true
|
docker rm traefik 2>/dev/null || true
|
||||||
|
|
||||||
# Recreate container with all standard entry points plus the new one
|
# Recreate container with all standard entry points plus the new one and extras
|
||||||
docker run -d \
|
docker run -d \
|
||||||
--name ${INSTANCE_NAME} \
|
--name ${INSTANCE_NAME} \
|
||||||
--restart=unless-stopped \
|
--restart=unless-stopped \
|
||||||
@ -2534,6 +2745,7 @@ add_traefik_entry_point() {
|
|||||||
-p 443:443 \
|
-p 443:443 \
|
||||||
-p "127.0.0.1:${DASHBOARD_PORT}:8080" \
|
-p "127.0.0.1:${DASHBOARD_PORT}:8080" \
|
||||||
-p "${port}:${port}" \
|
-p "${port}:${port}" \
|
||||||
|
${extra_port_maps} \
|
||||||
-v /var/run/docker.sock:/var/run/docker.sock:ro \
|
-v /var/run/docker.sock:/var/run/docker.sock:ro \
|
||||||
-v traefik_data:/etc/traefik \
|
-v traefik_data:/etc/traefik \
|
||||||
"${current_image}" \
|
"${current_image}" \
|
||||||
@ -2543,6 +2755,7 @@ add_traefik_entry_point() {
|
|||||||
--entrypoints.web.address=:80 \
|
--entrypoints.web.address=:80 \
|
||||||
--entrypoints.websecure.address=:443 \
|
--entrypoints.websecure.address=:443 \
|
||||||
"--entrypoints.${entry_point_name}.address=:${port}" \
|
"--entrypoints.${entry_point_name}.address=:${port}" \
|
||||||
|
${extra_ep_args} \
|
||||||
--certificatesresolvers.letsencrypt.acme.httpchallenge=true \
|
--certificatesresolvers.letsencrypt.acme.httpchallenge=true \
|
||||||
--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web \
|
--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web \
|
||||||
"--certificatesresolvers.letsencrypt.acme.email=${letsencrypt_email}" \
|
"--certificatesresolvers.letsencrypt.acme.email=${letsencrypt_email}" \
|
||||||
@ -2575,6 +2788,29 @@ setup_new_domain() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check if extra entrypoints need to be applied to the Traefik container
|
||||||
|
if [ -n "$EXTRA_ENTRYPOINTS" ]; then
|
||||||
|
parse_extra_entrypoints
|
||||||
|
if [ ${#EXTRA_ENTRYPOINT_ARGS[@]} -gt 0 ]; then
|
||||||
|
local current_cmd
|
||||||
|
current_cmd=$(docker inspect traefik --format='{{json .Config.Cmd}}' 2>/dev/null || echo "[]")
|
||||||
|
local needs_recreate=false
|
||||||
|
for ep_arg in "${EXTRA_ENTRYPOINT_ARGS[@]}"; do
|
||||||
|
if ! echo "$current_cmd" | grep -qF -- "${ep_arg}"; then
|
||||||
|
needs_recreate=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$needs_recreate" = true ]; then
|
||||||
|
log_info "Extra entrypoints changed, recreating Traefik container to apply..."
|
||||||
|
docker stop traefik 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
docker rm traefik 2>/dev/null || true
|
||||||
|
create_traefik_container_local
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Check if Application Service exists locally
|
# Check if Application Service exists locally
|
||||||
if ! check_app_service_local; then
|
if ! check_app_service_local; then
|
||||||
log_error "Application Service not found locally. Please ensure the service '$LOCAL_SERVICE_NAME' is running."
|
log_error "Application Service not found locally. Please ensure the service '$LOCAL_SERVICE_NAME' is running."
|
||||||
@ -2847,7 +3083,7 @@ Environment Variables (in .env.rvs-prxy file):
|
|||||||
|
|
||||||
Traefik Mode Variables (FRP=false):
|
Traefik Mode Variables (FRP=false):
|
||||||
LOCAL_SERVICE_NAME Name of the local Docker application container
|
LOCAL_SERVICE_NAME Name of the local Docker application container
|
||||||
LOCAL_SERVICE_PORT Port number of the local application service
|
LOCAL_SERVICE_PORT Port(s) of the local app service, e.g. 80 or 80,4443/udp
|
||||||
DOMAIN_NAME Domain name for reverse proxy routing
|
DOMAIN_NAME Domain name for reverse proxy routing
|
||||||
TRAEFIK_VER Traefik version (default: v3.6.9)
|
TRAEFIK_VER Traefik version (default: v3.6.9)
|
||||||
LETSENCRYPT_EMAIL Email for Let's Encrypt certificates
|
LETSENCRYPT_EMAIL Email for Let's Encrypt certificates
|
||||||
@ -2983,10 +3219,10 @@ manage_configurations() {
|
|||||||
if [ -n "$domain_name" ] && [ -n "$service_name" ]; then
|
if [ -n "$domain_name" ] && [ -n "$service_name" ]; then
|
||||||
log_info "Removing domain config from Traefik: ${domain_name}"
|
log_info "Removing domain config from Traefik: ${domain_name}"
|
||||||
# Remove the dynamic config file from Traefik volume
|
# Remove the dynamic config file from Traefik volume
|
||||||
# Use specific pattern: app-service-{domain}-{service}.yml
|
# Must use same domain_base logic as configure_traefik_local():
|
||||||
# This avoids accidentally removing port config files that share the same service name
|
# cut -d'/' -f1 (not dots-to-dashes) to match actual filename
|
||||||
local domain_base
|
local domain_base
|
||||||
domain_base=$(echo "$domain_name" | sed 's/\./-/g')
|
domain_base=$(echo "$domain_name" | cut -d'/' -f1)
|
||||||
docker run --rm -v "traefik_data:/etc/traefik" alpine:latest sh -c "rm -f /etc/traefik/config/app-service-${domain_base}-${service_name}.yml 2>/dev/null" || true
|
docker run --rm -v "traefik_data:/etc/traefik" alpine:latest sh -c "rm -f /etc/traefik/config/app-service-${domain_base}-${service_name}.yml 2>/dev/null" || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -3040,17 +3276,39 @@ manage_configurations() {
|
|||||||
local existing_entrypoints
|
local existing_entrypoints
|
||||||
existing_entrypoints=$(echo "$current_cmd" | grep -o 'entrypoints\.[a-zA-Z0-9_-]*\.address=[^"]*' | tr -d '"' || echo "")
|
existing_entrypoints=$(echo "$current_cmd" | grep -o 'entrypoints\.[a-zA-Z0-9_-]*\.address=[^"]*' | tr -d '"' || echo "")
|
||||||
|
|
||||||
# Build new entry point list excluding removed ports
|
# Also include extra entrypoints from EXTRA_ENTRYPOINTS config
|
||||||
local new_entrypoint_args="--entrypoints.web.address=:80 --entrypoints.websecure.address=:443"
|
parse_extra_entrypoints
|
||||||
local new_port_mappings="-p 80:80 -p 443:443 -p 127.0.0.1:${DASHBOARD_PORT}:8080"
|
local extra_ep_args=""
|
||||||
|
local extra_port_maps=""
|
||||||
|
for ep_arg in "${EXTRA_ENTRYPOINT_ARGS[@]}"; do
|
||||||
|
extra_ep_args="${extra_ep_args} ${ep_arg}"
|
||||||
|
done
|
||||||
|
for pm in "${EXTRA_PORT_MAPPINGS[@]}"; do
|
||||||
|
extra_port_maps="${extra_port_maps} -p ${pm}"
|
||||||
|
done
|
||||||
|
|
||||||
# Parse existing entry points
|
# Build new entry point list excluding removed ports
|
||||||
|
local new_entrypoint_args="--entrypoints.web.address=:80 --entrypoints.websecure.address=:443 ${extra_ep_args}"
|
||||||
|
local new_port_mappings="-p 80:80 -p 443:443 -p 127.0.0.1:${DASHBOARD_PORT}:8080 ${extra_port_maps}"
|
||||||
|
|
||||||
|
# Parse existing entry points (skip web/websecure and extra entries already covered)
|
||||||
while IFS= read -r ep; do
|
while IFS= read -r ep; do
|
||||||
if [ -n "$ep" ]; then
|
if [ -n "$ep" ]; then
|
||||||
local ep_name
|
local ep_name
|
||||||
ep_name=$(echo "$ep" | sed 's/entrypoints\.\(.*\)\.address=.*/\1/')
|
ep_name=$(echo "$ep" | sed 's/entrypoints\.\(.*\)\.address=.*/\1/')
|
||||||
|
local ep_address
|
||||||
|
ep_address=$(echo "$ep" | sed 's/entrypoints\.[a-zA-Z0-9_-]*\.address=//')
|
||||||
local ep_port
|
local ep_port
|
||||||
ep_port=$(echo "$ep" | grep -o ':[0-9]*' | sed 's/://')
|
ep_port=$(echo "$ep_address" | sed 's/^://' | sed 's/\/.*//')
|
||||||
|
|
||||||
|
# Check if this is already covered by extra entrypoints
|
||||||
|
local already_covered=false
|
||||||
|
for ep_arg in "${EXTRA_ENTRYPOINT_ARGS[@]}"; do
|
||||||
|
if echo "$ep_arg" | grep -q "entrypoints.${ep_name}.address"; then
|
||||||
|
already_covered=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# Check if this port is being removed
|
# Check if this port is being removed
|
||||||
local should_skip=false
|
local should_skip=false
|
||||||
@ -3061,11 +3319,16 @@ manage_configurations() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$should_skip" = false ] && [ "$ep_name" != "web" ] && [ "$ep_name" != "websecure" ]; then
|
if [ "$should_skip" = false ] && [ "$ep_name" != "web" ] && [ "$ep_name" != "websecure" ] && [ "$already_covered" = false ]; then
|
||||||
new_entrypoint_args="${new_entrypoint_args} --entrypoints.${ep_name}.address=:${ep_port}"
|
new_entrypoint_args="${new_entrypoint_args} --entrypoints.${ep_name}.address=${ep_address}"
|
||||||
|
# Handle protocol suffix in port mapping
|
||||||
|
if [[ "$ep_address" == *"/udp" ]]; then
|
||||||
|
new_port_mappings="${new_port_mappings} -p ${ep_port}:${ep_port}/udp"
|
||||||
|
else
|
||||||
new_port_mappings="${new_port_mappings} -p ${ep_port}:${ep_port}"
|
new_port_mappings="${new_port_mappings} -p ${ep_port}:${ep_port}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
done <<< "$existing_entrypoints"
|
done <<< "$existing_entrypoints"
|
||||||
|
|
||||||
# Stop and remove current container
|
# Stop and remove current container
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user