These are not instructions for setting up a secure hosting platform - just notes for my setup specifically.
“Hub” of the Wireguard hub/spoke setup. This contains the main nginx reverse proxy for public-facing apps on kurtw.dev. Very little-to-no computation happens here - this is mostly for forwarding packets around. Also hosts the static index page for kurtw.dev. Hosted on a Basic / 512 MB / 1 vCPU
DigitalOcean droplet - the smallest availible (at the time of writing). Has a public IP, with ports 80 and 443 open and serviced by nginx.
local ip: 192.168.4.1
SSH access only availible through EC2 config page or through Wireguard - key required.
nginx config path: /etc/nginx/
wireguard config path: /etc/wireguard/
Packets for Minecraft and Factorio ports are forwarded over wireguard to the big box using iptables rules. Don’t use nginx for these, since they usually don’t use HTTP. See https://kb.jarylchng.com/i/linux-port-forwarding-through-a-vps-with-the-hel-z4FxEVf3KT_/
wg genkey | tee privatekey | wg pubkey > publickey
This is the equivalent of:
wg genkey > privatekey
wg pubkey < privatekey > publickey
If you’re doing this for the first time, also create a keypair for the server
/etc/wireguard
folder.[Interface]
# replace the N on the next line. Must be unique per-device
Address = 192.168.4.N/32
PrivateKey = [contents of the client's private key]
[Peer]
PublicKey = [contents of the server's public key]
# replace with the _publicly facing_ ip address of the server
Endpoint = YOUR_SERVER_IP:51820
AllowedIPs = 192.168.4.0/24
PersistentKeepAlive = 25
# this block is only needed once
[Interface]
# the address the server will appear as to clients
Address = 192.168.4.1/32
ListenPort = 51820
PrivateKey = [the server's private key]
# repeat this block for each new client
[Peer]
PublicKey = [the client's public key]
# the same N from before
AllowedIPs = 192.168.4.N/32
sudo systemctl restart wg-quick@INTERFACE_NAME.service
, where INTERFACE_NAME is the name of the file you placed in /etc/wireguard
/etc/nginx/sites-availible
server {
location ~ {
# fill in the ip and port of the server hosting the app. Multiple things can run on that server, they just need unique ports.
# ip of kurtserver1
proxy_pass http://192.168.4.7:82;
}
# replace the domain and subdomain
server_name wiki.kurtw.dev;
listen 80;
listen [::]:80; // ipv6
}
Note that the lines for ssl are missing - these will be added in the next step
4. Add SSL support: sudo certbot --nginx -d wiki.kurtw.dev
. A new block should appear in the above config file, and it should resemble this:
server {
server_name wiki.kurtw.dev; # managed by Certbot
listen 443 ssl;
listen [::]:443 ssl;
location ~ {
proxy_pass http://192.168.4.7:82;
}
ssl_certificate /etc/letsencrypt/live/wiki.kurtw.dev/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/wiki.kurtw.dev/privkey.pem; # managed by Certbot
}
server {
if ($host = wiki.kurtw.dev) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name wiki.kurtw.dev;
listen 80;
listen [::]:80;
}
Certbot should have made 3 changes to this file: replaces the previous listen
directives so that they listen for ssl, adds the config paths for the generated SSL certificate, and add a dummy listen 80;
block that redirects to https.
This provides SSL encryption to clients accessing the app, but data passed between the nginx bastion and the app server will be in plaintext! This is probably ok if the bastion and app server are communicating over wireguard, since data passed over wireguard is encrypted.
sudo ln -s /etc/nginx/sites-available/videos.kurtw.dev /etc/nginx/sites-enabled/videos.kurtw.dev
sudo nginx -s reload
Hosts most of the apps on kurtw.dev, including Nextcloud and this wiki, as well as Minecraft and Factorio servers. Does not have a publicly accessible IP, so any apps hosted here need aws_wg as a reverse proxy. For web apps, see Adding a new app w/ nginx. For games, see Proxying games
local ip: 192.168.4.7
You’ll want to do this before doing the nginx setup above.
0. Clone/create the project
docker-compose.yml
(or whatever you choose) to map the internal port 80 to a unique port