274 lines
10 KiB
Markdown
274 lines
10 KiB
Markdown
# Technical Architecture and Implementation Details
|
|
|
|
## Script Architecture
|
|
|
|
The `deploy-rvs-prxy.sh` script is an automated deployment tool supporting both FRP and Traefik modes.
|
|
|
|
**Key Architecture:** The script runs directly on the same server where the application is hosted (local deployment), eliminating the need for SSH-based remote operations in Traefik mode.
|
|
|
|
**Deployment Modes:**
|
|
1. **Setup Reverse Proxy**: Deploys new Traefik or FRP Tunnel with Traefik
|
|
2. **Setup New Domain**: Adds new domain configuration to existing reverse proxy
|
|
|
|
**Configuration File Structure:**
|
|
- `.env.rvs-prxy` - Reverse proxy instance configuration (FRP mode, Traefik version, etc.)
|
|
- `.env-<domain>` - Domain-specific configuration (DOMAIN_NAME, LOCAL_SERVICE_NAME, LOCAL_SERVICE_PORT)
|
|
- Domain format: Any domain format supported (`.com`, `.net`, `.org`, `.org.hk`, `.com.hk`, subdomains, etc.)
|
|
- Filename pattern: Dots replaced with dashes (e.g., `app.example.com` → `.env-app-example-com`)
|
|
- `.env-port-<port>` - Port-based routing configuration (HOST_PORT, CONTAINER_NAME, CONTAINER_PORT)
|
|
- Multiple domain and port files can coexist for multiple domains and ports
|
|
|
|
**Automatic Mode Detection:**
|
|
- No config files → Interactive wizard for proxy setup
|
|
- `.env.rvs-prxy` exists, proxy not running → Setup Reverse Proxy
|
|
- `.env.rvs-prxy` exists, proxy running, no domain/port file → Interactive wizard for domain/port setup
|
|
- `.env.rvs-prxy` + `.env-<domain>` exists → Setup New Domain
|
|
- `.env.rvs-prxy` + `.env-port-<port>` exists → Setup Port Exposure
|
|
|
|
**Validation:**
|
|
- **Proxy Setup Mode**: Validates proxy-specific settings (TRAEFIK_VER, LETSENCRYPT_EMAIL for Traefik; FRP_SERVER_ADDR for FRP)
|
|
- **Domain Setup Mode**: Validates domain-specific settings (DOMAIN_NAME, LOCAL_SERVICE_NAME, LOCAL_SERVICE_PORT)
|
|
|
|
**Workflow:**
|
|
|
|
First Run (No .env.rvs-prxy):
|
|
1. Interactive wizard asks for proxy instance settings
|
|
2. Creates .env.rvs-prxy with Traefik/FRP settings
|
|
3. Validation checks proxy settings (TRAEFIK_VER, LETSENCRYPT_EMAIL)
|
|
4. Deploys reverse proxy
|
|
5. Shows message: "Next: Run the script again to setup your first domain or port"
|
|
|
|
Second Run (.env.rvs-prxy exists, proxy running):
|
|
1. Detects running proxy
|
|
2. Interactive wizard asks for domain or port settings
|
|
3. Creates .env-<domain> or .env-port-<port> with settings
|
|
4. Validation checks domain/port settings
|
|
5. Checks if application service/container is running
|
|
6. Configures domain/port in existing reverse proxy
|
|
7. Shows: "Service will be accessible at: https://domain.name or http://host-ip:port"
|
|
|
|
Three Deployment Modes:
|
|
1. Setup Reverse Proxy - Deploys Traefik or FRP Tunnel
|
|
2. Setup New Domain - Adds domain-based routing
|
|
3. Setup Port Exposure - Adds port-based routing
|
|
|
|
### Core Components
|
|
|
|
**1. Environment Loading (`load_env`)**
|
|
- Loads configuration from `.env.rvs-prxy.development`, `.env.rvs-prxy.production`, or `.env.rvs-prxy`
|
|
- Supports files in current directory or script directory
|
|
- **Interactive Setup Wizard**: If no `.env.rvs-prxy` file is found, automatically launches a guided setup wizard
|
|
- Normalizes boolean values (FRP variable)
|
|
- Validates required parameters for each mode
|
|
- Supports three modes: proxy setup, domain setup, and port exposure
|
|
|
|
**Interactive Setup Wizard Features:**
|
|
- Step-by-step guided configuration
|
|
- Mode selection (Traefik or FRP) for proxy setup
|
|
- Choice between domain setup or port exposure when proxy exists
|
|
- Mode-specific configuration prompts
|
|
- Sensible defaults for all settings
|
|
- Automatic saving to `.env.rvs-prxy`, `.env-<domain>`, or `.env-port-<port>` files
|
|
|
|
**2. Instance Management (`prompt_instance_name`)**
|
|
- Auto-detects existing instances from Docker volumes (FRP mode)
|
|
- Supports instance name override via `INSTANCE_NAME` environment variable
|
|
- Generates timestamped default names
|
|
- Saves selections to `.env` for future runs
|
|
|
|
**3. Docker Network Selection (`select_docker_network`)**
|
|
- Lists available Docker networks
|
|
- Supports custom network names
|
|
- Remembers previous selections via `.para` file in volume (FRP mode)
|
|
|
|
**4. Configuration Generation**
|
|
- **FRP Mode**: Generates `frpc.toml` with dynamic proxy configurations
|
|
- **Traefik Mode**: Generates YAML configuration files for routing rules (local deployment)
|
|
|
|
**5. Container Management**
|
|
- Creates and manages Docker containers with persistent volumes
|
|
- Supports container restart and lifecycle operations
|
|
- Displays operation commands for user reference
|
|
|
|
## Traefik Mode Implementation (Local Deployment)
|
|
|
|
### Setup Flow (`setup_traefik_only`)
|
|
|
|
1. **Pre-request Checks**
|
|
- Verify Docker command permissions
|
|
|
|
2. **Application Service Verification** (`check_app_service_local`)
|
|
- Confirms target service is running locally
|
|
- Verifies connection to `traefik-public` network
|
|
|
|
3. **Traefik Container Creation** (`create_traefik_container_local`)
|
|
- Creates `traefik_data` volume for persistence
|
|
- Generates dynamic configuration with:
|
|
- Dashboard routing
|
|
- HTTP to HTTPS redirect
|
|
- Security headers
|
|
- Creates `traefik-public` Docker network
|
|
- Uses Docker Compose for container orchestration
|
|
- Detects Docker version for command compatibility (`docker compose` vs `docker-compose`)
|
|
|
|
4. **Service Configuration** (`configure_traefik_local`)
|
|
- Generates service-specific routing rules
|
|
- Supports sub-path routing (e.g., `example.com/api`)
|
|
- Creates unique configuration filenames to avoid conflicts
|
|
- Supports dynamic configuration loading (no restart required by default)
|
|
|
|
### Local Docker Operations
|
|
|
|
- `local_docker_exec()`: Executes Docker commands directly on the local server
|
|
- `local_volume_copy()`: Copies files to Docker volumes using temporary containers
|
|
|
|
### Configuration File Structure
|
|
|
|
**Traefik Main Config** (`traefik.yml`):
|
|
```yaml
|
|
http:
|
|
routers:
|
|
api:
|
|
rule: "PathPrefix(`/api`)"
|
|
service: api@internal
|
|
dashboard:
|
|
rule: "PathPrefix(`/dashboard`)"
|
|
service: api@internal
|
|
http-catchall:
|
|
rule: "PathRegexp(`{any:.*}`)"
|
|
entryPoints:
|
|
- "web"
|
|
service: "noop@internal"
|
|
middlewares:
|
|
- "redirect-to-https"
|
|
middlewares:
|
|
api-headers:
|
|
headers:
|
|
customFrameOptionsValue: SAMEORIGIN
|
|
contentTypeNosniff: true
|
|
browserXssFilter: true
|
|
stsIncludeSubdomains: true
|
|
stsPreload: true
|
|
stsSeconds: 15552000
|
|
redirect-to-https:
|
|
redirectScheme:
|
|
scheme: "https"
|
|
permanent: true
|
|
```
|
|
|
|
**Service Config** (dynamic, per-service):
|
|
```yaml
|
|
http:
|
|
routers:
|
|
<service-name>-https:
|
|
rule: 'Host(`<domain>`)'
|
|
service: <service-name>-service
|
|
tls:
|
|
certResolver: letsencrypt
|
|
entryPoints:
|
|
- websecure
|
|
<service-name>-http:
|
|
rule: 'Host(`<domain>`)'
|
|
service: <service-name>-service
|
|
entryPoints:
|
|
- web
|
|
middlewares:
|
|
- redirect-to-https
|
|
services:
|
|
<service-name>-service:
|
|
loadBalancer:
|
|
servers:
|
|
- url: 'http://<service-name>:<port>'
|
|
passHostHeader: true
|
|
```
|
|
|
|
**Entrypoints Configuration:**
|
|
Default entrypoints (`web` on :80, `websecure` on :443) are defined in the docker-compose.yml command args. Additional entrypoints can be configured via the `EXTRA_ENTRYPOINTS` environment variable in `.env.rvs-prxy`:
|
|
- Format: `name=:port/protocol,name2=:port` (comma-separated)
|
|
- Example: `quic=:443/udp` enables HTTP/3 QUIC on UDP port 443
|
|
- These are injected into both the docker-compose.yml `command:` section and the `docker run` command
|
|
- Port mappings (TCP/UDP) are automatically added to the `ports:` section
|
|
- The `parse_extra_entrypoints()` function parses the variable and builds:
|
|
- `EXTRA_ENTRYPOINT_ARGS`: array of `--entrypoints.<name>.address=<address>` args
|
|
- `EXTRA_PORT_MAPPINGS`: array of port mappings in `host:container/protocol` format
|
|
- `EXTRA_COMPOSE_ENTRYPOINTS`: YAML lines for docker-compose.yml command section
|
|
- `EXTRA_COMPOSE_PORTS`: YAML lines for docker-compose.yml ports section
|
|
|
|
## FRP Mode Implementation
|
|
|
|
### Setup Flow
|
|
|
|
1. **Instance Setup**: Prompt for instance name
|
|
2. **Port Configuration**: Prompt for internal service port
|
|
3. **FRP Config Generation** (`generate_frpc_config`)
|
|
- Extracts existing configuration from volume
|
|
- Supports dynamic proxy configurations via `PROXY_*_PORT` variables
|
|
- Generates `frpc.toml` with TCP proxy rules
|
|
4. **Container Start** (`start_docker_container`)
|
|
- Creates volume if not exists
|
|
- Starts frpc container with configuration mounted
|
|
5. **Proxy Server Update** (`update_proxy_server_config`)
|
|
- Uploads dynamic configuration script to proxy server
|
|
- Updates `docker-compose.app.yml` with port mappings and labels
|
|
- Supports domain-based routing configuration
|
|
|
|
### Dynamic Proxy Configuration
|
|
|
|
The script supports dynamic proxy configurations through environment variables:
|
|
- `PROXY_<NAME>_PORT`: Defines remote port for proxy
|
|
- `PROXY_<NAME>_LOCAL_PORT`: Defines local port (defaults to `INTERNAL_SERVICE_PORT`)
|
|
|
|
Example:
|
|
```bash
|
|
PROXY_WEB_PORT=12077
|
|
PROXY_WEB_LOCAL_PORT=3000
|
|
PROXY_SSH_PORT=2222
|
|
PROXY_SSH_LOCAL_PORT=22
|
|
```
|
|
|
|
### Proxy Server Configuration Update
|
|
|
|
The script generates and executes a remote script on the proxy server that:
|
|
- Checks existing configuration status (not_found, up_to_date, outdated)
|
|
- Updates port mappings section in `docker-compose.app.yml`
|
|
- Updates labels section for Traefik routing
|
|
- Optionally restarts Docker Compose service
|
|
|
|
## File Deployment (Traefik Mode)
|
|
|
|
The `deploy` command syncs files from local folder to target server:
|
|
- Source: `LOCAL_FOLDER` (default: `../out/`)
|
|
- Destination: `DEST_PATH` on target server
|
|
- Uses rsync for efficient synchronization with `--delete` option
|
|
|
|
## Logging and Debugging
|
|
|
|
**Logging Functions:**
|
|
- `log_info()`: Green [INFO] messages
|
|
- `log_error()`: Red [ERROR] messages
|
|
- `log_warn()`: Yellow [WARN] messages
|
|
- `log_debug()`: Blue [DEBUG] messages (only when `DEBUG=true`)
|
|
|
|
**Status Commands:**
|
|
- `check_status_on_target()`: Shows Traefik and Application service status
|
|
- `view_traefik_logs()`: Displays last 50 lines of Traefik logs
|
|
|
|
## Error Handling
|
|
|
|
- Uses `set -e` for immediate exit on errors
|
|
- Validates required parameters before execution
|
|
- Provides detailed error messages with suggested fixes
|
|
- Graceful handling of missing configurations
|
|
|
|
## Version Compatibility
|
|
|
|
**Docker Version Detection:**
|
|
- Detects Docker version to determine command syntax
|
|
- Uses `docker compose` for Docker 20.10.0+
|
|
- Falls back to `docker-compose` for older versions
|
|
- Handles Compose file version field (deprecated in v2.0+)
|
|
|
|
**Traefik Version:**
|
|
- Default: `v3.6.9`
|
|
- Configurable via `TRAEFIK_VER` environment variable
|