Setting up your brand new CentOS 8 box for hosting a web project

Note: This guide does not take in mind using policies of SELinux. If you are using SELinux, various commands need also to be followed by policy changes, so tread carefully. To verify if you are running SELinux, you can run getenforce to verify. If you are not, you may safely proceed

To begin...Install basic packages

Let's install some basic packages we need for the rest of this how-to

sudo yum install epel-release #For adding certain packags
sudo yum install nano #Best text editor ever
sudo yum install htop #To be able to monitor our server
sudo yum install nginx #For adding a webserver
sudo yum install fail2ban fail2ban-systemd #For capturing failed logins

Hardening the server!

User accounts

We should not be using the root account to do our work. Instead, we should have a different one, that sudo's every time it needs to do a system change. Root creds should be ultra hard to come up with (you should have a huuugee password for it) and be kept somewhere out of sight!

So let's create a new user and add a password

useradd YOURUSER

Also add the new user to the WHEEL group to enable that user to use the sudo command.

usermod -aG wheel YOURUSER

Enable user account to login with an ssh key

Generate an ssh key on your client machine (use ssh-keygen, native on Mac, use in Bash if you have it on Windows. It usually ships with Git installations, or if you are using the linux subsystem)

After you have your key, run ON THE CLIENT machine the following command:

ssh-copy-id YOURUSER@<host>

Host can be your server domain, or IP. The command is going to attempt and login to your remote server, and install the key for the specified user automatically. During this process, password is going to be asked for the user. After successful authentication, the command copies the key on the server. You should be able to login over ssh using your key now. To test it, from bash, run:

ssh -i ~/.ssh/mykey YOURUSER@<host>

For making the key usable with Putty, run PuTTyGen, import the key (if you used the default settings, that would be id_rsa found in your home folder under the .ssh folder) and subsequently save it in a .ppk format.

SSH Service Configuration

We will try to implement the following

  • Disallowing root logins
  • Limit allowed users that can login through ssh
  • Block an IP after 3 failed login attempts
  • Changing the default port (Not Implemented yet)
  • Disabling password authentication (Not Implemented yet)

First open /etc/ssh/sshd_config on your server using your favorite editor (use nano, we installed it before!) so we can work with it

sudo nano /etc/ssh/sshd_config
Quick nano tutorial: to save anything, you hit 'Ctrl+X', and nano asks what to do. You can choose to discard changes, of save changes by hitting the appropriate letters on your keyboard. In case you are saving, it will also ask for a name. Hit enter to overwrite, or type a new one to create a new file. Super simple!

Disallowing Root Logins

Locate the following entry and change it to no

# Prevent root logins:
PermitRootLogin no

Setting allowed users

You can limit the possibility for login to specific user accounts. If you have limited people that should be able to login, then this greatly enhances your security policies!

Add this at the end of the sshd_config file, by separating different usernames using space. Only these users will be able to login afterwards


Now save all the changes to the file and restart sshd server to pickup the configuration

To restart the sshd server to apply all the changes...
Either run:

sudo systemctl reload sshd.service

Or run:

sudo service sshd restart 

Block an IP after 3 failed login attempts

To achieve this, we are gonna use the fail2ban. If you haven't done so, install the EPEL repository, and then install fail2ban

sudo yum install epel-release
sudo yum install fail2ban fail2ban-systemd

To configure fail2ban, we create an sshd.local file in the proper folder

sudo nano /etc/fail2ban/jail.d/sshd.local

with the following config

enabled = true
port = 22
logpath = %(sshd_log)s
maxretry = 3
bantime = 900 //That's in seconds. this equals to 15 minutes

Save the file, enable the service, and start it. By enabling the service, fail2ban will be autostarted automatically whenever the whole server gets rebooted.

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Setting up a firewall using firewalld

First, check the state of your firewalld, whether it's already running or not. If not, let's shoot it up! (Don't worry, you probably won't get locked out as the default config allows ssh port)

sudo firewall-cmd --state
sudo systemctl status firewalld
sudo systemctl start firewalld

To check current configuration (after you started the firewall), run

sudo firewall-cmd --zone=public --list-all

Notice the services that are being allowed right now. Probably you have ssh already configured.

FirewallD makes it convenient to set it up by using service definitions rather than using ports (although you can definitely use ports if you need to).

So you could enable ports 80 and 143 for http/https serving easily by issuing:

sudo firewall-cmd --add-service=http
sudo firewall-cmd --add-service=https

The services get enabled on the default interface, which if you haven't specified one, it will be 'public' by default. FirewallD allows you to have different configurations for different interfaces (eg for internal network, or a dmz or whatever) by it's too advanced for us to get into in this quick how-to!

Now, if the configuration feels ok (check the status and make sure ssh it's still available, so you do not get locked out), you need to make this configuration permanent. FirewallD, has 2 configuration levels. The runtime configuration, and the permanent one. With this method, if for some reason you do a setting that locks you out of your remote machine, you could restart it and get rid of that wrong configuration on reboot. Only when you are certain about a setting, you should move it to the permanent configuration. The permanent configuration it's the one loaded every time the system (and firewallD) starts.

To make our configuration permanent, you should either rerun the above commands using the --permanent flag

sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent

or issue

sudo firewall-cmd --runtime-to-permanent

which copies the current running configuration to the permanent one.

After saving our configuration and make it permanent, the firewall needs no further reloading.

In case we want to reload it to make sure it's running with the proper configuration (if you are the insecure type of person), then you can do so by issuing

sudo firewall-cmd --reload

Finally, let's enable the firewall to run automatically after system restarts, if it's not already enabled

sudo systemctl enable firewalld

Et voila! We are behind a firewall! If by any chance you have any other services running without your knowledge, you have at least blocked access to them from the outside. From now on, for whatever service you wanna expose to the outside world (eg adding ftp access, although you should be using ssh to transfer your files in the first place) you need to also add the service to the firewall using the firewall-cmd similarly as above.

For more info on firewalld configuration checkout:

RedHat Documentation - CentOS 7

Linode Tutorial

Installing Nginx for serving a web page/app

If you haven't installed it before, do it now:

sudo yum install nginx

Then start the service

sudo systemctl start nginx

Add Nginx to your firewalld rules, if you are running firewalld

sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload

Check that everything worked by visiting http://server_domain_or_ip. The nginx welcoming page should show up

Finally, make Nginx to automatically start after server reboots

sudo systemctl enable nginx

Final Notes

Configuration for Ngnix can vary a lot, depending on what type of a web app you will be serving, hence I am gonna leave that out for now. In case you are the Django type, you could check one of my other posts that goes through the steps of installing python, Let's Encrypt for issuing an SSL certificate and using systemd along with gunicorn to handle the django app!

Note: This article is a work in progress, as I keep updating it with more current information. If there is anything you would like me to address specifically, please leave a message to try and include it on future updates!

To sum up what we have achieved up to now: your brand new CentOS 8 Box has been configured to be slightly more secure, has a firewall up and running and does not allow brute-force attacks by blocking clients with more than 3 failed attemps. An Nginx webserver is also up and running and now it's pending configuration to be able to load your web project!