Production server

This is how the official The Hub server runs (an OVH VPS with 6 CPU cores, Ubuntu). Everything is in deploy/, so you can build the same setup on your own Linux server.

The layout

PartRuns asCoresWhat it does
nginxnginx4, 5HTTPS, the landing page and wiki, static files, rate limits, routing API calls to a pool
PHP pool synchub-php@sync0, 1sync, bot_events, typing, read: the polling every open app does every 1.5 s
PHP pool apihub-php@api2, 3Everything else people click: messages, settings, spaces, roles
PHP pool mediahub-php@media4Uploads, downloads, GIF search, Discord import, plugin installs
MariaDBmariadb5The database
PeerJShub-peerjs5Introduces people in calls (WebSocket at /peerjs/)
coturncoturn5STUN/TURN, so calls work behind strict networks

Each PHP pool is its own php-fpm with its own socket, worker limit, memory limit and timeouts, pinned to its cores with systemd's CPUAffinity. nginx picks the pool from the request's ?action=. That way a flood of one kind of request can't take the rest down: a thousand open apps polling sync can't slow message sending, and a pile of uploads can't hold up either.

Staying up under load

  • Rate limits per pool and per address in nginx (limit_req), answering 429 instead of queueing for ever, plus a cap on connections per address.
  • Bounded pools: each pool has a maximum number of workers sized to the server's memory, recycles workers every 2,000 requests, and kills any request that runs past its timeout.
  • Restarts on their own: every service has Restart=always, and a memory ceiling, so a leak restarts one pool instead of filling the machine.
  • Health checks every minute (hub-health.timer): each pool must answer ?action=health, including a database check; one that doesn't is restarted on its own. Restarts are logged in /var/log/thehub/health.log.
  • Releases switch in one step: each deploy is a new folder; the current link moves to it and the pools reload gracefully, so requests already running finish on the old code. The last 5 releases are kept to roll back to.

Deploying

From the project folder, on a computer with the deploy key:

bash deploy/deploy.sh --setup     # the first time: installs and configures the server
bash deploy/deploy.sh             # every update after that

server-setup.sh installs nginx, PHP, MariaDB, Node (for PeerJS) and coturn, creates the database and a config.local.php with this server's settings (PeerJS, TURN, the plugin shop), and opens the firewall for web and calls only. Server settings live in /srv/thehub/shared/, and survive every deploy.

Where things are

PathWhat
/srv/thehub/current/The live release (the app, the website and the wiki)
/srv/thehub/shared/config.local.php, database.php, data/ (cache, sessions, the plugin shop's files), uploads/, plugins/
/etc/thehub/fpm-*.confThe three PHP pools
/var/log/thehub/PHP errors and slow requests per pool, and the health log

Useful commands

systemctl status 'hub-php@*' hub-peerjs mariadb coturn nginx
journalctl -u hub-php@sync -f
sudo -u thehub php /srv/thehub/current/tools/shop-publish.php --list

This page is built from docs/wiki/production.md in The Hub's source.