Skip to main content

Overview

Heimdinger.lol is designed to run on Laravel Octane for high-performance request handling. This guide covers production deployment, server requirements, and configuration.

Server Requirements

Minimum Requirements

  • PHP: 8.2 or higher
  • Database: MySQL 8.0+ or MariaDB 10.3+
  • Memory: 512MB minimum, 2GB+ recommended
  • Extensions: Required PHP extensions

Required PHP Extensions

php -m | grep -E '(pdo|pdo_mysql|mbstring|xml|ctype|json|bcmath|gd)'
Required extensions:
  • pdo and pdo_mysql
  • mbstring
  • xml and dom
  • ctype
  • json
  • bcmath
  • gd or imagick (for Intervention Image)
  • curl
  • openssl
  • fileinfo

Octane Server Options

Laravel Octane supports multiple application servers:

Environment Configuration

Production Environment File

Create a production .env file based on .env.example:
.env (Production)
APP_NAME=Heimerdinger
APP_ENV=production
APP_KEY=base64:GENERATE_WITH_php_artisan_key:generate
APP_DEBUG=false
APP_TIMEZONE=Europe/Amsterdam
APP_URL=https://heimerdinger.lol

# Laravel Octane
OCTANE_SERVER=swoole
OCTANE_HTTPS=false  # Let reverse proxy handle HTTPS

# Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=heimerdinger_db
DB_USERNAME=heimerdinger
DB_PASSWORD=your_secure_password

# Caching
CACHE_STORE=file
SESSION_DRIVER=database

# Data Sources
BORIS_URL=https://boris.heimerdinger.lol
BORIS_API_KEY=your_boris_api_key
RGAPI_KEY="RGAPI-your-riot-api-key"

# Cloudflare
CLOUDFLARE_ZONE_ID="your_zone_id"
CLOUDFLARE_AUTH_BEARER="your_auth_token"

# Discord Logging
DISCORD_ALERT_WEBHOOK="https://discord.com/api/webhooks/..."
LOG_CHANNEL=stack
LOG_STACK=single,discord

# Security
HCAPTCHA_SECRET=your_hcaptcha_secret
HCAPTCHA_SITEKEY=your_hcaptcha_sitekey
HONEYPOT_NAME=honeypot

# Features
SALES_ENABLED=true
Never commit your production .env file to version control. Keep it secure and backed up separately.

Generate Application Key

php artisan key:generate
This sets APP_KEY which is used for encryption.

Octane Configuration

The Octane configuration is located at config/octane.php.

Key Configuration Options

Choose your application server:
config/octane.php:36
'server' => env('OCTANE_SERVER', 'roadrunner'),
Options: swoole, roadrunner, frankenphp
config/octane.php:49
'https' => env('OCTANE_HTTPS', false),
Set to false when using a reverse proxy (nginx/Caddy) that handles SSL.
Auto-reload workers when files change (development only):
config/octane.php:180
'watch' => [
    'app',
    'bootstrap',
    'config',
    'database',
    'routes',
    '.env',
],
config/octane.php:216
'max_execution_time' => 30,
Set to 0 for no time limit on worker execution.

Deployment Steps

1

Clone Repository

git clone https://github.com/rico-vz/HeimerdingerLoL.git
cd HeimerdingerLoL
2

Install Dependencies

composer install --no-dev --optimize-autoloader
npm install
npm run build
The --no-dev flag excludes development dependencies for smaller footprint.
3

Configure Environment

cp .env.example .env
php artisan key:generate
Edit .env with your production values.
4

Run Migrations

php artisan migrate --force
The --force flag is required in production.
5

Optimize Application

php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan optimize
6

Set Permissions

chmod -R 775 storage bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
7

Start Octane Server

php artisan octane:start --workers=4 --task-workers=6 --port=8000

Running Octane in Production

Systemd Service

Create a systemd service for automatic startup and management:
/etc/systemd/system/heimerdinger-octane.service
[Unit]
Description=Heimerdinger.lol Octane Server
After=network.target

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/heimerdinger.lol
ExecStart=/usr/bin/php /var/www/heimerdinger.lol/artisan octane:start --server=swoole --workers=4 --task-workers=6 --port=8000
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl enable heimerdinger-octane
sudo systemctl start heimerdinger-octane
sudo systemctl status heimerdinger-octane

Supervisor Configuration (Alternative)

Alternatively, use Supervisor:
/etc/supervisor/conf.d/heimerdinger-octane.conf
[program:heimerdinger-octane]
process_name=%(program_name)s
command=php /var/www/heimerdinger.lol/artisan octane:start --server=swoole --workers=4 --task-workers=6 --port=8000
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/heimerdinger.lol/storage/logs/octane.log
stopwaitsecs=60
Reload Supervisor:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start heimerdinger-octane

