1. What is Docker Portainer for WHMCS?
Docker Portainer for WHMCS is a server module that turns your existing Portainer instance into a billable hosting product inside WHMCS. Each WHMCS service maps to a Docker stack on your Portainer host, with full lifecycle control from the client area.
Key features:
- 30+ ready-to-deploy app templates (WordPress, Nextcloud, Ghost, Gitea, Vaultwarden, Immich, and more)
- Traefik integration with automatic Let's Encrypt SSL on client domains
- S3 backups via worker container, bypassing PHP memory and execution limits
- Client area with console, logs, file manager, env vars, metrics, and audit log
- Multi-host support with separate Portainer endpoints per server group
- Configurable resource limits via WHMCS Configurable Options (memory, CPU, disk)
- Non-blocking license validation, no client-area downtime if licensing server is unreachable
- ionCube-encoded with editable templates, stacks, and language files
Need to set up Portainer first? See the official Portainer installation guide.
2. Features
Automation
- Provisions Docker stacks when services are activated
- Suspends, unsuspends, and terminates stacks based on WHMCS lifecycle
- Daily cron handles scheduled backups, health checks, and orphan cleanup
- Automatic disk-quota checks per service
- License re-validation cached daily, no per-request HTTP overhead
App Templates
- 30+ ready-to-deploy templates included out of the box
- WordPress, Ghost, Nextcloud, Gitea, Joomla, Drupal, PrestaShop, Odoo
- n8n, Vaultwarden, BookStack, Matomo, Wiki.js, MinIO, Umami, Grafana
- NocoDB, listmonk, LinkStack, Stirling-PDF, IT-Tools, Planka, File Browser
- PrivateBin, Paperless-ngx, Outline, Chatwoot, Immich, and more
- Custom Docker Image mode for any container not covered by templates
- Drop-in support: add your own
.ymlfiles tostacks/and they appear in the dropdown
Backup System
- S3-compatible storage (AWS S3, MinIO, Backblaze B2, DigitalOcean Spaces, Wasabi)
- Backup data never passes through WHMCS, no PHP memory or execution limits apply
- Automatic database dump detection (MySQL, PostgreSQL)
- Configurable backup paths per product
- Presigned S3 URLs for direct client downloads
- Configurable retention period and daily scheduled backups
- Multi-gigabyte backups work without timeout issues
Traefik Integration
- Automatic Let's Encrypt SSL on client-facing domains
- Per-product Traefik network override
- Custom domain management with label sync
- Compatible with docker-socket-proxy for Docker 29+ deployments
Resource Management
- Configurable Options for Memory (MB), CPU Cores, and Disk (MB)
- Per-tier pricing handled natively by WHMCS
- Stacks run unlimited if no Configurable Options are set
- Multiple Portainer endpoints supported via Server Groups
Client Area Tabs
- Overview with status, resource usage, and quick links
- Console with optional command whitelist
- Logs viewer with service selector
- File manager: browse, edit, delete
- Environment variables editor with stack redeploy
- Per-container scheduled cron jobs
- Custom domain management
- Backup, restore, and download
- Auto-detected database connection details
- CPU/memory metrics history
- Paginated audit log
- Each tab can be enabled or disabled per product
Admin Area
- Live counts of services, backups, and total storage used
- Service overview across all clients with status and quick links
- Backup history with size, status, expiry, and admin download
- Global settings for Traefik network, S3, retention, and license
Languages
- Ships with English
- Drop-in language files in
lang/folder - Partial overrides supported via
lang/overrides/, survives module updates
WHMCS Integration
- Standard server module under System Settings → Servers
- Addon module for global settings and backup history
- Automated lifecycle hooks (DailyCronJob, AfterCronJob)
- Client-area integration via standard WHMCS hooks
Security
- API keys and S3 secrets encrypted using WHMCS encryption key
- ionCube-encoded core, editable templates and stacks
- Optional console command whitelist per product
- License validation is non-blocking and cached, no client-area downtime
3. Requirements
- WHMCS 8.x or 9.x
- PHP 8.1+ with ionCube Loader (already required by WHMCS)
- A running Portainer CE or BE 2.x instance you administer
- Portainer API key with admin rights, generated under My Account → Access Tokens
- Endpoint (Environment) ID of the Docker environment for client stacks
- Network access from WHMCS to the Portainer host on its API port (default 9443/9000)
- S3-compatible bucket for backups (AWS S3, MinIO, Backblaze B2, DigitalOcean Spaces, Wasabi, or any S3-compatible endpoint)
- Valid Docker Portainer for WHMCS license
Recommended (not strictly required):
- Traefik on the Docker host for client-facing domains with automatic SSL
- docker-socket-proxy if Traefik can't access the Docker socket directly (Docker 29+)
4. Portainer Server Configuration
This module assumes you already operate a Portainer host. It does not install Portainer for you.
Generate an API Key
- Log into your Portainer instance as an admin
- Click your username in the top-right corner
- Go to My Account → Access Tokens
- Click Add access token, give it a name, and copy the generated key
- The key is only shown once, store it securely
Find Your Endpoint ID
Open Portainer and navigate to your Docker environment. The endpoint ID appears in the URL:
https://portainer.example.com/#!/endpoints/3
The number at the end (here, 3) is your endpoint ID.
Test API Access
From your WHMCS server, test the API:
curl -k https://portainer.example.com/api/status -H "X-API-Key: your-api-key"
You should see a JSON response with version information.
5. Installation
Step 1: Upload Files
Upload the contents of the files/ folder into your WHMCS root, preserving the directory structure:
/modules
├─ addons
│ └─ portainer_for_whmcs_config
└─ servers
└─ portainer_for_whmcs
Important: Don't rename the folders.
Step 2: Activate the Addon
- Go to System Settings → Addon Modules
- Find Docker Portainer and click Activate
- Click Configure
- Paste your license key into the License Key field
- Click Save Changes
Step 3: Add Your Portainer Server
- Go to System Settings → Servers → Add New Server
- Fill in the fields as follows:
- Hostname: Your Portainer hostname (e.g.
portainer.example.com) - Port:
9443for direct HTTPS,9000for HTTP, or empty if behind a reverse proxy - Secure: Tick if HTTPS
- Username: Leave blank
- Password: Your Portainer API key
- Access Hash: The Portainer Endpoint ID (e.g.
3) - Server Module: Select
portainer_for_whmcs
- Hostname: Your Portainer hostname (e.g.
- Click Test Connection to verify
For multi-host deployments, add one server per Portainer endpoint and group them with WHMCS Server Groups.
Step 4: Configure Global Settings
- Open Addons → Docker Portainer → Settings
- Set the Traefik network name (default:
traefik-public) - Configure S3 backup credentials (endpoint, bucket, access key, secret)
- Set retention period and backup schedule
Step 5: Create a Product
- Go to System Settings → Products/Services
- Create a new product, set Module to
Docker Portainer - Pick a stack template, configure backup paths, and enable the client-area tabs you want
- Optionally assign a Configurable Options group for resource limits
How It Works
- Service activated: Provisions a Docker stack from the chosen template
- Service suspended: Stops the stack containers
- Service unsuspended: Restarts the stack
- Service terminated: Removes the stack and associated worker containers
- Daily cron: Runs scheduled backups, health checks, license refresh, orphan cleanup
6. Traefik Setup (Optional)
Required only if you want client stacks reachable on client-facing domains with automatic Let's Encrypt SSL.
Step 1: Create the Shared Network
docker network create traefik-public
Step 2: Deploy Traefik
version: '3'
services:
traefik:
image: traefik:v3.0
restart: unless-stopped
environment:
- DOCKER_API_VERSION=1.45
command:
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --providers.docker.network=traefik-public
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --certificatesresolvers.letsencrypt.acme.email=you@example.com
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik_letsencrypt:/letsencrypt
networks:
- traefik-public
volumes:
traefik_letsencrypt:
networks:
traefik-public:
external: true
Step 3: Set the Traefik Network in WHMCS
Go to Addons → Docker Portainer → Settings and set Traefik Network to traefik-public.
Step 4: Tell Clients to Point DNS
Clients must point an A record for their domain at the Docker host's public IP. Traefik handles routing and SSL automatically once the stack is up.
Docker 29+ note: If Traefik can't access the Docker socket directly, run docker-socket-proxy and point Traefik at --providers.docker.endpoint=tcp://socket-proxy:2375.
7. Configuration Options
Module-Level (per product)
- App Template
- Pick a stack template, a Portainer App Template, or
Custom Docker Image - Custom Docker Image
- Image name when using Custom mode (e.g.
nginx:latest) - Port Mappings
- Container ports for Custom mode (e.g.
80/tcp,443/tcp) - Environment Variables
- One
KEY=VALUEper line, supports placeholders{PASSWORD},{SERVICE_ID},{DOMAIN} - Restart Policy
- Unless Stopped, Always, On Failure, or No
- Network Mode
- Bridge, Host, or None
- Traefik Network
- Override the global Traefik network for this product
- Enable Backups
- Show the Backups tab in the client area
- Backup Paths
- Volume paths to back up (blank for auto-detect from compose)
- Database Dump Command
- Custom dump command (blank for auto-detect MySQL/PostgreSQL)
- Database Container
- Compose service name of the DB container (default
db) - Enable Console
- Show the Console tab in the client area
- Allowed Commands
- Console command whitelist, one per line (blank for unrestricted)
- Enable File Manager
- Show the Files tab in the client area
Global (Addon Settings)
- License Key
- Your ArkHost license
- Traefik Network
- Default network name for Traefik routing
- S3 Endpoint, Bucket, Access Key, Secret
- S3-compatible storage credentials, secret is encrypted
- Backup Retention
- Days to keep backups before automatic deletion
- Backup Schedule
- Cron schedule for automated backups
8. Resource Limits via Configurable Options
Create a Configurable Options group under System Settings → Configurable Options and assign it to your product. Use Dropdown type for each option. The module reads Memory (MB), CPU Cores, Disk (MB). Alternative names memory_mb, cpu_cores, disk_mb also work. Without these options, containers run unlimited.
Example Pricing
Base product at €2.50/mo, first tier included:
Memory (MB): 512 (€0), 1024 (€1), 2048 (€2.50), 4096 (€5)
CPU Cores: 0.5 (€0), 1 (€1), 2 (€3), 4 (€7)
Disk (MB): 5120 (€0), 10240 (€0.50), 20480 (€1.50), 51200 (€4)
A basic WordPress with included tiers costs €2.50. A larger setup (2 GB RAM, 1 CPU, 20 GB disk) costs €7.50.
9. Daily Use
Admin Features
- Live counts of services, backups, and total storage used
- Browse all Portainer-backed services across all clients
- Backup history with admin download
- Force a license refresh from the configuration page
- Manage global Traefik network, S3 credentials, and retention
Customer Features
- Overview tab with container status and resource usage
- Console for interactive shell access (optional whitelist)
- Logs viewer with service selector
- File manager to browse, edit, and delete files
- Environment variables editor with stack redeploy
- Per-container scheduled cron jobs
- Custom domain management with automatic SSL via Traefik
- Manual backup, restore, and download
- Auto-detected database connection details
- CPU and memory metrics history
- Paginated audit log of all actions
Backup Workflow
- Trigger: Daily cron or manual backup from client area
- Worker: WHMCS launches a temporary Alpine worker container on the Docker host
- Process: Worker dumps the database, tars the volume paths, and uploads to S3 via presigned URL
- Storage: WHMCS only stores metadata (filename, size, status, expiry)
- Download: Presigned S3 URL streams the file directly to the client browser
10. Best Practices
- Run Traefik with docker-socket-proxy on Docker 29+ for tighter security
- Configure S3 retention to match your client's backup expectations
- Set the console command whitelist for production deployments
- Use multiple Portainer endpoints with Server Groups for capacity scaling
- Test your stack templates against a real client lifecycle (order, suspend, terminate) before listing them publicly
- Keep custom
.ymlstacks instacks/under version control, they survive module updates - Use partial language overrides in
lang/overrides/instead of editing the main language files - Monitor your Docker host's disk and memory headroom, the module enforces resource limits but doesn't prevent overprovisioning at the host level
11. Troubleshooting
Check These First
- Module Activity Log: WHMCS logs all module operations
- Test API access:
curl -k https://portainer.example.com/api/status -H "X-API-Key: your-key" - List endpoints:
curl -k https://portainer.example.com/api/endpoints -H "X-API-Key: your-key" - Worker logs:
docker ps -a | grep portainer-backup-workeron the Docker host - License banner: Open Addons → Docker Portainer to force a fresh license check
Common Problems
- Connection timed out when adding the server
Wrong port, or the host blocks the API. If Portainer sits behind a reverse proxy, leave the port empty. - "Unable to find environment"
Wrong Endpoint ID in the Access Hash field. Check Portainer's URL when viewing the environment. - "No Docker image specified"
You picked Custom Docker Image but left the image field empty, or a template fetch failed. - Admin sees a license warning banner
The cached license result says invalid. Open the addon configuration page to force a fresh check. Provisioning continues regardless, the banner is non-blocking. - Backups are stuck "in progress"
Check the worker container on the Docker host (docker logs <worker>). Daily cron sweeps stale workers automatically. - ionCube errors in WHMCS error log
Your PHP ionCube Loader is older than the encoder used. Update ionCube Loader to the latest stable version. - Traefik can't reach the Docker socket (Docker 29+)
Use docker-socket-proxy and point Traefik attcp://socket-proxy:2375. - Stack created but no SSL
Check the client's A record points at the Docker host IP, and Traefik's Let's Encrypt resolver has a valid email configured.
FAQ
- Does this module install Portainer for me?
No. You must already have a running Portainer CE or BE 2.x instance. The module connects to it via API. - Can I use multiple Portainer hosts?
Yes. Add one server per Portainer endpoint in WHMCS and group them with Server Groups. The module picks the right one based on the product's assigned group. - What happens if your licensing server is unreachable?
Provisioning and client-area functionality keep working. The license is validated once per day by WHMCS cron and cached, no per-request HTTP calls. The admin sees a non-blocking banner if the check fails. - Where do backups live?
In your S3-compatible bucket. WHMCS only stores metadata. Backup data never passes through PHP, so PHP memory and execution limits don't apply. - Can I add my own stack templates?
Yes. Drop.ymlfiles intomodules/servers/portainer_for_whmcs/stacks/. They appear in the dropdown automatically. Custom stacks survive module updates. - Is the module ionCube-encoded?
The PHP core is encoded. Stack templates (.yml), language files, and Smarty templates are plain-text and editable. - How do I change the language or add a new one?
Copylang/english.phptolang/<language>.phpand translate. For partial changes, drop overrides intolang/overrides/, they survive updates. - Can clients break out of the console?
Set the per-product Allowed Commands whitelist to restrict which commands clients can run. Leave blank for unrestricted access.
12. Upgrading
- Back up your files and database
- Upload new files (overwrite old ones)
- Custom files in
stacks/,lang/overrides/, and Smarty templates are preserved - Go to Utilities → System → System Cleanup
- Click Empty Template Cache
- Open the addon to trigger any database updates automatically
13. Security
- Portainer API keys are stored in the WHMCS server password field
- S3 secrets are encrypted using WHMCS encryption key
- License validation is cached and non-blocking, no client-area downtime
- Clients can only access their own services and backups
- Optional console command whitelist per product
- ionCube-encoded core prevents tampering with billing logic
- Worker containers run in isolation and clean up after themselves
14. License and Support
Docker Portainer for WHMCS requires a paid license.
- Buy: Purchase here
- Manage: ArkHost client area
- Support: Open a ticket
- Portainer documentation: docs.portainer.io
- Traefik documentation: doc.traefik.io