docs
Try the demo Get started
Esc
↑↓ moveEnter openEsc close

Install it · 6 of 8

On a platform you already run

The console and the webmail as one compose file, on Dokploy, Coolify, Portainer or plain Docker Compose, in front of an inbuxa server on another machine.

Who needs this: Anyone who already runs containers on a machine of their own, with a platform that puts a proxy and certificates in front of them, and wants the console and the webmail there rather than on the mail server.

3 min read

On this page

The console and the webmail reach the mail server only over its HTTPS address, so they can run anywhere that reaches it. Keeping them off the mail host is the recommended arrangement.

If the machine can run the installer

inbuxa join does everything on this page in one run, with Caddy in front. This page is for a machine where a platform already owns ports 80 and 443 and runs the containers.

The examples use mail.example.com for the mail server, and admin.example.com and webmail.example.com for the two front ends.

1. Tell the server where they are

The server only lets the console and the webmail sign people in, and only answers their browsers, at addresses it knows. Make a shared secret for the webmail:

openssl rand -base64 48

Set these in the server's environment, then restart the server:

INBUXA_ADMIN_URL=https://admin.example.com
INBUXA_WEBMAIL_URL=https://webmail.example.com
INBUXA_WEBMAIL_CLIENT_SECRET=<the shared secret>

The addresses must match the ones browsers will use exactly: no trailing slash, no path. From them the server registers both sign-ins and allows both origins. Without the secret it registers no webmail, and says so in its log.

Then exempt the platform machine from the server's automatic bans. Every webmail sign-in reaches the server from that machine's address, so one person's mistyped passwords could get it banned, and everyone with it. In the console, under Settings › Security › Allowed IPs, add the address the server sees the platform machine at.

2. The compose file

services:
  console:
    image: registry.coffeylabs.org/inbuxa/inbuxa-admin:latest
    restart: unless-stopped
    environment:
      API_BASE_URL: https://mail.example.com

  webmail:
    image: registry.coffeylabs.org/inbuxa/inbuxa-webmail:latest
    restart: unless-stopped
    environment:
      MAIL_SERVER_URL: https://mail.example.com
      PUBLIC_URL: https://webmail.example.com
      ADMIN_URL: https://admin.example.com
      APP_NAME: inbuxa
      APP_SECRET: ${APP_SECRET}
      OAUTH_CLIENT_SECRET: ${OAUTH_CLIENT_SECRET}
    volumes:
      - webmail-data:/data
    read_only: true
    tmpfs:
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true

volumes:
  webmail-data:

Set two secrets in the platform's environment for this application, not in the file:

  • APP_SECRET: a new random value, from openssl rand -base64 48. It seals the webmail's sessions.
  • OAUTH_CLIENT_SECRET: the shared secret from step 1, the same value the server has.

Each container serves plain HTTP on port 8080 and publishes no port. The platform's proxy reaches them over its own network and adds TLS.

Which tag

Use the tag that matches the server. :latest goes with a 2026.x server. A 27.1 release candidate, which is what a server moved from Stalwart runs, takes :27.1-rc for both.

3. On your platform

  • Dokploy or Coolify: make a Docker Compose application from the file. Give the console service the hostname admin.example.com and the webmail service webmail.example.com, both on port 8080, in the platform's domain settings. Their proxy gets and renews the certificates.
  • Portainer: make a stack from the file. Portainer has no proxy of its own, so put the one you already use in front of the two services. The console and webmail pages have nginx and Caddy examples.
  • Plain Docker Compose: the same file, with ports: ["127.0.0.1:8081:8080"] on the console and ports: ["127.0.0.1:8082:8080"] on the webmail, and your reverse proxy in front of those.

Point the two hostnames at the platform machine in DNS. The mail server's own records don't change.

Replacing a webmail you run now

You can keep the hostname your people already use. Change the service's image to the one above, replace its environment with the variables above, and give it a new, empty volume. Keep the old service's volume until you're sure, rather than mounting it into the new one.

INBUXA_WEBMAIL_URL on the server must be that hostname. Everyone signs in again once, because sessions don't carry over from another app.

Check it worked

  • https://admin.example.com shows the console's sign-in, and signing in lands on its dashboard. If it says Failed to fetch, the browser can't reach mail.example.com, or the server doesn't list the console's address: see the console's page.
  • https://webmail.example.com sends you to the server's sign-in page and back. A sign-in that bounces straight back means PUBLIC_URL and INBUXA_WEBMAIL_URL don't agree.
  • https://webmail.example.com/api/health answers "ok":true.

Updating

Change the tag, or pull :latest again, and redeploy. The console and the webmail hold no mail, so updating them never touches the server's data. Update them after the server, not before.