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
apiservice 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
apiservice (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
.envis 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
apiservice 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 theapilogs.
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
apilogs first; it’s often missing env vars/secrets. - If you removed the
clientservice: that’s fine; the UI is served byapiin 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).