Deploy self hosting with docker compose behind nginx: TLS, per-client auth, and OAuth for Claude connectors - #36
Open
laazik wants to merge 10 commits into
Open
Deploy self hosting with docker compose behind nginx: TLS, per-client auth, and OAuth for Claude connectors#36laazik wants to merge 10 commits into
laazik wants to merge 10 commits into
Conversation
added 7 commits
August 13, 2026 13:26
This commit adds the nginx token frontend to the mcp server, which includes setting up the Docker Compose configuration, creating deployment scripts, and adding documentation. The nginx token frontend provides client authentication and rate control, enhancing the security and performance of the mcp server.
This commit adds an OAuth facade for the Anthropic Claude connector, which cannot send a static Authorization header. The facade allows the connector to authenticate using OAuth credentials instead.
This commit adds an OAuth facade for the Anthropic Claude connector, which cannot send a static Authorization header. The facade allows the connector to authenticate using OAuth credentials instead.
…into nginx-front
… a map file The OAuth client secret is now stored as a SHA-256 digest in a map file instead of being stored in an htpasswd file. This change was made to improve security and to make the OAuth client secret handling more consistent with the rest of the system. The njs module will now compare the SHA-256 digest of the client secret presented by the client with the stored digest.
There was a problem hiding this comment.
Pull request overview
This PR adds a self-hosting deployment for estonian-mcp using Docker Compose with an nginx edge proxy that terminates TLS (via Let’s Encrypt/certbot), enforces per-client bearer auth + rate limiting, and provides a minimal OAuth facade (implemented with nginx njs) for clients that can’t send static Authorization headers (e.g., Claude custom connectors).
Changes:
- Add a Compose stack (
app+nginx+certbot) that keeps the app off host-published ports and puts TLS, auth, and rate limiting at the edge. - Add nginx configuration/templates and njs handler to implement per-client token auth and an OAuth-like token endpoint for discovery-based clients.
- Add operator scripts + docs for issuing/revoking client credentials and bootstrapping/renewing certificates, plus supporting repo hygiene (.gitignore/.gitattributes/.dockerignore).
Reviewed changes
Copilot reviewed 19 out of 20 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| Dockerfile | Ensures /data exists and is writable by the non-root runtime user for persisted metrics. |
| docker-compose.yaml | New Compose stack wiring app/nginx/certbot, internal networking, and mounts. |
| deploy/revoke-client.sh | Script to revoke a client across all credential files. |
| deploy/README.md | Deployment/operator documentation for nginx + Compose + OAuth facade. |
| deploy/nginx/templates/mcp.conf.template | Nginx config template: TLS termination, auth, rate limiting, MCP proxying, OAuth metadata endpoints, and token endpoint wiring. |
| deploy/nginx/secrets/tokens.map.example | Example token map file for nginx map-based auth. |
| deploy/nginx/reload-loop.sh | Periodic nginx reload script to pick up renewed certificates. |
| deploy/nginx/njs/oauth.js | njs token endpoint implementation to support client_secret_post and client_secret_basic. |
| deploy/nginx/https-port-suffix.envsh | Entrypoint hook to compute a redirect port suffix for non-443 HTTPS. |
| deploy/nginx/Dockerfile | Custom nginx image with njs module and entrypoint hooks. |
| deploy/new-token.sh | Script to mint a static bearer token client entry. |
| deploy/new-oauth-client.sh | Script to mint OAuth facade client credentials (secret + access token + bearer token map line). |
| deploy/local-cert.sh | Helper to create a self-signed cert for local testing on non-80/443 ports. |
| deploy/lib.sh | Shared credential/map-file helper functions. |
| deploy/init-letsencrypt.sh | Bootstrap script to obtain the initial Let’s Encrypt cert by starting nginx with a throwaway cert. |
| .vscode/settings.json | Editor excludes for common generated/config files. |
| .gitignore | Ignore deployment secrets/state and local editor config (with allowlist exceptions). |
| .gitattributes | Enforces LF line endings for scripts/templates to avoid CRLF issues in containers. |
| .env.example | New example env file for Compose deployment variables. |
| .dockerignore | Excludes deployment artifacts and env files from the app image build context. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
added 3 commits
August 13, 2026 18:41
The OAuth authorization endpoint is added to handle client authorization requests. The rate limiting documentation is improved to better explain the rate limiting mechanism. The phase ordering is enhanced to ensure that rate limiting is applied correctly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This adds a Docker Compose deployment that runs estonian-mcp behind nginx, with certbot for Let's Encrypt certificates. Until now the ASGI wrapper in
server.pywas the only thing between the internet and the Python process, and it supports exactly one bearer token. nginx now terminates TLS and absorbs malformed requests, slow-client attacks, oversized bodies, connection floods and credential stuffing before any of it reaches uvicorn.It also holds as many tokens as there are clients, each with its own name in the access log, its own rate-limit bucket, and revocation that is one deleted line plus a reload. The app container is no longer published to the host: it is reachable only from nginx over an internal network, and it keeps its own bearer auth on that hop so it is not an open server if the network is ever misconfigured.
The second larger addition is an OAuth facade, because Claude's custom connector cannot send a static
Authorizationheader and runs OAuth discovery instead. nginx serves protected-resource and authorization-server metadata plus authorize and token endpoints.The token endpoint is the one piece that is not plain nginx config, because Claude authenticates with
client_secret_postand nginx core cannot read a request body. That is handled by njs, nginx's own JavaScript module, in about 40 lines; it acceptsclient_secret_basicas well, so curl and conforming clients keep working.NB! This is not a full fledged OAuth but rather naive implementation where the client credentials either for individual accounts or team accounts are used to fetch static tokens!
Has been tested in actual live environment and works as expected.