Edit history

Self-hosting: undocumented configuration requirements and missing documentation has not been edited, so there are no earlier versions.

Current version | Original by Rex
Show

Self-hosting: undocumented configuration requirements and missing documentation

Description

I used Claude to find and track all of its fixes, but I do not want to push AI generated code into a public repo, and felt it would be better to solve the issues in the way the project owners want to. Hell these may be by design I dont know, but I think it points to valuable details to get the self-hosting side up and running faster. After successfully deploying Fluxer in self-hosted monolith mode (Docker Compose, refactor branch), I've compiled a list of configuration requirements that aren't documented and caused issues during deployment. None of these are code bugs per se — they're documentation/configuration gaps that make self-hosting difficult without trial and error. This is a comprehensive deployment guide (linked below) that covers all of these. Sharing these findings in case they're useful for improving the self-hosting documentation.

Environment

  • Branch: refactor
  • Deployment: Docker Compose, monolith mode, built from source
  • Reverse proxy: Traefik with Cloudflare-terminated TLS

Gap 1: static_dir must be set in config.json

Symptom: Health check shows app: disabled and the web SPA doesn't serve (API works but no frontend). Details: The monolith server reads Config.services.server.static_dir from the JSON config file to know where to find the built frontend assets. This isn't mentioned in any example config. Without it, the app server component simply doesn't start. The correct value is "/usr/src/app/assets" (where the Dockerfile copies the built frontend).

Gap 2: NATS is a hard dependency, not optional

Symptom: Server crashes on startup with CONNECTION_REFUSED to NATS on port 4222. Details: The server uses NATS JetStream for its job queue (cron tasks, background processing) and will not start without it. Two NATS containers are needed: one for core pub/sub (port 4222) and one for JetStream (port 4223 with --jetstream --store_dir /data). The docker-compose example doesn't include NATS containers, and there's no documentation indicating they're required.

Gap 3: GHCR image is private / requires authentication

Symptom: docker pull ghcr.io/fluxerapp/fluxer-server:stable fails with pull access denied. Details: The README references a pre-built Docker image, but it requires authentication to pull. Self-hosters must build from source. This should be documented clearly, especially since building from source requires several Dockerfile fixes (see separate issue).

Gap 4: LiveKit webhook config requires api_key field

Symptom: LiveKit container enters a restart loop with api_key is required to use webhooks. Details: The webhook section in livekit.yaml must include an api_key field alongside the urls array. This isn't obvious from LiveKit's docs, and the error message only appears in LiveKit container logs (not in the Fluxer server logs).

Gap 5: sqlite_path must be an absolute path

Symptom: Database is created inside the container's filesystem (not in the mounted data volume) and is lost when the container is recreated. Details: Setting "sqlite_path": "./data/fluxer.db" in config.json resolves the path relative to the fluxer_server/ source directory inside the container, not relative to the data volume mount. It must be an absolute path: "/usr/src/app/data/fluxer.db". This is a subtle issue because everything appears to work until the container is recreated and all data is gone.

Gap 6: Build requires BASE_DOMAIN to match runtime config

Symptom: Frontend tries to connect to chat.example.com instead of the actual domain. Browser shows connect-src CSP errors. Details: The frontend build reads the config template which has chat.example.com as the default domain. This gets baked into the JavaScript bundle. The domain must be replaced at build time via the BASE_DOMAIN build arg, and it must exactly match the domain.base_domain value in the runtime config.json. There's no runtime override — it's compiled into the bundle.

Deployment Guide

I used Claude to write a comprehensive deployment guide documenting all 20 gotchas I encountered while self-hosting Fluxer: https://gist.github.com/PaulMColeman/e7ef82e05035b24300d2ea1954527f10