The first host, which must have a static IP, runs authentication and a VPN behind a reverse proxy, along with routing traffic to other notes. Currently, Authentik is used for authentication, Headscale is used for the VPN, and Caddy is used to reverse proxy. To set up this host, follow the steps below.
- Initial setup
- Restic setup (w/ cronjobs for
backup.shandremove-old.sh) - Run containers (Caddy and Authentik must be the first and second, respectively)
- Caddy-ingress
- Edit
hostmap.jsonto include the domain name and any subdomains that will be used - Generate a
caddy-ingress.jsonfile usingreload-caddy-json.sh - Bring up the ingress container
- Edit
- Caddy-docker-proxy
- run
docker network create cdpbefore bringing the container up
- run
- Authentik
- after bringing up authentik, create a user for yourself and another for
servers - create a
headscalarsgroup and add any users that should be able to access theheadscaleserver - create an OIDC provider, then create an application for
headscaleusing that provider
- after bringing up authentik, create a user for yourself and another for
- Headscale
- update the
.envfile with the OIDC provider and application details, as well as the domain name and other details
- update the
- Static-file-server
- Uptime Kuma
- Caddy-ingress
- Tailscale setup
Subsequently, as many nodes as desired can be added, with or without static IPs. To set up a worker node, follow the steps below.
- Initial setup
- Restic setup (w/ cronjobs for
backup.shonly) - Tailscale setup + join the network
- Run containers
- Caddy (use caddy-docker-proxy here)
- run
docker network create cdpbefore bringing the container up
- run
- Any subdomains that will be used must be added to the
hostmap.jsonfile on the auth host, and thecaddy-ingress.jsonfile must be regenerated and loaded usingreload-caddy-json.sh
- Caddy (use caddy-docker-proxy here)
If on a VPS with an automatically created user, you can optionally pick a new username as desired:
export NAME=avirutNext, create a new user with the same username as the automatically created user, add it to the sudo group, and copy over the SSH keys from the automatically created user:
sudo adduser $NAME
sudo usermod -aG sudo $NAME
sudo mkdir /home/$NAME/.ssh
sudo chmod 700 /home/$NAME/.ssh
sudo cp ~/.ssh/authorized_keys /home/$NAME/.ssh/authorized_keys
sudo chown -R $NAME:$NAME /home/$NAME/.ssh
sudo chmod 600 /home/$NAME/.ssh/authorized_keysFinally, SSH in with the new username and delete the automatically created user:
sudo deluser --remove-home <automatically created user>Set the timezone as appropriate:
sudo timedatectl set-timezone America/Chicago
timedatectlNext, install Docker by following the official instructions.
Complete the suggested post-installation steps:
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp dockerTest docker by running the hello-world container:
docker run hello-worldDownload and install Tailscale from the official website. Login with:
sudo tailscale up --login-server https://hs.${DOMAIN}Complete the printed steps to authorize the device.
For Docker swarm to work, certain ports must be open on all hosts. First, ensure that any swarm hosts with managed network ingress rules (e.g., on Oracle Cloud) have the appropriate ports open through the web GUI. These ports are:
- 2377/tcp
- 7946/tcp
- 7946/udp
- 4789/udp
- 2376/tcp
Both above and below, we can open hosts only to the tailnet IP range, i.e., 100.64.0.0/10.
Then, on all swarm hosts, use firewalld to edit iptables:
sudo apt install firewalld
sudo systemctl enable firewalld
sudo firewall-cmd --permanent --zone=public --add-port=2377/tcp
sudo firewall-cmd --permanent --zone=public --add-port=7946/tcp
sudo firewall-cmd --permanent --zone=public --add-port=7946/udp
sudo firewall-cmd --permanent --zone=public --add-port=4789/udp
sudo firewall-cmd --permanent --zone=public --add-port=2376/udp
sudo firewall-cmd --reloadNext, initialize the swarm:
docker swarm init --advertise-addr <tailnet IP>Finally, add the other hosts to the swarm:
docker swarm join-token worker # get the token from the swarm managerRun the command printed above on other hosts, adding in --advertise-addr <tailnet IP>.
Create a Docker overlay network for the swarm:
docker network create --driver overlay --attachable --subnetIf you see an error that looks like:
docker: Error response from daemon: error creating external connectivity network: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i docker_gwbridge -j RETURN: iptables: No chain/target/match by that name.
Then, try restarting Docker:
sudo systemctl restart docker