Installation
This guide walks you through installing OPBX using Docker Compose. This is the recommended method for production deployments and local development.
Prerequisites
Before you begin, ensure your system meets these requirements:
| Requirement | Minimum | Recommended |
|---|---|---|
| RAM | 4 GB | 8 GB |
| Disk Space | 20 GB | 50 GB |
| Docker | 20.10+ | Latest |
| Docker Compose | 2.0+ | Latest |
| Git | 2.30+ | Latest |
You also need these ports available on your host machine (all can be remapped via .env):
| Default Port | Service |
|---|---|
| 80 | Nginx reverse proxy |
| 3000 | React frontend (Vite dev server) |
| 6001 | Soketi WebSocket server |
| 4040 | ngrok web interface |
| 8081 | Dialer worker webhook listener |
Installation Steps
1. Clone the Repository
Download the OPBX source code from GitHub:
git clone https://github.com/greenfieldtech-nirs/opbx.git
cd opbx
2. Configure Environment Variables
Copy the example environment file and customize it for your deployment:
cp .env.example .env
cp docker-compose.yml.example docker-compose.yml
Edit the .env file and set these required variables at minimum:
| Variable | Description | How to Generate |
|---|---|---|
APP_KEY | Laravel encryption key | php artisan key:generate |
DB_PASSWORD | MySQL opbx user password | openssl rand -base64 32 |
DB_ROOT_PASSWORD | MySQL root password | openssl rand -base64 32 |
REDIS_PASSWORD | Redis authentication password | openssl rand -base64 32 |
PUSHER_APP_SECRET | Soketi application secret | openssl rand -base64 64 |
DIALER_WORKER_API_TOKEN | Go worker authentication token | openssl rand -hex 32 |
AMD_WORKER_API_TOKEN | AMD worker callback authentication token | openssl rand -hex 32 |
APP_URL | Your domain or IP address | http://localhost for local use |
Optional but commonly configured variables:
| Variable | Description | Default |
|---|---|---|
APP_PORT | Host port for Nginx | 80 |
FRONTEND_PORT | Host port for Vite dev server | 3000 |
NGROK_AUTHTOKEN | ngrok authtoken for local webhook development | (empty) |
NGROK_DOMAIN | Custom ngrok domain (paid plans) | (empty) |
USERCHECK_API_TOKEN | UserCheck email validation token | (empty) |
Cloudonix integration is configured through the web UI after your first login. Do not add Cloudonix credentials to the .env file.
Never commit .env or docker-compose.yml files to version control. The .env.example and docker-compose.yml.example templates are safe to commit because they contain no secrets.
3. Start the Services
Launch all OPBX services with Docker Compose:
docker compose up -d
This command builds images and starts the following services:
| Service | Container | Purpose | Exposed Port |
|---|---|---|---|
app | opbx_app | Laravel PHP-FPM backend | 9000 (internal) |
nginx | opbx_nginx | Reverse proxy and static file server | APP_PORT (default 80) |
frontend | opbx_frontend | React Vite dev server | FRONTEND_PORT (default 3000) |
mysql | opbx_mysql | MySQL 8 database | (internal by default) |
redis | opbx_redis | Cache, sessions, queues, locks | (internal by default) |
minio | opbx_minio | S3-compatible object storage | (internal by default) |
soketi | opbx_websocket | WebSocket server | 6001 |
queue-worker | opbx_queue_worker | Laravel queue worker | — |
scheduler | opbx_scheduler | Laravel task scheduler | — |
dialer-worker | opbx_dialer_worker | Go auto-dialer worker | 8081 |
amd-worker | opbx_amd_worker | Java/Vert.x AMD worker | (internal) |
ngrok | opbx_ngrok | Webhook tunnel (dev only) | 4040 |
The PHP entrypoint runs migrations, seeds, and configuration validation on first startup. Wait 120 seconds after starting containers before testing.
4. Verify Installation
Check that all services are running:
docker compose ps
Test the public health endpoint:
curl http://localhost/api/health
You should receive a JSON response similar to:
{
"status": "ok",
"timestamp": "2026-06-22T12:00:00+00:00"
}
5. Access the Application
Open your browser and navigate to:
| URL | Purpose |
|---|---|
http://localhost/ui | OPBX web application |
http://localhost/api/health | Public health check |
http://localhost:4040 | ngrok dashboard (when enabled) |
Proceed to First Login to create your organization and admin account. If you are enabling Auth0 social login, also see Auth0 Setup.
Troubleshooting
Port Conflicts
If you see errors about ports already in use, change the corresponding variable in your .env file:
APP_PORT=8080 # Use port 8080 instead of 80
FRONTEND_PORT=3001 # Use port 3001 instead of 3000
MySQL Slow Start
MySQL may take longer to initialize on first boot. Wait up to 120 seconds after starting containers before testing:
docker compose logs -f mysql
Permission Denied
If you encounter permission errors, ensure your user is in the docker group:
sudo usermod -aG docker $USER
# Log out and back in for changes to take effect
Container Failures
Check individual service logs for errors:
docker compose logs -f [service-name]
Common service names: app, nginx, mysql, redis, queue-worker, dialer-worker, amd-worker.
Migrations Do Not Run
The app container runs migrations only when RUN_MIGRATIONS=true (the default). If you set it to false, run migrations manually:
docker compose exec app php artisan migrate
Webhooks Not Receiving in Local Development
For Cloudonix to reach your local instance, enable ngrok:
- Add your
NGROK_AUTHTOKENto.env. - Restart the stack:
docker compose up -d. - Find your public HTTPS URL in the ngrok dashboard (
http://localhost:4040) or logs. - Enter that URL as the webhook base URL in Settings > Cloudonix.
Updating OPBX
To update to the latest version:
# Pull latest code
git pull
# Stop running containers
docker compose down
# Rebuild images without cache
docker compose build --no-cache
# Start updated services
docker compose up -d
Database and object-storage data are persisted in ./volumes/ bind mounts. These survive docker compose down. Data will be lost if you run docker compose down -v or delete the volumes/ directory.
Production Deployment
For production environments, consider these additional steps:
- Use a reverse proxy (nginx, traefik) with SSL termination
- Configure automated backups for MySQL (
./scripts/backup-database.sh) and MinIO data - Set strong passwords for all services and rotate tokens regularly
- Do not expose MySQL, Redis, or MinIO ports publicly
- Enable Redis persistence (already enabled via AOF in the example compose file)
- Configure log aggregation
- Set up monitoring and alerting
- Set
APP_ENV=productionandAPP_DEBUG=false - Restrict
SANCTUM_STATEFUL_DOMAINSto your actual domain
Never expose the MySQL, Redis, or MinIO ports to the public internet. Use Docker networks or private IPs for inter-service communication.