rvs-prxy/Design_Doc/architecture.md

14 KiB

Generic Reverse Proxy Architecture

Overview

This document describes a generic reverse proxy architecture that enables internal services to be accessible via public domains. The architecture uses FRP (Fast Reverse Proxy) for tunneling and Traefik for HTTP/HTTPS routing with automatic certificate management.

Architecture Block Diagram

+-------------------+    SSH Commands     +-------------------+
|   Local Host      | ------------------> |  Proxy Server     |
|                   |                     |                   |
|  +-------------+  |    FRP Tunnel       |  +-------------+  |
|  | Application |  | ------------------> |  |   FRPS      |  |
|  |   Service   |  |                     |  | (Server)    |  |<--- Public IPs
|  |             |  |                     |  |             |  |    Port: 16999
|  +-------------+  |                     |  +-------------+  |
|                   |                     |                   |
|  +-------------+  |    FRP Client       |  +-------------+  |
|  |   FRPC      |  | ------------------> |  |   Traefik   |  |<--- Domains
|  | (Client)    |  |                     |  | (Router)    |  |    HTTPS/TLS
|  |             |  |                     |  |             |  |
|  +-------------+  |                     |  +-------------+  |
|                   |                     |                   |
|  +-------------+  |                     |  +-------------+  |
|  | Docker      |  |                     |  | Docker      |  |
|  | Container   |  |                     |  | Container   |  |
|  +-------------+  |                     |  +-------------+  |
+-------------------+                     +-------------------+
        |                                           |
        |                                           |
        +------------------ Volumes ------------------+
        |    rad-git-sshd-itl-frpc-<instance>       |
        +-------------------------------------------+

Architecture Components

Core Components

  • FRP (Fast Reverse Proxy): Handles TCP/UDP tunneling between internal and external networks
    • FRPS (FRP Server): Runs on the public-facing server
    • FRPC (FRP Client): Runs on internal service hosts
  • Traefik: HTTP/HTTPS router with automatic Let's Encrypt certificate management
  • Docker & Docker Compose: Container orchestration and deployment
  • SSH: Secure communication for remote configuration management

Supporting Elements

  • Configuration Storage: Docker volumes for persistent configuration
  • DNS Management: Domain-to-IP mapping for public access
  • Certificate Management: Automatic SSL/TLS certificate provisioning and renewal

Prerequisites

  • FRP (Fast Reverse Proxy) service with frpc and frps
  • Traefik reverse proxy
  • Docker and Docker Compose installed
  • SSH key for remote server access
  • SSH key at ~/.ssh/itl-devs1 for proxy server access
  • User permissions for Docker commands
  • Authentication keys for secure access

Parameters

Required Parameters

  • Instance Name: Unique identifier for the service instance (alphanumeric, hyphens, underscores only)
  • Internal Service Port: The port exposed by the target Docker container (e.g., 3000)
  • Domain Name: Public domain for Traefik routing rules
  • FRP Server Address: Public IP address of the FRP server
  • FRP Server Port: Port for FRP communication (default 16999)

Optional Parameters

  • Docker Network: Network for connecting to internal service container (default uses Docker bridge)
  • Proxy Ports: Custom remote ports for external access (defaults: TCP ports matching internal ports)
  • Service Type: Protocol specification (TCP/UDP/HTTP/HTTPS)

Environment Configuration

The architecture supports environment-based configuration using .env files to provide default values:

  • Environment Files: .env, .env.development, .env.production
  • Default Values: Parameters from environment files are used as defaults during script execution
  • Interactive Fallback: If parameters are missing from environment files, scripts will prompt for input
  • Auto-Persistence: Answered parameters are automatically saved to the appropriate .env file for future use
  • Supported Variables:
    • INSTANCE_NAME: Default instance name
    • INTERNAL_SERVICE_PORT: Port exposed by the target Docker container (e.g., 3000)
    • DOCKER_NETWORK: Docker network for connecting to internal service container
    • FRP_SERVER_ADDR: FRP server address
    • FRP_SERVER_PORT: FRP server port (default 16999)
    • DOMAIN_NAME: Default domain name
    • RAD_REMOTE_PORT: Remote port for rad proxy (default 8779)
    • SSH_REMOTE_PORT: Remote port for SSH proxy (default 13076)
    • WEB_REMOTE_PORT: Remote port for web proxy (default 13077)
    • PROXY_*_PORT: Dynamic proxy configuration (e.g., PROXY_API_PORT=8080)
    • PROXY_*_LOCAL_PORT: Local port for the corresponding proxy (e.g., PROXY_API_LOCAL_PORT=8000)

