# Alpine Linux Service Setup This guide covers installing and running Immersive as a service on Alpine Linux using OpenRC. ## Prerequisites ```bash # Update packages apk update # Install Node.js 18+ and npm apk add nodejs npm # Install build dependencies (required for native modules like leveldown) apk add python3 make g++ git # Verify Node version (must be >= 18) node --version ``` ## Create Service User Create a dedicated user to run the service (security best practice): ```bash # Create immersive group and user (no login shell, no home directory) addgroup -S immersive adduser -S -G immersive -H -s /sbin/nologin immersive # Create directories with proper ownership mkdir -p /opt/immersive mkdir -p /var/log/immersive mkdir -p /var/run/immersive chown -R immersive:immersive /opt/immersive chown -R immersive:immersive /var/log/immersive chown -R immersive:immersive /var/run/immersive ``` ## Installation ```bash # Create application directory mkdir -p /opt/immersive cd /opt/immersive # Clone or copy the application git clone . # OR copy files manually # Install dependencies npm ci --production=false # Build the application NODE_OPTIONS='--max-old-space-size=4096' npm run build # Copy Havok physics WASM (if not already done by build) npm run havok # Create data directory for PouchDB mkdir -p /opt/immersive/data # Set ownership to immersive user chown -R immersive:immersive /opt/immersive ``` ## Start Script The `start.sh` script is included in the repository. After deployment, ensure it's executable: ```bash chmod +x /opt/immersive/start.sh ``` The script sets up the environment and starts the Node.js server, logging output to `/var/log/immersive/`. ## OpenRC Service Create `/etc/init.d/immersive`: ```bash #!/sbin/openrc-run name="immersive" description="Immersive WebXR Diagramming Application" command="/opt/immersive/start.sh" command_user="immersive:immersive" command_background="yes" pidfile="/var/run/immersive/immersive.pid" directory="/opt/immersive" output_log="/var/log/immersive/app.log" error_log="/var/log/immersive/error.log" depend() { need net after firewall } start_pre() { checkpath --directory --owner immersive:immersive --mode 0755 /var/log/immersive checkpath --directory --owner immersive:immersive --mode 0755 /var/run/immersive checkpath --file --owner immersive:immersive --mode 0644 /var/log/immersive/app.log checkpath --file --owner immersive:immersive --mode 0644 /var/log/immersive/error.log } ``` Make it executable and enable: ```bash chmod +x /etc/init.d/immersive rc-update add immersive default ``` ## Service Management ```bash # Start the service rc-service immersive start # Stop the service rc-service immersive stop # Restart the service rc-service immersive restart # Check status rc-service immersive status # View logs tail -f /var/log/immersive/app.log tail -f /var/log/immersive/error.log ``` ## Log Rotation Create `/etc/logrotate.d/immersive`: ``` /var/log/immersive/*.log { daily rotate 7 compress delaycompress missingok notifempty create 0644 immersive immersive postrotate rc-service immersive restart > /dev/null 2>&1 || true endscript } ``` Install logrotate if not present: ```bash apk add logrotate ``` ## Environment Variables Create `/opt/immersive/.env.production` for production settings: ```bash # Server NODE_ENV=production PORT=3001 # Auth0 (if using authentication) # VITE_AUTH0_DOMAIN=your-domain.auth0.com # VITE_AUTH0_CLIENT_ID=your-client-id # Database sync endpoint (optional) # VITE_SYNCDB_ENDPOINT=https://your-couchdb-server.com ``` ## Firewall (if using iptables) ```bash # Allow port 3001 iptables -A INPUT -p tcp --dport 3001 -j ACCEPT # Save rules rc-service iptables save ``` ## Reverse Proxy (Optional) If using nginx as a reverse proxy: ```bash apk add nginx ``` Create `/etc/nginx/http.d/immersive.conf`: ```nginx server { listen 80; server_name your-domain.com; location / { proxy_pass http://127.0.0.1:3001; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; 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_cache_bypass $http_upgrade; } } ``` Enable and start nginx: ```bash rc-update add nginx default rc-service nginx start ``` ## Gitea CI/CD Runner (Optional) If using a Gitea Actions runner to deploy, grant the runner user write access to `/opt/immersive`: ```bash # Add gitea-runner to immersive group adduser gitea-runner immersive # Set group write permissions on /opt/immersive chmod -R g+w /opt/immersive # Ensure new files inherit group ownership chmod g+s /opt/immersive # Allow runner to manage the service # Add to /etc/sudoers.d/gitea-runner: echo 'gitea-runner ALL=(ALL) NOPASSWD: /sbin/rc-service immersive *' > /etc/sudoers.d/gitea-runner echo 'gitea-runner ALL=(ALL) NOPASSWD: /bin/chown -R immersive\:immersive /opt/immersive' >> /etc/sudoers.d/gitea-runner chmod 440 /etc/sudoers.d/gitea-runner ``` The GitHub Actions workflow in `.github/workflows/build.yml` will handle deployment automatically on push to main. ## Troubleshooting **Service fails to start:** ```bash # Check logs cat /var/log/immersive/error.log # Run manually as immersive user to see errors su -s /bin/sh immersive -c "cd /opt/immersive && NODE_ENV=production node server.js" ``` **Native module errors (leveldown):** ```bash # Rebuild native modules cd /opt/immersive npm rebuild leveldown ``` **Permission issues:** ```bash # Ensure proper ownership (must be immersive user) chown -R immersive:immersive /opt/immersive chown -R immersive:immersive /var/log/immersive chown -R immersive:immersive /var/run/immersive chmod -R 755 /opt/immersive ``` **Port already in use:** ```bash # Find process using port 3001 lsof -i :3001 # Or netstat -tlnp | grep 3001 ```