Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Migrating from Supervisor to Systemd

Note: This guide assumes you are using a sudo user named ubuntu and UNIT3D is installed at /var/www/html.

Why Migrate?

Systemd offers several advantages over Supervisor for managing UNIT3D services:

AspectSupervisorSystemd
OverheadPython daemon, socket communicationNative kernel integration
Memory~20-50MB for supervisordAlready running (init system)
Boot IntegrationRequires separate serviceNative system integration
LoggingFile-basedJournald (structured, rotated)
SecurityBasicNamespaces, sandboxing, cgroups

1. Create Systemd Unit Files

UNIT3D-Announce

Caution

Only create this Systemd unit file if usings rust based unit3d-announce!

sudo nano /etc/systemd/system/unit3d-announce.service

Add the following:

# /etc/systemd/system/unit3d-announce.service
#
# Systemd service unit for UNIT3D-Announce

[Unit]
Description=UNIT3D Announce Tracker
Documentation=https://github.com/ReUnit3d/ReUnit3d-Announce
After=network.target mysql.service
Wants=mysql.service

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/html/unit3d-announce

# Environment file for the tracker
EnvironmentFile=/var/www/html/unit3d-announce/.env

# Main process
ExecStart=/var/www/html/unit3d-announce/target/release/unit3d-announce

# Restart policy
Restart=on-failure
RestartSec=5

# Resource limits (adjust based on your server)
# UNIT3D-Announce is very lightweight (~50k req/s per core)
LimitNOFILE=65535

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/www/html/unit3d-announce /var/www/html/storage/logs

# Logging - goes to journald, viewable with: journalctl -u unit3d-announce
StandardOutput=journal
StandardError=journal
SyslogIdentifier=unit3d-announce

[Install]
WantedBy=multi-user.target

Laravel Queue Workers

Using a template unit allows you to run multiple queue workers:

sudo nano /etc/systemd/system/unit3d-queue@.service

Add the following:

# /etc/systemd/system/unit3d-queue@.service
#
# Systemd template unit for Laravel Queue Workers

[Unit]
Description=UNIT3D Queue Worker %i
Documentation=https://laravel.com/docs/queues
After=network.target mysql.service redis.service
Wants=mysql.service redis.service

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/html

# Main process - runs one queue worker
# --tries=1: Retry failed jobs once
# --max-jobs=1000: Restart after processing 1000 jobs (prevents memory leaks)
# --max-time=3600: Restart after 1 hour (ensures fresh connections)
ExecStart=/usr/bin/php /var/www/html/artisan queue:work --tries=1 --max-jobs=1000 --max-time=3600

# Graceful stop - let the current job finish
TimeoutStopSec=3605

# Restart policy
Restart=always
RestartSec=3

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/www/html/storage /var/www/html/bootstrap/cache

# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=unit3d-queue-%i

[Install]
WantedBy=multi-user.target

Laravel Reverb (WebSocket Server)

sudo nano /etc/systemd/system/unit3d-reverb.service

Add the following:

# /etc/systemd/system/unit3d-reverb.service
#
# Systemd service unit for Laravel Reverb (WebSocket server for UNIT3D Chat)

[Unit]
Description=UNIT3D Chat Server (Laravel Reverb)
Documentation=https://laravel.com/docs/reverb
After=network.target mysql.service redis.service
Wants=mysql.service redis.service

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/html

# Main process
ExecStart=/usr/bin/php /var/www/html/artisan reverb:start --no-interaction

# Graceful shutdown
TimeoutStopSec=30

# Restart policy
Restart=on-failure
RestartSec=5

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/www/html/storage /var/www/html/bootstrap/cache

# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=unit3d-reverb

[Install]
WantedBy=multi-user.target

2. Stop and Disable Supervisor

sudo supervisorctl stop all
sudo systemctl stop supervisor
sudo systemctl disable supervisor

3. Enable and Start Systemd Services

# Reload systemd to recognize new units
sudo systemctl daemon-reload

# UNIT3D-Announce
sudo systemctl enable --now unit3d-announce

# Queue Workers (4 instances, equivalent to numprocs=4)
sudo systemctl enable --now unit3d-queue@{1..4}

# Laravel Reverb
sudo systemctl enable --now unit3d-reverb

4. Verify Services

Check all services are running:

systemctl status unit3d-announce
systemctl status unit3d-queue@1 unit3d-queue@2 unit3d-queue@3 unit3d-queue@4
systemctl status unit3d-reverb

View logs:

journalctl -u unit3d-announce -f
journalctl -u unit3d-queue@* -f
journalctl -u unit3d-reverb -f

5. Remove Supervisor Configuration (Optional)

Only after confirming everything works:

sudo rm /etc/supervisor/conf.d/unit3d.conf
sudo apt remove supervisor  # or keep it for other services

Managing Services

Start/Stop/Restart

# Single service
sudo systemctl restart unit3d-announce

# All queue workers at once
sudo systemctl restart 'unit3d-queue@*'

# Or individually
sudo systemctl restart unit3d-queue@1

Scaling Queue Workers

Add more workers:

sudo systemctl enable unit3d-queue@5 unit3d-queue@6
sudo systemctl start unit3d-queue@5 unit3d-queue@6

Remove workers:

sudo systemctl stop unit3d-queue@5 unit3d-queue@6
sudo systemctl disable unit3d-queue@5 unit3d-queue@6

View Logs

# Follow logs in real-time
journalctl -u unit3d-announce -f

# Show last 100 lines
journalctl -u unit3d-queue@1 -n 100

# Show logs since boot
journalctl -u unit3d-reverb -b

# Show logs for a time range
journalctl -u unit3d-announce --since "1 hour ago"

Troubleshooting

Service Won’t Start

# Check the full error
journalctl -u unit3d-announce -n 50 --no-pager

# Check service configuration
systemctl cat unit3d-announce

# Test the command manually
sudo -u www-data /var/www/html/unit3d-announce/target/release/unit3d-announce

Permission Issues

The unit files use ProtectSystem=strict for security. If you get permission errors:

# Check what paths the service can write to
systemctl show unit3d-announce -p ReadWritePaths

# Temporarily disable protection for debugging
sudo systemctl edit unit3d-announce

Add:

[Service]
ProtectSystem=false

Queue Jobs Not Processing

# Check all queue worker statuses
systemctl list-units 'unit3d-queue@*'

# Restart all workers
sudo systemctl restart 'unit3d-queue@*'

# Check for failed jobs
php /var/www/html/artisan queue:failed

See also

For further details, refer to the systemd documentation.