# MacroPad Relay Server - Deployment Guide ## Cloud Node Container Deployment For AnHonestHost cloud-node-container deployment: ### 1. Build Locally ```bash cd /home/jknapp/code/macropad/macropad-relay npm install npm run build # required: the build is no longer triggered automatically on install ``` > Note: the `postinstall` build hook was removed. Always run `npm run build` > explicitly (locally or in CI) after `npm install` to produce `dist/`. ### 2. Prepare Deployment Package The build outputs to `dist/` with public files copied. Upload: ```bash # Upload built files to your node container app directory rsync -avz --exclude 'node_modules' --exclude 'src' --exclude '.git' \ dist/ package.json public/ \ user@YOUR_SERVER:/path/to/app/ ``` ### 3. On Server The cloud-node-container will automatically: - Install dependencies from package.json - Start the app using PM2 - Configure the process from package.json settings ### 4. Create Data Directory ```bash mkdir -p /path/to/app/data ``` ## Directory Structure on Server ``` app/ ├── index.js # Main entry (compiled) ├── config.js ├── server.js ├── services/ ├── handlers/ ├── utils/ ├── public/ │ ├── login.html │ └── app.html ├── data/ │ └── sessions.json # Created automatically └── package.json ``` ## Update After Code Changes ```bash # On local machine: cd /home/jknapp/code/macropad/macropad-relay npm run build rsync -avz --exclude 'node_modules' --exclude 'src' --exclude '.git' --exclude 'data' \ dist/ package.json public/ \ user@YOUR_SERVER:/path/to/app/ # On server - restart via your container's control panel or: pm2 restart macropad-relay ``` ## Environment Variables Set these in your container configuration: - `PORT` - Server port (default: 3000) - `DATA_DIR` - Data storage path (default: ./data) - `NODE_ENV` - production or development - `LOG_LEVEL` - info, debug, error - `ALLOWED_ORIGINS` - Comma-separated list of allowed browser origins for the WebSocket Origin check (e.g. `https://macropad.example.com`). **Set this to your public origin(s) when running behind a reverse proxy** (see note below). > **Reverse proxy note (`ALLOWED_ORIGINS`):** When `ALLOWED_ORIGINS` is unset, > the WebSocket upgrade Origin check falls back to comparing the browser's > `Origin` host against the raw `Host` header seen by the app. Behind a reverse > proxy the internal `Host` (e.g. `localhost:3000`) often differs from the > public origin the browser sends (e.g. `https://macropad.example.com`), so > legitimate browser WebSocket upgrades get **rejected**. Set `ALLOWED_ORIGINS` > to your public origin(s) to fix this. (Forwarding the public host via > `proxy_set_header Host $host;`, as in the Nginx example below, also helps, but > setting `ALLOWED_ORIGINS` explicitly is the reliable fix.) ## Test It Works ```bash # Test health endpoint curl http://localhost:3000/health # Should return (counts only - no session ids are exposed): # {"status":"ok","desktops":0,"webClients":0,"uptime":1.23} ``` ## Nginx/Reverse Proxy (for HTTPS) ```nginx location / { proxy_pass http://localhost:3000; 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; # WebSocket timeout (24 hours) proxy_read_timeout 86400; } ``` ## Troubleshooting **Check logs:** ```bash pm2 logs macropad-relay ``` **Check sessions:** ```bash cat /path/to/app/data/sessions.json ``` **Port in use:** ```bash lsof -i :3000 ```