Files
MP-Server/macropad-relay/DEPLOY.md
T
shadowdao eba5a2a38e security(relay): harden internet-facing relay server
Closes the account-takeover chain and related issues found in audit:

- WS auth brute-force protection: per-session lockout (authThrottle) + per-
  socket failure cap that closes the socket (1008); applied to both web-client
  and desktop auth. Failed auth no longer leaves the socket open for unlimited
  guesses.
- WS upgrades now pass an IP-based rate limiter and Origin allowlist before
  handleUpgrade (previously bypassed all HTTP middleware); trust proxy set so
  limiting keys on the real client IP.
- /health no longer leaks live session IDs (counts only).
- .env.example rate-limit fixed (900000ms / 300) from the accidental ~11k rps.
- Credentials moved out of URLs into the X-MacroPad-Password header; images
  fetched via header + blob URLs; login stores creds in sessionStorage.
- Session creation bounded (max sessions, min password length) and TTL-pruned;
  session store writes are now atomic (temp+rename) and debounced.
- Session IDs lengthened to 12 chars with rejection sampling (no modulo bias).
- Enable helmet CSP; restrict CORS to configured origins.
- Request IDs use crypto.randomUUID; drop postinstall build hook and uuid dep.
- Uniform response for unknown session IDs (removes enumeration oracle).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 10:15:23 -07:00

2.8 KiB

MacroPad Relay Server - Deployment Guide

Cloud Node Container Deployment

For AnHonestHost cloud-node-container deployment:

1. Build Locally

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:

# 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

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

# 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

Test It Works

# 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)

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:

pm2 logs macropad-relay

Check sessions:

cat /path/to/app/data/sessions.json

Port in use:

lsof -i :3000