| from fastapi import FastAPI, HTTPException | |
| import subprocess | |
| import os | |
| import logging | |
| import threading | |
| # Set up logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| app = FastAPI() | |
| def run_setup_script(): | |
| """ | |
| Executes the run.sh script with root privileges. | |
| The script is expected to be at /opt/src/run.sh inside the container. | |
| """ | |
| script_path = "/opt/src/run.sh" | |
| logger.info(f"Attempting to execute setup script: {script_path}") | |
| # The container is running as root by default, so we don't need 'sudo'. | |
| # We execute the script directly. | |
| try: | |
| # Use subprocess.run to execute the script and wait for it to finish | |
| # We capture output for logging/debugging. | |
| result = subprocess.run( | |
| ["/bin/bash", script_path], | |
| check=True, # Raise an exception for non-zero exit codes | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.STDOUT, | |
| text=True | |
| ) | |
| logger.info("Setup script executed successfully.") | |
| logger.info(f"Script output:\n{result.stdout}") | |
| except subprocess.CalledProcessError as e: | |
| logger.error(f"Setup script failed with exit code {e.returncode}.") | |
| logger.error(f"Script output:\n{e.stdout}") | |
| # Depending on the application's requirement, we might want to exit here | |
| # or just log the error and continue with the web server. | |
| # For a critical setup script like this VPN one, failure is critical. | |
| # We will log and let the main thread decide if it should exit. | |
| # For now, we just log the error. | |
| except FileNotFoundError: | |
| logger.error(f"Setup script not found at {script_path}") | |
| except Exception as e: | |
| logger.error(f"An unexpected error occurred during script execution: {e}") | |
| # Run the setup script in a separate thread or before the uvicorn server starts. | |
| # Since the setup script is likely long-running and critical, we'll run it | |
| # synchronously before starting the web server. If the web server is meant to | |
| # serve status while the script runs, we'd use a thread. Given the context | |
| # of a VPN setup, the setup must complete first. | |
| # We will use a simple function call before uvicorn.run. | |
| # For a production-ready FastAPI app, this logic should be in a startup event handler, | |
| # but for a simple script, running it before uvicorn.run is sufficient. | |
| if __name__ == "__main__": | |
| # 1. Run the setup script | |
| run_setup_script() | |
| # 2. Start the web server | |
| import uvicorn | |
| logger.info("Starting Uvicorn server...") | |
| uvicorn.run(app, host="0.0.0.0", port=8000) | |