Single or multi-tenant
One fepli installation can serve one municipality or many. Each municipality is a tenant, with its own domains, admins, settings and data. This page explains the two setups and how to create the first tenant and the first admin, which can only be done on the command line.
Tenants
A tenant (in the admin: Mandant) is one holiday programme, usually run by one municipality. It has:
- a slug, its machine name, e.g.
musterstadt, - a name, e.g. "Ferienpass Musterstadt", which also appears as the sender of its e-mails,
- its domains,
- its own admins, organisers, families, offers, settings and CMS pages.
All tenants of an installation share one database, and fepli keeps their data apart. A family registered with Musterstadt doesn't exist for Beispielhausen, and an admin of one tenant can't see the other.
There is no separate single-tenant version: every image is the same. Whether an installation is single- or multi-tenant only depends on how many tenants you create, and on whether you switch on the platform console.
| Single-tenant | Multi-tenant | |
|---|---|---|
| Tenants | one | as many as you need |
| Admin | at /admin on the municipality's domain | at /admin on each tenant's domain, plus the platform console |
| Tenants are created | once, on the command line | by global admins in the platform console, or on the command line |
FERIENPASS_PLATFORM_HOST | not set | the console's domain |
Start with a single tenant if you are unsure. You can add a platform console and more tenants at any time, without moving data.
Domains
Every tenant claims the domains it is reached on. A domain serves one of two things:
- A public host serves the tenant's website, and its admin under
/admin. This is the usual case:https://ferienpass-musterstadt.deandhttps://ferienpass-musterstadt.de/admin. - An admin host serves only the admin, at the root of the domain, without
/admin. Once a tenant has an admin host, its public hosts stop serving the admin.
A request for a domain no tenant claims is answered with 404, before anything else happens. fepli never falls back to a default tenant. So when you add a domain, add it in two places: to the tenant, and to TRUSTED_HOSTS.
The platform console
On a multi-tenant installation, the platform console is the place to manage the installation itself. It has a domain of its own, e.g. platform.ferienpass-musterland.de, set with FERIENPASS_PLATFORM_HOST. It belongs to no tenant and serves only the admin, at the root of the domain.
Only global admins can sign in there. They see:
- Installation → Mandanten: the list of tenants, with Mandant anlegen to create one, and the switch to take a tenant offline.
- Wechseln: stepping into a tenant, to work in its admin as if they were one of its admins, for support.
- Installation → Systemwerte: the values all tenants share, such as the central mailbox (Zentrales Postfach) and the maintenance mode, which puts every tenant's website behind a maintenance page.
On a new installation without tenants, the console shows nothing but the tenant list, until the first tenant exists.
Run commands in the container
The first admin is created with a console command inside the web container. With Docker Compose, prefix every command on this page with docker compose exec web:
Run a console command
docker compose exec web php bin/console ferienpass:tenant:list
Other platforms have their own way to open a shell in a running container (kubectl exec, the terminal of Dokploy or Coolify, …). Run the commands from /app, which is where the container starts.
Set up a single tenant
Create the tenant with its public hosts, then its first admin:
Create the tenant
php bin/console ferienpass:tenant:create musterstadt "Ferienpass Musterstadt" \
--host=ferienpass-musterstadt.de \
--host=www.ferienpass-musterstadt.de
Create the first admin
php bin/console ferienpass:user:create anna.schmidt@musterstadt.de \
--tenant=musterstadt --firstname=Anna --lastname=Schmidt
The second command asks for the password twice. The admin is a super admin of Musterstadt: they may do everything in its admin, including payments, participants and the CMS, and invite everyone else from there. They sign in at https://ferienpass-musterstadt.de/admin.
Then give the tenant its website.
Set up several tenants
-
Set
FERIENPASS_PLATFORM_HOSTto the console's domain, add that domain toTRUSTED_HOSTS, and restart the containers. -
Create a global admin. It belongs to no tenant, so it needs no
--tenant:Create a global admin
php bin/console ferienpass:user:create you@example.org --global-admin -
Sign in at
https://platform.ferienpass-musterland.deand create the tenants under Installation → Mandanten → Mandant anlegen, with their domains. Or create them on the command line withferienpass:tenant:create, as for a single tenant. -
Give each tenant its first admin: switch into the tenant and create its admins there, or use
ferienpass:user:createwith--tenant.
Global admins are super admins in every tenant they switch into. Keep their number small.
The commands
- Name
ferienpass:tenant:create- Type
- slug name
- Description
Creates a tenant. The slug is kebab case (
musterstadt,bad-musterbach) and can't be changed later.--hostadds a public host,--admin-hostan admin host. Both can be repeated.
- Name
ferienpass:tenant:list- Description
Lists the tenants: slug, name, public and admin hosts, and whether they are online.
- Name
ferienpass:user:create- Type
- Description
Creates a super admin.
--tenant=<slug>names the tenant it belongs to,--global-adminmakes it an admin of the installation instead.--firstnameand--lastnameare optional.
Passwords:
- Run interactively,
ferienpass:user:createasks for the password. - Run without a terminal, e.g. from a script or with
docker compose exec -T, it generates a password and prints it once. Change it after signing in. --password=…works too, but leaves the password in your shell history and the process list. Prefer the prompt.
An e-mail address is unique per tenant, not per installation, so the same person can be an admin of two tenants with two accounts.
Give the tenant its website
The public website of a tenant is a page tree in the CMS. The CMS doesn't know about tenants on its own, so each tenant gets exactly one root page, and the root page says which tenant it belongs to. Until it exists, the tenant's domain has no website, though its admin works.
- Sign in to the tenant's admin and open CMS in the top bar.
- Go to Seitenstruktur and create a page of the type Startpunkt einer Webseite.
- Set its Domainname to the tenant's public host, e.g.
ferienpass-musterstadt.de, its Sprache tode, and choose the tenant under Mandant. - Publish it, and build the pages below it.
A tenant with only an admin host has no website and needs no root page.