Running Synaplan as a Platform for Hosting Companies

Synaplan is built to be operated as a product — not just installed once. If you are a hosting provider, a managed-services company, or a systems integrator, you can run Synaplan on your own infrastructure and sell AI as a service to your customers: chat, RAG knowledge bases, embeddable widgets, an OpenAI-compatible API, WhatsApp and email channels — all under your brand, in your data center, under your jurisdiction.

This page explains how we run Synaplan in production ourselves, why the update model is hoster-friendly (features change, customer data never moves), and how the built-in tiers, quotas and billing let you package and sell AI capacity to your customers.


Why Synaplan Fits a Hosting Business

Property Why it matters to a hoster
One immutable Docker image The whole application (Symfony backend + built Vue frontend, served by FrankenPHP/Caddy) ships as ghcr.io/metadist/synaplan. Updating means pulling a new image — no code deploys, no build servers on your side.
Stateless web layer Backend, worker and WebSocket gateway hold no local state. Add nodes behind your load balancer and they just work — sessions, caches, locks and queues live in a shared Redis.
Multi-user with commercial controls built in User tiers, per-tier rate limits, monthly cost budgets, usage tracking and Stripe payments are part of the core — you don't have to bolt a billing layer on top.
Data sovereignty Everything can run on your hardware: local AI models via Ollama on your GPUs, MariaDB and Qdrant on your disks, uploads on your storage. No data has to leave your infrastructure — a real selling point for EU customers.
Apache-2.0 licensed No per-seat license fees, no vendor lock-in, no "open core" surprises. You may run it commercially.

The Reference Production Setup

This is the topology we run web.synaplan.com on. It is deliberately boring, and every piece of it is reproducible from public repositories: synaplan (the app), synaplan-platform (the production compose files), and synaplan-charts (Helm charts for Kubernetes).

                         Load balancer / CDN
                                │
          ┌─────────────────────┼─────────────────────┐
          ▼                     ▼                     ▼
   ┌─ Web node 1 ──┐    ┌─ Web node 2 ──┐    ┌─ Web node 3 ──┐
   │ backend       │    │ backend       │    │ backend       │   Docker
   │ worker        │    │ worker        │    │ worker        │   (from the
   │ centrifugo    │    │ centrifugo    │    │ centrifugo    │   one image)
   ├───────────────┤    ├───────────────┤    ├───────────────┤
   │ MariaDB       │◄──►│ MariaDB       │◄──►│ MariaDB       │   native Galera
   │ (Galera node) │    │ (Galera node) │    │ (Galera node) │   (NOT Docker)
   │ Qdrant node   │◄──►│ Qdrant node   │◄──►│ Qdrant node   │   local SSD
   └───────┬───────┘    └───────┬───────┘    └───────┬───────┘
           │                    │                    │
           ├────────────────────┼────────────────────┤
           ▼                    ▼                    ▼
     Shared Redis 7      NFS shared storage     GPU server(s)
     (cache, sessions,   (uploads, shared       (Ollama: LLMs +
      locks, queues,      .env, plugins)         embeddings,
      realtime engine)                           Whisper, TTS)

     + a small tools box running Coolify (Tika document
       extraction, monitoring, dashboards, side projects)

Key decisions, and why they are the hoster-friendly ones:

The database runs outside Docker — as a Galera cluster

Each web node runs a native mariadbd as part of a 3-node MariaDB Galera cluster with synchronous replication. Every backend talks only to the Galera node on its own host; Galera keeps all three in sync. A node can die and the other two keep serving reads and writes.

We keep the stateful layer (Galera, Qdrant storage) native and scripted, while everything stateless lives in containers. Databases don't enjoy being rescheduled by an orchestrator — containers do. This split gives you painless app updates and a database layer you manage with the tools your DBAs already know.

Vector search scales the same way

Qdrant runs as a 3-node cluster on local SSDs (never on network storage — Qdrant uses mmap and file locks), one node per web node, with each backend talking to its local instance. Smaller installs can skip Qdrant entirely and use MariaDB's built-in VECTOR support (VECTOR_STORAGE_PROVIDER=mariadb).

One shared Redis makes the cluster "just work"

A single Redis 7 instance carries cache, sessions, cluster-wide locks, rate-limiter state, the background-job queues (Redis Streams) and the Centrifugo realtime engine. That's the entire reason no sticky sessions are needed and any node can serve any user — see Architecture & Realtime for the full picture.

GPU capacity: your servers, your models

AI inference runs on dedicated GPU servers — in our case in a German data center (Frankfurt region) — running Ollama with open-weight models for chat, embeddings and reranking, plus Whisper for transcription and Piper for TTS (synaplan-tts). The web cluster reaches them over a private network.

You have three ways to provide model capacity, and you can mix them per model:

  1. A GPU box or two with Ollama — the simplest start; one modern GPU server handles a surprising amount of traffic.
  2. A Kubernetes GPU cluster — use the synaplan-charts Helm charts to run Synaplan and scale GPU inference on Kubernetes.
  3. Cloud AI providers — plug in OpenAI, Anthropic, Groq or Gemini API keys for models you don't want to host. Users and admins pick models per task in the UI; nothing is hardcoded.

Auxiliary services via Coolify

Supporting services that don't belong in the hot path — Apache Tika for document text extraction, monitoring dashboards, internal tools — run on a small separate box managed with Coolify, a self-hosted PaaS. One cheap VM, git-push deploys, TLS handled for you. It keeps the production web nodes clean and single-purpose.


Updates: the Image Changes, Your Customers' Data Doesn't

