Absurd: Hosting at Home with Argo Tunnels

20220414

I have in the past covered both setting up and hosting WordPress on your own, and I have covered hosting from home. Now, let's do something a little more interesting. Hosting at home can be a less than pleasing experience. You may need a DynDNS service. Your ISP may not allow serving from home. You may not be comfortable opening the ports to your home network (who could blame you). There is a solution to all of these problems: Cloudflare's Argo Tunnels. This would also apply to a business that wants to make some site or service available on the internet without opening ports, not just nerds at home.

Where do we start? At Cloudflare, of course. If you do not yet have an account, create one. You then need to "Add Site" after which a new screen shows up, and you will need to enter a registered domain name (not a subdomain). You will then have the option to select a pricing tier. As of this writing, the free tier is at the bottom of the page. For Argo Tunnels to work, you will need to transfer your DNS to Cloudflare. You do not need to transfer the domain name registration, just the location of your DNS service. Cloudflare's nameservers are:

addyson.ns.cloudflare.com
aragorn.ns.cloudflare.com

With DNS setup, we can proceed to the more Linuxy side of things. The tool for this process is cloudflared. I use aarch64 most of the time, so these are arm64. If you use an Intel or AMD processor, change the arm64 to amd64.

wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb
sudo dpkg -i cloudflared-linux-arm64.deb

The next thing to do is login to Cloudflare with this tool:

cloudflared tunnel login

Depending upon how things are setup on your computer, you may then have a web browser window open with an option to select a domain for which the tunnel needs to be authoritative. If not, copy and paste the URL that the command provides you. Once the tunnel is associated with both your Cloudflare account and a domain, we have to configure things.

We need to create the first tunnel. You can really name the tunnel whatever you want. I actually use an acronym of the domain used with the tunnel.

cloudflared tunnel create awtf

You should get both an ID and a patch to a credentials file. Both of these are important. In the $HOME/.cloudflared directory, you should now have a cert.pem file. Copy that with a new name specific to the json

cp $HOME/.cloudflared/cert.pem $HOME/.cloudflared/the-super-long-id-number.pem

Now let's make the config directory

sudo mkdir /etc/cloudflared
sudo touch /etc/cloudflared/config.yml
sudo vim /etc/cloudflared/config.yml

Within that file you will want something similar to the following

tunnel: the-super-long-id-number
credentials-file: /home/user/.cloudflared/the-super-long-id-number.json
origincertpath: /home/user/.cloudflared/the-super-long-id-number.pem
  ingress:
   - hostname: domain.com
     service: http://localhost:80
   - hostname: www.domain.com
     service: http://localhost:80
   - service: http_status:404

Now we need to set the DNS entries for this

cloudflared tunnel route dns awtf domain.com
cloudflared tunnel route dns awtf www.domain.com

Now, assuming that all steps completed successfully, your site should be live. Cloudflare will handle adding TLS to the public site. If you want to encrypt the communication over the tunnel as well, you can download a certificate for that purpose from Cloudflare in your dashboard. This may help with certain applications where the protocol (http/https) is hard set.

If you only have the one domain, then you're basically done.

cloudflared tunnel run

If you have more domains you want to serve using tunnels... let's move some stuff.

sudo mv /etc/cloudflared/config.yml /etc/cloudflared/domain.com.yml
sudo rm -f $HOME/.cloudflared/cert.pem

Now, you redo the tunnel login and select the other domain, create your additional named tunnel, and prepare for the config

cloudflared tunnel login
cloudflared tunnel create arfcom
cp $HOME/.cloudflared/cert.pem $HOME/.cloudflared/the-super-long-id-number.pem
sudo touch /etc/cloudflared/config.yml
sudo vim /etc/cloudflared/config.yml

Let's make that config

tunnel: the-super-long-id-number
credentials-file: /home/user/.cloudflared/the-super-long-id-number.json
  origincertpath: /home/user/.cloudflared/the-super-long-id-number.pem
    ingress:
     - hostname: example.com
       service: http://localhost:80
     - hostname: www.example.com
       service: http://localhost:80
     - service: http_status:404

Then we need to map the DNS

cloudflared tunnel route dns arfcom example.com
cloudflared tunnel route dns arfcom www.example.com

Then we go ahead and clean things up again

sudo mv /etc/cloudflared/config.yml /etc/cloudflared/example.com.yml
sudo rm -f $HOME/.cloudflared/cert.pem

Now, with multiple domains and tunnels, starting your argo tunnels isn't as striaght forward, but it is still easy. I wrote a script to help with starting and stopping tunnels when you have multiple domains, as the standard systemd service won't do it. I call this argoctl.

#!/bin/bash
COUNT=0
declare -A DATA
for FILE in $(cd /etc/cloudflared; ls -1); do
  ID=$(grep tunnel /etc/cloudflared/$FILE | awk '{print $2}')
  DATA[$COUNT]="$ID"
  ((COUNT++))
  DATA[$COUNT]="$FILE"
  ((COUNT++))
done
case $1 in
  start)
    for (( i=0 ; i<$COUNT ; i++ )); do
      CN=$(echo $(( i + 1 )) )
      exec /usr/bin/cloudflared --no-autoupdate --config /etc/cloudflared/${DATA[$CN]} tunnel run ${DATA[$i]} &
      ((i++))
      sleep 10s
    done
  ;;
  stop)
    sudo killall -9 cloudflared
  ;;
  restart)
    $0 stop
    $0 start
  ;;
  status)
    ps -ef | grep cloudflared | grep -v grep
  ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
  ;;
esac
exit 0

With this in place and following these steps you should be able to start an arbitrary number of tunnels with an arbitrary number of domains as easily as argoctl start.

⇠ back

© MMIX - MMXXII, absurd.wtf

Licentiam Absurdum