How to Install and Secure Webmin on Ubuntu 24.04
Install Webmin on Ubuntu 24.04 in about one minute, then secure port 10000 with SSH tunneling or IP allowlisting, Let's Encrypt, 2FA, and Fail2ban.
Wetin you dey build
Webmin na web control panel wey put browser front end for one whole Linux server, users, packages, cron jobs, firewall, Apache, BIND, disks, and plenty other modules. You fit reach am through HTTPS for port 10000. The installation itself na just three commands and e dey take about one minute. The reason dis guide spend most of the length for the second half na because Webmin dey log in as root and e fit do anything wey root fit do. Webmin wey anybody fit reach or wey no require authentication no be "risk wey you fit manage"; na full server breach with login page for front. So install am within ten minutes, then use the rest of the hour make sure say na only you fit reach am.
Prerequisites and one honest warning
You need fresh Ubuntu 24.04 KVM VPS with root or sudo user. Webmin na Perl and e light, so 1 GB RAM plenty, and e dey use well below quarter gigabyte when idle. E dey listen on TCP 10000 through e own bundled web server (miniserv.pl), no be Apache or nginx, so you no need install anything first.
You get two things to decide before you start. First na the account wey you go use log in with: Webmin dey authenticate Unix accounts through PAM. So you go log in as root or as user wey dey inside sudo group, using that account Unix password. Cloud images usually dey use key-only login, with no password set for the default user. Webmin no fit log in to account wey no get password. Set password first with sudo passwd youruser, or login go fail no matter wetin you type.
Second one na this warning: no just open port 10000 to internet and leave am like that. Decide now whether you go reach Webmin through SSH tunnel (recommended, so nothing dey exposed) or restrict access to your own IP. This one decision go affect every step below, so read both options before you change the firewall.
Install Webmin from the official repository
Webmin dey publish signed apt repository. The setup script go add the repo and im GPG signing key, so future apt upgrade runs go pull Webmin like any other package. You go get authenticated updates instead of downloaded .deb wey no dey patch itself.
curl -o webmin-setup-repo.sh https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh
sudo sh webmin-setup-repo.shThe script go print wetin e wan do and ask Setup Webmin stable repository? (y/N). Answer y. When e finish, install the package. The --install-recommends flag go pull the common Perl and SSL module dependencies, so individual modules no go fail later because library dey miss.
sudo apt-get install --install-recommends webminWebmin don rename this script before. Older guides dey reference setup-repos.sh. So if the raw URL return 404, collect the current one-liner directly from webmin.com/download instead of pinning one name. Correct installation go end with line like Webmin install complete. You can now login to https://your-host:10000/ as root. The service don enable and dey run. Config dey under /etc/webmin. Requests dey log to /var/webmin/miniserv.log. Failed logins dey go syslog, or for Ubuntu 24.04, the systemd journal.
Confirm say e really dey up and listening before you open browser:
sudo systemctl status webmin --no-pager
sudo ss -tlnp | grep 10000You need see active (running) status and line wey show miniserv.pl bound to 0.0.0.0:10000. That address go change to 127.0.0.1:10000 once you use the tunnel route below. If ss show nothing on 10000, Webmin no start. Read journalctl -u webmin -n 50 before you continue.
First login, and the certificate warning
Point your browser go https://YOUR_SERVER_IP:10000. Two things go happen for fresh box.
If ufw dey active, Ubuntu own server image ships am inactive, but plenty providers dey pre-enable am, the page no go load at all. We cover this for the failure modes below. If the port dey open, your browser go show full-page block: "Your connection is not private" with code NET::ERR_CERT_AUTHORITY_INVALID for Chrome, or SEC_ERROR_UNKNOWN_ISSUER / "Warning: Potential Security Risk Ahead" for Firefox. This one dey expected and e no mean say person don break in. Webmin generate self-signed certificate during installation (/etc/webmin/miniserv.pem). Because no certificate authority vouch for am, browser no go trust am silently. The connection still dey encrypted; na only say nobody vouch for am. Click through (Advanced, then Proceed) for now. We go replace this certificate properly further down.
Log in with root or your sudo user and the Unix password wey belong to am. You go land for System Information dashboard. One common mistake na to type http:// instead of https://. miniserv dey answer plain HTTP for that port with the exact text "This web server is running in SSL mode. Try the URL https://...". To fix am, simply change http to https for the address bar.
Di security decision: how you go reach Webmin?
Now na the part wey matter. Panel wey get root-equivalent access no suppose dey open internet dey answer login attempts from every scanner for the whole world. You get two options wey make sense, arranged from the one we prefer pass. Every self-hosted admin surface go reach this same question. Na why whether Vaultwarden secure depend on the admin endpoint and backup file, no be on the encryption.
The SSH tunnel for Option B better, because e no expose anything at all. The IP allowlist for Option A acceptable if your address dey static. If you no do any of dem, na exactly the mistake wey this whole guide dey try prevent. If you prefer reach Webmin through private network instead of either option, put the box behind self-hosted WireGuard VPN and bind Webmin to the tunnel address instead of the public one.
Option A: limit Webmin make e only accept your IP
For the panel, open Webmin, then Webmin Configuration, then IP Access Control. Choose "Only allow from listed addresses" and enter your public IP. You fit find am by running curl ifconfig.me for your laptop. Save am. Webmin go write this for the allow= line inside /etc/webmin/miniserv.conf, then restart itself.
The trap be say if your home IP dey dynamic and e change, or you enter the address wrong, you go lock yourself out. Browser go then show "Access denied for <your IP>" without login form, and no web route go dey to enter again. You go fix am from the server console through SSH or your provider's VNC:
sudo nano /etc/webmin/miniserv.conf
# find the line that begins allow=
# correct your IP, or delete the whole line to allow all again
sudo systemctl restart webminIf you delete the allow= line, e go restore fully open access. Only do this to recover access, then set the correct value immediately.
Option B: bind go localhost and tunnel over SSH (recommended)
Better than any allowlist na to make sure say e no listen for public interface at all. Tell miniserv make e bind only to loopback, then reach am through an encrypted SSH tunnel wey you already trust.
Edit /etc/webmin/miniserv.conf and add, or change, one line:
bind=127.0.0.1Restart with sudo systemctl restart webmin. Webmin no dey reachable from internet again, port scan of 10000 no go find anything, and the ss check from earlier now go show say e bind to 127.0.0.1:10000. From your laptop, open tunnel:
ssh -L 10000:localhost:10000 youruser@YOUR_SERVER_IPLeave that session open and browse to https://localhost:10000. The traffic dey pass inside SSH. Your key don already authenticate and encrypt am, so you fit safely accept the self-signed certificate here; na the SSH layer dey provide the real protection. Close the SSH session and Webmin don disappear. Nothing to allowlist, nothing exposed, no extra service to harden.
If you set bind=127.0.0.1 and forget the tunnel, remote access go simply stop. Na the feature dey work, no be fault. Recover am the same way as Option A: from the console, remove the bind line or set bind=0.0.0.0, then restart. Na the same tunnelling habit you go use to reach remote development box wey dey run Claude Code for tmux, one SSH session, everything private, nothing extra listening on the public interface.
Replace the self-signed certificate with a real one
If you expose Webmin under Option A, use a real Let's Encrypt certificate make browser warning disappear. You need a name for the certificate and a way for Let's Encrypt to reach port 80 during validation. The name normally na DNS name, for example panel.example.com, with an A record wey point to the server. From Webmin 2.650 (released June 25, 2026), e fit also be the server public IP address, as long as Certbot 5.3 or later dey installed. Let's Encrypt dey issue IP certificates only for its short-lived profile. The certificate dey valid for about six days. So set Webmin automatic renewal interval in days. Webmin no go accept longer interval for IP certificate.
Webmin get this feature inside am: Webmin, then Webmin Configuration, then SSL Encryption, then the Let's Encrypt tab. Enter the hostname or IP address, choose validation method, then request the certificate. Webmin go obtain the certificate, update the certfile= and keyfile= lines inside miniserv.conf for you, and renew am automatically before e expire. Reload the page and the padlock go show clean.
The main issue be say Webmin own server dey run on 10000, no be 80. So something must answer the http-01 challenge for port 80. You get three ways to do am. If Apache or nginx already dey serve the name for port 80, point the validation to that site document directory. For IP address, this needs Certbot 5.4 or later. If nothing dey use port 80, choose Certbot built-in web server, the standalone mode wey Webmin add for version 2.110. Certbot go briefly run its own web server for port 80. So Certbot must dey installed, and port 80 must free and open for your firewall. Or use DNS validation. E dey work for hostnames but no dey work for IP addresses. Ubuntu 24.04 own certbot package na version 2.9. E good for standalone validation of hostname, but e too old for IP certificates. For IP certificates, install current Certbot, such as the snap, wey be version 5.8 as of October 2026. If you no use any of these methods, the request go fail with validation error. The process, DNS records, port-80 challenge, and renewal na the same as issuing certificate for any website. If you want understand the background, the Let's Encrypt TLS certificates with Certbot and nginx guide explain the validation flow and DNS setup in detail. If you use the SSH-tunnel route, you fit skip this section completely. The self-signed certificate dey okay behind SSH, and real certificate issued for panel.example.com go still produce name-mismatch warning when you visit https://localhost:10000.
On two-factor authentication
Password alone no strong enough protection for root panel, so add second factor. Open Webmin, then Webmin Configuration, then Two-Factor Authentication. Select the Google Authenticator provider. E use standard TOTP, so e work with Authy, 1Password, or any authenticator app, then save. Webmin go install the small Perl module wey e need (Authen::OATH plus QR generator) and enable the feature. This step alone no protect any account yet.
Each account go enrol its own device. When 2FA don enable, open Webmin, then Webmin Users, choose the account, select Enable Two-Factor For User, and Webmin go show QR code. Scan am with the app, then enter one generated code to confirm. From that time, login go ask for the six-digit token after password. Enrol before you log out. If 2FA dey required but your account never scan any code, you still fit clear the requirement from console, but e go less stressful if you enrol first.
Add Fail2ban to ban brute-force logins
Even restricted login endpoint suppose punish repeated failures. Webmin dey report failed logins to syslog as webmin[12345]: Invalid login as root from 10.0.0.9, or Non-existent login as ... when username no be Unix account at all. For Ubuntu 24.04, those lines dey enter systemd journal, because stock image no get /var/log/auth.log. Fail2ban get stock webmin-auth filter wey match exactly those two lines. The jail below set backend = systemd by itself, so e no need custom regex or log path.
Create /etc/fail2ban/jail.d/webmin.local:
[webmin-auth]
enabled = true
port = 10000
filter = webmin-auth
backend = systemd
maxretry = 4
bantime = 1hReload with sudo systemctl restart fail2ban, then confirm say the jail dey live:
sudo fail2ban-client status webmin-authYou suppose see the jail listed with ban counter wey start from zero. For journal backend, no File list: line dey. To prove say everything connect end to end, intentionally fail login some times from another network. Then run the status command again and monitor Currently banned as e dey increase. If e never increase, make sure say you no dey test from address wey dey inside Fail2ban's ignoreip. Also run journalctl SYSLOG_IDENTIFIER=webmin for the server to confirm say Invalid login lines dey actually write. If Fail2ban never install for this box, the Fail2ban for Ubuntu 24.04 SSH guide explain the installation and the SSH jail wey you suppose run together with this one.
Limit wetin each Webmin user fit touch
No be everybody wey need the panel need root access to everything. Under Webmin, then Webmin Users, create extra Webmin logins and give each one only the modules wey e need. For example, backups operator fit see only the cron and filesystem modules. When you edit user, you go see checklist of every module. If you untick one, e go remove am from that user menu and block the URLs wey dey behind am. Na defence in depth be this: even if person steal low-privilege Webmin session, e no fit rewrite /etc/shadow when Users module no dey the user list.
Webmin dey updated
Because you install am from apt repository, sudo apt update && sudo apt upgrade dey pull new Webmin releases together with the rest of the system. Apply patches quickly, because attackers dey target control panel often. Webmin fit also update itself through Webmin, then Webmin Configuration, then Upgrade Webmin, but apt method cleaner for Ubuntu because e keep versions consistent with your other package management. No treat this as optional: some past Webmin CVEs na remote-code-execution bugs, and the only thing between "patched" and "breached" na how quickly admin run the upgrade.
Failure modes, and the messages wey you go see
"Your connection is not private" / NET::ERR_CERT_AUTHORITY_INVALID. E go show for the very first load. Cause na say the self-signed certificate wey Webmin generate during installation no get trusted issuer. E no mean say attack dey happen; the channel dey encrypted, but nobody wey browser trust don verify am. Fix am by passing through the warning for now, then issue real Let's Encrypt certificate. You fit also accept am permanently if na SSH tunnel you dey use reach Webmin.
"This web server is running in SSL mode. Try the URL https://..." You type http://server:10000. miniserv only dey speak TLS for that port, so e dey tell you this with plain text. Fix am by changing http to https for the address bar.
Page times out, ERR_CONNECTION_TIMED_OUT / "This site can't be reached". The request no reach Webmin at all. For Ubuntu, ufw often dey drop port 10000, but check before you assume. Run sudo ufw status. If e report Status: inactive, ufw no dey block anything (Ubuntu ships with am disabled, and adding an allow rule no enable am), so check further upstream, like firewall for your provider's control panel. If e report Status: active, run sudo ufw status verbose to see the default incoming policy and any wider rules. If incoming traffic dey denied and 10000 no dey listed, either open am with sudo ufw allow 10000/tcp or, better, leave am closed and use the SSH tunnel from Option B. Remember the difference: a timeout mean firewall dey silently drop packets, while ERR_CONNECTION_REFUSED mean the port dey reachable but Webmin no dey run. Check sudo systemctl status webmin.
"Access denied for <your IP>." You set IP Access Control under Option A, but your current address no dey the allow list. E fit be dynamic IP wey change, or typo. Browser no get way to take you back in. Fix am from the console: edit the allow= line inside /etc/webmin/miniserv.conf, correct am or delete am, then run sudo systemctl restart webmin.
"Login failed. Please try again." with credentials wey you know say correct. The account no get Unix password. This one dey normal for key-only cloud images. Webmin dey authenticate through PAM against the Unix password, but that password no exist for the user. Fix am by running sudo passwd youruser for the server, then log in. If /var/webmin/miniserv.log show Non-existent login as ..., you dey type username wey no be Unix account at all.
For more than a few servers, automation dey scale better than putting control panel for every box: your first Ansible playbook na where e start.
FAQ
Webmin safe to expose for public internet?
Treat internet-facing Webmin like root shell wey get login page, because na exactly wetin e be. E safe enough only when you use different protection layers: real certificate, two-factor authentication, Fail2ban, and either tight IP allowlist or, better, no public exposure at all. The setup wey get the lowest risk na to bind Webmin to 127.0.0.1 and reach am through SSH tunnel, so nobody for open internet fit answer port 10000.
How I fit remove Webmin certificate warning?
The warning (NET::ERR_CERT_AUTHORITY_INVALID) dey show because Webmin ships self-signed certificate. Issue real one from Webmin, Webmin Configuration, SSL Encryption, Let's Encrypt. Use DNS name wey point to the server, or the server public IP address if Certbot 5.3 or later dey installed. Port 80 must dey reachable for the challenge. Either existing web server or Certbot own standalone server fit answer am. If na only through SSH tunnel to localhost you dey reach Webmin, the warning no be problem. SSH don already encrypt and authenticate the connection, so you fit safely accept the self-signed certificate.
How I fit restrict Webmin to only my IP address?
Go to Webmin, Webmin Configuration, IP Access Control, choose "Only allow from listed addresses", then enter your public IP from curl ifconfig.me. Webmin stores this for the allow= line of /etc/webmin/miniserv.conf. Watch out for dynamic home IP. If e change, you go lock yourself out and must repair the allow= line from the server console. Because of this, static address or the SSH-tunnel method dey more reliable for real use.
Why my login dey fail even when password correct?
Webmin authenticates through PAM against your Unix password. Cloud images usually dey use key-only login, and default account no get password set. Because of this, PAM no get anything to match, so e reject the login. Run sudo passwd youruser for the server to set password, then log in. If you see Non-existent login as ... line for /var/webmin/miniserv.log, e mean say the username itself no be real Unix account.
Wetin Webmin good for compared with plain SSH?
Webmin na layer for easier discovery and convenience. E useful for browsing log files, managing users and cron, editing firewall rules, and checking disk and service state without memorising every command. This fit help occasional admins or teams wey get different skill levels. Plain SSH dey faster, scriptable, and e expose much less attack surface for routine work. Plenty admins dey use both: SSH for daily work, and Webmin bound to localhost behind tunnel for occasional point-and-click task. If your real question na which panel to choose, instead of panel versus shell, e make sense to first compare Cockpit against Webmin, because the two differ for how much of the system each one fit change and how each one authenticates you.