refactor(scripts): simplify modes and harden cert automation
- New modes: lan-http, lan-tls (self-signed), public, full - Add flags: --no-sni443, --enable-web-https (lan-tls), --test-renewal - generate-config: lan-tls HTTPS on 8443 only when explicitly enabled; HSTS only in full; SNI 443 default in full - detect-environment: remove interactive prompt; adjust public description to 'HTTP + TURN' - deploy.sh: pass new flags, add certbot scheduler (systemd timer or cron fallback), add dry-run renewal test - Docs (EN/zh-CN): update quick start, modes overview, LAN TLS guidance, LE auto-issue/renew section
This commit is contained in:
@@ -39,21 +39,28 @@ Usage: $0 [options]
|
||||
|
||||
Options:
|
||||
--domain DOMAIN Specify domain (for HTTPS deployments)
|
||||
--mode MODE Deployment mode: basic|public|full|private
|
||||
basic/private: Intranet HTTP (default; private skips network detection)
|
||||
public: Public HTTP + TURN server
|
||||
full: Full HTTPS + TURN server
|
||||
--mode MODE Deployment mode: lan-http|lan-tls|public|full
|
||||
lan-http: Intranet HTTP (fast start; no TLS)
|
||||
lan-tls: Intranet HTTPS (self-signed; dev/managed env only)
|
||||
public: Public HTTP + TURN server
|
||||
full: Domain + HTTPS (Let’s Encrypt) + TURN server
|
||||
--with-nginx Enable Nginx reverse proxy
|
||||
--with-turn Enable TURN server
|
||||
--with-sni443 Enable 443 SNI routing (enabled by default in full mode)
|
||||
--with-sni443 Force enable 443 SNI routing (full; default enabled)
|
||||
--no-sni443 Disable 443 SNI routing (full; web listens directly on 443)
|
||||
--enable-web-https In lan-tls mode, enable self-signed HTTPS on 8443 (no HSTS)
|
||||
--le-email EMAIL Email for Let's Encrypt (recommended in full mode)
|
||||
--test-renewal Run 'certbot renew --dry-run' and reload services (verification)
|
||||
--clean Clean existing containers and data
|
||||
--help Show help
|
||||
|
||||
Examples:
|
||||
$0 # Basic deployment
|
||||
$0 --mode public --with-turn # Public deployment + TURN server
|
||||
$0 --domain example.com --mode full # Full HTTPS deployment
|
||||
$0 --mode lan-http # LAN HTTP quick start
|
||||
$0 --mode lan-http --with-turn # LAN HTTP with TURN (NAT-friendly)
|
||||
$0 --mode lan-tls --enable-web-https # LAN HTTPS (self-signed) on 8443 (dev/managed)
|
||||
$0 --mode public --with-turn # Public deployment + TURN server (no domain)
|
||||
$0 --mode full --domain example.com \\
|
||||
--with-nginx --with-turn --le-email you@domain.com # Full HTTPS deployment (LE auto-issue/renew)
|
||||
$0 --clean # Clean deployment
|
||||
|
||||
Requirements:
|
||||
@@ -71,6 +78,9 @@ parse_arguments() {
|
||||
CLEAN_MODE=false
|
||||
LE_EMAIL=""
|
||||
WITH_SNI443=false
|
||||
DISABLE_SNI443=false
|
||||
ENABLE_WEB_HTTPS=false
|
||||
TEST_RENEWAL=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
@@ -94,10 +104,22 @@ parse_arguments() {
|
||||
WITH_SNI443=true
|
||||
shift
|
||||
;;
|
||||
--no-sni443)
|
||||
DISABLE_SNI443=true
|
||||
shift
|
||||
;;
|
||||
--enable-web-https)
|
||||
ENABLE_WEB_HTTPS=true
|
||||
shift
|
||||
;;
|
||||
--le-email)
|
||||
LE_EMAIL="$2"
|
||||
shift 2
|
||||
;;
|
||||
--test-renewal)
|
||||
TEST_RENEWAL=true
|
||||
shift
|
||||
;;
|
||||
--clean)
|
||||
CLEAN_MODE=true
|
||||
shift
|
||||
@@ -222,6 +244,40 @@ EOF
|
||||
fi
|
||||
}
|
||||
|
||||
# Ensure renewal is scheduled daily: prefer systemd timer; fallback to cron
|
||||
ensure_renewal_scheduler() {
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
sudo systemctl enable --now certbot.timer 2>/dev/null || true
|
||||
return 0
|
||||
fi
|
||||
# Fallback: cron job every 12 hours
|
||||
if [ -w /etc/cron.d ] || sudo test -d /etc/cron.d; then
|
||||
sudo bash -c 'cat > /etc/cron.d/certbot' << 'EOF'
|
||||
# Auto-renew Let's Encrypt certificates for PrivyDrop
|
||||
SHELL=/bin/bash
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
0 */12 * * * root certbot renew -q
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
# Dry-run renewal test
|
||||
test_renewal() {
|
||||
log_info "Running certbot dry-run renewal test..."
|
||||
if ! command -v certbot >/dev/null 2>&1; then
|
||||
log_error "certbot not installed. Run full mode issuance first or install certbot manually"
|
||||
return 1
|
||||
fi
|
||||
sudo certbot renew --dry-run || {
|
||||
log_error "certbot dry-run failed"
|
||||
return 1
|
||||
}
|
||||
# Attempt hot-reload of nginx and coturn similar to deploy-hook
|
||||
docker compose exec -T nginx nginx -s reload 2>/dev/null || docker compose restart nginx || true
|
||||
docker compose exec -T coturn sh -c 'kill -HUP 1' 2>/dev/null || docker compose restart coturn || true
|
||||
log_success "Dry-run renewal completed; services reloaded"
|
||||
}
|
||||
|
||||
# Issue via webroot and enable 443 config
|
||||
provision_letsencrypt_cert() {
|
||||
# Only in full mode with nginx enabled and domain set
|
||||
@@ -238,6 +294,7 @@ provision_letsencrypt_cert() {
|
||||
|
||||
ensure_certbot
|
||||
install_certbot_deploy_hook
|
||||
ensure_renewal_scheduler
|
||||
|
||||
mkdir -p docker/letsencrypt-www docker/ssl
|
||||
|
||||
@@ -277,6 +334,7 @@ provision_letsencrypt_cert() {
|
||||
# Enable 443 config (certs ready): append only; pass SNI flag (enabled by default in full)
|
||||
local gen_args=(--mode full --domain "$DOMAIN_NAME" --no-clean --ssl-mode letsencrypt)
|
||||
[[ "$WITH_SNI443" == "true" ]] && gen_args+=(--enable-sni443)
|
||||
[[ "$DISABLE_SNI443" == "true" ]] && gen_args+=(--no-sni443)
|
||||
bash "$DOCKER_SCRIPTS_DIR/generate-config.sh" "${gen_args[@]}" || true
|
||||
|
||||
# Hot-reload nginx to enable 443
|
||||
@@ -336,6 +394,8 @@ setup_environment() {
|
||||
[[ -n "$DOMAIN_NAME" ]] && detect_args="--domain $DOMAIN_NAME"
|
||||
[[ -n "$DEPLOYMENT_MODE" ]] && detect_args="$detect_args --mode $DEPLOYMENT_MODE"
|
||||
[[ "$WITH_SNI443" == "true" ]] && detect_args="$detect_args --enable-sni443"
|
||||
[[ "$DISABLE_SNI443" == "true" ]] && detect_args="$detect_args --no-sni443"
|
||||
[[ "$ENABLE_WEB_HTTPS" == "true" ]] && detect_args="$detect_args --enable-web-https"
|
||||
|
||||
if ! bash "$DOCKER_SCRIPTS_DIR/detect-environment.sh" $detect_args; then
|
||||
log_error "Environment detection failed"
|
||||
@@ -619,6 +679,11 @@ main() {
|
||||
# Check dependencies
|
||||
check_dependencies
|
||||
echo ""
|
||||
|
||||
# If only testing renewal, run and exit
|
||||
if [[ "$TEST_RENEWAL" == "true" ]]; then
|
||||
test_renewal && exit 0 || exit 1
|
||||
fi
|
||||
|
||||
# Clean mode
|
||||
clean_deployment
|
||||
|
||||
@@ -236,18 +236,7 @@ detect_network_environment() {
|
||||
|
||||
if [[ -z "$FORCED_MODE" ]]; then
|
||||
if [[ "$mode_guess" == "public" ]]; then
|
||||
echo " Local IP: $LOCAL_IP"
|
||||
echo " Public IP: $PUBLIC_IP"
|
||||
printed_prompt_info="true"
|
||||
read -r -p "Continue in public mode? (Y/n): " confirm </dev/tty 2>/dev/null || confirm="Y"
|
||||
confirm=${confirm:-Y}
|
||||
if [[ "$confirm" =~ ^[Yy]$ ]]; then
|
||||
NETWORK_MODE="public"
|
||||
else
|
||||
NETWORK_MODE="private"
|
||||
PUBLIC_IP=""
|
||||
log_warning "Switched to private mode per user choice"
|
||||
fi
|
||||
NETWORK_MODE="public"
|
||||
else
|
||||
NETWORK_MODE="private"
|
||||
fi
|
||||
@@ -409,7 +398,7 @@ detect_deployment_mode() {
|
||||
log_success "Deployment mode: full (HTTPS + TURN server)"
|
||||
elif [[ "$NETWORK_MODE" == "public" ]]; then
|
||||
DEPLOYMENT_MODE="public"
|
||||
log_success "Deployment mode: public (HTTP + self-signed)"
|
||||
log_success "Deployment mode: public (HTTP + TURN)"
|
||||
else
|
||||
DEPLOYMENT_MODE="basic"
|
||||
log_success "Deployment mode: basic (intranet HTTP)"
|
||||
|
||||
@@ -37,6 +37,11 @@ TURN_MIN_PORT="$TURN_MIN_PORT_DEFAULT"
|
||||
TURN_MAX_PORT="$TURN_MAX_PORT_DEFAULT"
|
||||
ENABLE_SNI443="${ENABLE_SNI443:-}"
|
||||
|
||||
# Web HTTPS in LAN (self-signed only when explicitly enabled)
|
||||
WEB_HTTPS_ENABLED=false
|
||||
HTTPS_LISTEN_PORT=""
|
||||
HSTS_ENABLED=false
|
||||
|
||||
parse_turn_port_range() {
|
||||
local range="$1"
|
||||
if [[ -z "$range" ]]; then
|
||||
@@ -84,22 +89,24 @@ PrivyDrop Config Generator (Docker)
|
||||
Usage: bash docker/scripts/generate-config.sh [options]
|
||||
|
||||
Options:
|
||||
--mode MODE Generation mode: private|basic|public|full
|
||||
private/basic: Intranet HTTP; TURN disabled by default; frontend talks directly to backend
|
||||
public: Public HTTP + TURN enabled (works without domain; TURN host prefers public IP)
|
||||
full: Full HTTPS + TURN enabled (domain recommended; frontend via domain HTTPS)
|
||||
--with-turn Enable TURN in any mode (including private/basic). Default external-ip=LOCAL_IP
|
||||
--mode MODE Generation mode: lan-http|lan-tls|public|full
|
||||
lan-http: Intranet HTTP (fast start; no TLS)
|
||||
lan-tls: Intranet HTTPS (self-signed; dev/managed env only)
|
||||
public: Public HTTP + TURN (no domain)
|
||||
full: Domain + HTTPS (Let’s Encrypt) + TURN
|
||||
--with-turn Enable TURN in any mode. Default external-ip=LOCAL_IP
|
||||
--turn-external-ip IP Explicit TURN external-ip; if not set, use PUBLIC_IP, otherwise fallback to LOCAL_IP
|
||||
--turn-port-range R TURN UDP port range, format MIN-MAX; default 49152-49252
|
||||
--domain DOMAIN Domain (for Nginx/certs/TURN realm, e.g., turn.DOMAIN)
|
||||
--local-ip IP Local intranet IP (auto-detected if omitted)
|
||||
--enable-sni443 Enable 443 SNI split (turn.DOMAIN → coturn:5349, others → web:8443)
|
||||
--no-sni443 Disable 443 SNI split (HTTPS listens directly on 443)
|
||||
--enable-web-https In lan-tls mode, enable self-signed HTTPS on 8443 (no HSTS)
|
||||
--help Show this help
|
||||
--no-clean Skip cleaning previous outputs (useful for regeneration without wiping SSL)
|
||||
--reset-ssl Force clean docker/ssl/* (not cleaned by default)
|
||||
--ssl-mode MODE Cert mode: letsencrypt|self-signed|provided
|
||||
- full defaults to letsencrypt; private/public default to self-signed
|
||||
- full defaults to letsencrypt; lan-tls uses self-signed when --enable-web-https; others: none
|
||||
|
||||
Environment variables (optional):
|
||||
PUBLIC_IP Explicit public IP; only used in public/full.
|
||||
@@ -108,35 +115,28 @@ Environment variables (optional):
|
||||
|
||||
Outputs (with key variables set automatically):
|
||||
- .env Core env vars (including NEXT_PUBLIC_API_URL/CORS)
|
||||
- docker/nginx/* Nginx reverse proxy configs (HTTP also generated for private/basic)
|
||||
- docker/ssl/* Self-signed certs (generated for private/basic/public; replace with real certs for full)
|
||||
- docker/nginx/* Nginx reverse proxy configs
|
||||
- docker/ssl/* Self-signed certs (only when lan-tls + --enable-web-https)
|
||||
- docker/coturn/turnserver.conf Generated/overwritten in public/full or when --with-turn is set
|
||||
|
||||
Notes:
|
||||
- TURN external-ip is set as external-ip=${PUBLIC_IP:-${LOCAL_IP}}
|
||||
i.e., prefer PUBLIC_IP, otherwise fallback to LOCAL_IP.
|
||||
- private/basic does not overwrite docker/coturn/turnserver.conf;
|
||||
if TURN was generated before, that file may retain a previous external-ip.
|
||||
|
||||
Examples:
|
||||
# 1) Pure intranet (recommended for dev/quick LAN testing)
|
||||
bash docker/scripts/generate-config.sh --mode private [--local-ip 192.168.0.113]
|
||||
# 1) LAN HTTP (fastest path)
|
||||
bash docker/scripts/generate-config.sh --mode lan-http [--local-ip 192.168.0.113]
|
||||
|
||||
# 2) Intranet + TURN (default external-ip=LOCAL_IP, ports=49152-49252)
|
||||
bash docker/scripts/generate-config.sh --mode private --with-turn [--local-ip 192.168.0.113]
|
||||
# 2) LAN + TURN (default external-ip=LOCAL_IP)
|
||||
bash docker/scripts/generate-config.sh --mode lan-http --with-turn [--local-ip 192.168.0.113]
|
||||
|
||||
# 3) Intranet + TURN (custom port range / explicit external-ip)
|
||||
bash docker/scripts/generate-config.sh --mode private --with-turn \
|
||||
--turn-port-range 56000-56100 --turn-external-ip 192.168.0.113 \
|
||||
[--local-ip 192.168.0.113]
|
||||
# 3) LAN HTTPS (self-signed; dev/managed env only)
|
||||
bash docker/scripts/generate-config.sh --mode lan-tls --enable-web-https [--local-ip 192.168.0.113]
|
||||
|
||||
# 4) Public HTTP + TURN (auto-detect public IP; inject NEXT_PUBLIC_API_URL)
|
||||
bash docker/scripts/generate-config.sh --mode public --local-ip 192.168.0.113
|
||||
# 4) Public HTTP + TURN (no domain)
|
||||
bash docker/scripts/generate-config.sh --mode public [--local-ip 192.168.0.113]
|
||||
|
||||
# 5) Public HTTP + TURN (explicit public IP; avoid external detection)
|
||||
PUBLIC_IP=1.2.3.4 bash docker/scripts/generate-config.sh --mode public --local-ip 192.168.0.113
|
||||
|
||||
# 6) HTTPS + TURN (with domain)
|
||||
# 5) Full HTTPS + TURN (with domain; LE auto-issue/renew)
|
||||
bash docker/scripts/generate-config.sh --mode full --domain example.com --local-ip 192.168.0.113
|
||||
|
||||
For more scenarios and details, see:
|
||||
@@ -175,7 +175,7 @@ generate_env_file() {
|
||||
# Support both localhost and host IP for browser access; helpful for Docker direct access or local debugging
|
||||
local cors_origin="http://${LOCAL_IP}:3002,http://localhost:3002"
|
||||
local api_url="http://${LOCAL_IP}:3001"
|
||||
local ssl_mode="self-signed"
|
||||
local ssl_mode="none"
|
||||
local turn_enabled="false"
|
||||
local turn_host_value=""
|
||||
local turn_realm_value="${existing_env[TURN_REALM]:-turn.local}"
|
||||
@@ -184,19 +184,33 @@ generate_env_file() {
|
||||
local next_public_turn_username=""
|
||||
local next_public_turn_password=""
|
||||
|
||||
if [[ "$DEPLOYMENT_MODE" == "public" ]]; then
|
||||
# Public without domain: frontend connects directly to backend; use PUBLIC_IP (fallback LOCAL_IP)
|
||||
local effective_public_host="${PUBLIC_IP:-$LOCAL_IP}"
|
||||
cors_origin="http://${effective_public_host}:3002,http://localhost:3002"
|
||||
api_url="http://${effective_public_host}:3001"
|
||||
turn_enabled="true"
|
||||
elif [[ "$DEPLOYMENT_MODE" == "full" ]]; then
|
||||
# With domain + HTTPS: both frontend and backend via domain; Nginx proxies /api
|
||||
cors_origin="https://${DOMAIN_NAME:-$LOCAL_IP}"
|
||||
api_url="https://${DOMAIN_NAME:-$LOCAL_IP}"
|
||||
ssl_mode="letsencrypt"
|
||||
turn_enabled="true"
|
||||
fi
|
||||
case "$DEPLOYMENT_MODE" in
|
||||
lan-http)
|
||||
cors_origin="http://${LOCAL_IP}:3002,http://localhost:3002"
|
||||
api_url="http://${LOCAL_IP}:3001"
|
||||
;;
|
||||
lan-tls)
|
||||
if [[ "$WEB_HTTPS_ENABLED" == "true" ]]; then
|
||||
HTTPS_LISTEN_PORT="8443"
|
||||
cors_origin="https://${LOCAL_IP}:${HTTPS_LISTEN_PORT}"
|
||||
api_url="https://${LOCAL_IP}:${HTTPS_LISTEN_PORT}"
|
||||
ssl_mode="self-signed"
|
||||
fi
|
||||
;;
|
||||
public)
|
||||
local effective_public_host="${PUBLIC_IP:-$LOCAL_IP}"
|
||||
cors_origin="http://${effective_public_host}:3002,http://localhost:3002"
|
||||
api_url="http://${effective_public_host}:3001"
|
||||
turn_enabled="true"
|
||||
;;
|
||||
full)
|
||||
cors_origin="https://${DOMAIN_NAME:-$LOCAL_IP}"
|
||||
api_url="https://${DOMAIN_NAME:-$LOCAL_IP}"
|
||||
ssl_mode="letsencrypt"
|
||||
turn_enabled="true"
|
||||
;;
|
||||
*) : ;;
|
||||
esac
|
||||
|
||||
# If TURN explicitly enabled, override mode defaults
|
||||
if [[ "$WITH_TURN" == "true" ]]; then
|
||||
@@ -257,7 +271,7 @@ NEXT_PUBLIC_TURN_PASSWORD=${next_public_turn_password}
|
||||
FRONTEND_PORT=3002
|
||||
BACKEND_PORT=3001
|
||||
HTTP_PORT=80
|
||||
HTTPS_PORT=443
|
||||
HTTPS_PORT=${HTTPS_LISTEN_PORT:-443}
|
||||
|
||||
# =============================================================================
|
||||
# Redis config
|
||||
@@ -481,7 +495,7 @@ EOF
|
||||
|
||||
# Generate SSL certificates
|
||||
generate_ssl_certificates() {
|
||||
if [[ "$SSL_MODE" == "self-signed" ]] || [[ "$NETWORK_MODE" == "private" ]]; then
|
||||
if [[ "$SSL_MODE" == "self-signed" ]]; then
|
||||
log_info "Generating self-signed SSL certificates..."
|
||||
|
||||
mkdir -p docker/ssl
|
||||
@@ -533,8 +547,10 @@ EOF
|
||||
log_success "SSL certificates generated: docker/ssl/"
|
||||
log_info "To trust the cert, import the CA cert: docker/ssl/ca-cert.pem"
|
||||
|
||||
# For self-signed, generate 443 config immediately
|
||||
if [[ "$DEPLOYMENT_MODE" != "basic" ]]; then
|
||||
# For self-signed, generate HTTPS config only when explicitly enabled (lan-tls)
|
||||
if [[ "$WEB_HTTPS_ENABLED" == "true" ]]; then
|
||||
HSTS_ENABLED=false
|
||||
HTTPS_LISTEN_PORT="${HTTPS_LISTEN_PORT:-8443}"
|
||||
generate_https_nginx_config
|
||||
fi
|
||||
fi
|
||||
@@ -544,10 +560,20 @@ EOF
|
||||
generate_https_nginx_config() {
|
||||
log_info "Generating HTTPS Nginx config..."
|
||||
local https_port="443"
|
||||
if [[ "$ENABLE_SNI443" == "true" ]]; then
|
||||
if [[ -n "$HTTPS_LISTEN_PORT" ]]; then
|
||||
https_port="$HTTPS_LISTEN_PORT"
|
||||
elif [[ "$ENABLE_SNI443" == "true" ]]; then
|
||||
https_port="8443"
|
||||
fi
|
||||
|
||||
|
||||
local hsts_lines=""
|
||||
if [[ "$HSTS_ENABLED" == "true" ]]; then
|
||||
hsts_lines=$(cat << 'HSTSEOF'
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
HSTSEOF
|
||||
)
|
||||
fi
|
||||
|
||||
cat >> docker/nginx/conf.d/default.conf << EOF
|
||||
|
||||
# HTTPS server config
|
||||
@@ -565,7 +591,7 @@ server {
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
# Security headers
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
${hsts_lines}
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
@@ -669,7 +695,7 @@ stream {
|
||||
EOF
|
||||
}
|
||||
|
||||
# Enable 443 only when certs exist (for letsencrypt/provided)
|
||||
# Enable HTTPS only when certs exist (for letsencrypt/provided)
|
||||
enable_https_if_cert_present() {
|
||||
if [[ -f "docker/ssl/server-cert.pem" && -f "docker/ssl/server-key.pem" ]]; then
|
||||
# With SNI enabled, append stream split first, then generate HTTPS on 8443/443
|
||||
@@ -678,8 +704,10 @@ enable_https_if_cert_present() {
|
||||
fi
|
||||
# If HTTPS server is not present in default.conf, append it (port depends on SNI flag)
|
||||
local expected="listen 443 ssl"
|
||||
[[ "$ENABLE_SNI443" == "true" ]] && expected="listen 8443 ssl"
|
||||
[[ -n "$HTTPS_LISTEN_PORT" ]] && expected="listen ${HTTPS_LISTEN_PORT} ssl"
|
||||
[[ "$ENABLE_SNI443" == "true" && -z "$HTTPS_LISTEN_PORT" ]] && expected="listen 8443 ssl"
|
||||
if ! grep -q "$expected" docker/nginx/conf.d/default.conf 2>/dev/null; then
|
||||
HSTS_ENABLED=true
|
||||
generate_https_nginx_config
|
||||
else
|
||||
log_info "Existing HTTPS (${ENABLE_SNI443:+SNI=on}) config detected; skipping"
|
||||
@@ -837,11 +865,17 @@ main() {
|
||||
;;
|
||||
--mode)
|
||||
DEPLOYMENT_MODE="$2"
|
||||
if [[ "$2" == "private" || "$2" == "basic" ]]; then
|
||||
FORCED_MODE="private"
|
||||
elif [[ "$2" == "public" || "$2" == "full" ]]; then
|
||||
FORCED_MODE="public"
|
||||
fi
|
||||
case "$2" in
|
||||
lan-http|lan-tls)
|
||||
FORCED_MODE="private"
|
||||
;;
|
||||
public|full)
|
||||
FORCED_MODE="public"
|
||||
;;
|
||||
*)
|
||||
FORCED_MODE=""
|
||||
;;
|
||||
esac
|
||||
shift 2
|
||||
;;
|
||||
--local-ip)
|
||||
@@ -868,6 +902,11 @@ main() {
|
||||
ENABLE_SNI443=false
|
||||
shift
|
||||
;;
|
||||
--enable-web-https)
|
||||
WEB_HTTPS_ENABLED=true
|
||||
HTTPS_LISTEN_PORT="8443"
|
||||
shift
|
||||
;;
|
||||
--no-clean)
|
||||
NO_CLEAN=true
|
||||
shift
|
||||
@@ -904,7 +943,7 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
detect_deployment_mode
|
||||
# No automatic deployment-mode detection here; honor user-provided --mode
|
||||
echo ""
|
||||
|
||||
# Generate all configuration files
|
||||
@@ -915,13 +954,25 @@ main() {
|
||||
echo ""
|
||||
|
||||
# Certificate generation policy:
|
||||
# - private/public use self-signed; full uses letsencrypt (issued/copied by deploy script)
|
||||
# - full uses letsencrypt (issued/copied by deploy script)
|
||||
# - lan-tls uses self-signed only when --enable-web-https is set
|
||||
# - others: none
|
||||
if [[ -z "$SSL_MODE" ]]; then
|
||||
if [[ "$DEPLOYMENT_MODE" == "full" ]]; then
|
||||
SSL_MODE="letsencrypt"
|
||||
else
|
||||
SSL_MODE="self-signed"
|
||||
fi
|
||||
case "$DEPLOYMENT_MODE" in
|
||||
full)
|
||||
SSL_MODE="letsencrypt"
|
||||
;;
|
||||
lan-tls)
|
||||
if [[ "$WEB_HTTPS_ENABLED" == "true" ]]; then
|
||||
SSL_MODE="self-signed"
|
||||
else
|
||||
SSL_MODE="none"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
SSL_MODE="none"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# SNI on 443 enabled by default: full mode with domain, unless --no-sni443
|
||||
@@ -936,11 +987,20 @@ main() {
|
||||
generate_ssl_certificates
|
||||
echo ""
|
||||
|
||||
# full/provided/letsencrypt: enable 443 only when certs are ready
|
||||
if [[ "$DEPLOYMENT_MODE" == "full" ]]; then
|
||||
enable_https_if_cert_present
|
||||
echo ""
|
||||
fi
|
||||
# Enable HTTPS depending on mode/certs
|
||||
case "$DEPLOYMENT_MODE" in
|
||||
full)
|
||||
enable_https_if_cert_present
|
||||
echo ""
|
||||
;;
|
||||
lan-tls)
|
||||
# HTTPS already handled on generation when enabled
|
||||
:
|
||||
;;
|
||||
*)
|
||||
:
|
||||
;;
|
||||
esac
|
||||
|
||||
generate_coturn_config
|
||||
echo ""
|
||||
|
||||
+18
-36
@@ -6,10 +6,13 @@ This guide provides a one-click Docker deployment for PrivyDrop. It supports bot
|
||||
|
||||
```bash
|
||||
# Private LAN (no domain/public IP)
|
||||
bash ./deploy.sh --mode private
|
||||
bash ./deploy.sh --mode lan-http
|
||||
|
||||
# Private LAN + TURN (for complex NAT/LAN)
|
||||
bash ./deploy.sh --mode private --with-turn
|
||||
bash ./deploy.sh --mode lan-http --with-turn
|
||||
|
||||
# LAN HTTPS (self-signed; dev/managed env; explicitly enable 8443)
|
||||
bash ./deploy.sh --mode lan-tls --enable-web-https --with-nginx
|
||||
|
||||
# Public IP without domain (with TURN)
|
||||
bash ./deploy.sh --mode public --with-turn
|
||||
@@ -23,10 +26,10 @@ bash ./deploy.sh --mode full --domain your-domain.com --with-nginx --with-turn -
|
||||
|
||||
## Modes Overview
|
||||
|
||||
- basic: Intranet HTTP; auto-detect network environment
|
||||
- private: Intranet HTTP; skip network detection (faster; good for known LAN/CI)
|
||||
- public: Public HTTP; TURN enabled; works without a domain
|
||||
- full: Domain + HTTPS; TURN enabled; optional SNI 443 split
|
||||
- lan-http: Intranet HTTP; fastest to start; no TLS
|
||||
- lan-tls: Intranet HTTPS (self-signed; dev/managed env); 8443 disabled by default; enable via `--enable-web-https`; HSTS disabled; turns:443 not guaranteed
|
||||
- public: Public HTTP + TURN; works without a domain (no HTTPS/turns:443)
|
||||
- full: Domain + HTTPS (Let’s Encrypt auto-issue/renew) + TURN; SNI 443 split enabled by default (use `--no-sni443` to disable)
|
||||
|
||||
## 🎯 Deployment Advantages
|
||||
|
||||
@@ -424,32 +427,15 @@ bash deploy.sh --mode full --with-nginx
|
||||
|
||||
## 🔒 Security Configuration
|
||||
|
||||
### Domain + Self-signed Certificates (full + self-signed)
|
||||
### LAN HTTPS (lan-tls, self-signed, dev/managed env)
|
||||
|
||||
Use when you only need encrypted transport or have your own PKI.
|
||||
|
||||
Steps:
|
||||
|
||||
1) Generate configuration (self-signed + domain)
|
||||
- 8443 is disabled by default; explicitly enable with:
|
||||
|
||||
```bash
|
||||
SSL_MODE=self-signed \
|
||||
bash docker/scripts/generate-config.sh \
|
||||
--mode full --domain your-domain.com --with-nginx --with-turn
|
||||
bash ./deploy.sh --mode lan-tls --enable-web-https --with-nginx
|
||||
```
|
||||
|
||||
2) Start services manually (to avoid auto-provisioning Let’s Encrypt)
|
||||
|
||||
```bash
|
||||
docker compose build
|
||||
docker compose --profile nginx up -d
|
||||
```
|
||||
|
||||
3) Import the CA certificate `docker/ssl/ca-cert.pem` into your browser, or accept the risk on first visit
|
||||
|
||||
Optional: To use `turns:443`, enable SNI 443 split (see “Common Flags” and the generator help).
|
||||
|
||||
Note: For production, prefer Let’s Encrypt to avoid trust/HSTS issues.
|
||||
- For development or managed devices only (internal CA trusted fleet-wide); HSTS disabled; `turns:443` not guaranteed. For restricted networks (443-only), use full (domain + trusted cert + SNI 443).
|
||||
|
||||
### Public Domain Deployment (HTTPS + Nginx) — Quick Test
|
||||
|
||||
@@ -465,17 +451,13 @@ Note: For production, prefer Let’s Encrypt to avoid trust/HSTS issues.
|
||||
|
||||
4) Verify: visit `https://<your-domain>`, `/api/health` returns 200; open `chrome://webrtc-internals` and check for `relay` candidates (TURN)
|
||||
|
||||
### SSL/TLS Configuration
|
||||
### SSL/TLS Automation (Let’s Encrypt)
|
||||
|
||||
1. **Self-signed Certificates** (default):
|
||||
In full mode, certificates are auto-issued and auto-renewed:
|
||||
|
||||
- Automatically generated and configured
|
||||
- Suitable for private networks and testing
|
||||
- Certificate location: `docker/ssl/`
|
||||
|
||||
2. **Let's Encrypt Certificates** (planned):
|
||||
- Automatic application and renewal
|
||||
- Suitable for production with domain names
|
||||
- Initial issuance: webroot (no downtime); system certs live under `/etc/letsencrypt/live/<domain>/`; copied to `docker/ssl/` and 443 is enabled.
|
||||
- Renewal: `certbot.timer` or `/etc/cron.d/certbot` runs daily; the deploy-hook copies new certs to `docker/ssl/` and hot-reloads Nginx/Coturn.
|
||||
- Lineage suffixes (-0001/-0002) are handled automatically.
|
||||
|
||||
### Network Security
|
||||
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
|
||||
```bash
|
||||
# 内网(无域名/无公网IP)
|
||||
bash ./deploy.sh --mode private
|
||||
bash ./deploy.sh --mode lan-http
|
||||
|
||||
# 内网 + TURN(推荐用于复杂内网/NAT)
|
||||
bash ./deploy.sh --mode private --with-turn
|
||||
bash ./deploy.sh --mode lan-http --with-turn
|
||||
|
||||
# 内网 HTTPS(自签,开发/受管环境,需显式开启 8443)
|
||||
bash ./deploy.sh --mode lan-tls --enable-web-https --with-nginx
|
||||
|
||||
# 公网IP(无域名),含 TURN
|
||||
bash ./deploy.sh --mode public --with-turn
|
||||
@@ -23,10 +26,10 @@ bash ./deploy.sh --mode full --domain your-domain.com --with-nginx --with-turn -
|
||||
|
||||
## 模式一览
|
||||
|
||||
- basic:内网 HTTP;自动进行网络环境检测
|
||||
- private:内网 HTTP;跳过网络环境检测(更快,适合已知内网/CI 环境)
|
||||
- public:公网 HTTP;开启 TURN;无域名也可使用
|
||||
- full:域名 + HTTPS;开启 TURN;可选启用 SNI 443 分流
|
||||
- lan-http:内网 HTTP;最快上手,默认不启用 TLS
|
||||
- lan-tls:内网 HTTPS(自签,仅开发/受管环境);默认不启 8443,需 `--enable-web-https` 显式开启;禁用 HSTS;不保证 turns:443
|
||||
- public:公网 HTTP;开启 TURN;无域名也可使用(不提供 HTTPS/turns:443)
|
||||
- full:域名 + HTTPS(Let’s Encrypt 自动签发/续期)+ TURN;默认启用 SNI 443 分流(可 `--no-sni443` 关闭)
|
||||
|
||||
## 🎯 部署优势
|
||||
|
||||
@@ -418,32 +421,15 @@ bash deploy.sh --mode full --with-nginx
|
||||
|
||||
## 🔒 HTTPS 与安全
|
||||
|
||||
### 域名 + 自签证书(full + self-signed)
|
||||
### 内网 HTTPS(lan-tls,自签,开发/受管环境)
|
||||
|
||||
适用于仅需加密链路或内网 PKI 的场景。
|
||||
|
||||
步骤:
|
||||
|
||||
1) 生成配置(自签证书 + 域名)
|
||||
- 默认不启 8443;需 `--enable-web-https` 显式开启:
|
||||
|
||||
```bash
|
||||
SSL_MODE=self-signed \
|
||||
bash docker/scripts/generate-config.sh \
|
||||
--mode full --domain your-domain.com --with-nginx --with-turn
|
||||
bash ./deploy.sh --mode lan-tls --enable-web-https --with-nginx
|
||||
```
|
||||
|
||||
2) 启动服务(手动启动,避免自动申请 Let’s Encrypt)
|
||||
|
||||
```bash
|
||||
docker compose build
|
||||
docker compose --profile nginx up -d
|
||||
```
|
||||
|
||||
3) 在浏览器导入 CA 证书 `docker/ssl/ca-cert.pem`,或在首次访问时接受风险提示
|
||||
|
||||
可选:如需 `turns:443`,请启用 SNI 443 分流(参考“常用开关”与生成器帮助)。
|
||||
|
||||
注意:生产环境建议使用 Let’s Encrypt,避免浏览器信任问题与 HSTS 限制。
|
||||
- 仅用于开发或受管终端(全员导入内部 CA);禁用 HSTS;不保证 `turns:443`;受限网络(仅 443 出口)应使用 full(域名 + 受信证书 + SNI 443)。
|
||||
|
||||
### 公网域名部署(HTTPS + Nginx)快速测试
|
||||
|
||||
@@ -463,8 +449,8 @@ docker compose --profile nginx up -d
|
||||
|
||||
full 模式自动申请并续期证书:
|
||||
|
||||
- 首次签发:webroot 模式(无停机),系统证书保存在 `/etc/letsencrypt/live/<domain>/`,脚本复制到 `docker/ssl/` 并启用 443;
|
||||
- 续期:certbot deploy-hook 自动复制至 `docker/ssl/`,并热重载 Nginx 与重载(或重启)coturn;
|
||||
- 首次签发:webroot 模式(无停机),系统证书在 `/etc/letsencrypt/live/<domain>/`,脚本复制到 `docker/ssl/` 并启用 443;
|
||||
- 续期:`certbot.timer` 或 `/etc/cron.d/certbot` 每日尝试 `certbot renew`;deploy-hook 自动复制新证书并热重载 Nginx/Coturn;
|
||||
- 证书谱系(-0001/-0002)已自动适配,无需手动处理。
|
||||
|
||||
### 网络安全
|
||||
|
||||
Reference in New Issue
Block a user