How to Deploy ai-memory Behind a Caddy or Cloudflare TLS Reverse Proxy
Deploy ai-memory behind a TLS-terminating reverse proxy by using the provided Docker Compose templates in docker/compose.tls.caddy.yml or docker/compose.tls.cloudflared.yml, configuring environment variables like AI_MEMORY_BIND=0.0.0.0:49374 and AI_MEMORY_AUTH__SECURE_COOKIE=true, and allowing the external proxy to handle HTTPS termination while ai-memory listens on HTTP internally.
The akitaonrails/ai-memory repository intentionally omits native TLS termination to keep the core server lightweight and portable. Instead, the project expects operators to deploy an external reverse proxy—such as Caddy or Cloudflare Tunnel—to encrypt traffic. This architecture is mandatory when running multi-user mode or binding to non-loopback addresses, as bearer tokens and session cookies must travel over HTTPS to prevent sniffing on the LAN or internet.
Why Use a Reverse Proxy for ai-memory?
ai-memory’s HTTP server binds to localhost:49374 by default, which is safe for single-user local development. However, production deployments require external access and multi-user authentication, necessitating TLS encryption handled upstream.
Security Requirements for Multi-User Mode
When running in multi-user mode, ai-memory stores per-user bearer tokens that authenticate access to the /web interface and API. According to the source code analysis, these tokens and session cookies travel unencrypted if the connection uses plain HTTP. A TLS-terminating reverse proxy ensures credentials remain confidential when traversing untrusted networks.
Network Binding Considerations
Setting AI_MEMORY_BIND=0.0.0.0:49374 exposes the server to other machines on the network. As documented in docs/https-via-proxy.md, this binding pattern makes TLS mandatory for any production or multi-user deployment to prevent token leakage and man-in-the-middle attacks.
Deployment Option 1: Caddy with Let's Encrypt (Public Domain)
For deployments with a public domain and open ports 80/443, Caddy automates certificate provisioning via Let’s Encrypt. The repository provides a complete template in docker/compose.tls.caddy.yml.
Docker Compose Configuration
The compose file defines two services: the ai-memory application and the Caddy reverse proxy. Only Caddy exposes host ports; ai-memory remains on the internal Docker network.
services:
ai-memory:
image: akitaonrails/ai-memory:latest
expose:
- "49374"
env_file: .env.production
caddy:
image: caddy:2-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
Caddyfile Definition
Create a Caddyfile in the same directory with a three-line reverse-proxy definition. Caddy automatically manages the ACME HTTP-01 challenge, obtains a Let's Encrypt certificate, and renews it 30 days before expiry.
memory.example.com {
reverse_proxy ai-memory:49374
}
Required Environment Variables
Configure ai-memory to trust the proxy and enforce secure cookies. The AI_MEMORY_ALLOWED_HOSTS must include your public domain to prevent HTTP Host header attacks.
AI_MEMORY_AUTH_TOKEN=your-random-secure-token
AI_MEMORY_AUTH__SECURE_COOKIE=true
AI_MEMORY_ALLOWED_HOSTS=memory.example.com,localhost,127.0.0.1
AI_MEMORY_BIND=0.0.0.0:49374
Deployment Option 2: Caddy with Internal CA (LAN-Only)
For LAN-only deployments without public DNS, Caddy can function as an internal Certificate Authority. This path requires installing Caddy’s root certificate on each client device.
Local Certificate Configuration
Enable local_certs in the global block and specify internal hostnames or IP addresses in the site block.
{
local_certs
}
homelab.local, 192.168.1.50 {
reverse_proxy ai-memory:49374
}
Client Trust Installation
After starting the container, extract the root certificate from the Caddy volume (caddy-data) and install it on macOS, Linux, Windows, iOS, or Android clients. Without this step, browsers will reject the self-signed certificates generated by Caddy’s internal CA.
Deployment Option 3: Cloudflare Tunnel
Cloudflare Tunnel (cloudflared) provides TLS termination at Cloudflare’s edge without opening inbound ports on your firewall. This pattern suits deployments behind CGNAT or strict firewall rules.
Sidecar Container Setup
The template in docker/compose.tls.cloudflared.yml adds a cloudflared sidecar that establishes an outbound-only tunnel.
services:
cloudflared:
image: cloudflare/cloudflared:latest
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
Tunnel Token Configuration
Obtain a tunnel token from the Cloudflare dashboard and store it in your environment file. Clients connect via Cloudflare’s infrastructure and receive a publicly trusted certificate, eliminating the need for local root certificate distribution.
CLOUDFLARE_TUNNEL_TOKEN=eyJ...your-token...
Essential Environment Configuration
Regardless of the proxy choice, certain environment variables must be set in crates/ai-memory-cli/src/commands/serve.rs validated configurations:
AI_MEMORY_BIND=0.0.0.0:49374— Binds to all interfaces so the proxy can reach the containerAI_MEMORY_AUTH__SECURE_COOKIE=true— Enforces theSecureflag on session cookies, requiring HTTPSAI_MEMORY_ALLOWED_HOSTS— Whitelist of hostnames the server will accept to prevent DNS rebinding attacksAI_MEMORY_AUTH_TOKEN— Master token for multi-user authentication
Common Pitfalls and Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
| Port 80 not reachable → ACME errors | Router or firewall blocks inbound 80/443 | Forward ports to the Caddy host or switch to Cloudflare Tunnel |
| Certificate renewal silently fails | Caddy logs not monitored | Set up log monitoring (e.g., journalctl -u docker-compose@...) or health-checks |
| Clients reject TLS (LAN-only) | Root certificate not installed on client | Install the Caddy-generated root certificate on each device from the caddy-data volume |
| Token leakage (Cloudflare) | Tunnel token exposed in repository | Store .env files with mode 0600 and never commit them to version control |
Summary
- ai-memory intentionally does not terminate TLS; it requires an external reverse proxy for HTTPS.
- Use
docker/compose.tls.caddy.ymlfor public domains with automatic Let’s Encrypt certificates or internal LAN CA setups. - Use
docker/compose.tls.cloudflared.ymlfor outbound-only tunnels via Cloudflare when inbound ports are unavailable. - Always set
AI_MEMORY_BIND=0.0.0.0:49374,AI_MEMORY_AUTH__SECURE_COOKIE=true, andAI_MEMORY_ALLOWED_HOSTSwhen deploying behind a proxy. - Consult
docs/https-via-proxy.mdfor the full decision matrix on choosing between Caddy and Cloudflare deployment patterns.
Frequently Asked Questions
Does ai-memory support native TLS termination?
No. According to the architecture defined in the source code, ai-memory handles HTTP only and expects an external TLS-terminating reverse proxy such as Caddy or Cloudflare to manage HTTPS. This design keeps the core binary small and allows operators to choose their preferred certificate management strategy.
Why must I bind to 0.0.0.0 when using a reverse proxy?
Binding to 0.0.0.0:49374 instructs ai-memory to listen on all network interfaces, not just localhost. This is necessary because Docker containers communicate over internal bridge networks; if ai-memory binds only to 127.0.0.1, the Caddy or Cloudflare sidecar cannot reach the application container.
How do I obtain the Cloudflare Tunnel token?
Log in to the Cloudflare Zero Trust dashboard, navigate to Access > Tunnels, and create a new tunnel. The dashboard provides a command containing a TUNNEL_TOKEN (starting with eyJ). Copy this token into your .env file as CLOUDFLARE_TUNNEL_TOKEN. Never commit this token to version control.
Is the internal Caddy CA safe for production use?
The internal Caddy CA is designed for LAN-only deployments where devices are under your administrative control. While the cryptography is sound, browsers do not trust Caddy’s internal root certificate by default. For internet-facing production environments, use Caddy with Let’s Encrypt or Cloudflare Tunnel to provide publicly trusted certificates.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →