Running LibreChat on Coolify (and actually keeping it updated)

February 1, 2025

This post documents running a self-hosted LibreChat instance on a Coolify server. The first deploy is straightforward, but common failure modes (404 / bad gateway) and upgrades while using :latest are less obvious.

These are the key points that mattered.

The key gotcha: the API container serves the web UI

In LibreChat’s compose setup, the api service serves the static client assets. You typically do not need to expose a separate client container.

Reference (from my fork at the time): LibreChat API server source.

Practical implication:

  • Add your domain to the api service in Coolify.
  • You should be able to hit the domain and see the UI, not just an API response.

Deploying on Coolify with deploy-compose.yml

Steps:

  • Create a new resource from a public GitHub repo (your fork or the upstream LibreChat repo).
  • Choose “Docker Compose”.
  • Set the compose file to deploy-compose.yml.
  • Add a domain to the api service (with the default compose, the UI is on port 3080).
  • Deploy and then hit the URL.

Don’t rely on a committed .env

One trap: renaming .env.example to .env in your fork and assuming Coolify will use it.

  • LibreChat’s .env is typically gitignored, so it often won’t make it to the server through your repo anyway.
  • Treat Coolify’s environment variable editor as the source of truth for deployment-time env vars.

The minimum environment variables (and how to generate them)

LibreChat can appear to start while the real failure is only visible in logs. The fastest way to get unstuck is:

  • Check logs for the api service in Coolify.
  • When you see missing-secret / crypto-related errors, generate values with LibreChat’s toolkit: creds generator

Here’s the minimum set I used to get a clean first run with OpenAI models available. Generate your own secrets—do not copy/paste these placeholders as-is:

ALLOW_REGISTRATION=true
CREDS_IV=<generate>
CREDS_KEY=<generate>
JWT_REFRESH_SECRET=<generate>
JWT_SECRET=<generate>
MEILI_MASTER_KEY=<generate>
OPENAI_API_KEY=user_provided
RAG_PORT=8001

Notes:

  • ALLOW_REGISTRATION=true: needed so you can create the first user.
  • OPENAI_API_KEY=user_provided: makes the OpenAI models show up, and LibreChat will prompt you to supply a key in the UI.
  • The CREDS_* / JWT_* secrets: required for the app to behave correctly; missing values can lead to confusing 404s / gateway errors.
  • MEILI_MASTER_KEY: I included it because the creds generator produced it; if you’re not using search/RAG features, your needs may differ—again, follow the api logs.

Upgrades: why :latest may still be old

Coolify can end up reusing cached images even if your compose references :latest, leaving you on an older LibreChat tag after redeploys.

The fix was to add a custom start command so the deployment always pulls images:

docker compose -f ./deploy-compose.yml up -d --pull always

After that, redeploying correctly pulled the newer LibreChat image.

Troubleshooting checklist

  • If the domain shows 404: check api logs first; it’s often missing env vars/secrets.
  • If you removed the client service: that’s fine; the UI is served by api in this setup.
  • If upgrades don’t apply: force a pull with the custom start command above.

If you run into issues, the fastest path is usually: open the api service logs, find the first actionable error, and add the missing env var(s).