Expose HA to the internet via a cloud reverse proxy (fly.io) and a VPN (tailscale) for free (for now) without opening ports

This is a different take at exposing HA to the internet: rather than having a remote proxy in your LAN and punching holes in your router to have Internet getting inside your house, we’ll have the reverse proxy running into the cloud on a fly.io instance, that will communicate with your HA instance via a tailscale VPN.

Disclaimer: At time of writing, both fly.io and tailscale are startups looking at getting traction, so they offer generous free-tiered plan. As with all startups, they’ll likely need to cash-in at some point and reduce what they offer for free, or just disappear altogether.

Principle

  • Fly.io will run a docker container that contains a plain nginx reverse proxy doing one thing: redirecting to your HA instance
  • Tailscale is the VPN backbone: the container and your HA container will use it for communication. Due to its way of working, no LAN configuration is required.
  • Your external devices will connect securely to the container via a *.fly.dev hostname, that is provided by Fly and SSL secured by them.

Note: The docker image used is not specific to fly. It listens for anything on http 8080 and forwards it to the tailscale IP in parameters. So it can (normally) be reused on any cloud machine, provided DNS and certificate termination is done upfront.

Pros / Cons

Pros:

  • No fiddling with you local network configuration: tailscale is a P2P VPN based upon wireguard
  • Works with CGNAT
  • fly.io handles both SSL/TLS (via letsencrypt) and DNS for you, automatically, so you instantly have a https://my_ha.fly.dev endpoint
  • More secure: Nobody knows your actual public IP and nobody can get beyond your HA unless you want it to (or you blunder the tailscale configuration).
  • Relatively simple to implement through this guide

Cons:

  • See above: You might have to pay for this to work in the future
  • Although fly.io offers a generous free plan, you still have to register a credit card with them at signup time.
  • If someone gets access to the inner of your reverse proxy, they get access to your whole VPN.

Putting it together

All needed files are available on github: https://github.com/koying/ha-fly-tailscale-base

fly.io

  • Create a fly.io account. Warning: A credit card is needed for sign-up
  • Install the fly.io client, “flyctl”
    • Get flyctrl util (linux)
      curl -L https://fly.io/install.sh | sh
    • Get flyctrl util (windows)
      iwr https://fly.io/install.ps1 -useb | iex
  • login
    flyctl auth login

Tailscale

  • Create a Tailscale account if you don’t have one, already
  • Install the Tailscale client on your HA instance. If you are using a supervised HA install or HAssIO, just install the Tailscale addon
  • Create an one-off key

Adjust fly.toml

fly.toml is the configuration file that describes the service that will run on fly.io. Grab it from the repo above.
Adjust app = to a host name of your choice. It will be the hostname you’ll use to access HA from the internet, e.g. https://<my_app_id>.fly.dev

It must be unique across all fly.io, so be creative!

  TAILSCALE_HOSTNAME = "fly-tailscale-nginx"              # This will be the host name registered in Tailscale
  TAILSCALE_HA_SCHEME = "http"                            # The HA scheme, http or https
  TAILSCALE_HA_HOST = "<ha_taiscale_ip>"                  # The Tailscale address of your HA instance
  TAILSCALE_HA_PORT = "8123"                              # The HA port
  TAILSCALE_AUTHKEY = "<the_tailscale_one-off_key>"       # The Tailscale one-off key you created earlier

Create a Fly application with the util

  • flyctl apps create foobar-homeassistant (“foobar-homeassistant” will be the name of your application in fly)

Deploying the application

You have docker installed

Easy peasy. Just do flyctl -a foobar-homeassistant deploy to deploy the application on Fly.
After a little while, the application will just be there, ready for usage

You don’t have docker installed

A bit trickier, here. Obviously, you could install it, but it might be involving, especially on Windows.
The alternative route is to let Github do the job.

  • Fork this repository: ha-fly-tailscale-base
  • Get a Fly API token: flyctl auth token
  • Insert this token under the name FLY_API_TOKEN in github, in Settings-Secrets-New Repository secret
  • Enable Worflow on your fork: Actions-“I understand my workflows, go ahead and enable them”
  • Edit the fly.toml file, possibly in github itself, as described above.
  • Commit your changes.
  • Voilà! Github should handle the deployment of your Fly app via Actions.

SECURITY NOTE: Unfortunately, it’s not possible to make a fork of a public repository private in github, so you are now leaking private information in a public repository. Delete the repository from github as soon as the deployment is successful!

An alternative, more secure but more involving, way of working is to duplicate the repo and create a private copy, instead. See, e.g., GitHub: How to make a fork of public repository private?

Adjust configuration.yaml in HA to accept the remote proxy you just created

  • In the Tailscale dashboard, note the IP address that was assigned to your Fly application
  • In the “3-dots” menu, select "Disable key expiry’.
  • Add the IP to your HA “trusted_proxies”.
http:
  use_x_forwarded_for: true
  trusted_proxies:
    - "<tailscale_foobar-homeassistant_ip>"

All done!

Just go to https://<my_app_id>.fly.dev to access your HA instance from anywhere!

2 Likes

Hello

Thanks for the guide , it works well specially while my ISP uses CG-NAT. I have tried everything but this seems to work fine . But is it possible to run this without fly.io . Is it possible to deploy this on Oracle Cloud free tier or even in a cheap VPS . I know the point of using this is to be free usage of both fly.io and tailscale but fly.io have limitations . I want to use a VPS to do the fly.io side of work.
Please let me know

Thanks

I guess.
Point is to have some “cloud server” to act as a middle-tier between the external world and your actual HA instance, the link between the “cloud server” and HA being done through a tailscale VPN.

How to configure the “cloud server” is the tricky, ad-hoc and specific part, though.

I setup my instance on fly.io. Unfortunately could not get it to work yet… I see that my app has connected to Tailscale, but when I navigate to my fly.io app url then I get 400: Bad Request error.
Does anybody know what could be wrong?

Fixed it by adding correct trusted proxy IP to the HA config file. Looked at the HA logs and found that I had a following error: Received X-Forwarded-For header from an untrusted proxy …