-
Notifications
You must be signed in to change notification settings - Fork 0
Home Server Setup
This guide details how to set up a server at home to act as the Land Server. (see System Architecture) The main goal is to get a server with a public IP address and SSH access running from your home.
In the long term, it is safer and more stable to use a proper service like AWS EC2 or Microsoft Azure.
To run a home server, you will need to use a computer and leave it at home turned on 24/7. I used an old computer and hooked it up directly to my router using an ethernet cable.
You will have to forward some ports so that they are
publicly available on the internet.
Go on your routers homepage, and forward the ports
as seen in the image:
Of course, if you add more services to the server,
you will have to forward whatever ports it uses.
You probably want to go into your DHCP settings and give your server computer a static IP address. In the image, you can I set mine to have IP address 192.168.1.140.
I know that Jenkins and SSH only use TCP. However if you're unsure, you can always just set the protocol to "both" in order to forward TCP and UDP traffic.
I had to internally use a "dummy" port of 6666 for SSH. For some reason when I use the default port 22, I am not able to open new SSH connection as a client from within the server. Externally, the server is still accessible via port 22 however, since the input port is set to 22.
The "Application Name" column is useful to help you remember why you forwarded a certain port. You don't actually need to fill it out for it to work.
Ignore the "Synergy" line which is forwarding port 27015, it's for a videogame.
I decided to host the server inside a VM so that I could use a fresh debian instance to act as the server, as well as isolate the server from my home network.
First, install virt-manager:
sudo apt-get install virt-manager
virt-manager is a VM manager with a GUI.
I then downloaded a debian 10 image, and created a VM from this using virt-manager.
Click the top left to create a new VM. (I already have a machine "debian10-sailbot" running)
Select your debian image. It should end with .iso
Select the amount of RAM and disk space you want. I chose 1GB RAM and around 20GB of disk space.
Once you are done getting the VM set up and running, you will have to leave virt-manager running 24/7 if you want the server to be up 24/7. You can take the server "down" by simply pausing or stopping the VM.
The server is running inside a VM. There is actually another virtual NAT
which the VM is hiding behind.
This virtual NAT exists on your computer. You will have to forward the ports
again so that they are available inside the VM.
The first step is to give you VM a static IP address.
Do this by running sudo virsh net-edit default
(assuming
the network you are using in virt-manager is called default. It should
be if you didn't mess with it). Modify the "ip" section as follows:
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
<host mac='52:54:00:19:5b:6e' name='debian10-sailbot' ip='192.168.122.2'/>
</dhcp>
</ip>
The "host mac" you should change to match the mac address given to your system (this can be found
in the virt-manager), and the name should also match. Give it an IP address that falls inside the
DHCP range.
Here's how to find the mac address (hint: click on the VM and click "open". Then click the "i" tab in the top left):
The name of the vm you can just read off the main menu:
Now that your VM has a static IP address, you have to forward the required ports to the VM.
Edit/create the file /etc/libvirt/hooks/qemu
. This is a
script which runs when you start/stop the VM.
Change the text below so that it has the name of the VM (same one you used in virst net-edit default
)
and it has the correct GUEST_IP (same one you gave it when you ran virst net-edit default
).
Place the text below into the file /etc/libvirt/hooks/qemu
#!/bin/bash
if [ "${1}" = "<PUT MACHINE NAME HERE>" ]; then
# Update the following variables to fit your setup
GUEST_IP=<PASTE IP ADDRESS OF VM HERE>
# I have to use ports other than 22
# or else for some reason I can't start
# new SSH sessions from inside the VM
GUEST_SSH_PORT=6666
HOST_SSH_PORT=6666
GUEST_JENKINS_PORT=8080
HOST_JENKINS_PORT=8080
GUEST_VPN_PORT=655
HOST_VPN_PORT=655
if [ "${2}" = "stopped" ] || [ "${2}" = "reconnect" ]; then
# When the vm is stopped, delete all our rules
/sbin/iptables -D FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_SSH_PORT -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp --dport $HOST_SSH_PORT -j DNAT --to $GUEST_IP:$GUEST_SSH_PORT
/sbin/iptables -D FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_JENKINS_PORT -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp --dport $HOST_JENKINS_PORT -j DNAT --to $GUEST_IP:$GUEST_JENKINS_PORT
/sbin/iptables -D FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_VPN_PORT -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp --dport $HOST_VPN_PORT -j DNAT --to $GUEST_IP:$GUEST_VPN_PORT
/sbin/iptables -D LIBVIRT_FWO -i virbr0 -s $GUEST_IP -d 192.168.1.0/24 -j DROP
/sbin/iptables -D LIBVIRT_FWO -i virbr0 -s $GUEST_IP -d 192.168.1.1 -m state --state RELATED,ESTABLISHED -j ACCEPT
/sbin/iptables -D INPUT -i virbr0 -s $GUEST_IP -d 192.168.1.0/24 -j DROP
fi
if [ "${2}" = "start" ] || [ "${2}" = "reconnect" ]; then
# Forward SSH port
/sbin/iptables -I FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_SSH_PORT -j ACCEPT
/sbin/iptables -t nat -I PREROUTING -p tcp --dport $HOST_SSH_PORT -j DNAT --to $GUEST_IP:$GUEST_SSH_PORT
# Forward Jenkins port
/sbin/iptables -I FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_JENKINS_PORT -j ACCEPT
/sbin/iptables -t nat -I PREROUTING -p tcp --dport $HOST_JENKINS_PORT -j DNAT --to $GUEST_IP:$GUEST_JENKINS_PORT
# Forward VPN port
/sbin/iptables -I FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_VPN_PORT -j ACCEPT
/sbin/iptables -t nat -I PREROUTING -p tcp --dport $HOST_VPN_PORT -j DNAT --to $GUEST_IP:$GUEST_VPN_PORT
# The following 3 lines will (hopefully) prevent all
# communication between debian10-sailbot and anything else
# on the home network, including the host machine.
# You can test this by using nmap on debian10-sailbot
# to scan the local network. It should return 0 hosts found.
# Do not allow debian10-sailbot to communicate with anyone on the home network
/sbin/iptables -I LIBVIRT_FWO -i virbr0 -s $GUEST_IP -d 192.168.1.0/24 -j DROP
# UNLESS its communicating with the router, and even then only if its part of an already
# established connection.
/sbin/iptables -I LIBVIRT_FWO -i virbr0 -s $GUEST_IP -d 192.168.1.1 -m state --state RELATED,ESTABLISHED -j ACCEPT
# This line is needed to prevent communication with the host machine.
/sbin/iptables -I INPUT -i virbr0 -s $GUEST_IP -d 192.168.1.0/24 -j DROP
fi
fi
In summary, the required ports are being forwarded once from your physical router to your physical machine, and a second time from your physical machine to your VM. This allows services running on these ports to be publicly visible. The qemu script above actually does more than just forwarding, it sets up the iptables on the computer (NOT the VM) so that the VM cannot connect to other devices on your home network. In addition, it prevents the VM from opening a new connection with the gateway (ie, your router). All of this is done to improve security.
If you are stuck, visit these pages for help:
https://wiki.libvirt.org/page/VirtualNetworking
https://wiki.libvirt.org/page/Networking
My debian iso had the option to set up an SSH server on install.
However, if yours doesnt, or you missed that option,
you will need to install the open ssh server:
sudo apt-get install openssh-server
Use SSH keys instead of passwords. Passwords can be brute forced.
Edit
/etc/ssh/sshd_config
and set the following parameters (some may just need to be uncommented):
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
Also disable login as root:
PermitRootLogin no
Make sure to edit the .ssh/authorized_keys file to include you public SSH key. You can also ask other people for their keys and add them to this file if you want them to have access. In general, each line of this file contains a public key. You can read more about the file here
Also, I had to set the server to use a port other than 22.
For some reason, if I set the port to 22, I was not able
to SSH from the server to other locations.
Again, in /etc/ssh/sshd_config
, add/uncomment a line:
Port 6666
to set the port to 6666 for example.
At this stage, you should be able to make sure your home server is running.
Make sure the computer is on and the VM is running. For better connectivity
I make sure it is connected via an ethernet cable.
Then find you public ip address (google "whats my IP?"), and try the following command (on a different computer):
ssh <username>@<public ip>
Use whatever username you set up for the server.
Hopefully this works. If it hangs for a while and fails to connect, you might have not forwarded the ports correctly. Make sure you forwarded them on your router (by accessing the routers web page), and you forwarded them from the computer to the VM (by creating the /etc/libvirt/hooks/qemu script script). Also make sure you're forwarding to the correct IP address on both the router and to the VM.
If you get an error about rejected pubkey, you need to add your public key to the .ssh/authorized_keys file. Of course, you can't SSH in so you will have to manually go to the physical computer and do it there.
The main point of this guide is to just get a public server running with SSH access. Ill quickly go over setting up the VPN (tinc) and Jenkins.
To set up tinc, first install it:
sudo apt-get install tinc
Then, you can follow this guide to set up the configuration files and make tincd run on boot:
https://www.digitalocean.com/community/tutorials/how-to-install-tinc-and-set-up-a-basic-vpn-on-ubuntu-18-04
You will have to add some other "clients" to the VPN. Once theyre added, you should be able to communicate with
them via the "tun0" interface. They should work as if they are on the same local network, for example you can
SSH to them (assuming they have an ssh server running) without having to forward any ports or know their public IP
address.
You can install jenkins by following this guide: https://www.jenkins.io/doc/book/installing/
I skipped all the docker stuff and just ran
wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb https://pkg.jenkins.io/debian-stable binary/ > \
/etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins
If I remember correctly, after this Jenkins would automatically run on boot (might have to reboot, cant remember).
You can go to <public ip address>:8080
to go to the Jenkins page. The first time you go to this page,
you will need the generated admin password. You can get it from
/jenkins/home/secrets/initialAdminPassword
Use this password once on the initial webpage to get past the setup. The setup should involve creating a Jenkins
user. Make sure to write down the name/password you use for Jenkins, and you should be good to go.
ip link add veth0 type veth peer name veth1
ip addr add 10.0.1.1/24 dev veth0
ip addr add 10.0.1.2/24 dev veth1
ip link set veth0 up
ip link set veth1 up
After this, you can use virtual ethernet ports veth0/1.