Installation Guide
This guide covers everything required to install Online Casino Script on your own infrastructure. Two paths are documented: Docker (recommended for development and simple production deployments) and manual bare-metal (for operators running their own Ubuntu 22.04 server).
Table of Contents
- Server Requirements
- Option A — Docker Setup
- Option B — Manual Installation (Ubuntu 22.04)
- Environment Configuration
- Database Setup and Migrations
- SSL Certificate
- Systemd Services (Horizon + Reverb)
- Cron Schedule
- File Permissions
- Health Check and Smoke Tests
- Subsequent Deploys
- Troubleshooting Common Install Errors
1. Server Requirements
Docker (development / simple production)
| Requirement | Minimum |
|---|---|
| Docker Desktop | 4.0+ (includes Compose v2) |
| Git | Any recent version |
make |
Pre-installed on macOS/Linux; Windows: use Git Bash or WSL |
| RAM | 4 GB available to Docker |
Bare-metal production server
Hardware
| Resource | Minimum (500 concurrent players) | Recommended (5,000 concurrent players) |
|---|---|---|
| CPU | 4 vCPUs | 8 vCPUs |
| RAM | 8 GB | 16 GB |
| Disk | 50 GB SSD | 100 GB NVMe SSD |
| Bandwidth | 100 Mbps | 1 Gbps |
| OS | Ubuntu 22.04 LTS | Ubuntu 22.04 LTS |
Software versions
| Software | Minimum version |
|---|---|
| PHP | 8.3+ |
| Nginx | 1.24+ |
| MySQL | 8.0+ (or MariaDB 10.6+) |
| Redis | 7.0+ |
| Node.js | 20+ (build step only) |
| Composer | 2+ |
| Certbot | Latest |
Required PHP extensions
bcmath curl fileinfo gd mbstring pdo_mysql openssl pcntl redis tokenizer xml zip
2. Option A — Docker Setup
This is the fastest path. No PHP, MySQL, or Redis installation required — everything runs in containers.
Clone the repository
git clone <your-repo-url> casino
cd casino
Run the one-command setup
make setup
This single command:
- Copies
.env.docker→.env(pre-configured for Docker networking) - Builds all Docker images
- Starts all services:
app,nginx,mysql,redis,horizon,reverb,scheduler - Generates
APP_KEYandJWT_SECRET - Runs all database migrations
- Seeds default admin account, games, and demo data
Expected output:
[setup] Copying .env.docker → .env
[setup] Building images...
[setup] Starting services...
[setup] Waiting for database...
[setup] Running migrations...
[setup] Seeding database...
[setup] Done! Visit http://localhost
The first run downloads base images — this takes 3–10 minutes depending on connection speed. Subsequent starts take seconds.
Verify the install
| URL | What you should see |
|---|---|
http://localhost |
Player-facing casino lobby |
http://localhost/admin |
Admin login page |
http://localhost/health |
JSON health status — all "ok" |
Daily Docker workflow
make up # Start all services
make down # Stop all services
make dev # Start with Vite hot reload (development)
make logs # Tail all container logs
make logs-app # Tail only app container logs
make shell # Open a bash shell inside the app container
make ps # Show running container status
Database commands
make migrate # Run pending migrations
make seed # Re-run seeders
make fresh # Drop all tables, re-migrate, re-seed (prompts for confirmation — destructive)
Updating to a new version (Docker)
git pull
make down && make up
make migrate
3. Option B — Manual Installation (Ubuntu 22.04)
Use this path for production bare-metal deployments.
Step 1 — Install system dependencies
# Update the system
sudo apt update && sudo apt upgrade -y
# Add PHP 8.3 repository
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
# Install PHP 8.3 and all required extensions
sudo apt install -y php8.3-fpm php8.3-cli php8.3-mysql php8.3-redis
php8.3-bcmath php8.3-curl php8.3-fileinfo php8.3-gd php8.3-mbstring
php8.3-openssl php8.3-pcntl php8.3-tokenizer php8.3-xml php8.3-zip
# Install Nginx
sudo apt install -y nginx
# Install MySQL 8
sudo apt install -y mysql-server
sudo mysql_secure_installation
# Install Redis 7
sudo apt install -y redis-server
# Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
# Install Node.js 20 (build step only)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# Install Certbot (for SSL)
sudo apt install -y certbot python3-certbot-nginx
Step 2 — Deploy the application
# Create application directory
sudo mkdir -p /var/www/casino
sudo chown -R www-data:www-data /var/www/casino
# Clone the repository
cd /var/www/casino
git clone <your-repo-url> . --depth=1
# Install PHP dependencies (production — no dev packages)
composer install --no-dev --optimize-autoloader
# Install Node dependencies and build frontend assets
npm ci
npm run build
Step 3 — Configure Nginx
Save the following as /etc/nginx/sites-available/casino:
upstream php-fpm {
server unix:/run/php/php8.3-fpm.sock;
}
# Redirect HTTP → HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# Main HTTPS server block
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
root /var/www/casino/public;
index index.php;
# SSL — managed by Certbot (see Section 6)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript
text/xml application/xml image/svg+xml;
# Max upload size for KYC documents
client_max_body_size 10M;
# Laravel SPA entry point
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP handling
location ~ .php$ {
fastcgi_pass php-fpm;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_read_timeout 60;
}
# WebSocket proxy — Laravel Reverb
location /app/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
}
# Static asset caching (Vite generates content-hashed filenames)
location /build/ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Deny access to hidden and sensitive files
location ~ /. { deny all; }
location ~ .(env|log|htaccess)$ { deny all; }
}
Enable the site:
sudo ln -s /etc/nginx/sites-available/casino /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
Step 4 — Configure PHP-FPM
Create a dedicated pool at /etc/php/8.3/fpm/pool.d/casino.conf:
[casino]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500
php_value[memory_limit] = 256M
php_value[max_execution_time] = 60
php_value[upload_max_filesize] = 10M
php_value[post_max_size] = 12M
; OPcache (critical for performance)
php_admin_value[opcache.enable] = 1
php_admin_value[opcache.memory_consumption] = 256
php_admin_value[opcache.max_accelerated_files] = 20000
php_admin_value[opcache.validate_timestamps] = 0
sudo systemctl restart php8.3-fpm
4. Environment Configuration
Create and edit .env
cp .env.example .env
Open .env and set at minimum:
# Application
APP_NAME="Your Casino Name"
APP_ENV=production
APP_URL=https://example.com
APP_DEBUG=false
FORCE_HTTPS=true
# Database
DB_HOST=127.0.0.1
DB_DATABASE=online_casino
DB_USERNAME=casino
DB_PASSWORD=strong-password-here
# Redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=your-redis-password
REDIS_PORT=6379
# Mail
MAIL_MAILER=smtp
MAIL_HOST=smtp.your-provider.com
MAIL_PORT=587
MAIL_USERNAME=your@email.com
MAIL_PASSWORD=your-password
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="Your Casino"
# WebSockets
REVERB_APP_KEY= # openssl rand -hex 16
REVERB_APP_SECRET= # openssl rand -hex 32
REVERB_HOST=example.com
REVERB_PORT=443
REVERB_SCHEME=https
REVERB_ALLOWED_ORIGINS=https://example.com
For a full reference of every available variable, see the Configuration Reference.
Generate application secrets
# Application encryption key
php artisan key:generate
# JWT secret
php artisan jwt:secret
Cache the configuration
After editing .env, always cache the configuration:
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
Important: Run
php artisan config:clear && php artisan cache:clearany time you change.envon a server where config is cached.
5. Database Setup and Migrations
Create the database and user
CREATE DATABASE online_casino CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'casino'@'localhost' IDENTIFIED BY 'strong-password-here';
GRANT ALL PRIVILEGES ON online_casino.* TO 'casino'@'localhost';
FLUSH PRIVILEGES;
Configure MySQL for production
Add to /etc/mysql/mysql.conf.d/casino.cnf:
[mysqld]
# InnoDB buffer pool — set to 50–70% of available RAM
innodb_buffer_pool_size = 4G
innodb_log_file_size = 512M
# Financial data requires strict ACID compliance
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
max_connections = 300
# Binary log for point-in-time recovery
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 7
binlog_format = ROW
sudo systemctl restart mysql
Configure Redis for production
Edit /etc/redis/redis.conf:
bind 127.0.0.1
requirepass your-strong-redis-password
maxmemory 2gb
maxmemory-policy allkeys-lru
appendonly yes
appendfsync everysec
sudo systemctl restart redis-server
Run migrations and seed initial data
php artisan migrate --force
php artisan db:seed --force
The seeder creates:
- Default admin account (
admin@casino.com/password) — change immediately - All game configurations
- Default payment method templates
- Default role permissions
Create the storage symlink
php artisan storage:link
6. SSL Certificate
Use Let’s Encrypt (free) via Certbot:
sudo certbot --nginx -d example.com -d www.example.com
Certbot automatically edits your Nginx config to add the SSL block.
Verify auto-renewal:
sudo certbot renew --dry-run
sudo systemctl status certbot.timer
7. Systemd Services (Horizon + Reverb)
Two long-running processes must be kept alive by systemd.
Laravel Horizon (queue workers)
Save as /etc/systemd/system/casino-horizon.service:
[Unit]
Description=Online Casino Script — Laravel Horizon
After=network.target mysql.service redis.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/casino
ExecStart=/usr/bin/php artisan horizon
Restart=on-failure
RestartSec=5s
KillSignal=SIGTERM
TimeoutStopSec=60
[Install]
WantedBy=multi-user.target
Laravel Reverb (WebSocket server)
Save as /etc/systemd/system/casino-reverb.service:
[Unit]
Description=Online Casino Script — Laravel Reverb WebSocket Server
After=network.target mysql.service redis.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/casino
ExecStart=/usr/bin/php artisan reverb:start --host=127.0.0.1 --port=8080
Restart=on-failure
RestartSec=5s
KillSignal=SIGTERM
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
Enable and start services
sudo systemctl daemon-reload
sudo systemctl enable casino-horizon casino-reverb
sudo systemctl start casino-horizon casino-reverb
# Verify both are active
sudo systemctl status casino-horizon
sudo systemctl status casino-reverb
8. Cron Schedule
Add to /etc/cron.d/casino:
* * * * * www-data cd /var/www/casino && php artisan schedule:run >> /dev/null 2>&1
The Laravel scheduler manages:
- Daily ledger balance audit
- Daily multi-account detection scan
- Daily bonus abuse detection
- Daily betting velocity check
- Queue metrics snapshot every 5 minutes
9. File Permissions
sudo chown -R www-data:www-data /var/www/casino
sudo find /var/www/casino -type f -exec chmod 644 {} ;
sudo find /var/www/casino -type d -exec chmod 755 {} ;
sudo chmod -R 775 /var/www/casino/storage
sudo chmod -R 775 /var/www/casino/bootstrap/cache
sudo chmod 600 /var/www/casino/.env
The .env file must be readable only by the web server user — it contains secrets.
10. Health Check and Smoke Tests
Health endpoint
curl https://example.com/api/health
Expected response when fully healthy:
{
"status": "ok",
"database": "ok",
"redis": "ok",
"horizon": "ok",
"timestamp": "2026-01-01T00:00:00Z"
}
Pre-launch checklist
Infrastructure
- [ ] DNS records pointing to server IP
- [ ] SSL certificate issued and valid (
https://example.comloads without browser warning) - [ ] Both systemd services running:
casino-horizonandcasino-reverb - [ ] Cron running:
systemctl status cron
Application
- [ ] All migrations applied:
php artisan migrate:status(no pending) - [ ] Config cached:
php artisan config:cache - [ ] Storage symlink created:
ls -la public/storage - [ ] Frontend assets built:
ls public/build/manifest.json
Configuration
- [ ] Admin password changed (not
password) - [ ] 2FA enabled on admin account
- [ ] At least one payment method enabled
- [ ] At least one game enabled
- [ ] Email sending tested
- [ ]
APP_DEBUG=falseconfirmed
Security
- [ ] Redis requires a password (
requirepassinredis.conf) - [ ] MySQL user has no
SUPERorFILEprivileges - [ ] Firewall: only ports 80, 443, 22 exposed publicly
- [ ]
SESSION_SECURE_COOKIE=true - [ ]
.envhaschmod 600permissions
11. Subsequent Deploys
For zero-downtime deploys on bare-metal:
cd /var/www/casino
git pull
composer install --no-dev --optimize-autoloader
npm ci && npm run build
php artisan migrate --force
php artisan config:cache && php artisan route:cache && php artisan view:cache && php artisan event:cache
php artisan horizon:terminate # Horizon auto-restarts via systemd
sudo systemctl restart php8.3-fpm
12. Troubleshooting Common Install Errors
Connection refused — MySQL not running
sudo systemctl status mysql
sudo systemctl start mysql
Verify your .env values match the MySQL user and database you created.
Connection refused — Redis not running
sudo systemctl status redis-server
redis-cli ping # Should return PONG
APP_KEY not set / 500 on all requests
php artisan key:generate
php artisan config:clear
JWT Secret not set — login returns 500
php artisan jwt:secret
php artisan config:clear
Missing PHP extension
php -m | grep -E "bcmath|pdo_mysql|redis|gd|fileinfo|zip|mbstring|pcntl"
# Install any that are missing:
sudo apt install -y php8.3-<extension-name>
sudo systemctl restart php8.3-fpm
APP_DEBUG=true throws RuntimeException in production
Set APP_DEBUG=false in .env and clear the config cache.
SESSION_SECURE_COOKIE=true blocks local HTTP login
For local development only: set SESSION_SECURE_COOKIE=false in .env. Never set this to false in production.
WebSocket connection fails after deploy
Ensure REVERB_ALLOWED_ORIGINS in .env includes your domain URL, then restart Reverb:
php artisan config:clear
sudo systemctl restart casino-reverb
500 after deploy — stale config cache
php artisan optimize:clear
php artisan config:cache && php artisan route:cache && php artisan view:cache
Assets returning 404 — blank SPA
Ensure you ran npm run build as part of the deploy. Verify public/build/manifest.json exists.
For a complete reference of all .env variables, see Configuration Reference. For advanced scaling, see the infrastructure guides in docs/infrastructure/.