Skip to content

deploy: add Docker relay container, nginx alternative, and CN mirror docs - #36

Open
Hachiwa0 wants to merge 2 commits into
muggle-stack:masterfrom
Hachiwa0:feat/relay-docker
Open

deploy: add Docker relay container, nginx alternative, and CN mirror docs#36
Hachiwa0 wants to merge 2 commits into
muggle-stack:masterfrom
Hachiwa0:feat/relay-docker

Conversation

@Hachiwa0

Copy link
Copy Markdown

What

Adds an official container deploy option for the Relay, an nginx reverse-proxy alternative to the managed Caddy, and mainland-China mirror guidance.

Why

The project currently ships only a systemd venv + managed Caddy path. On a memory-constrained VPS (or any host that already manages services/TLS itself), a container is the natural fit. This was built and verified end-to-end against a real deployment (relay in Docker behind nginx, wrapper connected over wss).

What's in it

  • deploy/Dockerfile — multi-stage: Node stage builds web/dist from source (the repo does not track it), Python stage installs the same hash-locked wheels setup-vps.sh pins (--require-hashes --only-binary=:all: --no-binary=http-ece) and runs python -m cc_remote.relay as a non-root ccremote user (uid 10001, matching the systemd unit). Includes a HEALTHCHECK and parameterized PIP_INDEX_URL / PIP_EXTRA_INDEX_URL build args for mirrors.
  • deploy/docker-compose.yml — publishes the relay only to the host loopback (127.0.0.1:8765), a named volume for the SQLite device/Web Push state, read_only rootfs + tmpfs /tmp.
  • deploy/env.relay.docker.example — container-adapted env template.
  • deploy/nginx-reverse-proxy.conf.example — TLS + WebSocket front for hosts already running nginx; loopback-only requirement documented (the relay trusts forwarded transport metadata only from loopback peers).
  • .dockerignore
  • Docs: deploy/README.md container + nginx section, CN mirror tips in README.md / README_en.md, changelog entries.

Notes

  • Kept the relay's existing security posture: container runs non-root, compose publishes loopback-only, TLS termination stays with a host front.
  • http-ece is sdist-only on PyPI, so it is exempted with --no-binary exactly as the official installer does.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7ddf1d1dd3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread deploy/Dockerfile
# Relay application code, deploy reference files, and the hash-locked
# dependency list (the installed wheels are the ones setup-vps.sh pins).
COPY cc_remote/ ./cc_remote/
COPY deploy/ ./deploy/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exclude deploy/env.relay from the image

When users follow deploy/README.md and create deploy/env.relay with the login password, session secret, and wrapper token before building, this broad COPY deploy/ includes that file because neither .dockerignore nor .gitignore excludes it. The resulting image therefore contains all production credentials at /app/deploy/env.relay, exposing them to anyone who receives or can inspect the image; exclude the populated environment file and avoid copying deployment-only files into the runtime image.

Useful? React with 👍 / 👎.

Comment thread deploy/docker-compose.yml Outdated
ports:
# Loopback-only publish: the host nginx/Caddy terminates the public TLS
# and WebSocket connection and proxies it to 127.0.0.1:8765.
- "127.0.0.1:8765:8765"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve a loopback proxy peer through Docker

With the documented host-nginx topology and default Docker bridge networking, publishing host 127.0.0.1:8765 through this mapping does not make nginx appear as a loopback peer inside the container; Uvicorn therefore ignores X-Forwarded-Proto because cc_remote/relay/__main__.py trusts only 127.0.0.1,::1. The relay sees http instead of https, so the exact effective-target check in server.py rejects browser login and WebSocket Origins for the configured HTTPS PUBLIC_ORIGIN. Use a topology where the relay actually sees a loopback peer, or explicitly and narrowly trust the container bridge proxy.

AGENTS.md reference: AGENTS.md:L48-L55

Useful? React with 👍 / 👎.

Comment thread deploy/nginx-reverse-proxy.conf.example Outdated
Comment on lines +41 to +42
ssl_certificate /etc/letsencrypt/live/cc-remote.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cc-remote.example.com/privkey.pem;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bootstrap the certificate before enabling the TLS server

On a fresh host these certificate files do not exist, so enabling this configuration makes nginx -t fail before nginx or certbot --nginx can serve the included ACME challenge. Conversely, the numbered instructions run certbot before installing the configuration, so the claimed challenge location is not yet present. Provide an HTTP-only bootstrap configuration or use certbot certonly --webroot first, then enable this TLS block.

Useful? React with 👍 / 👎.

Comment thread README_en.md
Comment on lines +516 to +518
export UV_DEFAULT_INDEX=https://mirrors.aliyun.com/pypi/simple
# 2) Faster python-build-standalone runtime downloads (npmmirror)
export UV_PYTHON_INSTALL_MIRROR=https://registry.npmmirror.com/-/binary/python-build-standalone

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Forward the uv mirror variables through sudo

This mirror recipe does not work for the documented Linux installation path: deploy/install.sh crosses into sudo env at lines 120–128 while forwarding only CC_REMOTE_INSTALL_USER and the optional password-file variable, so normal sudo environment filtering removes both exported UV_* values before the bundled uv runs. Local sudo --help identifies -E/--preserve-env as the option for retaining these variables; alternatively, add both variables to the explicit sudo_env array.

Useful? React with 👍 / 👎.

Comment thread README_en.md Outdated
Comment on lines +522 to +523
If `install.sh` itself times out fetching the role bundle, pre-download the
release archive elsewhere and retry. When deploying the Relay in a Docker

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Point install.sh at the pre-downloaded release

Pre-downloading the archive does not affect a retry: deploy/install.sh always creates a new temporary directory and fetches both the archive and SHA256SUMS from CC_REMOTE_RELEASE_BASE_URL, with no local-cache lookup or archive argument. Users whose GitHub download times out will therefore hit the same failing request; document downloading both files and setting CC_REMOTE_RELEASE_BASE_URL=file:///..., or add an explicit local-source option.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant