So to start we need a hosted server, I’m using a virtual private server from Linode, but any suitable hosting provider will do. Linode includes a number of Operating Systems you can install with one touch, and I’m using their Debian 9 image, so installing Debian is outside the scope of this guide. Our first steps once the server is built should be to make sure that it is reasonably secure, so first turn off access to the root user over ssh using a password (I’m not happy that the default setting has this set to yes, but given the base image doesn’t include any none system user accounts it’s a compromise) by editing /etc/ssh/sshd_config and changing the line

PermitRootLogin yes

to

PermitRootLogin no

and restart the ssh daemon

service ssh restart

Then add a user so that you can get onto the server without having to login as root.

useradd user

This will prompt you for the new user’s password, this should be a good strong password, I suggest using a password manager for this, I use KeePass (also you don’t have to use “user” as the username, that’s just an example).

Now is a good time to install some packages for security, fail2ban to stop our user password being cracked by brute forced, iptables to protect us from opening services unexpectedly, and iptables-persistent to allow the rules we set to persist over reboots.

apt-get install fail2ban iptables iptables-persistent

The default settings for fail2ban on debian protect ssh, but we will add new settings later, iptables default settings are quite permissive however so these will need changing. The following commands will set what I expect to be a reasonably secure set of rules, blocking lots of incoming and outgoing network connections we don’t want, whilst allowing those that we do.

iptables -F
ip6tables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT DROP
iptables -A OUTPUT -o eth0 -p tcp -m state --state ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp -m state --state ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -o eth0 -p tcp -m state --state ESTABLISHED -j ACCEPT
ip6tables -A INPUT -i eth0 -p tcp -m state --state ESTABLISHED -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
ip6tables -A OUTPUT -p ipv6-icmp -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT
iptables -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
ip6tables -A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT
ip6tables -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
iptables -A OUTPUT -p udp -o eth0 --dport 123 -j ACCEPT
iptables -A INPUT -p udp -i eth0 --sport 123 -j ACCEPT
ip6tables -A OUTPUT -p udp -o eth0 --dport 123 -j ACCEPT
ip6tables -A INPUT -p udp -i eth0 --sport 123 -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -o eth0 -p tcp --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -o eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -o eth0 -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
ip6tables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
ip6tables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
ip6tables -A INPUT -i eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6

This will clear the current rules, and set the default action for incoming and outgoing connection to DROP, so if we don’t allow it the connection doesn’t happen. We allow some basics like connections that are already established, internal loopback connections, DNS and NTP requests going out and responses coming back over UDP, and DNS requests over TCP going out. We then allow the server to make HTTP and HTTPS requests, which we need for package management, and allow SMTP connections out, as we will probably want to allow this server to send emails, we also allow ssh conections out so that we can push to other git repositories if we need too. Finally we allow incoming connections to SSH HTTP and HTTPS, which will all be used for hosting our Git Repository server, and set these rules to be persistent.

Because we built our server from an image provided by our hosting provider we need to ensure that everything is up to date.

apt-get update
apt-get upgrade

Up till now we have been logged in as root, and run all our commands as root, but once we log off we cannot log back in as root, we saw to that earlier. We can log in as our user, and use the command su to escalate our session to root, but that isn’t the most secure way to manage our server, so next we need to install sudo, and configure it to allow our user to run commands as root.

apt-get install sudo
usermod -aG sudo user

Under a default debian install this will install sudo, create the sudo group, and give permission to that group to use sudo to run commands as root. We are then adding our user to the sudo group. Next time you log in you will be able to use sudo to run commands as root. (substitute “user” for the username you created earlier)

Now that we have everything up to date, and an unprivileged user now is a good time to log off, and restart the server to make sure all the running processes are using the up to date packages, this is an important step if their were kernel updates.

shutdown -r now

This will restart the server, and log us off. After a couple of minutes you should be able to ssh to the server as the user we have set up, and granted sudo rights too.

We now have what should be a reasonably secure base to start building our git server.