Reverse Proxy Configuration

Nginx

/etc/nginx/sites-available/heimerdinger.lol
server {
    listen 80;
    listen [::]:80;
    server_name heimerdinger.lol www.heimerdinger.lol;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name heimerdinger.lol www.heimerdinger.lol;
    
    ssl_certificate /etc/letsencrypt/live/heimerdinger.lol/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/heimerdinger.lol/privkey.pem;
    
    location / {
        proxy_pass http://127.0.0.1:8000;
        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-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
    
    location ~ /\.(?!well-known).* {
        deny all;
    }
}
Enable the site:
sudo ln -s /etc/nginx/sites-available/heimerdinger.lol /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Caddy

Caddy automatically handles HTTPS:
/etc/caddy/Caddyfile
heimdinger.lol www.heimerdinger.lol {
    reverse_proxy localhost:8000
    encode gzip
}
Reload Caddy:
sudo systemctl reload caddy

Database Setup

Create Database and User

CREATE DATABASE heimerdinger_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'heimerdinger'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON heimerdinger_db.* TO 'heimerdinger'@'localhost';
FLUSH PRIVILEGES;

Run Migrations

php artisan migrate --force

Database Backups

Configure automated backups with Spatie Backup:
php artisan backup:run
Schedule daily backups in app/Console/Kernel.php:
$schedule->command('backup:clean')->daily()->at('01:00');
$schedule->command('backup:run')->daily()->at('01:30');

Performance Optimization

Opcache Configuration

Enable OPcache for PHP bytecode caching:
/etc/php/8.2/cli/conf.d/10-opcache.ini
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0  # Production only

Redis Caching (Optional)

For better cache performance:
sudo apt-get install redis-server php8.2-redis
.env
CACHE_STORE=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

Application Optimization

php artisan optimize
php artisan config:cache
php artisan route:cache
php artisan view:cache
After making config changes, clear caches and reload Octane:
php artisan config:clear
php artisan octane:reload

Monitoring & Logging

Laravel Pulse

Access real-time monitoring at:
https://heimerdinger.lol/pulse
Authentication via HTTP Basic Auth (configured in routes/web.php:86).

Discord Logging

Production errors are logged to Discord via webhook:
.env:37
DISCORD_ALERT_WEBHOOK="https://discord.com/api/webhooks/your_webhook"
LOG_CHANNEL=stack
LOG_STACK=single,discord

Log Rotation

Configure logrotate:
/etc/logrotate.d/heimerdinger
/var/www/heimerdinger.lol/storage/logs/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data www-data
    sharedscripts
}

Deployment Automation

Deployment Script

Create a deployment script:
deploy.sh
#!/bin/bash
set -e

echo "Pulling latest changes..."
git pull origin main

echo "Installing dependencies..."
composer install --no-dev --optimize-autoloader
npm install && npm run build

echo "Running migrations..."
php artisan migrate --force

echo "Optimizing application..."
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan optimize

echo "Generating sitemap..."
php artisan sitemap:generate

echo "Reloading Octane workers..."
php artisan octane:reload

echo "Purging Cloudflare cache..."
php artisan cloudflare:purge

echo "Deployment complete!"
Make executable:
chmod +x deploy.sh

Health Checks

Octane Health Check

curl http://localhost:8000

Database Connection

php artisan db:show

Queue Workers Status

php artisan queue:work --once

Troubleshooting

Check logs:
tail -f storage/logs/laravel.log
Verify Swoole installation:
php --ri swoole
Check port availability:
sudo lsof -i :8000
Fix storage permissions:
sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cache
Clear all caches:
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
php artisan octane:reload
Test connection:
php artisan tinker
>>> DB::connection()->getPdo();
Verify credentials in .env and MySQL user permissions.

Security Checklist

1

Environment

  • APP_DEBUG=false
  • Strong APP_KEY generated
  • Secure database password
  • .env file not in version control
2

File Permissions

  • Storage directory writable by web server
  • .env file permissions set to 600
  • No write access to application code
3

Web Server

  • HTTPS configured with valid certificate
  • HTTP to HTTPS redirect enabled
  • Security headers configured
  • Access logs enabled
4

Application

  • All routes CSRF protected
  • Rate limiting configured
  • HCaptcha on forms
  • Honeypot enabled

Next Steps

Artisan Commands

Learn about maintenance commands

Data Sources

Configure API integrations

Build docs developers (and LLMs) love