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
.