My Server Setup ⚙️
This article outlines the steps I take on any new server, to configure it for security, consistency and convenience. It is written specifically for Debian, but will also directly apply to derivatives (such as Ubuntu), and will likely be very similar for for other distros.
I am in the process of writing automation scripts to cover all of these steps, in the form of Ansible Playbooks.
This guide is split into 10 sections:
- System Update - Upgrade the OS and enable automated security updates
- System Setup - Specify hostname, add users, configure server time etc
- Configure SSH - Setup keys, configure sshd_config and set permissions
- Install Essential Software - Including git, vim, zsh, tmux, ranger etc
- Enable Firewall - Manage allowed inbound/ outbound connections with UFW
- Setup Intrusion Prevention - Protect from brute force attacks with Fail2Ban
- Configure Malicious Traffic Detection - Flag malicious packets with MalTrail
- Implement Security Auditing and Scanning - With ClamAV, Lynis and RKhunter
- Fetch Dotfiles for Vim, ZSH, Tmux etc to make SSH sessions more comfortable
- Final Steps - Optional items (Go, Rust, Node, Python, Docker, NGINX etc..)
System Update
Update the System and Packages
apt update
- Update system packagesapt -y upgrade
- Upgrade OSapt autoremove
andapt clean
- Remove locally downloaded deb packages and apt-get caches
Enable Unattended Upgrades
apt install unattended-upgrades
- Install package (if not already installed)dpkg-reconfigure --priority=high unattended-upgrades
- Enable automatic upgradesvi /etc/apt/apt.conf.d/50unattended-upgrades
to update the configuration
System Setup
Specify Host Name
sudo hostnamectl set-hostname [new-host-name]
- Set the machines host name- Add
127.0.0.1 [hostname]
into/etc/hosts
- Add host name to the hosts file
Add New Users
useradd -m [username] -c "[user full name]"
- Create a new user (-c
Allows an associated name or comment)passwd [username]
- Specify a password for new usersudo usermod -a -G sudo [username]
- Gives the user root privileges (only apply if needed)
Set the Server Time
sudo timedatectl set-timezone Europe/London
sudo vi /etc/systemd/timesyncd.conf
and add the address of the local NTP serversudo systemctl restart systemd-timesyncd.service
- Restart the time sync service
Configure SSH
Setup SSH Keys for Authentication
sudo apt install openssh-server
- Install OpenSSH Server on remote hostssh-keygen -t rsa -b 4096
- On the local system. Generates a new SSH key pair (enter a strong passphrase when prompted)ssh-copy-id root@[0.0.0.0]
- Uploads to the remote server, and update the hosts filechmod go-w ~ ~/.ssh ~/.ssh/authorized_keys
- On the remote host, updated permissionssudo ufw allow ssh
- If UFW is enabled, then allow SSH access
Next we're going configure a couple of SSH security essentials
vim /etc/ssh/sshd_config
- To open the SSH daemon's config file , and update:Protocol 2
# Only use SSH 2 ProtocolPermitRootLogin no
# Disable root SSH loginPasswordAuthentication no
# Disable password-based SSH loginCompression delayed
# Compression could be dangerous, only allow it once authenticatedMaxAuthTries 5
# Limit the maximum authentication attemptsPrintLastLog yes
# Display last login date for an extra check (should be default)PermitEmptyPasswords no
# Disallow empty passwords (Not relevant for SSH Keys, but still good to have)IgnoreRhosts yes
# Disallow access via rhosts, which is rarely used anymoreIgnoreUserKnownHosts yes
# Only trust the global known hosts listHostBasedAuthentication no
# Similar to rhosts, this is rarely usedPort 2200
# Set SSH access to a non-standard portStrictModes yes
# Prevent users from accidentally leaving their directories/ files as writableUsePrivilegeSeparation sandbox
# Prevent privilege escalationPubkeyAuthentication yes
# Public key authentication should be preferred (should be default)GSSAPIAuthentication no
# If you are not using GSSAPI authentication, this should be disabledKerberosAuthentication no
# If you are not using Kerberos authentication, this again should be disabledCiphers aes128-ctr,aes192-ctr,aes256-ctr
# Use FIPS 140-2 compliant ciphers, to avoid weak encryption algorithmsMACs hmac-sha2-256,hmac-sha2-512
# Use FIPS 140-2 Compliant MACs, to avoid weak cryptographic hashes
The SSH daemon must be restarted, in order for these config changes to take effect: sudo systemctl restart ssh
Protect SSH Host Keys
sudo chmod 0600 /etc/ssh/*key
- Set permissions for private keyssudo chmod 0644 /etc/ssh/*pub
- Set permissions for public keys
If your system stores keys in a different directory, you can find them with grep -i hostkey /etc/ssh/sshd_config
. You can list the permissions of keys with ls -l /etc/ssh/*key
(or *pub
for public keys)
Install Essential Software
Install Packages
sudo apt update
- Ensure the package list is up-to-datesudo apt install -y git vim tmux zsh ranger
- Install essentials: vim, git, tmux, ZSH and rangersudo apt install -y make curl
- Install utilitiessudo apt install -y fzf exa
- Install command line improvementssudo apt install -y ctags xsel glances fonts-powerline
- Install visual improvementssudo apt install -y clamav rkhunter lynis
- Install security audit toolssudo apt install -y neofetch figlet lolcat
- Optionally, install fun stuffsudo apt install python3-pip nodejs npm
- If needed, install compilers
Configure Firewall with UFW
sudo apt install ufw
- Install UFWsudo vi /etc/default/ufw
and setIPV6=yes
to use IPv6sudo ufw default deny incoming
andsudo ufw default allow outgoing
to deny all incoming traffic, and allow outgoingsudo ufw allow 2200/tcp
to for example, allow incoming SSH traffic on port 2200sudo ufw disable
andsudo ufw enable
(orsystemctl restart ufw
) to restart UFWsudo ufw status
- Check the current status
Whenever a new application is configured, UFW needs to be updated to allow incoming traffic to that port and protocol.
Intrusion Prevention with Fail2Ban
sudo apt install fail2ban
- Install Fail2bansudo cp /etc/fail2ban/jail.{conf,local}
- Copyjail.conf
tojail.local
sudo vi /etc/fail2ban/jail.local
- To edit the local config file, and add:ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
- with local IP addressesbantime = 1d
- Increase the ban time to 1 dayfindtime = 10m
- Time between each attemptmaxretry = 7
- Number of failures before IP is banned
sudo systemctl restart fail2ban
- Restart Fail2ban, for changes to take effectsudo systemctl status fail2ban
- Show the current status
The fail2ban-client
can also be used to interact with the Fail2ban service from the CLI
Malicious Traffic Detection with MalTrail
For systems that have services exposed to the internet, or for a firewall device that
Install MalTrail and dependencies
sudo apt install schedtool python-pcapy git
- SchedTool for better CPU scheduling, and Python for MalTrailgit clone https://github.com/stamparm/maltrail.git
- Get the MalTrail codecd maltrail
- Navigate into the directoru
Run MalTrail. There are two components, a sensor and a server.
sudo python sensor.py &
- Start the sensor (&
will run it in the background)python server.py &
- Start the server, in order to log results and allow access through a GUI
Access the GUI
- Navigate to
http://[ip]:8338
and enter username:admin
and password:changeme!
- To test things are working correctly, try
ping -c 1 136.161.101.53
or, for DNS capturingnslookup morphed.ru
- Results for both should display on the dashboard and in the logs:
/var/log/maltrail/
- To view today's logs, run
cat /var/log/maltrail/$(date +"%Y-%m-%d").log
- Results for both should display on the dashboard and in the logs:
Configure MalTrail's Settings
echo -n '[your-desired-password]' | sha256sum | cut -d " " -f 1
- Choose a strong password and hash itsudo vim /home/tech/maltrail/maltrail.conf
- Open the configuration file- Under
USERS
section, replace the currentAdmin:05a181f00c15...
withAdmin:[your-hashed-password]
- From within the
maltrail.conf
you can configure other settings for the server component pkill -f server.py && python server.py &
- Restart MalTrail
Security Scanning with ClamAV, Lynis and RKhunter
For security monitoring, I am using Lynis to audit general system config, ClamAV for detecting malware and rkhunter for checking for root kits.
Install Packages
sudo apt install -y clamav rkhunter lynis
- Install security audit toolssudo rkhunter --propupd
- Update rkhunter's file properties database
Run a System Audit
sudo lynis audit system
- Run a full security auditsudo clamscan / -r
- Scan for malwaresudo rkhunter -c --sk --rwo
- Check for rootkits (c for check, sk for skip keypress and rwo for report wanrings only)
These commands can also be put into an .sh
file, and run periodically as a scheduled cron job, sending results to your email.
Setup Dotfiles
git clone https://github.com/Lissy93/dotfiles.git --recursive
- Download my dotfilescd ./dotfiles
- Navigate to directory./install.sh
- Run the install script
Final Steps
Setup Welcome Banner
sudo cp ~/dotfiles/utils/welcome-banner.sh /etc/profile.d/motd.sh
- Copy welcome banner from utils to systemsudo chmod +x /etc/profile.d/motd.sh
- Update permissions for all users
Install NetData, for web-based resource monitoring
bash <(curl -Ss https://my-netdata.io/kickstart.sh) --stable-channel --disable-telemetry
- Install NetData- You will need to allow firewall access,
sudo ufw allow from [your-static-ip] to any port 19999
- If using a cloud platform (like AWS, Azure, GCP) then you may need specify an inbound port rule to allow access
Setup Glances
- Install:
sudo apt install glances
- To enable Glances to start up at boot time, run it as a service with
systemd
. See docs for more info - If you need to access Glances remotely, either VPN into your server (recommended), or setup a reverse proxy to the Glances web page, as per docs
Install Bpytop
sudo pip3 install bpytop --upgrade
Additional Tasks:
- If needed, Install Go Lang
- If needed, Install Docker