UnderHost
Knowledgebase Docs

Install the CSF firewall on a Linux server without a control panel

Step by step: install CSF (Core Shield Firewall) 2.3 on a Linux server with no control panel, turn on protection safely, create your web interface login with two-factor authentication, and open the firewall web interface through an SSH tunnel or your own HTTPS reverse proxy.

On this page

CSF (Core Shield Firewall, formerly cPanel Shield Firewall) is UnderHost's free, open-source firewall and intrusion-prevention system, part of UnderShield. Since version 2.2 it also runs on Linux servers that have no control panel: the same nftables firewall, LFD 2.0 brute-force protection and Threat Intelligence feeds, with its own secure web interface instead of WHM. This guide takes you from a fresh server to a working, protected setup.

CSF 2.3 - stable

No-panel support is part of the stable CSF 2.3.2, tested on Debian 12 / 13, Ubuntu 22.04 / 24.04 / 26.04, AlmaLinux 8 / 9 / 10, Rocky Linux 9 and CloudLinux 9. CSF 2.3 can also scan uploaded website files for malware: run csf --scan-setup. Using CloudPanel? Follow Install CSF on CloudPanel instead.

Before you start

  • Root access over SSH. Keep that SSH session open during the whole setup.
  • A recent Linux: AlmaLinux, Rocky, RHEL or CloudLinux 8/9/10, or Ubuntu 22.04/24.04.
  • nftables and Perl. Most servers have both. If the installer says nftables is missing, install it with dnf install -y nftables (AlmaLinux and Rocky) or apt-get install -y nftables (Ubuntu).
  • The SSH port you use. The installer reads it from your SSH configuration, so a custom port is kept open.

1. Download and install

Run these commands as root. The checksum step makes sure the file was not changed on the way.

terminal (root)
cd /root
curl -fSLO https://shield.underhost.com/firewall/download/csf-2.3.2.tar.gz
curl -fSLO https://shield.underhost.com/firewall/download/csf-2.3.2.tar.gz.sha256
sha256sum -c csf-2.3.2.tar.gz.sha256
tar xzf csf-2.3.2.tar.gz
cd csf2 && sh install.sh

sha256sum must answer OK. The installer then detects that the server has no control panel and:

  • opens TCP 22 (or your SSH port), 80 and 443, and nothing else;
  • installs the firewall in TESTING mode: the rules are built and checked but not enforced yet, so a mistake cannot lock you out;
  • installs the web interface service csf2-ui, which listens on 127.0.0.1:6789 only.

If you run another firewall (ufw or firewalld), the installer may warn you. Leave it running for now; you will turn it off in step 3.

2. Check the ports

terminal (root)
csf --platform
grep -E '^(TCP_IN|UDP_IN|MGMT_PORTS) ' /etc/csf/csf.conf

The platform should show Linux (no control panel). If the server runs other services that must be reachable from the internet, such as a mail server, a game server or a database used by another server, add their ports to TCP_IN (or UDP_IN) in /etc/csf/csf.conf now, separated by commas. For example:

/etc/csf/csf.conf
TCP_IN = "22,80,443,25,587,993"

Do not add 6789: the web interface is reached through a tunnel or a reverse proxy, never directly.

3. Turn protection on safely

Edit /etc/csf/csf.conf and change TESTING = "1" to TESTING = "0". Then apply the rules with the safety net:

terminal (root)
csf --safe-reload

Now open a second SSH session to the server. If it connects, confirm in either session:

terminal (root)
csf --confirm
systemctl enable --now csf.service lfd.service

The second line starts LFD (brute-force detection) and makes everything start again after a reboot. Check that the server is really protected:

terminal (root)
csf -l
csf --selftest
The 30-second safety net

If you cannot open the second session, do nothing: --safe-reload puts the previous rules back after 30 seconds unless you run csf --confirm. Then check your ports and try again.

Once CSF is enforcing, turn off the old firewall so the two do not fight: ufw disable on Ubuntu, or systemctl disable --now firewalld on AlmaLinux and Rocky.

4. Create your web interface login

Nobody can sign in to the web interface until you create an account. Pick any user name:

