Install guides

Docker

Run WemX with Docker Compose, with the web server, queue worker, scheduler and database included.

The WemX repository ships with a production-ready Docker setup. One docker compose up gives you:

ContainerWhat runs inside
appNginx, PHP-FPM 8.3, the queue worker and the scheduler, managed by Supervisor
dbMariaDB 11.4

All data lives in named Docker volumes, so you can rebuild or update the containers without losing anything.

WemX v3 is in beta and needs a license key. Get a free key at app.wemx.net.

Requirements

  • Docker Engine 24+ with the Compose plugin (docker compose version)
  • 1 GB of RAM or more
  • A domain name and a reverse proxy for HTTPS in production (see HTTPS)

Installation

Get the code.

git clone https://github.com/wemxnet/wemx.git
cd wemx

Create your configuration. Copy the example and edit it:

cp docker/wemx.env.example docker/wemx.env
nano docker/wemx.env

At a minimum, set:

  • APP_URL: the address you'll open WemX on, for example https://billing.example.com
  • DB_PASSWORD and MARIADB_PASSWORD: the same long, random password
  • MARIADB_ROOT_PASSWORD: a different long, random password
  • FORCE_HTTPS=true if WemX will be served over HTTPS

Build and start the containers.

docker compose up -d --build

The first build takes a few minutes. It installs the PHP and Node dependencies and compiles the frontend assets. Follow the logs with:

docker compose logs -f app

Run the web installer. Open your APP_URL (by default http://localhost:8080). The installer checks the requirements, then asks for your database. The values from wemx.env are already filled in, so choose MySQL and continue. Then create your admin account and enter your license key.

Restart once after installing. This makes the queue worker and scheduler pick up the new configuration straight away:

docker compose restart app

WemX is ready. Continue with First steps.

How it works

Configuration and the .env file

WemX reads its configuration from two places:

  1. Container environment variables from docker/wemx.env. These always win.
  2. The .env file, which the web installer and the license page write to. It's stored on the wemx-config volume at /config/.env and linked into the application.

On first start the container creates /config/.env and generates a unique APP_KEY. This key encrypts your gateway and server credentials, so back it up:

docker compose cp app:/config/.env ./wemx-env-backup

Volumes

VolumeMounted atContains
wemx-config/configThe .env file, including APP_KEY
wemx-storagestorage/Logs, cache and uploaded files
wemx-extensionsextensions/Extensions installed from the marketplace
wemx-assetspublic/assets/Theme assets and images uploaded in the admin area
wemx-db/var/lib/mysqlThe MariaDB database

On every start the container refreshes the extensions and theme assets that ship with the image, and leaves everything you installed or uploaded alone.

Background processes

The app container runs the queue worker and scheduler for you, so there's no cron or systemd setup. The admin dashboard warns you if the queue worker stops.

To run them in separate containers instead, set WEMX_RUN_QUEUE=false or WEMX_RUN_SCHEDULER=false and start extra containers from the same image with php artisan queue:work or php artisan schedule:work as the command. They need the same volumes and environment.

Database migrations

Once WemX is installed, the container runs php artisan migrate --force on every start, so new database tables are created automatically after an update. Set WEMX_AUTO_MIGRATE=false to do this yourself.

HTTPS and reverse proxies

The app container serves plain HTTP on port 8080 on the host (change it with WEMX_HTTP_PORT). In production, put a reverse proxy in front of it to handle TLS, and set FORCE_HTTPS=true and an https:// APP_URL in wemx.env. WemX already trusts forwarded headers from proxies.

Caddy obtains certificates automatically:

Caddyfile
billing.example.com {
    reverse_proxy 127.0.0.1:8080
}
server {
    listen 443 ssl http2;
    server_name billing.example.com;
    # ssl_certificate / ssl_certificate_key …

    client_max_body_size 32m;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Remove the ports section from the app service, attach it to your Traefik network, and add labels:

services:
    app:
        labels:
            - traefik.enable=true
            - traefik.http.routers.wemx.rule=Host(`billing.example.com`)
            - traefik.http.routers.wemx.entrypoints=https
            - traefik.http.routers.wemx.tls.certresolver=letsencrypt
            - traefik.http.services.wemx.loadbalancer.server.port=80
        networks: [proxy, default]

networks:
    proxy:
        external: true

Updating

In Docker, update by rebuilding the image rather than with the in-app updater. Changes made by the updater inside a container are lost when the container is recreated.

# 1. Back up the database
docker compose exec db sh -c 'mariadb-dump -u root -p"$MARIADB_ROOT_PASSWORD" "$MARIADB_DATABASE"' > wemx-backup.sql

# 2. Get the new version and rebuild
git pull
docker compose up -d --build

Migrations run automatically on start-up. To pin a release, check out its tag first (for example git checkout v3-beta-0.1.1) and pass the version to the build so it shows in the admin area:

docker compose build --build-arg WEMX_VERSION=v3-beta-0.1.1 && docker compose up -d

Useful commands

docker compose ps                                  # status and health
docker compose logs -f app                         # application, queue and scheduler logs
docker compose exec -u www-data app php artisan …  # run any Artisan command
docker compose exec -u www-data app php artisan extension:list
docker compose down                                # stop (data is kept in volumes)

docker compose down -v deletes all volumes, including your database and APP_KEY. Only use it to start over.

Using an external database

To use a managed MySQL or PostgreSQL server instead of the bundled MariaDB, remove the db service and the depends_on block from docker-compose.yml, and point the DB_* variables in wemx.env at your server, for example DB_CONNECTION=pgsql and DB_PORT=5432.

Troubleshooting

ProblemFix
Styles or links point to https:// while testing on http://localhostSet FORCE_HTTPS=false and restart.
Payment gateways redirect to the wrong addressMake sure APP_URL matches the public URL exactly, then restart.
Queue worker is not running on the dashboardRun docker compose logs app and look for queue errors. Before installation the worker restarts until the database tables exist, which is expected.
Uploads fail for large filesRaise client_max_body_size in docker/nginx.conf and the upload limits in docker/php.ini, then rebuild.
"Cannot locate .env file" during installationThe wemx-config volume isn't mounted. Check the volumes section of the app service.

On this page