- Shell 100%
| .gitignore | ||
| bootstrap.sh | ||
| quadlet-phplist-db.container | ||
| quadlet-phplist.container | ||
| quadlet-phplist.network | ||
| README.md | ||
phpList on ps1raf
Rootless-podman quadlet deployment of phpList 3.6.16 — open-source mailing-list / newsletter manager — on ps1raf.
Access
- UI: http://localhost:8082/lists/admin/
- Login:
admin/admin - Admin email:
admin@ps1raf.local(placeholder — change in Config → Manage administrators) - Outbound mail host:
host.containers.internal(shared relay; seeapp.env)
Test install — replace admin with a strong password before putting this in front of real subscribers.
Layout
| File | Purpose |
|---|---|
~/.config/containers/systemd/phplist.network |
Internal podman network phplist |
~/.config/containers/systemd/phplist-db.container |
MariaDB 11 backend, data at data/db/ |
~/.config/containers/systemd/phplist.container |
phplist/phplist:3.6.16, published on host :8082, uploads at data/images/ |
db.env |
MariaDB root + app creds (mode 600, gitignored) |
app.env |
phpList DB_HOST/NAME/USER/PASSWORD/MAILHOST (mode 600, gitignored) |
bootstrap.sh |
Idempotent first-run helper: initialises tables via the web installer URL, then upserts the admin/admin row |
Secrets master copy lives in ~/.env (keys PHPLIST_DB_PASSWORD, PHPLIST_DB_ROOT_PASSWORD). The *.env files in this directory are derived copies.
Bring-up from scratch
# 1. generate creds (if not already in ~/.env)
openssl rand -hex 16 # PHPLIST_DB_PASSWORD
openssl rand -hex 16 # PHPLIST_DB_ROOT_PASSWORD
# …append to ~/.env, then regenerate db.env / app.env (see below).
# 2. regenerate the container env files from ~/.env
cat > db.env <<EOF
MARIADB_ROOT_PASSWORD=$(grep ^PHPLIST_DB_ROOT_PASSWORD= ~/.env | cut -d= -f2)
MARIADB_DATABASE=phplist
MARIADB_USER=phplist
MARIADB_PASSWORD=$(grep ^PHPLIST_DB_PASSWORD= ~/.env | cut -d= -f2)
EOF
cat > app.env <<EOF
DB_HOST=phplist-db
DB_NAME=phplist
DB_USER=phplist
DB_PASSWORD=$(grep ^PHPLIST_DB_PASSWORD= ~/.env | cut -d= -f2)
MAILHOST=host.containers.internal
EOF
chmod 600 db.env app.env
# 3. start the services
systemctl --user daemon-reload
systemctl --user start phplist-db.service
systemctl --user start phplist.service
# 4. first-run init (creates tables, sets admin/admin)
./bootstrap.sh
Why web-triggered init, not phplist CLI
The upstream entrypoint runs phplist -pinitialise but phpList issue #718 makes that a no-op. The web installer at ?page=initialise&firstinstall=1&tk=<csrf> is the only reliable path — bootstrap.sh scrapes the token from the landing page and GETs the URL.
The phplist_admin row seeded by the installer has empty password and email. Because config.php pins HASH_ALGO=sha256, we replace it via SQL with SHA256('admin') + a placeholder email + superuser=1.
Queue processing
Cron inside the container runs service cron start from the entrypoint. The image's default crontab invokes phplist -pprocessqueue periodically; no host-side timer is required for sending. Monitor with podman logs phplist.
Known caveats
- The image hard-codes
HASH_ALGO=sha256in/etc/phplist/config.php; if a future phpList release deprecates sha256 the bootstrap password hash will need updating. - No SSL yet — Step-CA cert will be added when phpList is used for anything more than local testing.
MAILHOSTis set to the LAN smarthost but no auth is passed; if the smarthost requires SMTP AUTH, extendapp.envwithPHPMAILERHOST/ user / pass and rebuildconfig.phpoverrides.
Related
- Wiki page:
/home/raf/llmwiki/services/phplist.md - Forgejo repo: https://ps1raf.tn.ps1.at:3300/raf/phplist.git (configs + bootstrap only, no data)