How to configure Umbrel LNbits app without Tor

This is a first-version guide. I’ll happily iterate on it based on feedback, I’m sure I missed something, somewhere.

To-Add:

  • Troubleshooting section
  • Improve proxy headers (Current ones are what I found to be functional thus far)
  • Add some follow-along pictures for each step

Quick how-to:

  • Register Domain
  • Configure DNS to point to desired IP
  • Get an SSL certificate for the domain/sub-domain
  • Setup reverse-proxy using nginx
  • Redirect web traffic from reverse-proxy to Umbrel device

I’d like to mention a few things prior to going ahead with this guide.

  1. You can follow this guide even if you run a single raspberry pi.

  2. Even though this guide is catered towards LNbits, a reverse-proxy is exceptionally useful for a multitude of other things.

  3. If you intend on having custody of people’s wallets and giving them Internet Access to it, you should have some technical expertise(or the drive to) in order to SECURE people’s data.
    I’m sure one can take this guide and make it super user-friendly, but I don’t want to encourage non-technical people to manage funds.

  4. For administrative purposes, I strongly encourage all users to keep remote access of their node on the Tor network. This goes for Umbrel’s dashboard, as well as any administrative components(This is outside the scope of the guide, but worth a mention).

  5. The scope of this guide extends solely to making LNbits available via the public Internet, and making it functional.

  6. Throughout this guide I’ll be using my own setup as a base, however this can be followed by most users for whichever hardware they have Umbrel running on.
    I’ll attempt to make it as universal as possible since we’re dealing with Linux anyway, but you may need to make adjustments throughout.

  7. Since you operate a node I’ll take on certain assumptions:

    • You have no problem with doing some research
    • You have the ability to log onto your device(s)

If you require further detail or help on something specific, simply ask.

  1. I do not use a raspberry Pi but I understand a lot of people do. I’ll be covering Arch distribution commands(which will work on Arch, Manjaro, etc) and for Raspberry Pi users I’ll be including Debian distribution commands.

  2. For those familiar with the LetEncrypt cert bot thinking about calling me out on utilising a DNS challenge as opposed to the “simple” HTTP challenge, don’t.
    I thought about this and purposefully went with the DNS challenge to ensure that any user attempting this guide with hopes of success HAS A DOMAIN.
    This is important because technically one can run this connecting by IP with no SSL Cert, but it means that their Wallet URL will be easily open to a MITM attack, and that’ll not only be an easy game-over, but also a fair game.

  3. I recommend having a dedicated front-end gateway device to redirect requests to your Umbrel node(wherever it may be), but you can do all this on a single device(although if you already have an up and running node, do so at your own risk, or at least take the necessary precautions).
    If using two devices, I also recommend that the connectivity between the two be hardwired, NO WI-FI.

    For anyone wondering about my setup:
    I have two servers running.
    A front-end gateway that handles traffic, and offers a suite of self-hosted services akin to the Google Suite, and a second server running Proxmox with a multitude of VMs.
    My Umbrel node runs on an Arch Linux VM on Proxmox with a 1TB SSD.#

  4. Feel free to open a channel, I’ll reciprocate asap:
    UbiquityRonin.net

Overview and why

@DarthCoin pushed me to do it. Special thanks to him/her.
I’ve had the majority of the setup below for a few years, but recently I started coding a Telegram bot that lets users make lightning payments from a Telegram chat, but obviously there would be 2 issues:

  • Getting LNbits accessible over the Internet without Tor
  • Making it functional (ex. the Export to Phone QR code would respond with a .onion or private IP address even though the Wallet was going over the internet, which would defeat the purpose.)
    These two points will be covered and your users will be able to access their LNbits wallets over the Internet.

Requisites

  • You will NEED a domain(shared or private, free or paid, preferably a subdomain for your LNbits service) I recommend dishing out a few $ for one.
    While I won’t cover how to set this up, I’ll be making remarks on the things required for the domain to be responsive.

  • You will NEED an SSL certificate for your domain. I’ll be covering this in this guide. As mentioned in the preface notes, since LNbits attaches your wallet-string to the URL, the last thing you want is that URL to be visible on the web.

Expected traffic flow:

[Internet] - [Home Router/Firewall] - [Front-End Gateway] - [Umbrel]

