Run many sites from one deployment
Fleet mode serves many small docs sites from one web service, one worker and one Postgres database. Each site keeps its own schema, settings, readers and secrets.
Most deployments run one site. Providers that host many small sites, such as free or trial plans, can run them as a fleet instead of giving each one its own services.
How sites stay apart
- Each site's tables live in their own Postgres schema,
site_<slug>. Its connections can only see that schema. - Requests are routed by host name. Each site runs as its own app, configured from its own settings, so it has its own session secret, admin token, caches and public URL.
- Notifications that clear caches carry the schema in their channel name, so one site's changes never touch another's.
- Each site's images, themes and PDFs are stored under a prefix of their own.
Per-reader filtering works exactly as on a single site.
Running a fleet
Run opend-server fleet serve as the web service and opend-server fleet
worker as the worker, with opend-server fleet migrate before each deploy so
an upgrade's database changes reach every site's schema first, both with the fleet variables in Environment variable reference. Point every site's host names (and editor host names) at the
web service, typically with wildcard DNS records.
Sites are managed through the fleet admin API, on OPEND_FLEET_HOST with the bearer
token OPEND_FLEET_TOKEN:
| Route | Does |
|---|---|
POST /fleet/api/sites | Creates a site from
slug, hosts, editorHosts and
env: the settings a single-site deployment would get as environment variables
(PUBLIC_URL, SESSION_SECRET, OPEND_ADMIN_TOKEN
and so on). The settings must form a valid configuration. The fleet supplies the database,
storage and address variables itself. |
GET /fleet/api/sites, GET /fleet/api/sites/:slug | Lists sites, with the names of their settings but never the values. |
PATCH /fleet/api/sites/:slug | Changes hosts or settings. The site restarts on its next request. |
POST /fleet/api/sites/:slug/suspend, /resume | Pauses a site (readers see that it is paused) or brings it back. |
DELETE /fleet/api/sites/:slug | Deletes the site, its schema and its stored files. |
PUT /fleet/api/forwards/:host | Forwards a host to
another server, with {"upstream": "https://…"}: see below. |
GET /fleet/api/forwards, DELETE /fleet/api/forwards/:host | Lists forwards, or removes one. |
Each site then has its own admin API at its own host, with its own admin token, for registering the docs repository, readers and orgs (Admin API reference).
Forwarding hosts to dedicated deployments
A provider that points a wildcard domain at the fleet cannot also give a dedicated deployment a name
under that domain directly. A forward lets the fleet answer for such a host and pass every request on
to the deployment's own address, unchanged apart from Host and the
X-Forwarded-* headers. Redirects to the upstream's address are rewritten to the public
host. The upstream must be an https origin (plain http only to a
loopback or .internal host), and its PUBLIC_URL is the forwarded host.
A host is either a site's or a forward's, never both. Give a site its own domain to connect without the
fleet in between.
Moving a site to its own deployment
Export the site with GET /admin/api/export on the site's own host. Start a
dedicated deployment with the same SESSION_SECRET (or OPEND_SECRET_KEY)
and import the export with POST /admin/api/import. Then request builds. Point the host
names at the new deployment, and delete the site from the fleet.