The challenge
I needed hosting for my own clients: PHP, WordPress and Node.js sites, Telegram bots and backup storage — all in one friendly portal, invite-only, and built so that client code can’t harm the server.
What I built
- A portal built on Reviactyl (Laravel + React) that I reworked into three sections: Sites, Bots, S3 Cloud. Passwordless login — an email code or a passkey.
- Every site and bot runs in its own container: read-only filesystem, unprivileged user, no extra capabilities, memory and disk limits.
- Domains and Let’s Encrypt certificates connect automatically: a non-root service renders nginx configs, and a tiny root helper only validates and applies them with rollback.
- Garage-based S3 storage with quotas, site backups to S3 with one-click restore, WordPress staging copies with automatic URL rewriting.
- An SMTP relay for site email written in Go, Redis and MariaDB for bots, Adminer with one-time-link sign-in.
- Minute-by-minute monitoring: downtime alerts via a Telegram bot and email, memory, CPU and traffic charts.
How it works
- Client
- nginx + TLS
- Portal (Laravel + React)
- Agent → containers
- MariaDB · Redis · S3
Requests pass through nginx to the portal; the portal manages containers via an agent, while data lives in services closed to the internet.
Screenshots




Outcome
- Running in production at app.bebb.be.
- End-to-end Playwright tests for every portal section and a check of the server against a baseline config after every change.
- Internal services (databases, Redis, mail relay) are invisible from the internet — reachable only from the container network.
What’s next
Invoices and payments in the portal, off-site backups to a separate server, and a VPS section.