Configuration Guide¶
This guide covers all configuration options for VPN Exit Controller, including environment variables, service settings, and advanced tuning parameters.
Configuration Overview¶
VPN Exit Controller uses a hierarchical configuration system:
- Environment Variables (
.envfile) - Service Configuration (systemd, Docker)
- Application Settings (API, load balancer, etc.)
- Runtime Configuration (via API)
Environment Variables¶
Essential Configuration¶
Create a .env file in the project root:
Core Settings¶
NordVPN Configuration¶
# Service credentials from NordVPN dashboard
NORDVPN_USER=your_service_username
NORDVPN_PASS=your_service_password
# Optional: Preferred protocol
NORDVPN_PROTOCOL=udp # or tcp
NORDVPN_TECHNOLOGY=openvpn_udp # or nordlynx
Getting NordVPN Credentials
- Log in to NordVPN Dashboard
- Navigate to Manual Configuration
- Generate service credentials
- Use these credentials (not your account login)
Tailscale Configuration¶
# Auth key for automatic node registration (use ephemeral keys for auto-cleanup)
TAILSCALE_AUTH_KEY=tskey-auth-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxx
# Optional: Custom hostname prefix
TAILSCALE_HOSTNAME_PREFIX=vpn-exit
# Optional: Exit node advertisement
TAILSCALE_ADVERTISE_EXIT_NODE=true
TAILSCALE_ADVERTISE_ROUTES=10.0.0.0/8,192.168.0.0/16
# DNS Configuration (Important: prevents HTTPS errors in incognito mode)
TAILSCALE_ACCEPT_DNS=false # Disables Tailscale DNS override
API Configuration¶
# API Authentication
API_USERNAME=admin
API_PASSWORD=strong_secure_password_here
# API Server Settings
API_HOST=0.0.0.0
API_PORT=8080
API_WORKERS=4
API_RELOAD=false # Set to true for development
# CORS Settings
API_CORS_ORIGINS=["https://vpn-docs.rbnk.uk", "https://admin.rbnk.uk"]
Redis Configuration¶
# Redis Connection
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_DB=0
REDIS_PASSWORD=redis_password_if_set
# Redis Settings
REDIS_MAX_CONNECTIONS=50
REDIS_DECODE_RESPONSES=true
REDIS_SOCKET_TIMEOUT=5
REDIS_CONNECTION_TIMEOUT=10
Proxy Server Configuration¶
# Proxy service settings
PROXY_HTTP_PORT=3128 # Squid HTTP/HTTPS proxy port
PROXY_SOCKS_PORT=1080 # Dante SOCKS5 proxy port
PROXY_HEALTH_PORT=8080 # Health check endpoint port
# DNS Configuration for VPN containers
VPN_DNS_PRIMARY=103.86.96.100 # NordVPN DNS server 1
VPN_DNS_SECONDARY=103.86.99.100 # NordVPN DNS server 2
VPN_DNS_FALLBACK_1=8.8.8.8 # Google DNS fallback 1
VPN_DNS_FALLBACK_2=1.1.1.1 # Google DNS fallback 2
# Squid proxy settings
SQUID_ACCESS_LOG=none # Disable access logging for privacy
SQUID_CACHE_ENABLED=false # Disable caching for privacy
SQUID_MAX_CONNECTIONS=1000 # Maximum concurrent connections
# SOCKS5 proxy settings
DANTE_MAX_CONNECTIONS=1000 # Maximum concurrent connections
DANTE_LOG_LEVEL=error # Logging level (error, warning, info, debug)
DNS Resolution Fix
The VPN containers are configured with specific DNS servers to resolve the "doesn't support secure connection" errors that occurred in incognito mode:
- Primary: NordVPN DNS servers (103.86.96.100, 103.86.99.100)
- Fallback: Google DNS (8.8.8.8, 1.1.1.1) if NordVPN DNS fails
- Tailscale DNS Disabled:
--accept-dns=falseprevents conflicts
Advanced Settings¶
Load Balancing¶
# Default strategy: round_robin, least_connections, weighted_latency, random, health_score
DEFAULT_LOAD_BALANCING_STRATEGY=health_score
# Auto-scaling
AUTO_SCALING_ENABLED=true
AUTO_SCALING_MIN_NODES=1
AUTO_SCALING_MAX_NODES=5
AUTO_SCALING_TARGET_CPU=70
AUTO_SCALING_TARGET_CONNECTIONS=100
# Connection limits
MAX_CONNECTIONS_PER_NODE=50
CONNECTION_DRAIN_TIMEOUT=30
Health Monitoring¶
# Health check intervals (seconds)
HEALTH_CHECK_INTERVAL=30
HEALTH_CHECK_TIMEOUT=10
HEALTH_CHECK_RETRIES=3
HEALTH_CHECK_BACKOFF_FACTOR=2
# Failover settings
FAILOVER_ENABLED=true
FAILOVER_THRESHOLD=3 # Failed health checks before failover
FAILOVER_COOLDOWN=300 # Seconds before retry
Speed Testing¶
# Speed test configuration
SPEED_TEST_ENABLED=true
SPEED_TEST_INTERVAL=3600 # Run every hour
SPEED_TEST_TIMEOUT=60
SPEED_TEST_SERVERS=["fast.com", "speedtest.net", "google.com"]
# Test file sizes
SPEED_TEST_DOWNLOAD_SIZE=10MB
SPEED_TEST_UPLOAD_SIZE=5MB
Metrics and Logging¶
# Logging
LOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR, CRITICAL
LOG_FORMAT=json # json or text
LOG_FILE=/var/log/vpn-controller/app.log
LOG_ROTATION=daily
LOG_RETENTION_DAYS=30
# Metrics
METRICS_ENABLED=true
METRICS_RETENTION_HOURS=168 # 7 days
METRICS_AGGREGATION_INTERVAL=60 # seconds
Security Settings¶
# API Security
API_RATE_LIMIT_ENABLED=true
API_RATE_LIMIT_PER_MINUTE=100
API_RATE_LIMIT_BURST=20
# IP Whitelisting (comma-separated)
API_WHITELIST_IPS=10.0.0.0/8,192.168.0.0/16
API_BLACKLIST_IPS=
# Session Management
SESSION_TIMEOUT=3600 # 1 hour
SESSION_SECURE_COOKIE=true
SESSION_SAME_SITE=strict
Domain and SSL Configuration¶
# Domain settings
DOMAIN=rbnk.uk
API_SUBDOMAIN=vpn-api
DOCS_SUBDOMAIN=vpn-docs
# Cloudflare
CF_API_TOKEN=your_cloudflare_api_token
CF_ZONE_ID=your_zone_id
CF_PROXY_ENABLED=true
# SSL/TLS
[email protected]
SSL_STAGING=false # Set to true for Let's Encrypt staging
Service Configuration¶
Systemd Service¶
Edit /etc/systemd/system/vpn-controller.service:
[Unit]
Description=VPN Exit Controller API
After=network.target redis.service docker.service
Wants=redis.service docker.service
[Service]
Type=exec
User=root
Group=docker
WorkingDirectory=/opt/vpn-exit-controller
# Environment
Environment="PATH=/opt/vpn-exit-controller/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
EnvironmentFile=/opt/vpn-exit-controller/.env
# Process management
ExecStart=/opt/vpn-exit-controller/venv/bin/python -m uvicorn api.main:app --host 0.0.0.0 --port 8080
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
# Restart policy
Restart=always
RestartSec=10
RestartPreventExitStatus=0
# Resource limits
LimitNOFILE=65536
LimitNPROC=4096
# Security
PrivateTmp=true
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
Docker Configuration¶
Docker Compose Override¶
Create docker-compose.override.yml for local settings:
version: '3.8'
services:
vpn-controller:
environment:
- LOG_LEVEL=DEBUG
- API_RELOAD=true
volumes:
- ./custom-configs:/app/custom-configs
ports:
- "8081:8080" # Different port for development
Docker Resource Limits¶
services:
vpn-controller:
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
HAProxy Configuration¶
Load Balancer Tuning¶
Edit /opt/vpn-exit-controller/proxy/haproxy.cfg:
global
# Performance tuning
maxconn 10000
nbproc 4
nbthread 8
cpu-map auto:1/1-8 0-7
# Timeouts
timeout connect 5s
timeout client 30s
timeout server 30s
timeout tunnel 1h
# SSL/TLS tuning
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers ECDHE+AESGCM:ECDHE+AES256:ECDHE+AES128
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
Backend Configuration¶
backend proxy_us
# Load balancing algorithm
balance leastconn # or roundrobin, source, uri
# Health checks
option httpchk GET /health HTTP/1.1\r\nHost:\ localhost
http-check expect status 200
# Connection settings
option http-server-close
option forwardfor
http-reuse safe
# Servers with advanced options
server vpn-us-1 10.0.0.11:8888 check inter 5s rise 2 fall 3 weight 100
server vpn-us-2 10.0.0.12:8888 check inter 5s rise 2 fall 3 weight 100 backup
Traefik Configuration¶
Dynamic Configuration¶
Create traefik/dynamic/vpn-controller.yml:
http:
routers:
vpn-api:
rule: "Host(`vpn-api.rbnk.uk`)"
service: vpn-api
entryPoints:
- websecure
tls:
certResolver: cf
middlewares:
- rate-limit
- security-headers
services:
vpn-api:
loadBalancer:
servers:
- url: "http://localhost:8080"
healthCheck:
path: /api/health
interval: 30s
timeout: 10s
middlewares:
rate-limit:
rateLimit:
average: 100
burst: 50
period: 1m
security-headers:
headers:
customFrameOptionsValue: SAMEORIGIN
contentTypeNosniff: true
browserXssFilter: true
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
Application Configuration¶
API Settings¶
Create api/config.py for application-specific settings:
from pydantic_settings import BaseSettings
from typing import List, Optional
class Settings(BaseSettings):
# API Settings
title: str = "VPN Exit Controller API"
version: str = "1.0.0"
description: str = "Professional VPN node management system"
docs_url: str = "/api/docs"
redoc_url: str = "/api/redoc"
# Feature flags
enable_metrics: bool = True
enable_webhooks: bool = True
enable_speed_tests: bool = True
enable_auto_scaling: bool = True
# Performance tuning
connection_pool_size: int = 100
request_timeout: int = 30
background_task_workers: int = 4
class Config:
env_file = ".env"
case_sensitive = False
settings = Settings()
Runtime Configuration API¶
Configure settings via API without restart:
# Update load balancing strategy
curl -X PUT -u admin:password \
-H "Content-Type: application/json" \
-d '{"key": "load_balancing.strategy", "value": "health_score"}' \
https://api.vpn.yourdomain.com/api/config
# Update health check interval
curl -X PUT -u admin:password \
-H "Content-Type: application/json" \
-d '{"key": "health_check.interval", "value": 60}' \
https://api.vpn.yourdomain.com/api/config
Configuration Best Practices¶
Environment Management¶
-
Development Environment
-
Production Environment
-
Environment Loading
Secret Management¶
Security Best Practice
Never commit secrets to version control. Use secure secret management solutions.
Options for secret management:
-
HashiCorp Vault
-
AWS Secrets Manager
-
Environment Variable Encryption
Configuration Validation¶
Validate configuration on startup:
def validate_config():
"""Validate all configuration settings"""
errors = []
# Check required variables
required = ['NORDVPN_USER', 'NORDVPN_PASS', 'TAILSCALE_AUTH_KEY']
for var in required:
if not os.getenv(var):
errors.append(f"Missing required: {var}")
# Validate formats
if os.getenv('API_PORT'):
try:
port = int(os.getenv('API_PORT'))
if not 1 <= port <= 65535:
errors.append("Invalid port range")
except ValueError:
errors.append("API_PORT must be integer")
if errors:
raise ConfigurationError("\n".join(errors))
Monitoring Configuration¶
Use these commands to verify configuration:
# Check loaded environment
./scripts/check-config.sh
# Validate configuration
python -m api.config validate
# Test configuration changes
curl -u admin:password https://api.vpn.yourdomain.com/api/config/test
Next Steps¶
- 🚀 Deploy to Production
- 🔒 Security Hardening
- 📊 Monitoring Setup
- 🔧 Troubleshooting
Configuration Tips
- Always use
.env.exampleas a template - Keep production secrets in a secure vault
- Monitor configuration changes with audit logs
- Test configuration changes in staging first
- Document all custom configuration options