chore(docker): rename compose folder and fix review follow-ups from #4057 (#4129)

Follow-up to the review of #4057.

- Rename apps/logos_delivery_node/compose -> apps/logos_delivery_node/docker
  (review request); the only path reference was in the folder's own README.
- run_certbot.sh: pass the configured EMAIL to certbot instead of the
  hardcoded admin@$DOMAIN, and forward EMAIL to the certbot container so
  setting it in .env takes effect. Empty still falls back to admin@$DOMAIN.
- set_storage_retention.sh: `grep -c` always prints a count, so the old
  sudo test was always true and sudo was used whenever ./postgresql existed.
  Test readability of the data directory directly instead.
- chkhealth.sh: drop the stray `GET` argument, which curl treated as an
  extra (failing) URL.
- docker-compose.yml: put certbot behind the `wss` profile so it no longer
  publishes host port 80 on deployments that do not use WebSocket-Secure,
  and drop the node's meaningless `depends_on: certbot` (run_node.sh polls
  for the certificate on disk anyway).
This commit is contained in:
NagyZoltanPeter
2026-08-18 18:03:04 +02:00
committed by GitHub
parent 2fb625f463
commit d3c0979dd5
21 changed files with 44 additions and 12 deletions
@@ -18,8 +18,15 @@ LOGOS_IMAGE=
# NODEKEY: P2P node private key (64 char hex) for a stable peer identity.
NODEKEY=
# DOMAIN: public domain for WebSocket-Secure (TLS via certbot). Leave empty to
# disable WSS.
# disable WSS. When set, also set COMPOSE_PROFILES=wss below, otherwise
# certbot is not started and the node waits forever for a certificate.
DOMAIN=
# COMPOSE_PROFILES: set to `wss` (together with DOMAIN) to run the certbot
# service. It binds host port 80 for the ACME HTTP-01
# challenge, so it stays off unless requested.
COMPOSE_PROFILES=
# EMAIL: registration address for Let's Encrypt. Defaults to admin@$DOMAIN.
EMAIL=
# EXTRA_ARGS: extra logosdeliverynode CLI flags appended verbatim.
EXTRA_ARGS=
# STORAGE_SIZE: store retention size, e.g. 1GB. Empty defaults to size:1GB.
@@ -1,4 +1,4 @@
# logosdeliverynode compose
# logosdeliverynode docker compose stack
A `docker compose` project that runs a **logosdeliverynode** as a full service
node on the **Logos Dev** network (`--preset=logos.dev`), backed by Postgres
@@ -17,12 +17,12 @@ RLN keystore tooling are intentionally omitted for now.
| `postgres-exporter` | Exposes Postgres metrics to Prometheus |
| `prometheus` | Scrapes node (`:8003`) and postgres-exporter |
| `grafana` | Dashboards (`http://localhost:3000`, anonymous admin) |
| `certbot` | Optional Let's Encrypt certs for WebSocket-Secure (needs DOMAIN) |
| `certbot` | Let's Encrypt certs for WebSocket-Secure; only with the `wss` profile |
## Quick start
```bash
cd apps/logos_delivery_node/compose
cd apps/logos_delivery_node/docker
cp .env.example .env # edit POSTGRES_PASSWORD etc.
# Build the logosdeliverynode image from the repo Dockerfile
@@ -57,6 +57,8 @@ Key `.env` values:
| `POSTGRES_USER` / `_PASSWORD` | postgres / test123 | Store DB credentials |
| `NODEKEY` | *(random)* | Stable P2P identity (64 char hex) |
| `DOMAIN` | *(empty)* | Public domain for WebSocket-Secure; empty disables WSS |
| `COMPOSE_PROFILES` | *(empty)* | Set to `wss` together with `DOMAIN` to run `certbot` |
| `EMAIL` | `admin@$DOMAIN` | Let's Encrypt registration address |
| `STORAGE_SIZE` | `1GB` | Store retention size |
| `EXTRA_ARGS` | *(empty)* | Extra CLI flags appended to the node |
@@ -73,4 +75,19 @@ tuned `POSTGRES_SHM` / `STORAGE_SIZE` values to `.env` based on the host.
| 8645 | node REST | bound to 127.0.0.1 |
| 8003 | node metrics | bound to 127.0.0.1 |
| 3000 | grafana | |
| 80 | certbot | ACME HTTP-01 |
| 80 | certbot | ACME HTTP-01, only with the `wss` profile |
## WebSocket-Secure
WSS is off by default. To enable it, set both values in `.env` and bring the
stack back up:
```bash
DOMAIN=node.example.com
COMPOSE_PROFILES=wss
```
`certbot` publishes host port 80 for the ACME HTTP-01 challenge, which is why
it is kept behind a profile rather than started unconditionally. With `DOMAIN`
set but the profile off, no certificate is ever issued and the node stays in
its certificate-wait loop.
@@ -38,7 +38,7 @@ then
exit 1
fi
response=$(curl --connect-timeout 6 -s GET http://${ip_address}/health)
response=$(curl --connect-timeout 6 -s http://${ip_address}/health)
if [[ $? -ne 0 ]]; then
echo -e "$(date +'%H:%M:%S') - Node may not be running or not reachable at http://${ip_address}\n"
@@ -67,16 +67,22 @@ services:
# crash-loops on store setup until the DB is ready (restart: on-failure).
postgres:
condition: service_healthy
certbot:
condition: service_started
certbot:
# Only started when the `wss` profile is enabled (COMPOSE_PROFILES=wss in
# .env, alongside DOMAIN). It binds host port 80 for the ACME HTTP-01
# challenge, which would otherwise be occupied even on deployments that do
# not use WSS. run_node.sh polls for the certificate on disk, so the node
# needs no depends_on ordering against it.
profiles: ["wss"]
image: certbot/certbot
restart: on-failure
ports:
- 80:80 # Let's Encrypt
environment:
DOMAIN: ${DOMAIN}
# Empty falls back to admin@$DOMAIN inside run_certbot.sh.
EMAIL: ${EMAIL}
volumes:
- ./run_certbot.sh:/opt/run_certbot.sh:Z
- ${CERTS_DIR:-./certs}:/etc/letsencrypt/:Z
@@ -36,7 +36,7 @@ if [ ! -d "${LETSENCRYPT_PATH}" ]; then
--agree-tos\
--no-eff-email\
--no-redirect\
--email admin@${DOMAIN}\
--email "${EMAIL}"\
-d ${DOMAIN}\
--standalone
@@ -25,6 +25,7 @@ if [ -n "${DOMAIN}" ]; then
while true; do
if [ ! -f "${CERT}" ] || [ ! -f "${KEY}" ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] Certificate files not found yet. Waiting..."
echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] If no certbot container is running, set COMPOSE_PROFILES=wss in .env and re-run docker compose up -d."
elif ! openssl x509 -checkend 0 -noout -in "${CERT}" >/dev/null 2>&1; then
echo "$(date '+%Y-%m-%d %H:%M:%S') [WARN] Certificate exists but is expired. Waiting for renewal..."
echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] If that takes more than 15 minutes, please remove --quiet attr in run_certbot.sh so that you can see the reason why renewal is not working."
@@ -47,7 +47,7 @@ fi
# Check we are in right folder
if ! [ -f "./run_node.sh" ]; then
>&2 echo "This script must be run from inside the compose folder"
>&2 echo "This script must be run from inside the docker folder"
exit 1
fi
@@ -64,8 +64,9 @@ fi
SUDO=""
PGSQL_SIZE_MB=0
if [ -d "./postgresql" ]; then
# Check if we need to use SUDO moving forward
if [ "$(ls postgresql/* 2>&1 | grep -c "Permission denied")" ]; then
# Check if we need to use SUDO moving forward: the data directory is
# created by the postgres container and may not be readable by this user.
if ! ls ./postgresql >/dev/null 2>&1; then
SUDO="sudo"
fi