Virtual hosts
Once the plugin is installed, super administrators get a Virtual hosts entry in the admin navigation. This page covers how virtual hosts are created, what their provisioning status means, and how to manage them.
Creating a virtual host
Virtual hosts are created by linking a hostname to a mail domain — there is no separate "new virtual host" form. When you assign a hostname to a domain, the plugin creates the matching VirtualHost (if it does not exist yet) and links the domain to it.
- Go to Domains and create a new domain, or edit an existing one.
- In the domain form, open the Virtual host step / panel (added by the plugin).
- Enter the public hostname for this domain, for example
mail.example.com. - Save the domain.
The hostname must be:
- lowercase — mixed-case hostnames are rejected with an explicit message;
- a valid hostname (validated with Modoboa's hostname validator).
Saving creates the virtual host and — if Let's Encrypt and/or Nginx are enabled — immediately kicks off its provisioning chain.
TIP
Several domains can point at the same virtual host: re-use the same hostname on each domain's Virtual host field and they will all be linked to it.
The virtual hosts list
The Virtual hosts admin page lists every virtual host with:
- its name (hostname);
- the domains linked to it;
- whether it currently has a certificate and its expiry date;
- its provisioning status;
- whether it is enabled.
From the list you can enable/disable, retry provisioning, edit the theme and delete each virtual host.
Provisioning lifecycle
When Let's Encrypt and/or Nginx are enabled, creating a virtual host enqueues a chain of background jobs:
generate bootstrap Nginx config (privileged queue)
↓
issue Let's Encrypt certificate (modoboa queue)
↓
generate final Nginx config (privileged queue)
↓
mark provisioning ready (privileged queue)The chain is strict: each step depends on the previous one succeeding. If any step fails, the remaining steps are cancelled so a broken certificate can never produce an Nginx config that references missing files.
A virtual host therefore has one of three provisioning statuses:
| Status | Meaning |
|---|---|
pending | The provisioning chain is in flight. Some jobs have not finished yet. |
ready | Every job in the chain succeeded — the host is fully provisioned and serving. |
failed | A job failed. The chain was cancelled and the error is recorded on the virtual host. |
INFO
If both Let's Encrypt and Nginx are disabled, there is nothing to provision: the virtual host is created directly in the ready state.
Retrying after a failure
When a virtual host is in the failed state, its recorded error is shown in the list. After fixing the underlying cause (DNS not yet propagated, port 80 blocked, wrong ACME directory, unwritable Nginx directory…), use Retry provisioning to re-run the whole chain.
Retry is only accepted for hosts that are currently failed — a host that is still pending or already ready returns a 409 Conflict so a stray retry can't fight an in-flight chain or pile redundant work onto a healthy host.
Common causes of a failed provisioning:
- the hostname does not resolve in public DNS yet, or port 80 is not reachable from the internet (the ACME HTTP-01 challenge fails);
ACME_DIRECTORY_URLis wrong, or the account email is missing;- the worker on the
privilegedqueue cannot write the Nginx directories.
See TLS certificates and Nginx integration for the details of each step.
Enabling and disabling
Toggling a virtual host off removes it from Nginx's enabled sites (its configuration file stays on disk, but the symlink/inclusion is dropped) and the change is applied asynchronously on the privileged queue. Toggling it back on re-enables the site and reloads Nginx.
WARNING
The daily certificate-renewal scanner skips disabled virtual hosts: with their Nginx site disabled, the ACME HTTP-01 challenge can't be served, so a renewal would fail. Re-enable a host before its certificate approaches expiry.
Deleting
Deleting a virtual host removes the model row and enqueues a job on the privileged queue to delete its Nginx configuration file (and reload Nginx). The linked domains are not deleted — only their association with the virtual host is removed.
Access control
The plugin enforces tenancy at login time. When a non-superuser signs in through a virtual host's hostname, login is denied unless that virtual host is linked to a domain the user belongs to (their mailbox domain, or a domain they administer). Super administrators and logins through the instance's primary hostname are never restricted.
This means each branded hostname only lets in the users that belong to its domains.