How to Install HestiaCP on Ubuntu 24.04 VPS: Free Open-Source Web Hosting Control Panel
Running a self-hosted web hosting control panel gives you full control over every site, database, mailbox, and DNS record on your server -- without paying per-domain licensing fees. HestiaCP (Hestia Control Panel) is one of the best open-source alternatives to commercial panels like Plesk and cPanel. It is free, actively maintained, and ships with everything you need to host websites, email, DNS, and databases from a single clean web interface.
This tutorial walks you through installing HestiaCP on a fresh Ubuntu 24.04 LTS VPS, from system prep to running the hst-install.sh installer with the right flags, adding your first user and domain, enabling Let's Encrypt, and keeping the panel upgraded.
Skip the manual install? Deploy a ready-to-go web hosting VPS with our CloudCore Starter plan and be serving sites in under 10 minutes.
Table of Contents
What is HestiaCP?
HestiaCP is a free, open-source web hosting control panel originally forked from VestaCP in 2019. It gives you a polished web UI (and equally capable CLI) for managing everything a hosting server typically does: websites with Nginx and Apache or Nginx with PHP-FPM, MySQL/MariaDB and PostgreSQL databases, email via Exim and Dovecot, DNS via Bind9, FTP via vsftpd, SSH user management, scheduled cron jobs, quotas, backups, and Let's Encrypt SSL issuance.
What sets HestiaCP apart from other free panels is its balance of power and simplicity. The interface is fast and responsive, the codebase is actively maintained by a transparent community team, and every feature that exists in the UI is also fully scriptable from the command line -- every /usr/local/hestia/bin/v-* command maps to a panel action. That makes it a strong fit for both beginners setting up their first reseller server and experienced sysadmins automating multi-tenant hosting.
HestiaCP supports a broad range of deployment patterns. Freelance developers use it to host client sites, each isolated under its own Linux user. Agencies run it as a white-label reseller environment. Small hosting providers use it as the backbone of a shared-hosting product line. Self-hosters run a single-domain instance for a personal blog, mail server, and git-adjacent services. Because the panel cleanly separates admin-level operations from user-level operations, the same installation scales from one domain to several hundred.
Why Self-Host with HestiaCP Instead of Plesk or cPanel?
Commercial control panels dominate shared hosting, but they come with recurring license fees that scale with the number of accounts or domains. For small teams, freelance developers, and anyone running a handful of sites, HestiaCP delivers the same day-to-day workflow for free.
- Zero licensing cost -- cPanel licenses start at roughly $22/month for a single-account VPS and climb to $65+/month for 100-account tiers. Plesk sits in a similar range. HestiaCP is MIT-licensed and always free, no matter how many domains, users, or mailboxes you create.
- No per-account upsells -- every HestiaCP feature (email, DNS, SSL, backups, multi-PHP) is included in the base install. There are no paid add-ons for SpamAssassin, ImunifyAV equivalents, or Let's Encrypt.
- You own the stack -- HestiaCP writes clean, standard config files to
/etc/nginx,/etc/apache2,/etc/exim4, etc. If you ever outgrow the panel or want to migrate, nothing is locked inside a proprietary database. - Active open-source community -- the hestiacp/hestiacp GitHub repo has thousands of stars, regular releases, and responsive maintainers. Security issues are triaged quickly in public.
- Built-in multi-tenant isolation -- each user gets their own Linux account, home directory, and quota. File and process isolation is enforced at the OS level, not just at the panel layer.
- Full CLI parity -- every action in the web UI has a matching
v-*CLI command, which makes backups, migrations, and provisioning scripts trivially automatable. - Predictable resource usage -- HestiaCP itself runs as a small Node.js + PHP backend. Unlike heavyweight panels, it rarely pushes past 300-500 MB of RAM on its own, leaving most of your VPS free for actual websites.
Cost Comparison: HestiaCP vs. Commercial Panels
| Item | cPanel/WHM | Plesk Web Pro | HestiaCP |
|---|---|---|---|
| Panel license (1-5 accounts) | ~$22/month | ~$15/month | Free |
| Panel license (30+ accounts) | ~$37/month | ~$35/month | Free |
| SSL (Let's Encrypt) | Included | Included | Included |
| Mail server (Exim/Dovecot) | Included | Included | Included |
| DNS server (Bind9) | Included | Included | Included |
| Anti-spam (SpamAssassin) | Included | Add-on in some tiers | Included |
| Antivirus (ClamAV) | Add-on | Add-on | Included |
| Multi-PHP versions | Included | Included | Included |
| White-label rebranding | Paid add-on | Paid tier | Free (template edit) |
| Annual cost (single VPS) | ~$264-$444 | ~$180-$420 | $0 |
Prerequisites
Before you begin, make sure you have:
- A fresh VPS running Ubuntu 24.04 LTS with root access (HestiaCP must be installed on a clean system -- do not run it on a server that already has Apache, Nginx, or MariaDB configured)
- SSH access to your server (PuTTY on Windows, or the built-in terminal on macOS/Linux)
- A fully-qualified hostname you control (for example,
host.example.com) pointing to the server's public IPv4 address - At least 2 GB of RAM (4 GB recommended if you plan to enable ClamAV antivirus, which is memory-hungry)
- At least 20 GB of free disk space (40 GB+ recommended once you factor in sites, mailboxes, and backups)
Recommended Plan: CloudCore Starter>
For a first HestiaCP deployment hosting up to a few dozen small websites with mail, we recommend the CloudCore Starter plan. It gives you enough CPU, memory, and disk headroom to enable the full stack -- web, mail, DNS, antivirus, and backups -- without feeling cramped.>
As your account count grows, you can scale vertically to CloudCore Professional or higher without reinstalling the panel.
Connect to your server via SSH to get started:
ssh root@your-server-ipStep 1: Update the System and Set the Hostname
HestiaCP strongly recommends running the installer on a fully updated system. Start by refreshing the package index and upgrading:
apt update && apt upgrade -yIf the kernel was updated, reboot before continuing:
rebootReconnect after a minute and verify you are on Ubuntu 24.04:
lsb_release -aExpected output:
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 24.04 LTS
Release: 24.04
Codename: nobleNext, set a proper fully-qualified hostname. HestiaCP uses this as the panel hostname and as the default mail server identity. Pick a subdomain you control, for example host.example.com:
hostnamectl set-hostname host.example.comVerify:
hostname -fExpected output:
host.example.comPoint the DNS A record for host.example.com at your server's public IPv4 address before moving on -- the Let's Encrypt step later relies on this.
Step 2: Download the HestiaCP Installer
HestiaCP ships a single shell script, hst-install.sh, that handles every step: adding repositories, installing packages, generating default configs, creating the admin user, and starting all services.
Download the latest installer from the official HestiaCP repository:
wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.shExpected output (abbreviated):
--2026-04-16 10:00:00-- https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh Resolving raw.githubusercontent.com... Connecting to raw.githubusercontent.com... connected. HTTP request sent, awaiting response... 200 OK Length: 85234 (83K) [text/plain] Saving to: 'hst-install.sh'hst-install.sh 100%[========================>] 83.24K --.-KB/s in 0.05s
2026-04-16 10:00:00 (1.58 MB/s) - 'hst-install.sh' saved [85234/85234]
Make sure the script is readable (you do not need to chmod +x, as you will invoke it with bash):
ls -l hst-install.shStep 3: Understand the Installer Flags
Before running the installer, it is worth knowing what each flag does. Running bash hst-install.sh --help prints the full list; the most important ones are:
| Flag | Purpose |
|---|---|
--nginx yes / no | Install Nginx (front web server). Recommended: yes. |
--apache yes / no | Install Apache behind Nginx for .htaccess compatibility. Set no if you prefer Nginx + PHP-FPM only. |
--phpfpm yes / no | Install PHP-FPM. Set yes when --apache no is used. |
--multiphp yes / no | Install multiple PHP versions (7.4, 8.0, 8.1, 8.2, 8.3) for per-site selection. |
--named yes / no | Install Bind9 DNS server. Set yes if you want to run your own authoritative nameservers. |
--mysql yes / no | Install MariaDB (drop-in MySQL replacement). |
--postgresql yes / no | Install PostgreSQL. Can be enabled alongside MariaDB. |
--exim yes / no | Install Exim mail server. |
--dovecot yes / no | Install Dovecot IMAP/POP3 for mailbox access. Requires Exim. |
--clamav yes / no | Install ClamAV antivirus for mail scanning. Adds ~1 GB RAM usage. |
--spamassassin yes / no | Install SpamAssassin for spam filtering. |
--iptables yes / no | Enable iptables-based firewall rules. |
--fail2ban yes / no | Install Fail2ban to block brute-force attempts. |
--quota yes / no | Enable filesystem quotas (requires / with usrquota,grpquota mount options). |
--api yes / no | Enable the JSON API for remote automation. |
--port NNNN | Panel port. Default is 8083. Pick something non-default for a small security win. |
--lang en | Panel UI language. |
--hostname host.example.com | Panel hostname (matches your DNS A record). |
--email [email protected] | Admin email (used by Let's Encrypt and notifications). |
--password StrongPassword! | Initial admin password (quote it if it contains shell characters). |
--with-debs /path | Install from a local package cache instead of downloading. Useful for air-gapped installs. |
--force | Skip the interactive confirmation and system-compatibility checks. |
--clamav no and optionally --spamassassin no.Step 4: Run hst-install.sh with Your Chosen Stack
Pick the command that matches your use case.
Option A: Full stack (recommended, Nginx + Apache + mail + DNS + antivirus)
Best for servers with 4 GB+ RAM that will host websites and email:
bash hst-install.sh \
--nginx yes \
--apache yes \
--phpfpm yes \
--multiphp yes \
--named yes \
--mysql yes \
--postgresql no \
--exim yes \
--dovecot yes \
--clamav yes \
--spamassassin yes \
--iptables yes \
--fail2ban yes \
--quota yes \
--api yes \
--port 8083 \
--lang en \
--hostname host.example.com \
--email [email protected] \
--password 'ChangeMeToAStrongOne!' \
--forceOption B: Lean stack (Nginx + PHP-FPM only, no mail)
Best for 2 GB VPS instances running web apps where mail lives elsewhere (for example, Google Workspace):
bash hst-install.sh \
--nginx yes \
--apache no \
--phpfpm yes \
--multiphp yes \
--named no \
--mysql yes \
--postgresql no \
--exim no \
--dovecot no \
--clamav no \
--spamassassin no \
--iptables yes \
--fail2ban yes \
--quota no \
--api yes \
--port 8083 \
--hostname host.example.com \
--email [email protected] \
--password 'ChangeMeToAStrongOne!' \
--forceOption C: PostgreSQL-centric stack
If your apps rely on PostgreSQL, enable it alongside (or instead of) MariaDB:
bash hst-install.sh \
--nginx yes --apache yes --phpfpm yes --multiphp yes \
--mysql yes --postgresql yes \
--named yes --exim yes --dovecot yes \
--clamav no --spamassassin yes \
--iptables yes --fail2ban yes --quota yes --api yes \
--port 8083 --hostname host.example.com \
--email [email protected] --password 'ChangeMeToAStrongOne!' --forceWhat the installer does
Installation takes 10-20 minutes depending on bandwidth and flag choices. You will see progress output such as:
_ _ _ _ ____ ____
| | | | ___ ___| |_(_) __ _ / ___| _ \
| |_| |/ _ \/ __| __| |/ _ | | | |_) |
| _ | __/\__ \ |_| | (_| | |___| __/
|_| |_|\___||___/\__|_|\__,_|\____|_|The following software will be installed on your system:
- Nginx Web Server
- Apache Web Server (as backend)
- PHP-FPM Application Server
- Bind DNS Server
- Exim Mail Server + Antispam + Antivirus
- Dovecot POP3/IMAP Server
- MariaDB Database Server
- Vsftpd FTP Server
- Firewall (iptables) + Fail2Ban Access Monitor
[ * ] Installing repositories...
[ * ] Updating system...
[ * ] Installing packages...
[ * ] Configuring system settings...
[ * ] Configuring Hestia Control Panel...
[ * ] Generating SSL certificate...
[ * ] Starting services...
Congratulations!
You have successfully installed Hestia Control Panel on your server.
Ready to get started? Log in at the following URL:
https://host.example.com:8083
Username: admin
Password: ChangeMeToAStrongOne!
Please rebooting the system for changes to take effect.</code></pre></div>
Reboot once as requested:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">reboot</code></pre></div>
Step 5: Log In to the HestiaCP Admin Interface
After the reboot, open the panel in your browser at:
<div class="code-block" data-lang="text"><div class="code-block__header"><span class="code-block__lang">text</span></div><pre><code class="language-text">https://host.example.com:8083</code></pre></div>
Your browser may warn about the certificate the first time -- HestiaCP self-signs a certificate on first boot. That gets replaced automatically with a Let's Encrypt certificate once the hostname is reachable (covered in Step 8).
Log in with:
Username: admin
Password: the one you passed to --password
Once logged in you will land on the dashboard showing system load, disk usage, memory, and a list of panel modules (USER, WEB, DNS, MAIL, DB, CRON, BACKUP, PACKAGES, IP, FIREWALL, UPDATES, LOG).Set a stronger admin password and 2FA
From USER → admin → Edit, set a long random password (HestiaCP does not cap password length) and enable two-factor authentication by scanning the QR code with an authenticator app such as Aegis, 1Password, or Bitwarden.
Step 6: Configure DNS for Your Server
If you installed Bind9 with --named yes, HestiaCP can act as an authoritative DNS server. Before using this feature, your domain's registrar needs to know your server is a nameserver.
Register glue records at your registrar
At your domain registrar (Cloudflare, Namecheap, GoDaddy, etc.), create two "child nameservers" or "glue records":
- ns1.example.com
→ your server IPv4
ns2.example.com → your server IPv4 (or a secondary NS server IP)
Then set the domain's nameservers to ns1.example.com and ns2.example.com.Tell HestiaCP which nameservers to advertise
In the panel, go to SERVER → Configure → DNS Server and set:
NS1: ns1.example.com
NS2: ns2.example.com
These values are written into every new zone HestiaCP creates.> Prefer to keep DNS at Cloudflare? Skip the --named yes flag and manage DNS externally. HestiaCP still works fine -- you simply point each domain's A record at your HestiaCP server manually. For most freelance and agency setups, this is the simpler path.
Step 7: Add a User and a Domain
HestiaCP is multi-tenant. Each "user" gets their own Linux account, home directory, quota, and set of domains. Create one user per client (or one per project).
Create a user via the web UI
Go to USER → Add User.
Fill in username, email, password, full name.
Pick a package (the default one restricts web, DNS, mail, DB, and disk quota; clone and edit it for finer control).
Click Save. Create a user via the CLI
The equivalent command-line call:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">v-add-user johndoe 'UserStrongPass!' [email protected] default 'John Doe'</code></pre></div>
Add a web domain
As root, add a domain under that user:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">v-add-web-domain johndoe example.com 203.0.113.10</code></pre></div>
Or via the UI: log in as johndoe, go to WEB → Add Web Domain, enter example.com, pick the IP, and save. HestiaCP:
Creates /home/johndoe/web/example.com/public_html
- Writes Nginx (and Apache, if installed) vhost configs
- Optionally enables DNS and mail for the same domain
Add a matching DNS zone (if using Bind9)
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">v-add-dns-domain johndoe example.com 203.0.113.10</code></pre></div>
Add a matching mail domain
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">v-add-mail-domain johndoe example.com
v-add-mail-account johndoe example.com info 'MailboxPass!'</code></pre></div>
You now have [email protected] reachable via IMAP (host.example.com:993, STARTTLS/SSL) and SMTP (host.example.com:587, STARTTLS).
Step 8: Enable Let's Encrypt SSL Automatically
HestiaCP has first-class Let's Encrypt support. Once the domain's A record resolves to your server's public IP, enabling SSL is a single checkbox.
Enable SSL for a web domain via the UI
Go to WEB (logged in as the user that owns the domain).
Click the edit (pencil) icon next to the domain.
Check SSL Support.
Check Lets Encrypt Support.
Optionally check Enable automatic HTTPS redirection from HTTP.
Click Save. HestiaCP runs a v-add-letsencrypt-domain call behind the scenes, which obtains a certificate via ACME HTTP-01 validation, installs it into Nginx/Apache, and reloads the web servers.
Enable SSL via the CLI
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">v-add-letsencrypt-domain johndoe example.com www.example.com</code></pre></div>
Enable SSL for the panel hostname
The panel itself should use a real certificate rather than its self-signed one:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">v-add-letsencrypt-host</code></pre></div>
This issues a certificate for host.example.com (the panel hostname) and automatically reconfigures HestiaCP, Exim, Dovecot, and vsftpd to use it.
Automatic renewal
HestiaCP schedules a daily cron job (v-update-lets-encrypt-ssl) that renews every certificate within 30 days of expiry. No further action is needed.
Step 9: Configure Mail with Exim, Dovecot, SpamAssassin, and ClamAV
If you installed --exim yes --dovecot yes --spamassassin yes --clamav yes, HestiaCP already configured a full mail stack. There are a few finishing touches worth applying.
Verify Exim and Dovecot are running
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">systemctl status exim4 dovecot</code></pre></div>
Both services should show active (running).
Configure SPF, DKIM, and DMARC
HestiaCP auto-generates SPF and DKIM DNS records when you add a mail domain. Check the generated zone under DNS → example.com for records like:
- example.com. TXT "v=spf1 a mx ip4:203.0.113.10 ~all"
mail._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSI..."
If you host DNS externally, copy these records into your registrar or Cloudflare dashboard exactly as shown. Then add a DMARC record:<div class="code-block" data-lang="text"><div class="code-block__header"><span class="code-block__lang">text</span></div><pre><code class="language-text">_dmarc.example.com. TXT "v=DMARC1; p=quarantine; rua=mailto:[email protected]"</code></pre></div>
SpamAssassin tuning
SpamAssassin runs as a daemon (spamd) and scores each incoming message. Adjust thresholds in /etc/spamassassin/local.cf:
<div class="code-block" data-lang="text"><div class="code-block__header"><span class="code-block__lang">text</span></div><pre><code class="language-text">required_score 5.0
rewrite_header Subject [SPAM]
report_safe 0</code></pre></div>
Restart:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">systemctl restart spamassassin</code></pre></div>
ClamAV updates
ClamAV's virus signature database is updated by freshclam. Make sure it is enabled:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">systemctl enable --now clamav-freshclam</code></pre></div>
You can force an immediate signature refresh with:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">systemctl stop clamav-freshclam
freshclam
systemctl start clamav-freshclam</code></pre></div>
On low-memory servers, ClamAV's clamd process can consume 700 MB-1 GB of RAM. If that is a problem, disable the daemon and scan on-demand only:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">systemctl disable --now clamav-daemon</code></pre></div>
Test mail delivery
From your workstation:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">swaks --to [email protected] --server host.example.com --port 587 --tls --auth LOGIN \
--auth-user [email protected] --auth-password 'MailboxPass!' \
--body "Test message"</code></pre></div>
Or send a plain test via any email client (Thunderbird, Apple Mail) configured with IMAP on 993/SSL and SMTP on 587/STARTTLS.
Step 10: Enable Quotas and Backups
Filesystem quotas
If you passed --quota yes, HestiaCP enabled user-level disk quotas. Verify:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">quotaon -p /</code></pre></div>
Expected output:
<div class="code-block" data-lang="text"><div class="code-block__header"><span class="code-block__lang">text</span></div><pre><code class="language-text">group quota on / (/dev/vda1) is on
user quota on / (/dev/vda1) is on</code></pre></div>
Each user's disk limit is controlled by their package under PACKAGES. Edit the default package or create new ones (for example, starter-1gb, pro-10gb) with different DISK_QUOTA values, then assign packages per user.
Automated backups
HestiaCP includes a backup engine that tars each user's data (home directory, databases, mail, DNS zones) into a single archive placed under /backup.
Create a manual backup for a user:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">v-backup-user johndoe</code></pre></div>
The result lands in /backup/johndoe.2026-04-16_03-00-01.tar.
Scheduled nightly backups
A cron entry at /etc/cron.d/hestia already runs v-backup-users once per day. Confirm:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">cat /etc/cron.d/hestia</code></pre></div>
Look for a line similar to:
<div class="code-block" data-lang="text"><div class="code-block__header"><span class="code-block__lang">text</span></div><pre><code class="language-text">10 05 * root /usr/local/hestia/bin/v-backup-users</code></pre></div>
Off-site backups (S3, FTP, SFTP)
In SERVER → Configure → Backup, you can register a remote destination (S3, FTP, SFTP, Backblaze B2, Google Drive). HestiaCP will push daily backups off-server automatically, which is strongly recommended -- a local-only backup does not survive a destroyed VPS.
Restore
From the UI, go to BACKUP, pick a user's backup, and click Restore. Or via CLI:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">v-restore-user johndoe johndoe.2026-04-16_03-00-01.tar</code></pre></div>
You can restore selectively (just web, just mail, just DNS) with additional flags -- see v-restore-user --help.
Step 11: Upgrade HestiaCP
HestiaCP updates via the standard apt package manager. The project ships its own APT repository, which the installer already configured at /etc/apt/sources.list.d/hestia.list.
Check for updates from the UI
Go to UPDATES. Any new package versions appear with a green Update button per component (hestia, hestia-nginx, hestia-php). Click each to upgrade.
Upgrade from the CLI
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">apt update
apt install --only-upgrade hestia hestia-nginx hestia-php</code></pre></div>
Or, to upgrade every HestiaCP component at once:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">apt update
apt upgrade -y</code></pre></div>
Major version upgrades
For major version jumps (for example, 1.8.x → 1.9.x), read the release notes at github.com/hestiacp/hestiacp/releases first. Take a full v-backup-users snapshot and a VPS-level snapshot before upgrading -- it is easy to roll back from a snapshot if something regresses.
Post-Install Hardening
HestiaCP ships reasonable defaults, but a few extra steps noticeably reduce attack surface.
Restrict the panel port to your IP
By default the panel listens on 0.0.0.0:8083. If you always log in from the same office/home IP, lock it down in FIREWALL:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">v-add-firewall-rule ACCEPT 203.0.113.50 8083 TCP "Panel from office"
v-add-firewall-rule DROP 0.0.0.0/0 8083 TCP "Block panel elsewhere"</code></pre></div>
Disable SSH password login
After confirming key-based SSH login works:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">sed -i 's/^#PasswordAuthentication ./PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart ssh</code></pre></div>
Enable Fail2ban jails for Exim/Dovecot/sshd
Fail2ban was installed with --fail2ban yes and HestiaCP enables the most common jails. Verify:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">fail2ban-client status</code></pre></div>
Expected output lists jails like sshd, hestia, exim, dovecot, vsftpd, and recidive.
Keep the system patched
Unattended-upgrades is worth enabling:
<div class="code-block" data-lang="bash"><div class="code-block__header"><span class="code-block__lang">bash</span></div><pre><code class="language-bash">apt install -y unattended-upgrades
dpkg-reconfigure --priority=low unattended-upgrades</code></pre></div>
Troubleshooting
<div class="article-table-wrap"><table><thead><tr><th>Problem</th><th>Cause</th><th>Solution</th></tr></thead><tbody><tr><td><code>Error: unable to resolve host</code> during install</td><td>Hostname not set or not FQDN</td><td>Run <code>hostnamectl set-hostname host.example.com</code> and rerun installer</td></tr><tr><td>Installer fails with "detected existing web server"</td><td>Apache/Nginx/MariaDB was previously installed</td><td>HestiaCP needs a clean system -- use a fresh VPS or <code>apt purge</code> those packages before retrying</td></tr><tr><td>Panel unreachable on <code>:8083</code></td><td>Firewall or cloud provider security group blocks the port</td><td>Open TCP 8083 in UFW/iptables and in your cloud panel</td></tr><tr><td>Let's Encrypt fails: "DNS problem: NXDOMAIN"</td><td>Domain A record does not point to this server yet</td><td>Update DNS at your registrar, wait for propagation, retry</td></tr><tr><td>Let's Encrypt rate-limited</td><td>Too many failed attempts in 1 hour</td><td>Wait 1 hour; debug with <code>tail -f /var/log/hestia/letsencrypt.log</code></td></tr><tr><td>Outbound mail marked as spam everywhere</td><td>Missing SPF/DKIM/DMARC, or provider blocks port 25</td><td>Verify DNS records, ask VPS provider to unblock port 25 (most do on request), consider a smarthost like Amazon SES/SendGrid</td></tr><tr><td>ClamAV OOM-kills itself on 2 GB VPS</td><td><code>clamd</code> needs ~1 GB RAM</td><td>Disable daemon: <code>systemctl disable --now clamav-daemon</code>, rely on <code>freshclam</code> + on-demand scans</td></tr><tr><td>Forgot admin password</td><td>Normal recovery not possible without access</td><td>SSH in as root and run <code>v-change-user-password admin 'NewStrongPass!'</code></td></tr><tr><td>Panel shows "Update failed"</td><td>Partial apt state</td><td>SSH in: <code>apt update && apt -f install && apt upgrade -y</code></td></tr></tbody></table></div>
Useful log locations
Installer log: /root/hst_install_backups/YYYYMMDD/hst_install.log
Panel log: /var/log/hestia/error.log, /var/log/hestia/auth.log
Let's Encrypt: /var/log/hestia/letsencrypt.log
Nginx: /var/log/nginx/error.log
Apache: /var/log/apache2/error.log
Exim: /var/log/exim4/mainlog
Dovecot: /var/log/dovecot.log
FAQ
Is HestiaCP really free, with no hidden paid tiers?
Yes. HestiaCP is MIT-licensed and completely free. There is no "pro" edition, no per-account fee, and no paid feature gating. The project is supported by donations and community contributions. You can host one site or five hundred on the same install and pay nothing beyond your VPS cost.
Can I run HestiaCP on an existing server that already has websites?
Not safely. The installer expects a clean Ubuntu 24.04 system and will refuse to proceed if it detects a conflicting web server, database, or mail server. Migrate existing sites to a fresh VPS with HestiaCP installed, then point DNS to the new server. If you absolutely must reuse a host, purge all conflicting packages (apt purge nginx apache2 mariadb-server bind9 exim4 dovecot-core) and their configs first, but a fresh VPS is much less error-prone.
How does HestiaCP compare to CyberPanel, aaPanel, and Webmin/Virtualmin?
HestiaCP is the best all-round choice for classic LAMP/LEMP hosting with email: stable, actively maintained, clean UI, MIT license, excellent CLI parity. It is our default recommendation for agencies and freelancers. See our HestiaCP vs. CyberPanel guide for deeper comparisons.
CyberPanel is built around OpenLiteSpeed/LiteSpeed and excels at raw PHP performance, especially for WordPress. Pick CyberPanel if LiteSpeed Cache and LSPHP are must-haves.
aaPanel is the English-language distribution of BT Panel. It has a polished UI and a huge one-click-app marketplace, but parts of the codebase are closed-source and some plugins are paid. See our aaPanel install guide for details.
Webmin/Virtualmin is the oldest and most flexible option. Virtualmin GPL is free; Virtualmin Pro is paid. It supports far more distributions than HestiaCP but has a denser, less beginner-friendly UI. See the Webmin/Virtualmin install guide if you need Virtualmin's advanced multi-OS and reseller features.
How many websites can HestiaCP handle on a single VPS?
That depends on site traffic, not the panel. HestiaCP itself scales to several hundred domains per server without stress. In practice a CloudCore Starter VPS handles 20-50 small/medium WordPress sites comfortably; CloudCore Professional or bigger suits 100+. The real bottleneck is almost always PHP-FPM worker memory plus MariaDB cache, not HestiaCP.
Can I white-label HestiaCP for my clients?
Yes. HestiaCP supports custom themes under /usr/local/hestia/web/css/themes/, custom logos under /usr/local/hestia/web/images/, and a custom brand name via the config file /usr/local/hestia/conf/hestia.conf (BRAND variable). Everything is file-editable -- no paid "branding add-on" like cPanel or Plesk. For a full agency-branded experience, combine a custom theme with a vanity URL (e.g. panel.youragency.com) and disable the public version banner.
Does HestiaCP support Node.js, Python, or Ruby apps?
Natively, HestiaCP focuses on PHP via PHP-FPM and Apache/Nginx. For Node.js/Python/Ruby, you run the app as a systemd service (or PM2) on a local port and use HestiaCP's "proxy template" feature to route requests from the domain to that port. This is well-documented and works reliably, it just is not a one-click flow the way it is in CyberPanel's Node.js app manager.
Next Steps
Now that HestiaCP is installed and secured, here are useful next steps:
Install WordPress with one command -- Use v-add-web-app wordpress to drop a ready-to-go WordPress install into any domain, with database and wp-admin user pre-created.
- Compare other control panels -- If you are still deciding, read our CyberPanel install guide, aaPanel install guide, and Webmin/Virtualmin install guide to see which panel best fits your workflow.
- Set up off-site backups to S3 -- Under SERVER → Configure → Backup, register an S3-compatible bucket (Backblaze B2 and Wasabi are the cheapest options). Nightly backups will push there automatically.
- Add monitoring -- Deploy Uptime Kuma on a separate small VPS to monitor the HestiaCP panel, each hosted site, and Exim/Dovecot. Alerts via email, Telegram, or Slack.
- Read the official docs -- The HestiaCP documentation covers advanced topics: custom templates, API integration, high-availability setups, and upgrade procedures.
Automate provisioning with the API -- With --api yes`, every panel action is also available over a REST API. Great for integrating HestiaCP with a billing system like Invoice Ninja or a provisioning tool.
Skip the Manual Install -- Get a Web Hosting VPS Ready to Go
>
Our CloudCore Starter plan gives you the ideal base for HestiaCP: enough CPU and RAM to run the full stack, NVMe storage for fast page loads, and unmetered bandwidth for your sites and mail.
>
- 30-second deploy
- Full root SSH access
- Ubuntu 24.04 LTS pre-installed
- Free snapshots for safe upgrades
>
Deploy Your CloudCore Starter VPS and have HestiaCP running before your coffee gets cold.