it is a common task to have to forward ports, but in america especially ISPs block ports, or for example university students often can't forward ports due to being behind multiple NATs. here's how you solve this problem, and make your own git server, the easy way and the hard way (the way i did it)

the easy way [#]

just use a reverse SSH tunnel

the hard way [#]

using a reverse SSH tunnel is pretty easy, but in my experience running a random daemon can be unreliable and isn't especially elegant. we are going to be reversing a wireguard vpn session instead.

  1. make a wireguard VPN server on your proxy host. pi-hole's guide is nice
  2. make a VLAN and have the wireguard client as the gateway using this 'official' guide. in my home network i have this Swiss VPN network
  3. configure your switches with the vlan tags as appropriate to your devices of choice, this will depend a lot on the switches you have, I like the TP Link TL-RP108GE as it is very cheap, has VLAN management and can be powered off PoE
  4. add the VLAN, e.g. with debian:
auto eth0.22
iface eth0.22 inet dhcp
  1. reboot or just get a fresh DHCP address
sudo dhclient -r
sudo dhclient
  1. configure the port forwarding in pfsense. As we don't have a proper 'site-to-site' setup (that's too complicated), all of our VPN client devices are behind a NAT so we need to configure port forwarding. my setup remaps the SSH port of the git server from 22 to 2222 on the other end, and klaus, the git web ui, is on port 81:

port forwarding to swiss VPN client

  1. it might be a good time to check that the reverse VPN tunnel works, SSH into the proxy server and try curl 10.99.0.2:81 and ssh 10.99.0.2 -p 2222 where 10.99.0.2 is the VPN client on the server. if the curl request returns some HTML and the ssh works then you've set it up correctly
  2. setup an nginx reverse proxy for web stuff, e.g. my configuration for klaus is:
server {
    server_name git.eda.gay;
    listen 80;

    location / {
        proxy_pass http://10.99.0.2:81;
    }
}
  1. then use certbot to get HTTPS if you want to
  2. 'forwarding' the SSH port is a little bit more difficult. git has to use port 22 unless you want to do client-side configuration for every client. what we are going to do instead is check if the user is git and if it is, forward the connection to the VPN client. we use a Match and a ForceCommand block in our sshd_config:
Match User git
    ForceCommand ssh -p 2222 git@10.99.0.2 $SSH_ORIGINAL_COMMAND

where the VPN client is 10.99.0.2 and port 2222. However doing it this way has some serious disadvantages. the authentication happens on the proxy not in on the git server. this is a problem since git servers like gitolite and others do a hook on the incoming SSH key to differentiate between different users. consequently, this setup basically only works with a single user. which is fine for me. if you did need to make a multi-user setup, you can instead make it call a script that pushes the SSH key to the git server, something like this