For an (ethical) scraping project I found that my low-volume scraper was working from my laptop but was being blocked by Cloudflare when I attempted to run it in GitHub Actions, presumably because the GitHub Actions IP range was disallowed.
I figured out how to use Tailscale to allow GitHub Actions to transparently proxy traffic via my home network - using a Tailscale exit node running on an Apple TV.
Configure the Apple TV as a “home hub”. To do this I had to reconfigure my Apple TV to have a default iCloud account - we had previously configured it with no default account and two different associated accounts. I got various unhelpful error messages until I finally figured this out. The Apple documentation wasn’t quite helpful enough here either.
Configure the Apple TV to work as a Tailscale exit node. Here’s the Tailscale guide to doing this - you configure it in the Apple TV app (“Run as Exit Node”) and then separately in the Tailscale web console. The hardest part here was finding the option there - it was tucked away in the ”…” menu against the Apple TV machine under “Edit route settings”.
The great thing about an Apple TV for this is that it’s an existing low power device that is always on and connected to the internet. A Raspberry Pi or similar would be another good choice.
As far as I can tell this needs the “Devices: Core” scopes configured for both read and write access, plus a tag. It also needed read/write access for Auth Keys.
Here’s how I configured that device access:
Plus I selected the read and write checkboxes for “Auth Keys”.
This took a lot of experimenting, but eventually I figured out this recipe which works. I had to set three repository secrets first:
TAILSCALE_OAUTH_CLIENT_ID - for the OAuth client I created earlier
TAILSCALE_OAUTH_SECRET - also for that client
TAILSCALE_EXIT_NODE - I was hoping I could set this to the name of my Apple TV within Tailscale, but that didn’t seem to work - here’s a relevant Tailscale issue thread. Setting it to the Tailscale IP address of that device - which starts 100.106.... - worked for me.
Using the exit node’s name instead of an IP address#
Bill Mill gave me some great feedback on this article, including sharing this example of running a second command to set the exit node using its name rather than the IP address I describe above:
timeout 5m sudo -E tailscale set --exit-node=apple-tv --exit-node-allow-lan-access=true
I had to look up that sudo -E option - it’s short for --preserve-env and causes the user’s current environment to be inherited by the command that is running with elevated privileges.