Overview of steps:

  • Install components, this includes Nginx & the LetsEncrypt CertBot.
    I am aware there is the certbot-nginx plugin, but I setup both components individually - This will make it easier for me to help users troubleshoot if they come across any issues.
    Further, for the users attempting this guide, having an understanding of both of these components individually pays off in the future if they wish to expand their infrastructure.
  • Get an SSL Certificate
  • Configure components
  • Test

Henceforth I’ll refer to our domain as domain.com, and for our LNbits subdomain I’ll refer to it as lightning.domain.com

  1. Installing components

    SSH onto your device and use your package manager to install the necessary packages.

    Arch:
    sudo pacman -Sy nginx certbot
    
    Debian:
    sudo add-apt-repository ppa:certbot/certbot <-- This adds the certbot repository
    sudo apt update
    sudo apt install nginx certbot
    
  2. DNS configuration

    Before we move on, using the DNS manager from where you bought your domain(or wherever if you delegated your domain), you’ll want to setup an A record.

    • Create an A record pointing lightning.domain.com to your home IP. If you’re not behind a VPN, ifconfig.me will show you your IP.

    • For longevity’s sake, it’s also recommended you setup a DNS updater, so that your A record automatically updates to your latest IP in case your ISP changes it.
      Some providers have dedicated applications for this. Others utilise a single unique string URL that when hit, is updated with hitter’s IP. If you use a provider that employs this method(or delegated your domain to one who does), feel free to use the following python script:
      https://gitlab.com/Fragments-form-function/multi-scripts/-/blob/master/DNS-Script.py

      Download/copy it, place it on your server and create a system service for it.

  3. Port-Forwarding

    On your home router, port-forward port 443 and point it to the device you install nginx + certbot on.
    If your ISP does not allow you to port-forward a standard port such as 443, you may choose another port and change the nginx configuration accordingly.

  4. SSL Certificate

    On the device you installed certbot on, run:

    	sudo certbot certonly --manual --preferred-challenges dns
    

    Certbot will ask you for the domain, and will also ask you to place a TXT record for _acme-challenge.lightning.domain.com with a string it gives as the value.

    Give it the lowest TTL you can(5 mins is fine), as you’ll remove this TXT record once validated.

    Once the TXT record is in place, using another SSH session run

    dig -t txt _acme-challenge.lightning.domain.com 
    

    every few minutes until the string appears. This can take 15-30 minutes. Your challenge won’t timeout.

    Once the record is successfully retrieved by dig, hit Enter on certbot, and you should receive your certificate. If it didn’t work, retry, give it more time. It can take a while for DNS to propagate.

    Your new certificate should be under /etc/letsencrypt/live/lightning.domain.com/ Remember this path as we’ll need it shortly.

  5. Configuring nginx reverse-proxy

    Navigate to /etc/nginx/sites-available/ and you should have a reverse-proxy.conf here.
    Open it using a text editor such as nano,
    nano reverse-proxy.conf
    Once inside, you’ll want setup a new server block dedicated to LNbits. This is where the magic happens.

	server {
        listen 443 ssl; # Here, you'll tell nginx to listen on port 443 for SSL connections
				server_name lightning.domain.com; # Here you'll tell nginx the expected domain for requests

        access_log /var/log/nginx/reverse-access.log; # Your first go-to for troubleshooting
        error_log /var/log/nginx/reverse-error.log; # Same as above

        location / {
										proxy_pass http://10.13.37.5:3007 # Change this to point to your umbrel node's private IP and LNbits port. You can try to use umbrel.local, but I recommend using the device's actual IP. To find this IP run "ping umbrel.local", and it should return the IP.
										proxy_set_header Upgrade $http_upgrade
										proxy_set_header Connection 'upgrade';
		    						proxy_set_header X-Forwarded-Proto https;
										proxy_set_header Host $host;
		    						proxy_http_version 1.1; # These are the headers I've found to both give access to LNbits, AND ensure that replies back are re-written with the lightning.domain.com URL as opposed to the private IP or .onion. 
  }
        ssl on; # This is important and declares connections should be secured with SSL.
        ssl_certificate /etc/letsencrypt/live/lightning.domain.com/fullchain.pem; # Point to the fullchain.pem 
        ssl_certificate_key /etc/letsencrypt/live/lightning.domain.com/privkey.pem; # Point to the private key.
  1. Restart services and test

    Run

    sudo systemctl restart nginx
    

    On a browser, head over to https:// lightning.domain.com.

    Access your wallet via https:// lightning.domain.com/wallet?usr={YourUserString}

9 Likes

Questions:

  • after configuring LNbits, can the port used be changed, for example 8443?
  • what if I want to have BTCpay (from Umbrel) using the same port 443?
  • can have both LNbits and BTCpay on the same port?

I’m changing the order of your questions as it’ll make more sense to respond to them this way:

  • can have both LNbits and BTCpay on the same port?

From the perspective of the reverse-proxy, yes! The cool thing about a reverse-proxy is that the proxy will be listening on port 443, and then redirect the request to the correct [PrivateIP:Port], based on the domain requested.

So you can have 443 listening for requests to lightning.domain.com & btcpay.domain.com.
End-users shouldn’t need to care about mutiple custom ports, so they just need to know 1 port.

It would look something like this:


server {
        listen 443 ssl;
        server_name lightning.domain.com;
(...)
        location / {
										proxy_pass http://10.13.37.5:3007 
(...)
  }
server {
        listen 443 ssl;
        server_name btcpay.domain.com;
(...)
        location / {
										proxy_pass http://10.13.37.5:3001
(...)
  }
  • what if I want to have BTCpay (from Umbrel) using the same port 443?

As mentioned above, for end-users it’s best to let them deal with a single port. Since they’ll most likely be using a browser or an application that makes web-requests, they just need to deal with 443, and the differentiation will be based on the domain/sub-domain that was requested.

It’s not recommended to run two services on the same port. You could do this if you use two devices as I recommended, but then you’d have setup specific firewall rules on a router/firewall to properly forward requests and can get muddy - This is exactly what a reverse-proxy is built to do in an easier fashion, so you should let it take over such requests and let it deal with them.

Having an extra device act as a web-gateway greatly simplifies things in this regard.

  • after configuring LNbits, can the port used be changed, for example 8443?

The LNbits port can be changed on the docker config when spinning up the LNbits container. This can be changed in ~/umbrel/app-data/lnbits/docker-compose.yml
I believe this is reset after an update, so either change it manually after each update or automate the process with a simple script.

2 Likes

THIS IS AWESOME!
I hope many other Umbrelians will take in consideration to use LNbits.

Fantastic guide. I have been trying to do the same thing, but for BTCPay (and to create a guide like this one), but I keep messing up and bricking my Pi, so I think I’m going to stop until I can get a developer friend to help.
I don’t understand this stuff much, and I think I installed nginx in the wrong place, messed up the network settings, etc.

1 Like

Hi there,
I’m taking another stab at this, but could use some help.
As far as I can tell, Nginx is already installed on the Umbrel installation, which makes me hesitant to install it again with this command:

sudo apt install nginx certbot

I think that’s what broke my connectivity last time - especially because I probably didn’t install it in the right place.
Would you be able to help me get this up and running, so I can make a guide for how to do this with BTCPay?

I already have the certificate installed, as well as the port forwarding, and everything - just need to get this one last step working. I’m so close!

1 Like

Hi @The_Lorax, very sorry for the (very) late reply, I had to be away dealing with other stuff.

It seems like you’re trying to do this directly on the pi, which is why I made mention that this is best done utilising a front-end gateway device on point ‘9.’ .

While I did mention in point ‘0.’ one can follow this guide using a single pi, it can get quite messy trying to do so (I’ll make mention of this).

I don’t use a pi, but I’ve confirmed it runs slightly different - Umbrel spins up Docker containers for each of the Umbrel-related services, and any nginx config seems to be bundled with the respective docker containers.

However, on the pi, the nginx config is present on bare-metal (outside docker) and mounted, hence any extra nginx config using the guide above within the pi, messes everything up.

One alternative is, as suggested, run an extra device AS the reverse-proxy, this can be an extra pi, an old laptop, a VM that is always on, whatever.
It’s also possible to run a VM within the pi as the reverse-proxy at the expense of some resources. While not encouraged it’s possible and works fine if you have enough resources(a 512MB RAM 2 vCPU vm for instance).

Or, you may need to look at the nginx config present and hook up the new config, but again, messy I’d say not worth the trouble. Umbrel as a full-stack Node is designed to work out of the box, which it does, and as such should be left alone, instead look to scale up your infrastructure from the outside of it.

Seems I can no longer edit the OP.
I’d like to mention the following.

While on point 0. it is mentioned this can be run on a single raspberry pi, this isn’t fully true and my mistake. An Umbrel installaltion on Linux-based setups (non-pi) come with nginx bundled in their respective docker containers, hence there is no outside nginx config and one can easily do everything on a single device.
The ready-to-go bare-metal installation of Umbrel on the Pi is slightly different in that it places nginx config outside docker environments and mounts it.

As such, it is still highly recommended to use an extra device as the front-end gateway / reverse-proxy mentioned in point 9. Having to hook up the existing nginx config on the pi with new config is not worth the trouble in the majority of cases.

thanks so much for the reply. I ended up going through various iterations, including on the same pi, on another pi in my home, and finally, a VPS in the cloud. The VPS in the cloud is currently working, but it takes 3-4 seconds for the modal pop-up to show for BTCPay, so I don’t think it’s an effective long-term solution unfortunately…

If there’s a delay in certain web pop-ups on BTCPay, that sounds more like it might be config/application related than network.

Play around with the nginx config headers, you might find something more performing for such requests.

Awesome post/guide, It was not easy, since I’m a total newbie, but now I have my lnbits accessible from the web, this open a tons of possibilities, btw I also think that the best approach is to run reverse-proxy in a second device, my umbrel installation is running on a Raspberry PI 4 and the Reverse-Proxy on a Raspberry PI 3. Please don’t stop updating this guide, it is an amazing!!! Thanks for sharing it.

I’m glad this helped you, it indeed paves the way for a lot of possibilities.
Unfortunately I haven’t had time to update it much further due to other projects taking priority, but will try to get some time to at least refine a few points.

1 Like

I beat my head against this for hours, but couldn’t manage to get it to work. I’ve got the domain connected and pointed to my IP, it’s finding my network, but for some reason it’s routing to pages from my Synology DSM. I don’t know how to tell if this is an issue with how the router is configured or how nginx is configured. I’ve fiddled and fiddled with the configs/settings on both to no avail (I’m in over my head).

Thanks for writing it up, it sounds like it works for others, I’m just too new to linux/command line/networking to troubleshoot.

If this is the case, then it means you have a clear route for traffic between your router and your Synology - As such a few points come to mind:

  • Do you want Synology to be behind nginx?
    If so, make sure that your router is port-forwarding traffic to your nginx, instead of the Synology DSM. Once this is done, add a server block that takes requests for a specific subdomain (for instance, assign one to your DSM, such as dsm.mydomain.com), and point it to the correct private IP & port.

It sounds like your router may be bypassing nginx and going straight to synology, so really, all you have to do is take that config on the router and move it to nginx, in other words, let nginx be the one managing incoming internet traffic.

  • If you don’t want Synology behind nginx:
    Then you’ll need to ensure that the expected traffic is coming into another port.
    When you input your domain on a browser, it assumes you’re looking for ports 80, or 443, in this case most likely 443, unless you specifically state otherwise. If traffic is coming in on 443, and the router is told to forward this to your Synology, it’ll bypass nginx. As such, nginx won’t be able to be listening on port 443 as well. In such a case you’ll have two options:

One of the reasons why nginx should be in front handling all traffic is merely out of convenience because since browsers assume port 443, and nginx has the capability to handle requests TO different IPs/Ports, FROM a a specific subdomain+443, it’s much easier to type https://dsm.mydomain.com (In which case traffic goes to the router, nginx then takes it and forwards it to PrivateIP:{PortSynologyListensOn}, while if you go to https://lightning.mydomain.com, nginx will know, based on the “Lightning” that it needs to go to UmbrelP:{LNBitsPort}.

Also, are you running nginx on a separate device from Umbrel, or same?

This worked! I found out where I had turned on listening for 443 on the Synology ages ago (and forgotten about it).

I managed to get the whole thing working, it’s pretty amazing. Thank you so much for taking the time to write this and for getting back to me.

@occupy Glad you got it sorted! Have fun!

BTW you can also use this for Matrix / Element. It works perfectly.

1 Like

Yep, I have this in place for a multitude of different services, not aggregated to Umbrel (nextcloud, element & synapse, vaultwarden, bookstack, trilium, media library, etc ) Lots of possibilities.

1 Like