reverse proxy (nginx) - tulliolo/mobybolt GitHub Wiki

Several components of this guide will expose a communication port, for example, the Block Explorer, or the ThunderHub web interface for your Lightning node. Even if you use these services only within your own home network, communication should always be encrypted. Otherwise, any device in the same network can listen to the exchanged data, including passwords.
We use Ngnix to encrypt the communication with SSL/TLS (Transport Layer Security). This setup is called a "reverse proxy": Nginx provides secure communication to the outside and routes the traffic back to the internal service without encryption.
âšī¸ Even if some services, such as Fulcrum, natively support encrypted communication, for simplicity and architectural cleanliness, we will still use nginx as a single point of access to all services.
â To follow this section, log in to your node as admin user via Secure Shell (SSH) and access the project's home:
$ cd apps/mobybolt
Create the nginx directory:
$ mkdir nginx
Edit the .env file and append the following content to the end:
$ nano .env
# nginx
NGINX_VERSION=mainline
NGINX_GID=101
NGINX_UID=101đĄ In this file:
- we define the
NGINX_VERSIONasmainline(stable) - we define the
uid(user id) andgid(group id) of the nginx user
Create the Dockerfile and populate it with the following content:
$ nano nginx/Dockerfile
ARG NGINX_VERSION='latest'
# cert image
FROM alpine AS certimage
ARG DOMAIN_NAME=localhost
ARG DAYS_VALID=3650
# install dependencies
RUN set -eux && \
apk add --no-cache openssl
RUN set -eux && \
echo "Creating self-signed certificate valid for ${DAYS_VALID} days for domain ${DOMAIN_NAME}" && \
openssl \
req -x509 \
-nodes \
-subj "/CN=${DOMAIN_NAME}" \
-addext "subjectAltName=DNS:${DOMAIN_NAME}" \
-days ${DAYS_VALID} \
-newkey rsa:4096 \
-keyout /tmp/nginx-selfsigned.key \
-out /tmp/nginx-selfsigned.crt
# base image
FROM nginx:$NGINX_VERSION AS base
# install dependencies
RUN set -eux && \
apt update && \
apt install -y curl && \
rm -rf /var/lib/apt/lists/*
# result image
FROM base
ARG NGINX_GID=101
ARG NGINX_UID=101
# copy certificates
COPY --from=certimage /tmp/nginx-selfsigned.crt /tmp/nginx-selfsigned.key /etc/nginx/ssl/
RUN set -eux && \
# setup user
groupmod --gid $NGINX_GID nginx && \
usermod --uid $NGINX_UID nginx && \
# setup dirs
mkdir /run/nginx/ && \
# set ownership and permissions
chown -R nginx:nginx /etc/nginx/ /run/nginx/ /var/cache/nginx/
# switch user
USER nginx
đĄ In this file:
- we define a support image (
certimage) to generate a self-signed SSL certificate; - we extend the official nginx image:
- installing curl (for healthcheck purposes);
- importing the SSL certificate;
- configuring the nginx user and the directories to which he will have access.
Create some directories:
$ mkdir -p nginx/config/sites-enabled
$ mkdir -p nginx/config/streams-enabled
Create the nginx.conf file and populate it with the following content:
$ nano nginx/config/nginx.conf
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx/nginx.pid;
worker_rlimit_nofile 1536;
events {
worker_connections 768;
}
http {
ssl_certificate /etc/nginx/ssl/nginx-selfsigned.crt;
ssl_certificate_key /etc/nginx/ssl/nginx-selfsigned.key;
ssl_session_cache shared:HTTP-TLS:1m;
ssl_session_timeout 4h;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
include /etc/nginx/sites-enabled/*.conf;
}
stream {
ssl_certificate /etc/nginx/ssl/nginx-selfsigned.crt;
ssl_certificate_key /etc/nginx/ssl/nginx-selfsigned.key;
ssl_session_cache shared:STREAM-TLS:1m;
ssl_session_timeout 4h;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
include /etc/nginx/streams-enabled/*.conf;
}
Create a test site to check the container health:
$ nano nginx/config/sites-enabled/test-site.conf
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server {
listen 443 ssl;
error_page 497 =301 https://$host:$server_port$request_uri;
location / {
proxy_pass http://127.0.0.1:80;
}
}
Create the Docker Compose file and populate it with the following content:
$ nano nginx/docker-compose.yml
services:
nginx:
build:
context: .
args:
NGINX_VERSION: ${NGINX_VERSION}
NGINX_GID: ${NGINX_GID}
NGINX_UID: ${NGINX_UID}
container_name: ${COMPOSE_PROJECT_NAME}_nginx
healthcheck:
test: ["CMD-SHELL", "curl -fk https://localhost || exit 1"]
interval: 1m
timeout: 10s
retries: 3
image: ${COMPOSE_PROJECT_NAME}/nginx:${NGINX_VERSION}
restart: unless-stopped
volumes:
- ./config/nginx.conf:/etc/nginx/nginx.conf:ro
- ./config/sites-enabled/:/etc/nginx/sites-enabled/:ro
- ./config/streams-enabled/:/etc/nginx/streams-enabled/:ro
đĄ In this file:
- we
buildthe Dockerfile and create an image namedmobybolt/nginx:mainline; - we define a
healthcheckthat will query the test site every minute; - we define the
restartpolicy of the container in case of failures; - we provide the container with the previously defined configurations (bind mount)
Edit the main Docker Compose file and link the nginx docker compose file in the include section:
$ nano docker-compose.yml
The file should look like this:
include:
- nginx/docker-compose.ymlRun the following command and check the output:
$ docker compose config --quiet && printf "OK\n" || printf "ERROR\n"
> OK
đĄ If the output is not OK, check the error reported... Maybe some wrong indentation in the yaml files?
Let's build the nginx image by typing:
$ docker compose build nginx
Check for a new image called mobybolt/nginx:mainline:
$ docker images | grep nginx
> mobybolt/nginx mainline 64ea9ecb52dd 37 seconds ago 188MB
Run the following command and check the output:
$ docker compose up -d nginx
> [+] Running 2/2
> â Network mobybolt_default Created
> â Container mobybolt_nginx Started
Check the container logs:
$ docker logs mobybolt_nginx
> ...
> 2024/05/07 11:50:50 [notice] 1#1: nginx/1.25.5
> 2024/05/07 11:50:50 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14)
> 2024/05/07 11:50:50 [notice] 1#1: OS: Linux 6.1.0-20-amd64
> 2024/05/07 11:50:50 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
> 2024/05/07 11:50:50 [notice] 1#1: start worker processes
> ...
Check the container status:
$ docker ps | grep nginx
> bec6cf2a7403 mobybolt/nginx:mainline "/docker-entrypoint.âĻ" 5 minutes ago Up 5 minutes (healthy) 80/tcp mobybolt_nginx
(healthy), or (health: starting). Any other status is incorrect.
đĄ If the container is in (health: starting) state, wait a few minutes and repeat the above command until the state changes to (healthy). If this does not happen, the run has failed.
âšī¸ If not already present, docker will also create the mobybolt network. You can check for it with the command:
$ docker network ls | grep mobybolt
> b73804f9dc97 mobybolt_default bridge local
To upgrade nginx, you can simply redo the steps described in:
If a new version of nginx has been released, docker will rebuild the image and hot-swap the old container with the updated one.
Later, you can delete the old image and clean the build cache with the following commands (type y when prompted):
$ docker image prune
> WARNING! This will remove all dangling images.
> Are you sure you want to continue? [y/N] y
> Deleted Images:
> deleted: sha256:2aafbb312ce58b974c131de147bb9d22cf7e200b825496b25fad2413685e808c
$ docker buildx prune
> WARNING! This will remove all dangling build cache. Are you sure you want to continue? [y/N] y
> ID RECLAIMABLE SIZE LAST ACCESSED
> fjap6n77y7o38fzxb0p76xtz3 true 15.4kB 7 hours ago
> sg8tzhtf1m1vhufjzvetukgmy* true 1.212kB 13 minutes ago
> ...
> Total: 5.862MB
Follow the next steps to uninstall nginx:
-
Remove the container:
$ docker compose down nginx > [+] Running 2/1 > â Container mobybolt_nginx Removed > ... -
Remove the image:
$ docker image rm $(docker images | grep nginx | awk '{print $3}') > Untagged: mobybolt/nginx:mainline > Deleted: sha256:411a5102d61a972fcf049c85dfbe387fe15560640b0fe7da9ada1562085afdc8 -
Clean the build cache:
$ docker buildx prune > WARNING! This will remove all dangling build cache. Are you sure you want to continue? [y/N] y > ID RECLAIMABLE SIZE LAST ACCESSED > 7r8ccrpq0g0e03deu2dh53ob6* true 9.69MB 19 minutes ago > ndrhcdo756vejnx17qm775t08* true 1.212kB 24 minutes ago > ... -
Remove files and directories (optional):
$ rm -rf nginx