https://ivansalloum.com/category/server-security/
====== STEPS ======
**1. Update OS **
apt update && apt upgrade -y
**1. Install essential tools **
apt install -y htop git curl wget unzip net-tools
==== PRELIMINARY ====
Updating the Server
After connecting to your server, you may encounter a message indicating that there are packages, including security patches, available for updating.
Using outdated software may exposes your server to security vulnerabilities.
Therefore, a very important step in securing and maintaining your server’s health is to update your server’s packages and download any available security patches.
Begin by updating the package list on your server with the following command:
sudo apt update
This command prompts the server to scan the server’s packages and identify those requiring updates, including security patches.
Once this is done, run the following command to update your server’s packages that need updating:
sudo apt upgrade
The server may ask for confirmation by displaying a prompt that requires a yes or no response. Make sure to type yes.
The updating process may take a while, depending on the number of updates needed.
Note: Some immediately reboot after updating, but I prefer waiting until the server setup is complete to ensure all changes apply.
Regularly updating your server is not just recommended – it’s essential.
Updates provide critical security patches, performance improvements, and software bug fixes.
Neglecting updates can leave your server vulnerable to attacks.
Read more: I wrote a detailed guide on automating security updates for a Linux server. Check it out after finishing this one.
Changing Server Hostname
Setting a meaningful hostname for your servers is like giving them a name tag — it makes them easily recognizable and more user-friendly.
This comes in handy when you want to double-check that you’re working on the right server, reducing the chances of accidentally messing with the wrong one.
But, there are two main reasons why setting a hostname is important:
Some programs need the hostname to work correctly. Properly configuring a server’s hostname is essential for certain network services to function as they should.
If a server’s hostname can’t be resolved to an IP address, it can cause communication and networking issues. This may result in timeouts, connection errors, and other unexpected behavior.
To change the hostname, use the following command:
sudo hostnamectl set-hostname
Typically, a hostname has two parts: the server name and the domain name.
For instance, if you’re naming your server myserver and your domain is example.com, your hostname would be myserver.example.com.
Note: Make sure to add an A record for your hostname.
Changing Timezone
Setting the timezone for your server is important because it ensures that the server’s clock matches the correct time in your specific location.
If the server’s timezone is not set right, it can cause problems like wrong timestamps on log files, scheduling issues with tasks (cron jobs), and other issues that depend on accurate time information.
Use the following command to list the available timezones:
timedatectl list-timezones
This will show you a long list of timezones to choose from.
Once you’ve picked the right one, type the following command to set it:
sudo timedatectl set-timezone
Your server is now in sync with the correct timezone.
Changing Default Editor
You can change the default editor used by your server, such as when running the crontab or visudo commands.
It’s usually Nano, but you can switch it to Vim or any other preferred editor using the following command:
sudo update-alternatives --config editor
Enter the number corresponding to the chosen editor and press the ENTER key.
Installing Essential Software
Depending on your specific needs and the purpose of your server, there may be additional essential packages you’d want to install.
I always install these packages on my servers:
sudo apt install htop git curl wget unzip net-tools
These packages cover a range of common tasks that you may encounter while managing and using your server.
install Postfix and Configuring SMTP Relay
It is very important to install Postfix and configure it to use an external SMTP server for sending emails.
By doing this, your server will be able to send email notifications and alerts from packages like Unattended Upgrades, for example, in case an updating process fails.
Email notifications and alerts play a crucial role in maintaining the health of your server.
Read more: I’ve written a detailed guide on configuring Postfix to use an external SMTP relay service. Be sure to check it out!
Rebooting
Now, let’s give the server a little reboot to make sure everything takes effect.
Use the following command to reboot:
sudo reboot
Now, all changes should be applied.
=== 1. DOCUMENT MACHINE INFO ===
Go to the specific [[homelab_assets|page for the machine]] (create it from the [[:new_machine_template|new machine template]] if it doesn't exist) and update it for each step that follows.
=== 2. LOGIN TO SERVER AND RUN SYSTEM UPDATES ===
ssh root@[server_ip]
apt update && apt upgrade -y
=== 3. RECONFIGURE NANO KEY BINDINGS (TO USE STANDARD SHORTCUTS) ===
wget -c https://raw.githubusercontent.com/don-ferris/bash-scripts/main/fixnano.sh && bash fixnano.sh
Go to the bottom of the file, uncomment the lines for the key bindings that make more sense.
=== 4. ASSIGN A STATIC IP ADDRESS ===
([[https://www.linuxtechi.com/static-ip-address-on-ubuntu-server|https://www.linuxtechi.com/static-ip-address-on-ubuntu-server]]) \\
Get name of ethernet interface:
ip a
Scan for IP addresses on local segment (optional - to insure that you don't try to use an IP address that's already in use.
sudo arp-scan --localnet --numeric --ignoredups | grep -E '([a-f0-9]{2}:){5}[a-f0-9]{2}'
//NOTE: That command takes a little while to run.//
Open the network interface configuration file:
nano /etc/network/interfaces
Look for (eth0 may not be the ethernet internet face name; it could be something different like enp1s0. )
iface eth0 inet dhcp
Edit (replacing 'dhcp' with 'static' then adding the additional lines) as follows:
iface eth0 inet static
address 10.1.1.111
netmask 255.255.255.0
gateway 10.1.1.1
dns-nameservers 1.1.1.1
dns-nameservers 8.8.8.8
Reboot:
reboot now
The ssh connection will be closed. Wait a minute or so then login using the new IP address.
=== 5. CHANGE HOSTNAME ===
//Unless the hostname was set as desired during OS install//
sudo hostname [new hostname]
exit
and reestablish SSH connection:
ssh root@[ip_address]
=== 6. ENABLE AUTOMATIC UPDATES ===
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
=== ===
=== 7. CREATE SYSTEM USER AND GIVE SUDO PERMISSIONS ===
//Unless the system user was created as desired during OS install//
adduser [username]
usermod -aG sudo [username]
Switch to the new user account…
su [username]
=== 8. DOWNLOAD AND SETUP ALIASES ===
wget https://raw.githubusercontent.com/don-ferris/bash-scripts/main/.aliases && source .aliases && alias
Review aliases
alias
====== HARDEN SERVER/SECURE SSH ======
=== 9. CHANGE SSH PORT ===
//This is a minor, and probably unnecessary step since I probably don’t need any security beyond using public/private RSA key pairs but there’s no reason not to add any extra layer of security, no matter how trivial.//
ssh [username]@[server_ip]
sudo nano /etc/ssh/sshd_config
Uncomment the line that says “Port 22” and change 22 to a random 4 or 5 digit port number. Document it.
=== 10. DISABLE IPV6 ===
//As above, probably not necessary; just a minor extra layer of security…// While still editing /etc/ssh/sshd_config - or
sudo nano /etc/ssh/sshd_config
Uncomment “[[:addressfamily|AddressFamily]]” line and change “any” to “inet” Save and exit Restart SSH daemon
sudo systemctl restart sshd
=== 11. ENABLE PUBLIC/PRIVATE KEY PAIR (run from main server) ===
Create public/private key pair //for posterity - skip this step; it's already been done//
mkdir ~/.ssh && chmod 700 ~/.ssh
logout
ssh-keygen -b 4096
(Enter to accept default location; skip passphrase)
Copy ssh key to new server
cd ~/.ssh && ssh-copy-id -p [port#] [user]@[server_ip]
Test the new passwordless login:
ssh -p [port#] [user]@[server_ip]
Copy key from iPad (using Termius) and test login
=== 12. DISABLE ROOT LOGIN ===
sudo nano /etc/passwd
Find and go to root user line (should be the first line) and change “/bin/bash” (at end of line) to “/bin/nologin”\\
Save and exit
sudo nano /etc/ssh/sshd_config
Find “[[:permitrootlogin|PermitRootLogin]]” line and change “yes” to “no” //Technically, this is already covered by changing root’s shell to /bin/nologin but what the heck…// Uncomment the lines "MaxAuthTries" and "MaxSessions"
=== 13. DISABLE PASSWORD LOGIN (use keys only) ===
While still editing /etc/ssh/sshd_config - or…
sudo nano /etc/ssh/sshd_config
Find “[[:passwordauthentication|PasswordAuthentication]]” line, uncomment it, and change “yes” to “no” Save and exit Restart SSH daemon
sudo systemctl restart sshd
***IMPORTANT:*** Test - //before logging out// - to verify that everything works properly by logging into the server in a new terminal window. (If there’s a problem, I need troubleshoot and fix while you’re still logged in on the other terminal window.)
ssh [username]@[server_ip] -p [port]
=== 14. SETUP Fail2ban (LOCKOUT IPs AFTER MULTIPLE FAILED CONNECTION ATTEMPTS ===
sudo apt install -y fail2ban
sudo bash -c 'echo "ignoreip = 10.1.x.x"> /etc/fail2ban/jail.d/00-sshd.conf'
sudo bash -c 'echo "port = [custom SSH port]">> /etc/fail2ban/jail.d/00-sshd.conf'
sudo bash -c 'echo "findtime = 1m">> /etc/fail2ban/jail.d/00-sshd.conf'
sudo bash -c 'echo "maxretry = 5">> /etc/fail2ban/jail.d/00-sshd.conf'
sudo bash -c 'echo "bantime = 10m">> /etc/fail2ban/jail.d/00-sshd.conf'
sudo systemctl enable fail2ban (authenticate 4 times)
sudo systemctl start fail2ban
systemctl status fail2ban
Check jail status (any time)…
sudo fail2ban-client status sshd
=== 15. CHECK PORTS & ENABLE/CONFIGURE FIREWALL ===
Review open ports:
sudo netstat -tulpn | grep LISTEN
Look over the listed ports. You’ll see 0.0.0.0:[custom SSH port #] (the one you setup above). Google for information on any open ports that you don’t recognize.
Install and enable UFW firewall
sudo apt install -y ufw
Open port for SSH logins:
sudo ufw allow [custom SSH port#]
sudo ufw enable
sudo ufw status
(review output)
Switch to a different/new terminal window and confirm ability to login
=== 16. DISABLE PING ===
sudo bash -c 'echo "net.ipv4.icmp_echo_ignore_all=1">> /etc/sysctl.conf'
sudo bash -c 'echo "net.ipv6.icmp.echo_ignore_all=1">> /etc/sysctl.conf'
apply the changes:
sudo sysctl -p
test by trying to ping from your workstation
=== 17. Check AppArmor Status (install as necessary) ===
sudo apparmor_status
[[https://www.howtogeek.com/118222/htg-explains-what-apparmor-is-and-how-it-secures-your-ubuntu-system/|https://www.howtogeek.com/118222/htg-explains-what-apparmor-is-and-how-it-secures-your-ubuntu-system/]]
=== 18. RUN SYSTEM UPDATES ===
sudo apt update && sudo apt upgrade -y
=== 19. INSTALL DOCKER AND DOCKER-COMPOSE ===
(Also installs Python3)
sudo apt install -y docker.io && sudo docker version
sudo apt install -y docker-compose && sudo docker-compose version
sudo groupadd docker && sudo usermod -aG docker $USER
Restart the server then log back in to test Docker (and no-sudo)
docker run hello-world