Publish on host loopback for NPMplus with host networking

NPMplus runs with network_mode: host, so it cannot reach the container by
name on a shared Docker network. Publish the app on 127.0.0.1:4181 instead
and drop the NPM_NETWORK setting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
uhlwoogiandClaude Opus 5.5 committed 2026-10-02 22:11:06 +00:00
1 parent 5b7b73225f
commit a51d5825ce
3 files changed
+14 -16

No files matched your search

+4 -2
View File
@@ -1,8 +1,10 @@
# Stack settings. In Portainer, enter these under the stack's "Environment variables".
# For the docker compose CLI, copy this file to .env next to compose.yaml. Never commit the completed file.
# Docker network Nginx Proxy Manager is attached to (Portainer > Networks shows the name).
NPM_NETWORK=npm_default
# Host port the app listens on, bound to loopback so only NPMplus (host networking) can reach it.
# Change PROPOSAL_BOT_PORT if 4181 is already taken on the host.
PROPOSAL_BOT_BIND=127.0.0.1
PROPOSAL_BOT_PORT=4181
# Absolute host folders. The data folder must be writable by UID 1000.
PROPOSAL_BOT_DATA_HOST_PATH=/opt/proposal-bot/data
+6 -6
View File
@@ -14,7 +14,7 @@ The image contains only the app code and Chromium (used by the InDesign export).
## Deploy with Portainer
The stack has no published port. Nginx Proxy Manager (NPM) handles HTTPS and reaches the container by name over NPM's Docker network.
NPMplus handles HTTPS. It runs with host networking, so the container publishes its port on the host's loopback address only (`127.0.0.1:4181`). NPMplus can reach that port; other machines cannot.
### 1. Put the project and photo folders on the Docker host
@@ -29,7 +29,7 @@ sudo chown -R 1000:1000 /opt/proposal-bot/data # the container runs as UID 10
### 2. Create the Microsoft Entra app registration
1. Create a web app registration for Proposal Bot with a client secret.
2. Register the callback `https://<proposal-bot-hostname>/auth/microsoft/callback`, using the hostname NPM will serve.
2. Register the callback `https://<proposal-bot-hostname>/auth/microsoft/callback`, using the hostname NPMplus will serve.
### 3. Create the stack
@@ -38,16 +38,16 @@ In Portainer, go to **Stacks > Add stack > Repository**:
- **Repository URL:** this repo's Gitea URL. Turn on **Authentication** and use a Gitea access token if the repo is private.
- **Compose path:** `compose.yaml`
- **Environment variables:** add every entry from `.env.example`. **Advanced mode** accepts the whole file pasted in.
- `NPM_NETWORK`: the network NPM's container is attached to. To find it, open NPM's container in Portainer and look at its network section, usually something like `npm_default`.
- `PROPOSAL_BOT_PORT`: leave at `4181` unless that port is already in use on the host.
- `PROPOSAL_BOT_DATA_HOST_PATH` and `PROPOSAL_BOT_PROJECT_IMAGES_HOST_PATH`: the folders from step 1. Use absolute paths. A relative path would end up inside Portainer's copy of the repo and be lost on redeploy.
- `MICROSOFT_REDIRECT_URI`: exactly the callback from step 2.
Deploy the stack. Portainer builds the image on the host, which takes a few minutes the first time because it installs Chromium. The container should show **healthy**. Its logs show startup warnings, such as missing sign-in settings or a `data` folder the container cannot write to.
### 4. Add the NPM proxy host
### 4. Add the NPMplus proxy host
- **Domain:** the Proposal Bot hostname
- **Forward:** scheme `http`, hostname `proposal-bot`, port `4181`
- **Forward:** scheme `http`, hostname `127.0.0.1`, port `4181` (or your `PROPOSAL_BOT_PORT`)
- **SSL tab:** request or choose a certificate, and turn on **Force SSL**
- **Advanced tab:** paste the lines below so long InDesign exports are not cut off after 60 seconds:
@@ -68,7 +68,7 @@ Copy `.env.example` to `.env`, fill it in, and run `docker compose up -d --build
## Sign-in
Sign-in uses Microsoft Entra and the email allowlist in `PROPOSAL_BOT_ALLOWED_EMAILS` (comma-separated). Microsoft only accepts HTTPS callbacks, which NPM provides.
Sign-in uses Microsoft Entra and the email allowlist in `PROPOSAL_BOT_ALLOWED_EMAILS` (comma-separated). Microsoft only accepts HTTPS callbacks, which NPMplus provides.
Sessions are kept in memory, so restarting or redeploying the container signs everyone out.
+4 -8
View File
@@ -9,9 +9,10 @@ services:
restart: unless-stopped
# Reaps the headless Chromium processes the InDesign export starts.
init: true
# No published port: Nginx Proxy Manager reaches http://proposal-bot:4181 over its Docker network.
networks:
- proxy
# Published on the host's loopback only. NPMplus (host networking) forwards to http://127.0.0.1:4181;
# other machines cannot reach the port directly.
ports:
- "${PROPOSAL_BOT_BIND:-127.0.0.1}:${PROPOSAL_BOT_PORT:-4181}:4181"
environment:
HOST: 0.0.0.0
PORT: 4181
@@ -33,8 +34,3 @@ services:
source: ${PROPOSAL_BOT_PROJECT_IMAGES_HOST_PATH:?Set PROPOSAL_BOT_PROJECT_IMAGES_HOST_PATH to an absolute host folder for the photo library}
target: /app/Project Images
read_only: true
networks:
proxy:
external: true
name: ${NPM_NETWORK:?Set NPM_NETWORK to the Docker network Nginx Proxy Manager is attached to}