DocumentationDeployment

Rust · 0.1.0

Reverse proxy and TLS

Put a public origin in front of a privately reachable application port.

Origins and forwarding

Terminate TLS with your chosen proxy and forward the application paths to its private listener. Set MEMOS_INSTANCE_URL to the external origin, for example https://notes.example.com. Keep the application port off the public network. Configure the proxy to preserve the host and forwarded protocol, and allow streamed responses and sufficiently large authorized uploads.

Trust only your proxy

MEMOS_TRUSTED_PROXIES controls which peers may supply client-address information. Its default is private-network trust. Set it to the actual proxy network where possible, and confirm that untrusted clients cannot forge forwarded addresses. Rate limits rely on correct client identity. A proxy that buffers events or closes idle streams can disrupt live updates even while ordinary pages load.

Test from outside

Check the external health endpoint, sign-in and sign-out, an attachment upload/download, and an event stream through the proxy. Confirm TLS and cookie behavior in the browser. Use the troubleshooting guide to separate proxy failures from application failures.

Nginx example for a same-host native backend

Prerequisites: a domain pointing at this host, Nginx already installed, an issued certificate and key, and a native Memos process reachable only on 127.0.0.1:5230. Set MEMOS_INSTANCE_URL=https://notes.example.com and MEMOS_TRUSTED_PROXIES=127.0.0.1/32 on the application; replace the domain and certificate paths below. This assumes Nginx itself runs on the host. For a proxy container or Docker-published backend, bridging/NAT can change the peer seen by Memos: use its actual reachable backend and observed proxy peer range instead of copying 127.0.0.1/32. The certificate is not created by this snippet.

server {
    listen 80;
    server_name notes.example.com;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl;
    server_name notes.example.com;
    ssl_certificate /etc/ssl/memos/fullchain.pem;
    ssl_certificate_key /etc/ssl/memos/privkey.pem;
    client_max_body_size 50m;

    location / {
        proxy_pass http://127.0.0.1:5230;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_buffering off;
        proxy_read_timeout 300s;
        proxy_cache off;
    }
}

Validate before opening traffic

Place the server blocks in the include location used by your Nginx installation. Run nginx -t before reloading its service. The single-proxy example overwrites forwarded client addresses instead of preserving untrusted values sent by an internet client. The 50 MiB proxy request limit is an example transport ceiling, not a change to the application upload limit. Consult the Nginx proxy directives when adapting buffering or timeouts.

nginx -t
curl --fail --show-error http://127.0.0.1:5230/healthz
curl --fail --show-error https://notes.example.com/healthz

Interpret the checks

If the direct check fails, fix the application listener first. If only the HTTPS check fails, check DNS, certificate validity, proxy upstream connectivity and Nginx logs. A 413 means a size limit rejected the request; increasing only one layer may not help. A 502/504 usually requires inspecting the upstream connection or timing. Finish with a normal-account sign-in, upload/download and live-update check in the browser. Do not disable TLS verification to turn a failed test green.