DEV Community

Gene Liverman
Gene Liverman

Posted on • Originally published at beanbag.technicalissues.us on

Proxying Bitcoin Core and LND with Tailscale and Nginx

Recently I decided I wanted to run my own Bitcoin and Lightning node and I wanted it to be reachable on the public internet. I didn’t, however, want it to actually reside on the server that has the static public IPv4 and IPv6 addresses available. Thus, a reverse proxy was needed. This turned out to be a pretty simple thing to solve for thanks to the Nginx Stream Proxy module and Tailscale. Here’s the basic architecture:

  • Nginx on a virtual private server (VPS) at Hetzner listens on ports 8333 & 9735 for TCP connections
  • The stream proxy module forwards those connections to bitcoind and lnd over Tailscale
  • The server running bitcoind and lnd uses the Hetzner VPS as a Tailscale exit node so that all outbound traffic is via the VPS

Here’s a technical breakdown of how I make that happen. My configuration is done via NixOS flakes, but the general process would work on anything using Nginx and Tailscale.

{ config, username, ... }: let 
  domain = "example.com";
  private_btc = "some-host.your-domain.ts.net";
in {
  networking.firewall.allowedTCPPorts = [
    8333 # Bitcoin Core
    9735 # LND
  ];

  services = {
    nginx = {
      enable = true;
      streamConfig = ''
        server {
          listen 0.0.0.0:8333;
          listen [::]:8333;
          proxy_pass ${private_btc}:8333;
        }

        server {
          listen 0.0.0.0:9735;
          listen [::]:9735;
          proxy_pass ${private_btc}:9735;
        }
      '';
    }; # end nginx
    tailscale = {
      enable = true;
      authKeyFile = config.sops.secrets.tailscale_key.path;
      extraUpFlags = [
        "--advertise-exit-node"
        "--operator"
        "${username}"
        "--ssh"
      ];
      useRoutingFeatures = "both";
    }; # end tailscale
  }; # end services

  sops = {
    age.keyFile = "${config.users.users.${username}.home}/.config/sops/age/keys.txt";
    defaultSopsFile = ../secrets.yaml;
    secrets = {
      tailscale_key = {
        restartUnits = ["tailscaled-autoconnect.service"];
      };
    };
  }; # end sops
}

Enter fullscreen mode Exit fullscreen mode

Breaking that down a little:

  1. networking.firewall.allowedTCPPorts opens the firewall ports needed for bitcoind and lnd
  2. services.nginx configures two ngx_stream_proxy_module instances within the streamConfig section that route traffic to the backend using the dns name from Tailscale
  3. services.tailscale enables Tailscale on the VPS and configures it as an exit node.
  4. sops configures SOPS to securely store secrets

And that’s it on the VPS. For the backend, you could be running a variety of different options from Umbrel to Nix Bitcoin to the services manually configured on a variety of operating systems. Settings those up is best left to a different post, but the keys that relates to this setup are:

  • that where ever they run uses the VPS as an exit node
  • the services listen on for connections incoming via Tailscale
  • the services advertise the IP of the VPS as their public address

Note: the links to Hetzner and Tailscale in this post are referral / affiliate links. The Hetzner one is mine and the Tailscale one is from Jupiter Broadcasting’s Linux Unplugged podcast. I’ve used the JB link because Chris Fisher, Alex Kretzschmar, Brent Gervais, & Wes Payne have taught me about much of what’s here through their podcasting.

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay