Changeset f99bbe8 in Klonkt


Ignore:
Timestamp:
06/23/2026 10:00:00 PM (3 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
5eef817
Parents:
09ee2bd
Message:

security: bind to 127.0.0.1 by default behind a reverse proxy

New HOST env (default 0.0.0.0 for Docker/back-compat). The VPS installer now
writes HOST=127.0.0.1 and Docker maps the host port to loopback (127.0.0.1:3000:3000)
+ overrides HOST=0.0.0.0 inside the container — so the app is never reachable
directly on its port from the internet, only via the proxy. .env.example defaults
to 127.0.0.1 (manual installs); docs explain it. Existing installs hardened on
re-run of install.sh.

Co-Authored-By: Claude <noreply@…>

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • .env.example

    r09ee2bd rf99bbe8  
    11NODE_ENV=development
    22PORT=3000
     3
     4# Network interface to bind. 127.0.0.1 = only reachable via a reverse proxy on the
     5# same machine (recommended for a manual install behind Caddy/nginx — keeps the app
     6# off the public internet). Use 0.0.0.0 only if you need direct external access
     7# (no proxy/HTTPS — not recommended). Docker sets this to 0.0.0.0 itself.
     8HOST=127.0.0.1
    39# Secret used to sign login-session cookies. Leave EMPTY to auto-generate a strong
    410# one on first start (saved to storage/.session-secret, stays stable across
  • README.md

    r09ee2bd rf99bbe8  
    115115```
    116116
     117By default the app binds to `127.0.0.1` (via `HOST` in `.env`), so only your
     118reverse proxy can reach it — not the open internet. Local testing on the same
     119machine (`localhost:3000`) still works. Only set `HOST=0.0.0.0` if you need direct
     120external access without a proxy (then open the port in your firewall and add HTTPS
     121yourself).
     122
    117123(`cwebp` is optional — `apt install webp` — for WebP image conversion.)
    118124
  • docker-compose.yml

    r09ee2bd rf99bbe8  
    1616    env_file: .env
    1717    environment:
    18       # In de container draait 'ie altijd op 3000 en in productie-modus,
    19       # ongeacht wat er in .env staat.
     18      # Inside the container it always runs on port 3000 in production mode and
     19      # binds all interfaces (so the port mapping works) — overrides .env. The
     20      # loopback host-mapping below is what keeps it off the public internet.
    2021      NODE_ENV: production
    2122      PORT: "3000"
     23      HOST: "0.0.0.0"
    2224    ports:
    23       # host:container — wijzig de host-poort (links) als 3000 al bezet is.
    24       - "3000:3000"
     25      # Bind the host port to loopback only — reach the app through your reverse
     26      # proxy (Caddy/nginx) on this host, not directly from the internet.
     27      # Change the left side if 3000 is taken, e.g. "127.0.0.1:3001:3000".
     28      - "127.0.0.1:3000:3000"
    2529    volumes:
    26       # Alle data (database, geüploade media + audio) blijft hier bewaard.
     30      # All data (database, uploaded media + audio) is kept here.
    2731      - klonkt-data:/app/storage
    2832
  • scripts/install.sh

    r09ee2bd rf99bbe8  
    160160    echo "NODE_ENV=production"
    161161    echo "PORT=${KLONKT_PORT}"
     162    # Bind to loopback only: Caddy (this host) reaches it; the internet cannot
     163    # hit the app directly on its port, bypassing HTTPS.
     164    echo "HOST=127.0.0.1"
    162165    echo "SESSION_SECRET=${SECRET}"
    163166    echo "DATABASE_PATH=./storage/database.sqlite"
     
    168171  } > "$ENV"
    169172  chown "$KLONKT_USER:$KLONKT_USER" "$ENV"; chmod 600 "$ENV"
    170   ok "new .env (random SESSION_SECRET)"
     173  ok "new .env (random SESSION_SECRET, app bound to 127.0.0.1)"
    171174else
    172175  # sync the port in an existing .env with the chosen port
    173176  if grep -q '^PORT=' "$ENV"; then sed -i "s/^PORT=.*/PORT=${KLONKT_PORT}/" "$ENV"; fi
    174   ok "kept existing .env (port synced)"
     177  # harden older installs: bind to loopback if not already configured
     178  grep -q '^HOST=' "$ENV" || echo "HOST=127.0.0.1" >> "$ENV"
     179  ok "kept existing .env (port synced, bound to 127.0.0.1)"
    175180fi
    176181
  • src/server.js

    r09ee2bd rf99bbe8  
    8787const __dirname = path.dirname(fileURLToPath(import.meta.url));
    8888const PORT = process.env.PORT || 3000;
     89// Interface to bind. Default 0.0.0.0 (needed for Docker port-forwarding). Behind a
     90// reverse proxy on the same host, set HOST=127.0.0.1 so the app is NOT reachable
     91// directly from the internet (only via the proxy) — see README/install docs.
     92const HOST = process.env.HOST || '0.0.0.0';
    8993const isDev = process.env.NODE_ENV !== 'production';
    9094
     
    427431});
    428432
    429 server.listen(PORT, () => {
     433server.listen(PORT, HOST, () => {
    430434  console.log('');
    431435  console.log('🪶 Klonkt Beta');
Note: See TracChangeset for help on using the changeset viewer.