Hi all,
We run HestiaCP for a few dozen hosting clients. Some of them need the panel from time to time — mostly to manage their mailboxes — but we did not want port 8083 open to the whole internet. Keeping it open means every scanner gets to hammer the login page, and every future pre-auth bug in the panel is reachable by anyone.
What we wanted: 8083 stays closed (only our VPN), and a client can still get into the panel on demand, without us opening firewall rules by hand.
What we built: hestiacp-gate
A small PHP app that sits on 443 in front of the panel, as an ordinary Hestia web domain with its own nginx template:
- The client opens
https://panel.example.comand enters their Hestia username. - The gate reads the contact e-mail from their Hestia account, through the Hestia API with a key limited to
v-list-user, and sends a one-time link there. The e-mail shows which IP asked and when. - The link opens an Open access page with a button (so mail scanners that pre-open links cannot burn the token). The browser gets a pass cookie for 4 hours.
- The client lands directly on Hestia’s password page: the gate has already done the username step.
Until then nothing reaches Hestia at all. Without a pass, every URL shows the gate form.
On top of that the gate:
- only lets the client sign in as the user the pass was issued for.
adminand admin-role users are never allowed; - revokes the pass after 5 wrong passwords or 2FA codes. fail2ban cannot do this behind a proxy, because Hestia sees everyone as 127.0.0.1;
- keeps the web terminal, the file manager and
/api/closed. Everything else in the panel works; - rate-limits link requests and never reveals whether a username exists;
- looks like the Hestia sign-in page, so clients don’t notice a difference.
Install
Code, README and a step-by-step ONBOARDING guide: andreydruz/hestiacp-gate · GitHub (GPLv3)
There are Playwright end-to-end tests that click through the real gate and panel, including creating, editing and deleting a mail domain and a mailbox.
Tested on HestiaCP 1.10.5, Ubuntu 24.04, nginx + PHP-FPM 8.3 (no Apache).
Feedback, issues and PRs are welcome, especially from anyone running a different Hestia setup (Apache + nginx, other PHP versions).