chore(docker): pass PAPERCLIP_ALLOWED_HOSTNAMES through to quickstart (#6846)

## Thinking Path

> - Operators run Paperclip in many places: localhost dev, LAN servers,
Tailscale meshes, cloud VMs
> - The server already supports a `PAPERCLIP_ALLOWED_HOSTNAMES` env var
for hostname allow-listing (`server/src/config.ts`)
> - But `docker/docker-compose.quickstart.yml` did not forward that env
var from the host to the container
> - So an operator running quickstart on a LAN gets "Hostname '<lan-ip>'
is not allowed for this Paperclip instance" with no env-only escape
hatch — they're forced to run the CLI inside the container to write
`config.json`
> - This PR adds a one-line passthrough so the existing env var works
end-to-end with the quickstart compose file
> - The benefit is parity with the server's documented config surface:
anything settable via env on a bare-metal run is now settable via env on
a quickstart docker run

## Linked Issues or Issue Description

**What happened?**

Running the quickstart compose file on a LAN host and opening the UI by
the machine's LAN address fails with "Hostname '<lan-ip>' is not allowed
for this Paperclip instance". The server supports
`PAPERCLIP_ALLOWED_HOSTNAMES` for exactly this case and `doc/DOCKER.md`
tells operators to set it, but `docker/docker-compose.quickstart.yml`
never forwards the variable into the container, so setting it on the
host has no effect.

**Expected behavior**

Setting `PAPERCLIP_ALLOWED_HOSTNAMES` on the host before `docker compose
up` reaches the server, the same way `PAPERCLIP_PUBLIC_URL` and the
provider keys do.

**Steps to reproduce**

1. `export PAPERCLIP_ALLOWED_HOSTNAMES=my-lan-host` alongside the other
quickstart variables.
2. `docker compose -f docker-compose.quickstart.yml up --build`.
3. Open `http://my-lan-host:3100` and observe the hostname rejection.

**Paperclip version or commit**

`master` when this PR was opened (May 2026); the quickstart file on
current `master` still has no passthrough. The branch is rebased onto
current `master`.

**Deployment mode**

Docker quickstart (`docker-compose.quickstart.yml`), authenticated and
private.

## What Changed

- `docker/docker-compose.quickstart.yml`: forward
`PAPERCLIP_ALLOWED_HOSTNAMES` from the host environment with an empty
default, matching the existing pattern used for `PAPERCLIP_PUBLIC_URL`,
`OPENAI_API_KEY`, etc.

## Verification

```sh
# 1. Set the env var
echo \"PAPERCLIP_ALLOWED_HOSTNAMES=localhost,my-lan-ip\" >> .env

# 2. Bring up the quickstart
docker compose --env-file .env -f docker/docker-compose.quickstart.yml up -d

# 3. Confirm the value reached the container
docker compose -f docker/docker-compose.quickstart.yml exec paperclip \\
  sh -c 'echo \"\$PAPERCLIP_ALLOWED_HOSTNAMES\"'
# → localhost,my-lan-ip

# 4. Confirm boot-time trusted-origins log includes the LAN host
docker compose -f docker/docker-compose.quickstart.yml logs paperclip | grep trustedOrigins

# 5. Confirm a request from the LAN host returns 401 (auth required), not the hostname rejection
curl -i -H \"Host: my-lan-ip:3100\" http://localhost:3100/api/auth/get-session
# → HTTP/1.1 401 Unauthorized
```

Tested locally on Linux with an authenticated/private deployment,
migrated DB from another paperclip instance, and a LAN host reaching the
container. The image was rebuilt with \`--no-cache\` from a clean
checkout of this branch's tip (no other unmerged work in the build
context) to confirm the change is self-contained.

## Risks

Low risk.
- Default value is empty string — behavior identical to before for any
operator who doesn't set the var.
- Env var name and semantics already implemented and documented on the
server side (\`server/src/config.ts\`); this PR only routes the value
through compose.
- One-line yaml change, no code touched, no tests affected.

## Model Used

- Claude (Anthropic) — Opus 4.7 (1M context). Used for the bug
isolation, the env-var-vs-config-file choice, and the PR write-up.
Authored alongside Ross Sclafani who tested end-to-end against a
migrated LAN deployment.

## Checklist

- [x] Thinking path traces from project context to this change
- [x] Model used specified (with version + capability details)
- [x] Checked ROADMAP.md — not a feature, no overlap with planned work
- [x] Ran tests locally (\`pnpm install --frozen-lockfile\`, \`pnpm
build\` clean; container rebuilt \`--no-cache\` from this branch tip and
verified end-to-end)
- Added or updated tests — N/A (compose env passthrough; no executable
code path)
- UI change screenshots — N/A (no UI)
- [x] No documentation updates needed (env var already documented
server-side)
- [x] Considered risks (above)
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] Will address all Greptile/reviewer comments before requesting
merge
This commit is contained in:
Ross Sclafani 2026-09-03 22:22:33 -05:00 committed by GitHub
parent b98badb246
commit 82ee0a68d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 3 additions and 0 deletions

View File

@ -33,6 +33,9 @@ services:
PAPERCLIP_DEPLOYMENT_EXPOSURE: "private"
# Base URL users will access the UI at
PAPERCLIP_PUBLIC_URL: "${PAPERCLIP_PUBLIC_URL:-http://localhost:3100}"
# Extra hostnames the instance accepts beyond the public URL host
# (LAN or Tailscale aliases), comma-separated; empty means none
PAPERCLIP_ALLOWED_HOSTNAMES: "${PAPERCLIP_ALLOWED_HOSTNAMES:-}"
# ── Required secret for session signing (generate with: openssl rand -hex 32) ──
BETTER_AUTH_SECRET: "${BETTER_AUTH_SECRET:?BETTER_AUTH_SECRET must be set}"