Helix Swarm (P4 Code Review) on Apache + PHP-FPM, drop-in for perforce/helix-swarm
296
epicmorg/swarmPerforce Helix Swarm (P4 Code Review) on Debian 13 trixie, built FROM
epicmorg/apache2:php8.4
(Apache + PHP-FPM, no mod_php). A drop-in for perforce/helix-swarm: the same variables, the same
data volume layout (/opt/perforce/swarm/data), the same vhost file name - change the image: line and keep the
environment, volumes and a bind-mounted perforce-swarm-site.conf. Pair it with
epicmorg/redis (drop-in for
bitnami/redis) and epicmorg/p4d.
r<yy.n>/bin.multiarch/swarm.tgz, sha256-checked against their
SHA256SUMS) in /opt/perforce/swarm - the same source as our p4 binaries; p4 of the matching Helix
release from epicmorg/perforce;helix-swarm deb of the same build at build time
(sha256-checked, unpacked - not installed);p4-bin/bin.linux26x86_64/perforce-php84-ssl3.so, sharing PHP's baked
OpenSSL 3.5), redis (igbinary), imagick, gd, mbstring, xml, xsl; memory_limit 2048M;helix-swarm-optional);apache2, php-fpm, cron (Swarm workers via swarm-cron.sh), swarm-websocket (opt-in);/opt/perforce/swarm/data, ports 80 / 443; HEALTHCHECK = php-fpm ping through Apache.Fatal build-time checks: Swarm release and build, P4PHP is Swarm's and the only one, one libssl in a PHP
process and it is the baked one, the PHP extensions Swarm needs, no mod_php, the Swarm vhost is the only site,
bundled Node present.
public/.htaccess guards (<IfModule mod_php.c>) are switched to
mod_proxy_fcgi, its php_value lines moved to conf.d/30-swarm.ini; CGIPassAuth On for the Swarm
directory so the API sees HTTP basic auth.configure-swarm.sh), the same steps:
Swarm user + password (super-set, then re-set by the user - a super-set password is "expired" on current P4D),
admin protections line, long-lived ticket group swarm-group, data/config.php, worker token, server-side
extension (global + instance config). Secrets are never printed.data/docker/php.ini as an overlay ini (an upstream volume's whole Ubuntu
php.ini is kept aside as php.ini.upstream).pam_loginuid is optional - required, it silently drops every job in a container.| Variable | Default | Meaning |
|---|---|---|
P4D_PORT | ssl:perforce:1666 | P4D address (ssl: = p4 trust -y first) |
P4D_SUPER / P4D_SUPER_PASSWD (_FILE) | super / (none) | super user, first start only |
P4D_GRACE | 30 | seconds to wait for P4D |
SWARM_USER / SWARM_PASSWD (_FILE) | swarm / (none) | Swarm's P4D user (created if missing), first start only |
SWARM_HOST | helix-swarm | environment.hostname, vhost ServerName |
SWARM_EXT_URL | http://${SWARM_HOST}/ | Swarm URL written into the extension (where P4D reaches Swarm) |
SWARM_MAILHOST | localhost | mail relay |
SWARM_REDIS / SWARM_REDIS_PORT | helix-redis / 7379 | redis server |
SWARM_REDIS_PASSWD (_FILE) / SWARM_REDIS_NAMESPACE | (none) | redis password / key namespace |
SWARM_FORCE_EXT | n | y = replace an already installed Swarm extension |
SWARM_WS_ENABLED | n | y = WebSocket live updates (fresh install only) |
SWARM_WS_ALLOWED_ORIGINS | (derived) | gateway's allowed origins |
Configuration happens once, when data/config.php does not exist; later starts only restore the persisted
pieces (cron hosts, public/custom, PHP overlay, vhosts in data/docker/sites-available if an upstream volume
has them). Edit data/config.php for anything else and restart.
Every tag is pushed to docker.io, quay.io and ghcr.io (epicmorg/swarm:<tag> on each) - same digest everywhere.
services:
swarm:
image: epicmorg/swarm:2026.4
restart: always
stop_grace_period: 30s
ports:
- "80:80"
- "443:443"
environment:
P4D_PORT: ssl:p4.example.com:1666
P4D_SUPER: super
P4D_SUPER_PASSWD_FILE: /run/secrets/p4super
SWARM_USER: swarm
SWARM_PASSWD_FILE: /run/secrets/swarm
SWARM_HOST: swarm.example.com
SWARM_MAILHOST: mail.example.com
SWARM_REDIS: helix-redis
SWARM_REDIS_PORT: "6379"
volumes:
- ./swarm:/opt/perforce/swarm/data
# HTTPS: your own vhost (the shipped one is plain :80)
# - ./perforce-swarm-site.conf:/etc/apache2/sites-available/perforce-swarm-site.conf:ro
# - ./certs:/etc/apache2/ssl:ro
secrets: [p4super, swarm]
depends_on: [helix-redis]
helix-redis:
image: epicmorg/redis:8
restart: always
environment:
ALLOW_EMPTY_PASSWORD: "yes" # or REDIS_PASSWORD + SWARM_REDIS_PASSWD
volumes:
- ./redis:/data
secrets:
p4super:
file: ./p4super.txt
swarm:
file: ./swarm.txt
SWARM_EXT_URL when that differs from
http://SWARM_HOST/ (e.g. HTTPS). Later: p4 extension --configure Perforce::helix-swarm.Content type
Image
Digest
sha256:394de6da5…
Size
1.7 GB
Last updated
about 3 hours ago
docker pull epicmorg/swarm