Adds a complete deployment surface for production:
Dockerfile multi-stage 3.12-slim build, collectstatic
baked into the image, runs as non-root mnemosyne
uid/gid 1000.
docker/entrypoint.sh dispatches `web | mcp | worker | beat | migrate
| setup | shell` from a single image, so every
service in compose runs the same artifact.
docker-compose.yaml five services: static-init (one-shot copies
statics into the shared volume on every up),
web (gunicorn), mcp (uvicorn), worker (celery),
nginx. External services (Postgres, Neo4j,
RabbitMQ, S3, Memcached, embedder, reranker)
reached over the 10.10.0.0/24 internal network
and configured via mnemosyne/.env.
nginx/mnemosyne.conf reverse proxy: /library/* and /admin/* → web,
/mcp/* → mcp, /static/* → volume, /metrics
internal-network-only (127/8 + RFC1918), /healthz
proxies to /mcp/health for liveness probes.
.gitea/workflows/ CVE scan + image build, image pushed to
git.helu.ca/r/mnemosyne. Trivy scans pyproject
extras (dev/test/lint/docs) and the built image.
pyproject.toml adds [test], [lint], [docs] extras so the CI
pip-compile step has something to resolve.
README documents the bring-up flow (`docker compose run --rm web migrate`,
then `setup`, then `up -d`), day-to-day commands, and the env-var values
that need adjusting for production (DEBUG=False, KVDB_LOCATION pointing
at the external memcached, AWS keys filled in, etc.).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
87 lines
3.0 KiB
Plaintext
87 lines
3.0 KiB
Plaintext
# Mnemosyne nginx — single virtual host that fronts the Django web app
|
|
# and the FastMCP server. HAProxy on Titania terminates TLS and routes by
|
|
# hostname; this nginx is plain HTTP on the internal network.
|
|
|
|
# Map of upstreams to give us readable proxy_pass targets and easy retries.
|
|
upstream mnemosyne_web {
|
|
server web:8000 max_fails=3 fail_timeout=30s;
|
|
}
|
|
|
|
upstream mnemosyne_mcp {
|
|
server mcp:22091 max_fails=3 fail_timeout=30s;
|
|
}
|
|
|
|
server {
|
|
listen 80 default_server;
|
|
server_name _;
|
|
|
|
# Reasonable limits — file uploads to the ingest endpoint can be big,
|
|
# but the bulk path is S3-direct from Daedalus. 64 MB covers admin
|
|
# uploads and direct REST POST /library/api/items/upload.
|
|
client_max_body_size 64m;
|
|
client_body_timeout 120s;
|
|
|
|
# Mnemosyne's REST API — Django REST Framework views + admin.
|
|
# Under /library/api/* per mnemosyne/urls.py and /admin/* per Django.
|
|
location /library/ {
|
|
proxy_pass http://mnemosyne_web;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_read_timeout 300s;
|
|
}
|
|
|
|
location /admin/ {
|
|
proxy_pass http://mnemosyne_web;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_read_timeout 300s;
|
|
}
|
|
|
|
# FastMCP Streamable HTTP at /mcp/ and SSE at /mcp/sse/.
|
|
# Long-running streams need disabled buffering and a generous timeout.
|
|
location /mcp/ {
|
|
proxy_pass http://mnemosyne_mcp;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header Connection "";
|
|
proxy_buffering off;
|
|
proxy_cache off;
|
|
proxy_read_timeout 600s;
|
|
}
|
|
|
|
# Static files baked into the image at /app/staticfiles, mounted into
|
|
# this nginx via a named volume populated by the web service.
|
|
location /static/ {
|
|
alias /var/www/static/;
|
|
access_log off;
|
|
expires 30d;
|
|
}
|
|
|
|
# Prometheus scrape endpoint — internal networks only.
|
|
# Allows: localhost + RFC1918 private ranges (10/8, 172.16/12, 192.168/16).
|
|
location /metrics {
|
|
allow 127.0.0.0/8;
|
|
allow 10.0.0.0/8;
|
|
allow 172.16.0.0/12;
|
|
allow 192.168.0.0/16;
|
|
deny all;
|
|
proxy_pass http://mnemosyne_web;
|
|
access_log off;
|
|
}
|
|
|
|
# Liveness probe — proxies through to the MCP health endpoint.
|
|
location = /healthz {
|
|
proxy_pass http://mnemosyne_mcp/mcp/health;
|
|
access_log off;
|
|
}
|
|
}
|