Deploy
ZealPHP is a long-lived OpenSwoole server process. One process per port, N workers per process. Run behind a reverse proxy (nginx or Caddy) for TLS, static assets, and request logging.
systemd
A reference unit is shipped at deploy/zealphp.service. Copy it to /etc/systemd/system/zealphp.service, adjust User, WorkingDirectory, and ExecStart, then:
Enable and start the service
sudo systemctl daemon-reload
sudo systemctl enable zealphp
sudo systemctl start zealphp
sudo systemctl status zealphp
# Logs:
sudo journalctl -u zealphp -f
The unit is Type=simple — do not pass -d in ExecStart, systemd manages the lifecycle.
Environment variables
| Variable | Default | Purpose |
|---|---|---|
ZEALPHP_HOST | 0.0.0.0 | Bind address |
ZEALPHP_PORT | 8080 | Listen port |
ZEALPHP_WORKERS | CPU count | HTTP worker processes |
ZEALPHP_TASK_WORKERS | 0 | Background task workers |
ZEALPHP_SESSION_SECURE | auto-detect | Force Secure cookie flag (1/0). Auto-detects HTTPS via HTTPS, HTTP_X_FORWARDED_PROTO, or SERVER_PORT=443 headers. |
ZEALPHP_COMPRESSION_MIDDLEWARE | 0 | Enable the reference PHP compression middleware (only if OpenSwoole's native http_compression is disabled). |
ZEALPHP_HTTP_COMPRESSION | 1 | Enable OpenSwoole native HTTP compression. |
ZEALPHP_SITE_URL | request host | Override the URL used in demo links rendered by the site. |
nginx reverse proxy
/etc/nginx/sites-available/zealphp
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
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;
# WebSocket upgrades on /ws/*
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# SSE: disable response buffering and bump timeout
proxy_buffering off;
proxy_read_timeout 86400;
}
}
Caddy reverse proxy
Caddyfile
example.com {
reverse_proxy 127.0.0.1:8080 {
flush_interval -1 # streaming SSE / WebSocket
}
}
Docker
The repo ships a Dockerfile and docker-compose.yml. For production:
docker-compose.yml (production sketch)
services:
app:
image: zealphp:0.2.0
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
environment:
ZEALPHP_HOST: 0.0.0.0
ZEALPHP_PORT: 8080
ZEALPHP_WORKERS: 8
ZEALPHP_SESSION_SECURE: "1"
volumes:
- sessions:/var/lib/php/sessions
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/"]
interval: 30s
timeout: 5s
retries: 3
volumes:
sessions:
Production checklist
- Run as a non-root user; bind to
8080, not80. - Pin OpenSwoole + uopz extension versions in your Dockerfile.
- Set
ZEALPHP_WORKERS≈ CPU cores. - Ensure the session save path (
/var/lib/php/sessions) is writable by the service user and mode0700. - Disable debug logging in production (
ZEALPHP_DEBUG=0or unset). - Rotate logs in
/tmp/zealphp/withlogrotate. - Behind a TLS-terminating proxy, leave
ZEALPHP_SESSION_SECUREunset — the framework auto-detects HTTPS fromX-Forwarded-Proto. - Use
php app.php restartfor graceful, zero-downtime worker recycling.
More
Detailed write-up: docs/deployment.md on GitHub.