This is the part hosters care about most, so let's be precise.

Every merge to main in the synaplan repository runs the full CI pipeline (linting, static analysis, backend and frontend test suites, E2E smoke tests) and then builds and publishes the Docker imageghcr.io/metadist/synaplan:latest for main, plus semantic-version tags for releases. The image is immutable: application code, built frontend, web-server config, all baked in.

Everything stateful lives outside the image, in places an update never touches:

Data Where it lives Survives an update
Users, chat history, settings, widgets, API keys MariaDB (Galera)
Uploaded files (documents, images, audio) Volume / NFS mount (up/)
Vector data (RAG embeddings, AI memories) Qdrant / MariaDB VECTOR
Local AI models Ollama on the GPU servers
Secrets & configuration .env on your host

An update is therefore a rolling image swap, one node at a time:

docker compose down
docker compose pull          # fetch the new image
docker compose up -d         # start; migrations run automatically
curl -sf http://localhost/api/health   # wait until healthy, then next node

Database schema changes ship as migrations inside the image and run automatically on container start — idempotent and Galera-safe. No re-vectorization, no re-uploading, no data migration scripts. Your customers keep their documents, their chat history, their trained knowledge bases and their widget configurations; they just wake up to new features. That's the whole update story.

Pin a version tag instead of latest if you want to control exactly when each customer environment moves forward.


Selling AI to Your Customers

Synaplan ships the commercial plumbing you need to package and sell AI capacity. It's a single deployment, multi-user model: one instance serves many customer accounts, each metered and limited individually. (For customers who demand full isolation, run them a dedicated instance — it's one compose file.)

Tiers, quotas and budgets

  • User levels — every account has a tier: ANONYMOUS, NEW (free), PRO, TEAM, BUSINESS, plus ADMIN for your operators. Admins change a user's level in the built-in admin area (/admin → Users).
  • Per-tier rate limits — messages, image/video/audio generations, file analyses, uploads and storage are capped per tier. Free tiers get lifetime totals (e.g. 50 messages, then upgrade); paid tiers get hourly + monthly allowances. All limits are configuration (RATELIMITS_* config groups), not code.
  • Monthly cost budgets — each paid tier carries a monthly provider-cost budget in EUR. Every AI call's actual cost is computed and logged; when a customer's consumption reaches their budget, the gate closes until the next period or a top-up. A configurable markup percentage sits between the raw provider cost and what counts against the customer's budget — that margin is your revenue on metered usage.
  • Usage tracking — every billable call is logged with tokens, cost, model, provider and latency. Customers see their own consumption on their usage page; you see everything (including top users by cost) in the admin area.

Payments

Stripe integration is built in: subscription checkout for the paid tiers, a customer billing portal, webhooks that upgrade/downgrade accounts automatically, and one-time top-ups that extend a customer's current budget — effectively selling extra tokens mid-month. Mobile in-app purchases (Apple/Google) are supported too. Don't want online payments? Leave Stripe unconfigured and set tiers manually — invoice your customers however you already do.

Everything a customer creates bills the customer

Per-user API keys (including the OpenAI-compatible endpoint) and per-user chat widgets all meter against the owning account's tier and budget. A customer can embed their widget on their own website; the traffic it generates counts against their plan — and if they run out, the widget pauses gracefully until they upgrade. Your pricing stays enforceable end to end.

How-to: from zero to selling

  1. Start on one machine. Clone synaplan, docker compose up -d, and you have the full stack — including local models — for evaluation.
  2. Build the production layout. Use synaplan-platform as the template for a multi-node setup (Galera + shared Redis + NFS + GPU node), or synaplan-charts on Kubernetes. Set real secrets in .env — the app refuses changeme_* defaults in production.
  3. Provide model capacity. Ollama on your GPUs for sovereignty, cloud provider keys for frontier models, or both. Curate which models are active and default in the admin model catalog.
  4. Define your packages. Set the per-tier rate limits and monthly budgets, choose your markup percentage, create the matching prices in Stripe, and connect the webhook.
  5. Put your brand on it. Your domain, your login page, your favicon — and every widget your customers embed carries your infrastructure underneath.
  6. Operate it like a pro. Watch /api/health per node, back up Galera (dumps or snapshots), snapshot Qdrant collections on a schedule, and keep uploads on redundant storage. Update by rolling the image as described above.

A Fair Open-Source Deal

Synaplan is Apache-2.0. You can take everything on this page and build a business on it without paying us a cent — that's the license, and we mean it.

We're building Synaplan the way the open-source businesses we admire grew: WordPress became the backbone of the hosting industry because thousands of hosters ran it commercially and the ecosystem fed improvements back. Red Hat proved you can build a serious company on genuinely free software plus honest support relationships. That's the model we work in — a real open-source business, not open-core bait.

So if Synaplan starts making money for you, here's what we kindly ask:

  • Contribute back. Bug reports, fixes, docs, translations, plugins — send PRs to github.com/metadist. Fixes you upstream are fixes you never have to re-apply after an image update.
  • Consider a monthly support agreement. If Synaplan is running well for your business, a modest monthly support fee gets you priority answers from the people who wrote the code, guidance on cluster architecture and scaling, and a direct line into the roadmap — and it funds the development every hoster benefits from. Talk to us: [email protected].
  • Tell us what you're building. Hosting partners shape where the platform goes — multi-tenant tooling, reseller features, operator dashboards all get prioritized by real operator demand.

No pressure, no license traps, no rug pulls. Run it, sell it, grow with it — and if it works well, help keep it thriving.


Related