import os import subprocess import time import signal import sys def run_command(command, background=True): print(f"Starting: {command}") if background: return subprocess.Popen(command, shell=True) else: return subprocess.run(command, shell=True) def main(): # 1. Start Xvfb (Virtual Framebuffer) # This creates a virtual display that the browser can draw on. resolution = os.environ.get('RESOLUTION', '1280x720') xvfb_cmd = f"Xvfb :0 -screen 0 {resolution}x24" xvfb_process = run_command(xvfb_cmd) # Wait for Xvfb to initialize time.sleep(2) # 2. Start Fluxbox (Window Manager) # Essential for handling window placement and maximizing the browser. run_command("fluxbox") # 3. Start x11vnc # Connects the X server to a VNC port (5900). run_command("x11vnc -display :0 -forever -shared -rfbport 5900 -nopw") # 4. Start websockify (noVNC) # Bridges the web browser (WebSocket) to the VNC server (TCP). # We serve the default noVNC web files located at /usr/share/novnc. novnc_cmd = "websockify --web /usr/share/novnc 7860 localhost:5900" run_command(novnc_cmd) # 5. Start Brave Browser # --kiosk: runs in full screen restricted mode # --no-sandbox: required for some docker environments # --disable-dev-shm-usage: prevents crashing in containers with low shared memory print("Starting Brave Browser...") brave_cmd = ( "brave-browser " "--no-sandbox " "--disable-dev-shm-usage " "--kiosk " "--start-maximized " "--user-data-dir=/home/user/brave-data " "https://www.google.com" # Change this URL to your desired start page ) # Run Brave and wait for it. If Brave closes, the container should stop (or restart it). # Here we keep the script alive. brave_process = subprocess.Popen(brave_cmd, shell=True) try: # Keep the main thread alive to monitor processes while True: time.sleep(1) if brave_process.poll() is not None: print("Brave exited. Restarting...") brave_process = subprocess.Popen(brave_cmd, shell=True) except KeyboardInterrupt: print("Stopping services...") xvfb_process.terminate() brave_process.terminate() sys.exit(0) if __name__ == "__main__": main()