terminal (root)
csf --ui-user add admin
  1. Type a password of at least 12 characters, then repeat it.
  2. CSF prints a Secret and a URI (starting with otpauth://). This is your two-factor authentication setup.
  3. Open your authenticator app (Google Authenticator, Microsoft Authenticator, 1Password, Authy…), choose Enter a setup key, and type the Secret. Use time-based, 6 digits.

Prefer to scan a QR code? Install qrencode (apt-get install -y qrencode on Ubuntu, dnf install -y qrencode on AlmaLinux and Rocky, from EPEL if it is not found) and show the URI as a QR code right in your terminal:

terminal (root)
qrencode -t ansiutf8 'PASTE-THE-otpauth://-URI-HERE'

Keep the secret private: anyone who has it can generate your login codes. Clear your screen afterwards with clear.

5. Open the web interface

For security, the web interface only listens on the server itself (127.0.0.1:6789) and is never published on the internet directly. You reach it in one of two ways.

Option A: SSH tunnel (quickest, nothing to set up)

An SSH tunnel carries the web interface through your existing SSH connection, so it stays encrypted and only you can use it.

macOS, Linux or Windows 10/11 (PowerShell):

on your computer
ssh -L 6789:127.0.0.1:6789 root@YOUR-SERVER-IP

Add -p 2222 if your SSH port is not 22. Leave that window open and visit http://127.0.0.1:6789 in your browser.

Windows with PuTTY:

  1. Enter your server in Session as usual.
  2. Go to Connection → SSH → Tunnels. Source port: 6789. Destination: 127.0.0.1:6789. Click Add.
  3. Click Open and log in. While the PuTTY window is open, visit http://127.0.0.1:6789.

Sign in with your user name, password and the 6-digit code from your authenticator app.

Option B: your own HTTPS domain

To open the interface from anywhere, publish it behind a web server with HTTPS on a domain you own, for example fw.example.com. Point the domain's DNS at the server first. The interface keeps its own login and two-factor check behind the proxy.

nginx (with a Let's Encrypt certificate already issued for the domain):

/etc/nginx/conf.d/csf-ui.conf
server {
    listen 443 ssl http2;
    server_name fw.example.com;
    ssl_certificate     /etc/letsencrypt/live/fw.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/fw.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:6789;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}

Caddy (gets the certificate by itself):

/etc/caddy/Caddyfile
fw.example.com {
    reverse_proxy 127.0.0.1:6789
}

The X-Real-IP and X-Forwarded-Proto headers matter: they let the interface see the visitor's real IP (for lockouts and logs) and mark its session cookie as HTTPS-only. Caddy sends them automatically.

Managing logins and access

TaskCommand or setting
List userscsf --ui-user list
New password (also issues a new 2FA secret and signs the user out)csf --ui-user passwd admin
Remove a usercsf --ui-user del admin
Only allow some IPs to reach the interfaceUI_ALLOW = "203.0.113.10,198.51.100.0/24" in /etc/csf/csf.conf, then systemctl restart csf2-ui
Change the portUI_PORT in /etc/csf/csf.conf, then systemctl restart csf2-ui
Sign-in log/var/log/csf2-ui.log (also watched by LFD)

Sessions end after 30 minutes without activity and after 12 hours at most. After 5 wrong sign-ins in 15 minutes, the interface refuses that IP address for 15 minutes.

Troubleshooting

ProblemWhat to do
The tunnel page does not loadCheck the service with systemctl status csf2-ui and start it with systemctl start csf2-ui. Make sure your SSH tunnel window is still open.
Wrong user name, password or codeCheck the clock: two-factor codes need the right time on both your phone and the server (timedatectl). If you lost the code, run csf --ui-user passwd admin and add the new secret to your app.
Too many failed attemptsWait 15 minutes, or sign in through the SSH tunnel from another IP.
Locked out of SSH after turning protection onIf you used --safe-reload, the old rules return within 30 seconds. Otherwise, open the server console (VNC or IPMI) and run csf --flush to remove the firewall rules, then fix TCP_IN and reload.
A website or service stopped workingIts port is not in TCP_IN. Add it, then run csf --safe-reload and csf --confirm.
Sign-in works but you are sent back to the login page (proxy)Your proxy must send X-Forwarded-Proto https and serve the site over HTTPS.

FAQ

A firewall's control page is a prime target. Listening only on 127.0.0.1 means attackers cannot even reach the login page; you get there through SSH or through your own HTTPS proxy, which also gives you a trusted certificate.
No. Everything works from the command line with the familiar commands: csf -a IP to allow, csf -d IP to block, csf -g IP to check an address, csf -r to reload. If you never use the interface, you can stop it with systemctl disable --now csf2-ui.
Yes. It is free and open source under the GNU GPL v3, on UnderHost servers and anywhere else.
Run csf --self-update. It downloads the release, checks its SHA-256 checksum and installs it while keeping your configuration, allow and deny lists.

Related: Install CSF on CloudPanel | Full CSF documentation | SSH key authentication | UnderShield monitoring

Was this article helpful?

Need security-focused hosting?

UnderHost services include DDoS-aware infrastructure, SSL support, account isolation, backups, and security guidance.

Related articles

Back to Security