Dynamic Proxy Configuration

The system supports dynamic proxy configuration through environment variables:

  • Format: Use PROXY_*_PORT format to define additional proxies
  • Examples: PROXY_API_PORT=8080, PROXY_DATABASE_PORT=5432
  • Local Port Override: Use PROXY_*_LOCAL_PORT to specify a different local port
  • Flexibility: Allows configuration of any number of application-specific proxies

Internal Service Connection

The architecture connects to internal services on the same computer as the script execution:

  • Connection Method: FRP client connects to target service on the same physical/virtual machine
  • Local IP: Connection made via 127.0.0.1 (localhost) to the service port
  • Port Configuration: Target service must be accessible on the specified port (e.g., 3000)
  • Service Discovery: No container name resolution needed, connects directly to localhost
  • Local IP Setting: FRP client configuration uses 127.0.0.1 as the local IP
  • Naming Convention: Container and volume names follow the format {INSTANCE_NAME}-frpc

Outcomes

  • Public domain connectivity to internal service
  • Secure encrypted tunnel between internal and external networks
  • Automatic SSL/TLS certificates via Let's Encrypt
  • Persistent configuration through Docker volumes
  • Automated service discovery and routing

Architecture Flow

1. Configuration Phase

  1. User provides service parameters via interactive prompts or command-line
  2. System validates parameters and checks for existing configurations
  3. Generates appropriate FRP client configuration (frpc.toml)
  4. Persists configuration to Docker volumes for continuity

2. Deployment Phase

  1. Creates Docker container with FRP client
  2. Establishes connection to FRP server
  3. Sets up port forwarding rules
  4. Updates proxy server to recognize new instance

3. Routing Phase

  1. Traefik configuration updated with new routing rules
  2. Domain name routes to appropriate internal service
  3. Automatic SSL/TLS certificate provisioned
  4. Health checks and monitoring established

4. Management Phase

  1. Persistent configuration for service continuity
  2. Backup and recovery mechanisms
  3. Restart procedures for configuration changes
  4. Service status monitoring

Real-World Example: Using auto-sys-deploy.sh and update-compose-config.sh

Example: Deploying a New FRP Client Instance

Based on auto-sys-deploy.sh.md and update-compose-config.sh.md, here's a real-world example of the architecture in action:

Initial Setup

  • Prerequisites: Docker, SSH key at ~/.ssh/itl-devs1
  • Command: ./auto-sys-deploy.sh setup-rvs-prxy

Interactive Configuration (from auto-sys-deploy.sh)

  1. Instance Name Selection:

    • Default: setup-rvs-prxy-$(date +%Y%m%d-%H%M%S)
    • User input: my-app-instance-20231005-143000
    • Validation: alphanumeric, hyphens, underscores only
  2. Docker Network Selection:

    • Options: Select from existing networks, custom network, or default
    • User input: Select network bridge or create custom
    • Outcome: Container runs on specific Docker network
  3. FRP Server Configuration:

    • Server Address: 192.168.1.100 (example IP)
    • Server Port: 16999 (default)
    • Validation: Ensure server is accessible
  4. Dynamic Proxy Configuration:

    • Proxies are configured dynamically based on environment variables following the format PROXY_*_PORT
    • Default rad proxy (if RAD_REMOTE_PORT is set):
      • Local Port: 8776 (default)
      • Remote Port: Value of RAD_REMOTE_PORT environment variable
      • Name: rad-my-app-instance-20231005-143000
    • Default SSH proxy (if SSH_REMOTE_PORT is set):
      • Local Port: 22 (default)
      • Remote Port: Value of SSH_REMOTE_PORT environment variable
      • Name: ssh-my-app-instance-20231005-143000
    • Default Web proxy (if WEB_REMOTE_PORT is set):
      • Local Port: Service port or 80 (default)
      • Remote Port: Value of WEB_REMOTE_PORT environment variable
      • Name: web-my-app-instance-20231005-143000
    • Additional proxies can be configured using PROXY_*_PORT environment variables
    • Format: PROXY_API_PORT=8080, PROXY_DATABASE_PORT=5432, etc.
    • The script will create as many proxies as defined by the environment variables
  5. Domain Configuration:

    • Input: myapp.example.com
    • Used for Traefik routing rules

Configuration Generation (from auto-sys-deploy.sh)

The script generates frpc.toml with:

serverAddr = "192.168.1.100"
serverPort = 16999

