container detection implemented
This commit is contained in:
@@ -16,9 +16,9 @@ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
|||||||
# MSS Clamping (Path MTU Tuning)
|
# MSS Clamping (Path MTU Tuning)
|
||||||
iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
|
iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
|
||||||
|
|
||||||
# Minimal OpenRC initialization to allow rc-service to work in Alpine
|
# Ensure /run exists for PID files
|
||||||
mkdir -p /run/openrc
|
mkdir -p /run
|
||||||
touch /run/openrc/softlevel
|
|
||||||
|
|
||||||
# Initialize Easy-RSA if not already present in /app/easy-rsa
|
# Initialize Easy-RSA if not already present in /app/easy-rsa
|
||||||
if [ ! -f /app/easy-rsa/easyrsa ]; then
|
if [ ! -f /app/easy-rsa/easyrsa ]; then
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ def configure_server(db: Session = Depends(get_db)):
|
|||||||
# Generate to a temporary location or standard location
|
# Generate to a temporary location or standard location
|
||||||
# As per plan, we behave like srvconf
|
# As per plan, we behave like srvconf
|
||||||
output_path = "/etc/openvpn/server.conf"
|
output_path = "/etc/openvpn/server.conf"
|
||||||
# Since running locally for dev, maybe output to staging
|
|
||||||
import os
|
# Ensure we can write to /etc/openvpn
|
||||||
if not os.path.exists("/etc/openvpn"):
|
if not os.path.exists(os.path.dirname(output_path)) or not os.access(os.path.dirname(output_path), os.W_OK):
|
||||||
# For local dev safety, don't try to write to /etc/openvpn if not root or not existing
|
# For local dev or non-root host, use staging
|
||||||
output_path = "staging/server.conf"
|
output_path = "staging/server.conf"
|
||||||
os.makedirs("staging", exist_ok=True)
|
os.makedirs("staging", exist_ok=True)
|
||||||
|
logger.info(f"[SERVER] /etc/openvpn not writable, using staging path: {output_path}")
|
||||||
|
else:
|
||||||
|
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
content = generator.generate_server_config(db, output_path=output_path)
|
content = generator.generate_server_config(db, output_path=output_path)
|
||||||
return {"message": "Server configuration generated", "path": output_path}
|
return {"message": "Server configuration generated", "path": output_path}
|
||||||
|
|||||||
@@ -6,13 +6,19 @@ import psutil
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def get_os_type():
|
def is_container():
|
||||||
"""
|
"""
|
||||||
Simple check to distinguish Alpine from others.
|
Checks if the application is running inside a Docker container.
|
||||||
"""
|
"""
|
||||||
if os.path.exists("/etc/alpine-release"):
|
if os.path.exists('/.dockerenv'):
|
||||||
return "alpine"
|
return True
|
||||||
return "debian" # default fallback to systemctl
|
try:
|
||||||
|
with open('/proc/self/cgroup', 'rt') as f:
|
||||||
|
if 'docker' in f.read():
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
def control_service(action: str):
|
def control_service(action: str):
|
||||||
"""
|
"""
|
||||||
@@ -21,7 +27,63 @@ def control_service(action: str):
|
|||||||
if action not in ["start", "stop", "restart"]:
|
if action not in ["start", "stop", "restart"]:
|
||||||
raise ValueError("Invalid action")
|
raise ValueError("Invalid action")
|
||||||
|
|
||||||
|
CONFIG_PATH = "/etc/openvpn/server.conf"
|
||||||
|
PID_FILE = "/run/openvpn.pid"
|
||||||
|
|
||||||
|
# In Container: Use direct execution to avoid OpenRC/cgroups issues
|
||||||
|
if is_container():
|
||||||
|
logger.info(f"[PROCESS] Container detected, using direct execution for {action}")
|
||||||
|
|
||||||
|
def start_vpn_direct():
|
||||||
|
if not os.path.exists(CONFIG_PATH):
|
||||||
|
# Check for alternative location in dev/non-root environments
|
||||||
|
if os.path.exists("staging/server.conf"):
|
||||||
|
alt_path = os.path.abspath("staging/server.conf")
|
||||||
|
logger.info(f"[PROCESS] Using alternative config: {alt_path}")
|
||||||
|
config = alt_path
|
||||||
|
else:
|
||||||
|
return {"status": "error", "message": f"Configuration not found at {CONFIG_PATH}. Please generate it first."}
|
||||||
|
else:
|
||||||
|
config = CONFIG_PATH
|
||||||
|
|
||||||
|
# Check if already running
|
||||||
|
for proc in psutil.process_iter(['name']):
|
||||||
|
if proc.info['name'] == 'openvpn':
|
||||||
|
return {"status": "success", "message": "OpenVPN is already running"}
|
||||||
|
|
||||||
|
cmd = ["openvpn", "--config", config, "--daemon", "--writepid", PID_FILE]
|
||||||
|
try:
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
return {"status": "success", "message": "OpenVPN started successfully (direct)"}
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
return {"status": "error", "message": f"Failed to start OpenVPN: {str(e)}"}
|
||||||
|
|
||||||
|
def stop_vpn_direct():
|
||||||
|
stopped = False
|
||||||
|
for proc in psutil.process_iter(['name']):
|
||||||
|
if proc.info['name'] == 'openvpn':
|
||||||
|
proc.terminate()
|
||||||
|
stopped = True
|
||||||
|
|
||||||
|
if os.path.exists(PID_FILE):
|
||||||
|
try: os.remove(PID_FILE)
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
if stopped:
|
||||||
|
return {"status": "success", "message": "OpenVPN stopped successfully"}
|
||||||
|
else:
|
||||||
|
return {"status": "success", "message": "OpenVPN was not running"}
|
||||||
|
|
||||||
|
if action == "start": return start_vpn_direct()
|
||||||
|
elif action == "stop": return stop_vpn_direct()
|
||||||
|
elif action == "restart":
|
||||||
|
stop_vpn_direct()
|
||||||
|
time.sleep(1)
|
||||||
|
return start_vpn_direct()
|
||||||
|
|
||||||
|
# On Host OS: Use system service manager
|
||||||
os_type = get_os_type()
|
os_type = get_os_type()
|
||||||
|
logger.info(f"[PROCESS] Host OS detected ({os_type}), using service manager for {action}")
|
||||||
|
|
||||||
cmd = []
|
cmd = []
|
||||||
if os_type == "alpine":
|
if os_type == "alpine":
|
||||||
@@ -30,27 +92,27 @@ def control_service(action: str):
|
|||||||
cmd = ["systemctl", action, "openvpn"]
|
cmd = ["systemctl", action, "openvpn"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Capture output to return it or log it
|
|
||||||
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
||||||
return {
|
return {
|
||||||
"status": "success",
|
"status": "success",
|
||||||
"message": f"Service {action} executed successfully",
|
"message": f"Service {action} executed successfully via {cmd[0]}",
|
||||||
"stdout": result.stdout
|
"stdout": result.stdout
|
||||||
}
|
}
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
logger.error(f"Service control failed: {e.stderr}")
|
logger.error(f"Service control failed: {e.stderr}")
|
||||||
return {
|
return {
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"message": f"Failed to {action} service",
|
"message": f"Failed to {action} service via {cmd[0]}",
|
||||||
"stderr": e.stderr
|
"stderr": e.stderr
|
||||||
}
|
}
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
# Happens if rc-service or systemctl is missing (e.g. dev env)
|
|
||||||
return {
|
return {
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"message": f"Command not found found for OS type {os_type}"
|
"message": f"Command {cmd[0]} not found found for OS type {os_type}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_process_stats():
|
def get_process_stats():
|
||||||
"""
|
"""
|
||||||
Returns dict with pid, cpu_percent, memory_mb, uptime.
|
Returns dict with pid, cpu_percent, memory_mb, uptime.
|
||||||
|
|||||||
Reference in New Issue
Block a user