fepli
Hostingenterprise

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-tenantMulti-tenant
Tenantsoneas many as you need
Adminat /admin on the municipality's domainat /admin on each tenant's domain, plus the platform console
Tenants are createdonce, on the command lineby global admins in the platform console, or on the command line
FERIENPASS_PLATFORM_HOSTnot setthe 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.de and https://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

  1. Set FERIENPASS_PLATFORM_HOST to the console's domain, add that domain to TRUSTED_HOSTS, and restart the containers.

  2. 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
    
  3. Sign in at https://platform.ferienpass-musterland.de and create the tenants under Installation → Mandanten → Mandant anlegen, with their domains. Or create them on the command line with ferienpass:tenant:create, as for a single tenant.

  4. Give each tenant its first admin: switch into the tenant and create its admins there, or use ferienpass:user:create with --tenant.

  5. Give each tenant its website.

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. --host adds a public host, --admin-host an 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
    email
    Description

    Creates a super admin. --tenant=<slug> names the tenant it belongs to, --global-admin makes it an admin of the installation instead. --firstname and --lastname are optional.

Passwords:

  • Run interactively, ferienpass:user:create asks 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.

  1. Sign in to the tenant's admin and open CMS in the top bar.
  2. Go to Seitenstruktur and create a page of the type Startpunkt einer Webseite.
  3. Set its Domainname to the tenant's public host, e.g. ferienpass-musterstadt.de, its Sprache to de, and choose the tenant under Mandant.
  4. Publish it, and build the pages below it.

A tenant with only an admin host has no website and needs no root page.

Was this page helpful?