rvs-prxy/Design_Doc/Tech_Desc.md

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