|
# retoor <retoor@molodetz.nl>
|
|
|
|
import logging
|
|
import subprocess
|
|
import threading
|
|
from pathlib import Path
|
|
from devplacepy.services.tunnel.config import TUNNEL_NGINX_TUNNEL_DIR
|
|
|
|
logger = logging.getLogger(__name__)
|
|
_lock = threading.Lock()
|
|
|
|
_TEMPLATE = """location / {
|
|
proxy_pass http://127.0.0.1:{remote_port};
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection $connection_upgrade;
|
|
proxy_read_timeout 86400s;
|
|
proxy_send_timeout 86400s;
|
|
}
|
|
"""
|
|
|
|
|
|
def _tunnel_dir() -> Path:
|
|
return TUNNEL_NGINX_TUNNEL_DIR
|
|
|
|
|
|
def _ensure_tunnel_dir() -> None:
|
|
_tunnel_dir().mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
def add_subdomain(subdomain: str, remote_port: int) -> bool:
|
|
with _lock:
|
|
try:
|
|
_ensure_tunnel_dir()
|
|
snippet = _TEMPLATE.format(remote_port=remote_port)
|
|
config_path = _tunnel_dir() / f"{subdomain}.conf"
|
|
config_path.write_text(snippet)
|
|
logger.info(
|
|
"Wrote nginx tunnel snippet for %s -> port %d",
|
|
subdomain,
|
|
remote_port,
|
|
)
|
|
_reload_nginx()
|
|
return True
|
|
except OSError:
|
|
logger.exception("Failed to write nginx config for %s", subdomain)
|
|
return False
|
|
|
|
|
|
def remove_subdomain(subdomain: str) -> bool:
|
|
with _lock:
|
|
config_path = _tunnel_dir() / f"{subdomain}.conf"
|
|
try:
|
|
if config_path.exists():
|
|
config_path.unlink()
|
|
logger.info("Removed nginx tunnel snippet for %s", subdomain)
|
|
_reload_nginx()
|
|
return True
|
|
except OSError:
|
|
logger.exception("Failed to remove nginx config for %s", subdomain)
|
|
return False
|
|
|
|
|
|
def _reload_nginx() -> None:
|
|
try:
|
|
result = subprocess.run(
|
|
["nginx", "-s", "reload"],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=10,
|
|
)
|
|
if result.returncode != 0:
|
|
logger.error("nginx reload failed: %s", result.stderr.strip())
|
|
else:
|
|
logger.info("nginx reloaded successfully")
|
|
except FileNotFoundError:
|
|
logger.warning("nginx command not found - skipping reload")
|
|
except (subprocess.TimeoutExpired, OSError):
|
|
logger.exception("nginx reload command failed")
|