This is a basic collection of things I do when setting up a new headless ubuntu machine as a webserver. Following the steps below should give you a reasonable secure server with HTTP/2 support (including ALPN in chrome) and the fast NGINX server. I am happy to add things so leave a comment.
After creating the server (droplet on DigitalOcean) log in with
ssh root@[IP ADDRESS]Once inside the machine set a password for root:
passwdUpdate your package manager:
apt-get update
apt-get upgrade
apt-get dist-upgradeInstall fail2ban:
apt-get install fail2banInstall vim:
apt-get install vim vim-scripts vim-doc vim-latexsuite vim-gui-common vim-gnome vim-gtkCreate a new user:
useradd deploy
mkdir /home/deploy
mkdir /home/deploy/.ssh
chmod 700 /home/deploy/.sshGive the new user a sudo password:
passwd deployAdd your ssh key:
vim /home/deploy/.ssh/authorized_keys #add your public ssh key here, copy your public ssh key from your local with: `pbcopy < ~/.ssh/id_rsa.pub`, create a new one with `ssh-keygen -t rsa`
chmod 400 /home/deploy/.ssh/authorized_keys #permissions
chown deploy:deploy /home/deploy -R #ownerAnd add the user to the superuser group
visudoAdd into the file:
root ALL=(ALL) ALL
deploy ALL=(ALL) ALLDisable root login and password authentication
vim /etc/ssh/sshd_configEdit:
PermitRootLogin no
PasswordAuthentication no
AllowUsers deploy@(your-ip) deploy@(another-ip-if-any) #you can even whitelist IPs from where you connect from (optional)Restart the ssh service
service ssh restartNow test your login with the new user in a new shell:
ssh deploy@[ID ADDRESS]Install unattended-upgrades
sudo apt-get install unattended-upgradesEdit what is updated:
sudo vim /etc/apt/apt.conf.d/10periodicModify so you have:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";and specify what upgrades should be done:
sudo vim /etc/apt/apt.conf.d/50unattended-upgradesThe default here is often fine:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
};Now install logwatch:
(This will typically install postfix and ask you about your mail setup)
sudo apt-get install logwatchNow edit what to do with the logs. I usually have them send to my email to sort them into a folder there:
sudo vim /etc/cron.daily/00logwatchModify so you have something like (change [email protected] to your email):
/usr/sbin/logwatch --output mail --mailto [email protected] --detail highI like to disable /run/shm read/write privileges as they are not needed in a headless server:
sudo vim /etc/fstabAnd add the following line:
none /run/shm tmpfs defaults,ro 0 0Install rootkit detection with RKHunter and CHKRootKit:
sudo apt-get install rkhunter chkrootkitConfigure CHKRootKit:
sudo vim /etc/chkrootkit.confModify so you have:
RUN_DAILY="true"To run RKHunter execute the following command as often as you update apt-get:
sudo rkhunter --update(This will update it’s database and performe a check)
I like to change the shell to bash as that’s what I like.
sudo apt-get install csh
sudo chsh -s /bin/bash deploy(see after reconnect)
First make sure you have IPv6 enabled:
sudo vim /etc/default/ufwIt should say:
IPV6=yesThen make sure you are not locked out:
sudo ufw allow sshI would also usually do:
sudo ufw allow https
sudo ufw allow http
sudo ufw allow ftpThen enable the firewall:
sudo ufw enableAnd to make sure you have everything enabled and no useless ports open:
sudo ufw statusTo reload the firewall you can:
sudo ufw reloadAnd to see the log you do:
sudo grep UFW /var/log/syslogTo set your correct timezone:
sudo dpkg-reconfigure tzdataInstall the time protocol daemon
sudo apt-get install ntpNow as we all have moved to SSD servers we don’t need this anymore. :)
For legacy reasons:
get memory with `free -m`
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo sh -c 'echo "/swapfile none swap sw 0 0" >> /etc/fstab'sudo apt-get install vsftpdEdit the config:
sudo vim /etc/vsftpd.confModify so you have:
anonymous_enable=NO
write_enable=YESAnd restart your service:
sudo service vsftpd restart(connection via SFTP)
Install git if it isn’t already:
sudo apt-get install gitAnd set your account:
git config --global user.name "Your Name"
git config --global user.email "[email protected]"Install node and NPM:
sudo apt-get install nodejs
sudo apt-get install npmBecause there was a name clash in the package manager we have to add a symlink to get the node namespace working:
sudo ln -s /usr/bin/nodejs /usr/bin/nodeInstall your server of choice. NGINX is what I like:
sudo apt-get install nginxFor HTTP/2 to be supported you will need to check the version of NGINX and openSSL:
nginx -v
openssl versionNGINX needs to be at least 1.9.5 or above and OpenSSL needs to be at least 1.0.2 or above (for ALPN to work in chrome).
Create a symlink to get to your html folder quickly and give permission:
sudo ln -s /var/www/html/ /www
sudo chown deploy:deploy /var/www/html/ -RAnd edit the NGINX config:
sudo vim /etc/nginx/sites-available/defaultTo delete a page in vim just type :1,$d in the command prompt. I usually write the config locally and then just past it into vim. So: copy content, open file in vim, do :1,$d to delete contents, type i to set vim into insert mode, paste.
(I’ve attached my basic config that works for me below, note that this config assumes SSL and the cypher below)
To create a strong cypher:
sudo mkdir /etc/nginx/ssl/
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096(This takes some time)
Restart the server with the new config:
sudo nginx -s reloadInstall letsencrypts certbot because we want to add SSL to our website?
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx Now let's run the certbot
sudo certbot --nginx certonlySet up auto renewal. Open crontab:
sudo crontab -eAnd add the two following lines:
SHELL=/bin/bash # I like bash
# add timestamp to your log file for easier parsing
29 2 * * 1 date >> /var/log/letsencrypt-renewal.log 2>&1
# runs every Monday at 2:30AM, output is saved to /var/log/letsencrypt-renewal.log
30 2 * * 1 certbot renew >> /var/log/letsencrypt-renewal.log 2>&1
# restart the server 2:50AM
50 2 * * 1 /etc/init.d/nginx restart >> /var/log/letsencrypt-renewal.log 2>&1
# empty line at the end so cron doesn’t ignore the last commandThis will try to renew your certs every Monday night and restart NGINX while saving the log into /var/log/letsencrypt-renewal.log. (Check your log if you have issues with vim /var/log/letsencrypt-renewal.log)
Now test your SSL certs via: