Jexactyl Docker
Dockerised Jexactyl panel (v3.7.4).
Stack: PHP 8.2 · Nginx · MariaDB 11 · Valkey 8
Prerequisites
- Docker with the Compose plugin (v2)
Quick start
git clone <this-repo>
cd jexpanel-docker
docker compose up -d --build
The panel will be available at http://localhost once the container is healthy.
On first boot the entrypoint automatically:
- Writes the
APP_KEYfrom your environment into.env - Waits for MariaDB to accept connections
- Runs
php artisan migrate - Caches config and views
- Starts Nginx, PHP-FPM, and the queue worker under supervisord
Configuration
All configuration is done via environment variables in docker-compose.yml. The defaults are suitable for local use only — change the following before exposing the panel publicly.
Required changes for production
| Variable | Default | Notes |
|---|---|---|
APP_URL |
http://localhost |
Set to your full public URL, e.g. https://panel.example.com |
DB_PASSWORD |
secret |
Use a strong password (must match MYSQL_PASSWORD) |
MYSQL_PASSWORD |
secret |
Must match DB_PASSWORD |
MYSQL_ROOT_PASSWORD |
root_secret |
Set a strong root password |
APP_KEY
You must set APP_KEY in docker-compose.yml before starting the stack. Generate one with:
php -r "echo 'base64:' . base64_encode(random_bytes(32));"
Then set it in docker-compose.yml:
APP_KEY: "base64:your-generated-key-here"
If APP_KEY is not set, a temporary key is generated at startup and lost when the container is recreated — sessions and encrypted data will be invalidated.
By default mail is written to the container log (MAIL_MAILER=log). To send real email set:
MAIL_MAILER: smtp
MAIL_HOST: smtp.example.com
MAIL_PORT: 587
MAIL_USERNAME: user@example.com
MAIL_PASSWORD: yourpassword
MAIL_ENCRYPTION: tls
MAIL_FROM_ADDRESS: noreply@example.com
MAIL_FROM_NAME: Jexactyl
Timezone
APP_TIMEZONE: America/New_York # any PHP timezone string
Ports
| Port | Service |
|---|---|
80 |
Jexactyl panel (HTTP) |
For HTTPS, terminate TLS with a reverse proxy (e.g. Nginx, Caddy, or Traefik) in front of the container and pass traffic to port 80.
Persistent data
The following Docker volumes are created automatically and persist across container restarts and rebuilds:
| Volume | Contents |
|---|---|
panel_storage |
Uploaded files, logs, framework cache |
mysql_data |
MariaDB database files |
redis_data |
Valkey (Redis-compatible) data |
Common operations
View logs
# All services
docker compose logs -f
# Panel only
docker compose logs -f panel
Run an Artisan command
docker compose exec panel php artisan <command>
Create the first admin user
docker compose exec panel php artisan p:user:make
Stop the stack
docker compose down
Stop and delete all data (destructive)
docker compose down -v
Rebuild after a config change
docker compose up -d --build
Updating Jexactyl
To pull a newer release, update the JEXACTYL_VERSION build arg in Dockerfile:
ARG JEXACTYL_VERSION=v3.x.x
Then rebuild:
docker compose up -d --build
Migrations are run automatically on startup.
Known limitations
- Route caching is disabled. Jexactyl v3.7.4 has duplicate route names (
admin.tickets.index) that causephp artisan route:cacheto fail. Routes are loaded dynamically instead, with a negligible performance difference for most deployments.