[[proxies]]
name = "rad-my-app-instance-20231005-143000"
type = "tcp"
localPort = 8776
localIP = "rad-git-sshd-my-app-instance-20231005-143000"
remotePort = 8779

[[proxies]]
name = "ssh-my-app-instance-20231005-143000"
type = "tcp"
localPort = 22
localIP = "rad-git-sshd-my-app-instance-20231005-143000"
remotePort = 13076

[[proxies]]
name = "web-my-app-instance-20231005-143000"
type = "tcp"
localPort = 80
localIP = "rad-git-sshd-my-app-instance-20231005-143000"
remotePort = 13077

Container Deployment (from auto-sys-deploy.sh)

  • Creates Docker volume: rad-git-sshd-itl-frpc-my-app-instance-20231005-143000
  • Starts container: rad-git-sshd-frpc-my-app-instance-20231005-143000
  • Uses image: snowdreamtech/frpc:0.62.0-alpine3.21
  • Mounts config volume: /etc/frp

Proxy Server Configuration (from update-compose-config.sh)

The script updates docker-compose.app.yml with:

Ports Section:

ports:
  # ... other ports ...
  
  # my-app-instance-20231005-143000 Self-hosting ports ====
  - "8779:8779/tcp"
  - "13076:13076/tcp" 
  - "13077:13077/tcp"
  # =========================
  
  # ... other ports ...

Labels Section:

labels:
  # ... other labels ...
  
  # my-app-instance-20231005-143000 Self-hosting labels ====
  - "traefik.http.routers.frps-my-app-instance-20231005-143000-http.entrypoints=web"
  - "traefik.http.routers.frps-my-app-instance-20231005-143000-http.rule=Host(`myapp.example.com`)"
  - "traefik.http.routers.frps-my-app-instance-20231005-143000-http.service=frps-my-app-instance-20231005-143000"
  - "traefik.http.routers.frps-my-app-instance-20231005-143000-http.middlewares=http2https@file"

  - "traefik.http.routers.frps-my-app-instance-20231005-143000-https.entrypoints=websecure"
  - "traefik.http.routers.frps-my-app-instance-20231005-143000-https.rule=Host(`myapp.example.com`)"
  - "traefik.http.routers.frps-my-app-instance-20231005-143000-https.service=frps-my-app-instance-20231005-143000"
  - "traefik.http.routers.frps-my-app-instance-20231005-143000-https.tls=true"
  - "traefik.http.routers.frps-my-app-instance-20231005-143000-https.tls.certresolver=letsencrypt"
  - "traefik.http.routers.frps-my-app-instance-20231005-143000-https.tls.domains[0].main=myapp.example.com"

  - "traefik.http.services.frps-my-app-instance-20231005-143000.loadbalancer.server.port=13077"
  # =========================
  
  # ... other labels ...

Backup and Service Restart (from update-compose-config.sh)

  • Creates backup: docker-compose.app.yml.backup_YYYYMMDD_HHMMSS
  • Restarts service with: ./stop.sh && ./start.sh
  • Verifies deployment with: docker logs --tail 50 frps_frps_1

Extensibility Points

Protocol Support

  • TCP/UDP: Native FRP support for any TCP/UDP based service
  • HTTP/HTTPS: Enhanced routing via Traefik with automatic certificates
  • Custom Protocols: Extensible architecture for proprietary protocols

Service Types

  • Web Applications: HTTP/HTTPS routing with domain-based access
  • Database Services: Secure TCP tunneling for database connections
  • SSH Services: Encrypted access to internal SSH servers
  • API Services: Secure API endpoint exposure

Scaling Options

  • Load Balancing: Multiple instances behind single domain
  • Geographic Distribution: Multiple proxy servers in different regions
  • Protocol Multiplexing: Multiple services through single tunnel

Security Considerations

  • Encrypted tunnels between internal and external networks
  • Access control through SSH keys and authentication
  • Firewall isolation of internal services
  • Automatic certificate management for HTTPS
  • Docker container isolation

Maintenance Requirements

  • Regular backup of configuration files
  • Certificate renewal monitoring
  • Connection health monitoring
  • Log aggregation and analysis
  • Docker image updates

Generic Application Examples

Web Application Deployment

  • Parameters: Instance name, internal web port (80/443), domain name
  • Outcome: Public website accessible via configured domain

Database Access

  • Parameters: Instance name, internal database port, restricted domain
  • Outcome: Secure external access to internal database

Custom Service Exposure

  • Parameters: Instance name, custom application port, specific domain
  • Outcome: External access to internal custom service