Running on Docker
bipanel runs on Docker as one container: Apache, PHP-FPM, MariaDB and the panel ship in the same image, and persistent data lives in the /data volume. It suits websites, databases and apps; email, a DNS server, FTP and system-level tools exist only on a server installation.
On this page
#What container mode is
In a container installation bipanel is a single Debian-based image. It contains Apache 2.4 (mpm_event), PHP-FPM for PHP 8.2, 8.3 and 8.4, an embedded MariaDB, Node.js 22, Python 3, phpMyAdmin, git, rclone and certbot. The panel process starts Apache, PHP-FPM and MariaDB itself. Apache listens on the port in the PORT variable (8080 by default), and the panel and phpMyAdmin are reached through that port.
Unlike a server installation there are no separate admin and user ports. On the same address:
- Server Admin:
https://<panel address>/admin(first useradmin) - User panel:
https://<panel address>/panel
System users, Apache virtual hosts and PHP-FPM pools are not kept inside the container; they are rebuilt from the panel database in /data on every start. As long as the volume is attached, deleting and recreating the container is safe.
Licensing works the same way: without a license key the Community edition runs up to 3 hosting accounts, and Pro features need a Pro license. See Licensing and Pricing.
#Docker Compose with Caddy
On your own VPS you need Docker Engine 24 or later and Docker Compose v2. 2 GB of RAM works, 4 GB is recommended. You need a domain for the panel with an A record pointing at the server, and ports 80 and 443 open.
The release package includes Dockerfile, docker-compose.yml and deploy/caddy/Caddyfile. Get the package and the current commands from the Download page. After unpacking it, create a .env file in the folder with BIPANEL_PANEL_HOST, BIPANEL_ADMIN_PASSWORD and ACME_EMAIL, then run:
docker compose up -d --build
docker compose logs -f bipanel
The first start prepares the MariaDB data directory, so the panel can take a few minutes to come up. The image health check polls /api/health and allows 180 seconds for startup.
#What Caddy does
The compose file defines two services: bipanel, which publishes no ports, and caddy in front of it (80, 443 and 443/UDP). Caddy obtains a Let's Encrypt certificate for each domain on its first request, but only for domains registered in bipanel: before requesting a certificate it asks the panel's internal check endpoint. Plain HTTP is redirected to HTTPS. This setup sets BIPANEL_SSL_MODE=edge and BIPANEL_TRUST_PROXY_HOPS=2 (Caddy plus Apache), so brute-force protection sees the real client IP.
If you use another reverse proxy instead of Caddy, forward the X-Forwarded-For and X-Forwarded-Proto headers, leave the Host header unchanged, allow WebSocket upgrades (for the web terminal and live logs) and set BIPANEL_TRUST_PROXY_HOPS to the number of proxies plus one.
#Environment variables
| Variable | Default | Description |
|---|---|---|
BIPANEL_ADMIN_PASSWORD | random | First admin password. If unset, a random one is generated, printed once in the log and saved to /data/initial-admin.txt. Used only on the first start. |
BIPANEL_ADMIN_USER | admin | First admin's username. |
BIPANEL_ADMIN_EMAIL | none | First admin's email address. |
BIPANEL_PANEL_HOST | the container's hostname | The panel's domain. In a container the hostname cannot be changed from the panel; this variable sets it. |
BIPANEL_SSL_MODE | acme (edge in the Compose example) | edge: the reverse proxy in front terminates TLS. acme: the panel obtains Let's Encrypt certificates itself with certbot. off: no certificate management. |
BIPANEL_TRUST_PROXY_HOPS | 1 (2 in the Compose example) | Number of trusted proxies, Apache included. |
PORT | 8080 | The port Apache listens on inside the container. |
BIPANEL_MYSQL_URL or MYSQL_URL | none | An external MySQL/MariaDB server instead of the embedded MariaDB (e.g. mysql://root:password@mysql:3306). |
BIPANEL_MYSQL_BUFFER_POOL | 128M | InnoDB buffer pool of the embedded MariaDB; lower it on servers with little memory. |
BIPANEL_MAX_UPLOAD_MB | 1024 | File Manager upload limit in MB. |
BIPANEL_SECRET | /data/secret.key | The panel's secret key (at least 32 characters). If unset, it is generated on first start and stored in the volume. |
#Persistent data: /data
The only persistent directory in the container is the /data volume:
| Path | Contents |
|---|---|
/data/bipanel.db | Panel database: accounts, domains, settings |
/data/home/<account> | Account files |
/data/mysql | Embedded MariaDB data directory |
/data/backups, /data/logs, /data/ssl, /data/jobs | Backups, logs, certificates, job records |
The installation identity and license settings live in this volume too. If the volume is lost, the installation starts from scratch and you have to enter the license key again. Sending account backups to a remote target with rclone is recommended (see Backups and migration).
#What is different in container mode
The following are not available in a container; the panel shows these screens as disabled, with the reason:
| Feature | In a container |
|---|---|
| Mail server and webmail | Not available; email needs a server installation |
| Authoritative DNS server | Not available; the DNS zone editor gives record suggestions and records can sync to Cloudflare |
| FTP, SSH and SFTP | Not available; use the File Manager, the web terminal and Git deployment |
| Firewall and nftables DDoS protection | Not available; the Docker host manages networking. In-panel brute-force protection works |
| Disk quotas | Not enforced; disk usage is only monitored |
| Per-account CPU and memory limits, account isolation | Not available (no systemd); apps only get a process count limit |
| Disk Manager | Not available; the Docker host manages disks and volumes |
| Automatic OS security updates | Not available; packages come with the image |
| Server reboot, root password, DNS resolvers | Not available; managed on the Docker host |
| Remote desktop (Pro) and Podman containers | Not available |
What works: accounts and packages, domains, PHP 8.2–8.4, MySQL/MariaDB and phpMyAdmin, Node.js and Python apps, Git deployment, the App Installer, cron (through the panel's own scheduler), backups, the File Manager, the web terminal and the API. The installation report is always on in containers as well; what is sent is shown under Server Admin → Installation Report.
#Updating
A container installation does not update the panel in place the way a server installation does; you update by redeploying with the new release's image. Change the bipanel image tag in docker-compose.yml to the new version and recreate the container:
docker compose pull
docker compose up -d
If you built from the release package, unpack the new package and run docker compose up -d --build. Accounts, sites and settings stay in the volume. See Updates for release channels.
#Resetting the admin password
Changing BIPANEL_ADMIN_PASSWORD later does not reset the password. Run the reset tool inside the container (add --disable-2fa to also turn off two-factor authentication):
docker compose exec bipanel node /opt/bipanel/deploy/tools/reset-admin.mjs admin 'NewPassword123!'
The command-line tool is in the image too: docker compose exec bipanel bipanel account list (the token is read from /data/cli.token).
Something missing or wrong on this page? Let us know.