From fcb543e1fc8756623fe85201b515aabd7e85f128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Cohen=20Arazi?= Date: Tue, 10 Mar 2026 15:05:10 -0300 Subject: [PATCH] Bug 40901: Add koha-systemd package with native systemd units This patch introduces the koha-systemd package, which provides native systemd service units for managing Koha instances. Each service type (Plack, Zebra, SIP, Z3950, workers, indexers) is managed as a separate systemd unit using instance templates. The package includes: - 8 service templates (plack, zebra, sip, z3950, worker, worker-long, indexer, es-indexer) - 2 target units (koha@.target for per-instance, koha.target for global) - Helper script (koha-systemd-ctl) for managing services All service units include: - KOHA_HOME environment variable pointing to /usr/share/koha - WorkingDirectory set to /var/lib/koha/%i - Proper user/group permissions (%i-koha) This allows granular control over individual services per instance and leverages systemd features like dependency management, resource limits, and journald logging. Test plan: 1. Build and install the package 2. Enable services for an instance 3. Verify all services start correctly 4. Check journalctl logs show no errors --- debian/control.in | 16 +++++ debian/koha-systemd.README.Debian | 88 ++++++++++++++++++++++++ debian/koha-systemd.dirs | 1 + debian/koha-systemd.install | 3 + debian/koha-systemd.postinst | 13 ++++ debian/koha-systemd.prerm | 14 ++++ debian/systemd/koha-es-indexer@.service | 19 +++++ debian/systemd/koha-indexer@.service | 19 +++++ debian/systemd/koha-plack@.service | 21 ++++++ debian/systemd/koha-sip@.service | 21 ++++++ debian/systemd/koha-systemd-ctl | 56 +++++++++++++++ debian/systemd/koha-worker-long@.service | 21 ++++++ debian/systemd/koha-worker@.service | 21 ++++++ debian/systemd/koha-z3950@.service | 21 ++++++ debian/systemd/koha-zebra@.service | 19 +++++ debian/systemd/koha.target | 6 ++ debian/systemd/koha@.target | 7 ++ 17 files changed, 366 insertions(+) create mode 100644 debian/koha-systemd.README.Debian create mode 100644 debian/koha-systemd.dirs create mode 100644 debian/koha-systemd.install create mode 100644 debian/koha-systemd.postinst create mode 100644 debian/koha-systemd.prerm create mode 100644 debian/systemd/koha-es-indexer@.service create mode 100644 debian/systemd/koha-indexer@.service create mode 100644 debian/systemd/koha-plack@.service create mode 100644 debian/systemd/koha-sip@.service create mode 100755 debian/systemd/koha-systemd-ctl create mode 100644 debian/systemd/koha-worker-long@.service create mode 100644 debian/systemd/koha-worker@.service create mode 100644 debian/systemd/koha-z3950@.service create mode 100644 debian/systemd/koha-zebra@.service create mode 100644 debian/systemd/koha.target create mode 100644 debian/systemd/koha@.target diff --git a/debian/control.in b/debian/control.in index 899b31947a..10f8801495 100644 --- a/debian/control.in +++ b/debian/control.in @@ -3,6 +3,7 @@ Maintainer: Mason James Section: web Priority: optional Standards-Version: 3.8.4 +# koha-systemd package provides systemd units only # WARNING: The "control" file is automatically generated from the "control.in" file. # Do not manually edit "control" or your changes will be clobbered when you # run update-control @@ -146,3 +147,18 @@ Description: integrated (physical) library management system systems such as MariaDB, RabbitMQ, et cetera. . This package is EXPERIMENTAL and not recommended for production use. + +Package: koha-systemd +Architecture: all +Depends: ${misc:Depends}, systemd, koha-common +Description: systemd units for Koha ILS + Koha is an Integrated Library Management system for real-world libraries + (the kinds with books). + . + This package provides native systemd service units for managing Koha + instances. Each service type (Plack, Zebra, SIP, Z3950, workers, indexers) + is managed as a separate systemd unit using instance templates. + . + This allows granular control over individual services per instance and + leverages systemd features like dependency management, resource limits, + and journald logging. diff --git a/debian/koha-systemd.README.Debian b/debian/koha-systemd.README.Debian new file mode 100644 index 0000000000..2f71bf14ca --- /dev/null +++ b/debian/koha-systemd.README.Debian @@ -0,0 +1,88 @@ +# Koha systemd Units + +This package provides native systemd service units for Koha ILS. + +## Architecture + +Each Koha service type runs as a separate systemd unit using instance templates: + +- `koha-plack@.service` - Plack/Starman web application server +- `koha-zebra@.service` - Zebra search indexing server +- `koha-sip@.service` - SIP2 circulation protocol server +- `koha-z3950@.service` - Z39.50/SRU server +- `koha-worker@.service` - Background job worker (default queue) +- `koha-worker-long@.service` - Background job worker (long_tasks queue) +- `koha-indexer@.service` - Zebra indexing daemon +- `koha-es-indexer@.service` - Elasticsearch indexing daemon + +Instance grouping: +- `koha@.target` - Groups all services for a single instance +- `koha.target` - Groups all Koha instances + +## Usage + +### Managing a complete instance + +```bash +# Start all services for instance "library" +systemctl start koha@library.target + +# Enable at boot +systemctl enable koha@library.target + +# Check status +systemctl status koha@library.target +``` + +### Managing individual services + +```bash +# Start only Plack for instance "library" +systemctl start koha-plack@library.service + +# Restart SIP server +systemctl restart koha-sip@library.service + +# Check worker status +systemctl status koha-worker@library.service +systemctl status koha-worker-long@library.service +``` + +### Logs + +```bash +# View logs for all services of an instance +journalctl -u 'koha-*@library.service' + +# View Plack logs +journalctl -u koha-plack@library.service -f + +# View all Koha logs +journalctl -u 'koha-*.service' +``` + +## Service Enablement + +Some services are conditionally enabled based on configuration files: + +- **SIP**: Requires `/var/lib/koha/{instance}/sip.enabled` and `/etc/koha/sites/{instance}/SIPconfig.xml` +- **Z3950**: Requires `/etc/koha/sites/{instance}/z3950/config.xml` + +## Migration from init scripts + +The koha-systemd package is designed to coexist with koha-common but provides +an alternative service management approach. To migrate: + +1. Stop services via init script: `service koha-common stop` +2. Install koha-systemd package +3. Enable instance target: `systemctl enable koha@{instance}.target` +4. Start services: `systemctl start koha@{instance}.target` + +## Advantages + +- **Granular control**: Start/stop individual services per instance +- **Resource limits**: Apply CPU/memory limits via systemd +- **Dependency management**: Proper service ordering and failure handling +- **Logging**: Centralized logging via journald +- **Security**: Modern sandboxing options available +- **Monitoring**: Native systemd health checks and status reporting diff --git a/debian/koha-systemd.dirs b/debian/koha-systemd.dirs new file mode 100644 index 0000000000..8efa80f4d9 --- /dev/null +++ b/debian/koha-systemd.dirs @@ -0,0 +1 @@ +usr/lib/systemd/system diff --git a/debian/koha-systemd.install b/debian/koha-systemd.install new file mode 100644 index 0000000000..06952f8299 --- /dev/null +++ b/debian/koha-systemd.install @@ -0,0 +1,3 @@ +debian/systemd/*.service usr/lib/systemd/system +debian/systemd/*.target usr/lib/systemd/system +debian/systemd/koha-systemd-ctl usr/sbin diff --git a/debian/koha-systemd.postinst b/debian/koha-systemd.postinst new file mode 100644 index 0000000000..72efb7a6d9 --- /dev/null +++ b/debian/koha-systemd.postinst @@ -0,0 +1,13 @@ +#!/bin/sh +set -e + +case "$1" in + configure) + # Reload systemd daemon + systemctl daemon-reload || true + ;; +esac + +#DEBHELPER# + +exit 0 diff --git a/debian/koha-systemd.prerm b/debian/koha-systemd.prerm new file mode 100644 index 0000000000..651fc77873 --- /dev/null +++ b/debian/koha-systemd.prerm @@ -0,0 +1,14 @@ +#!/bin/sh +set -e + +case "$1" in + remove|deconfigure) + if [ -d /run/systemd/system ]; then + systemctl --system daemon-reload >/dev/null || true + fi + ;; +esac + +#DEBHELPER# + +exit 0 diff --git a/debian/systemd/koha-es-indexer@.service b/debian/systemd/koha-es-indexer@.service new file mode 100644 index 0000000000..d236dee5f2 --- /dev/null +++ b/debian/systemd/koha-es-indexer@.service @@ -0,0 +1,19 @@ +[Unit] +Description=Koha Elasticsearch indexer daemon for %i +PartOf=koha@%i.target +After=koha@%i.target + +[Service] +Type=simple +User=%i-koha +Group=%i-koha +WorkingDirectory=/var/lib/koha/%i +Environment=KOHA_CONF=/etc/koha/sites/%i/koha-conf.xml +Environment=KOHA_HOME=/usr/share/koha +Environment=PERL5LIB=/usr/share/koha/lib +ExecStart=/usr/share/koha/bin/workers/es_indexer_daemon.pl +Restart=on-failure +RestartSec=30s + +[Install] +WantedBy=koha@%i.target diff --git a/debian/systemd/koha-indexer@.service b/debian/systemd/koha-indexer@.service new file mode 100644 index 0000000000..ed8de97364 --- /dev/null +++ b/debian/systemd/koha-indexer@.service @@ -0,0 +1,19 @@ +[Unit] +Description=Koha Zebra indexer daemon for %i +PartOf=koha@%i.target +After=koha@%i.target koha-zebra@%i.service + +[Service] +Type=simple +User=%i-koha +Group=%i-koha +WorkingDirectory=/var/lib/koha/%i +Environment=KOHA_CONF=/etc/koha/sites/%i/koha-conf.xml +Environment=KOHA_HOME=/usr/share/koha +Environment=PERL5LIB=/usr/share/koha/lib +ExecStart=/usr/share/koha/bin/migration_tools/rebuild_zebra.pl -daemon -sleep 5 +Restart=on-failure +RestartSec=30s + +[Install] +WantedBy=koha@%i.target diff --git a/debian/systemd/koha-plack@.service b/debian/systemd/koha-plack@.service new file mode 100644 index 0000000000..0c9412732d --- /dev/null +++ b/debian/systemd/koha-plack@.service @@ -0,0 +1,21 @@ +[Unit] +Description=Koha Plack server for %i +PartOf=koha@%i.target +After=koha@%i.target + +[Service] +Type=forking +User=%i-koha +Group=%i-koha +WorkingDirectory=/var/lib/koha/%i +Environment=KOHA_CONF=/etc/koha/sites/%i/koha-conf.xml +Environment=KOHA_HOME=/usr/share/koha +Environment=PERL5LIB=/usr/share/koha/lib +PIDFile=/var/run/koha/%i/plack.pid +ExecStart=/usr/bin/plackup -s Starman --daemonize --pid /var/run/koha/%i/plack.pid --listen /var/run/koha/%i/plack.sock /etc/koha/plack.psgi +ExecReload=/bin/kill -HUP $MAINPID +Restart=on-failure +RestartSec=5s + +[Install] +WantedBy=koha@%i.target diff --git a/debian/systemd/koha-sip@.service b/debian/systemd/koha-sip@.service new file mode 100644 index 0000000000..d3b8118558 --- /dev/null +++ b/debian/systemd/koha-sip@.service @@ -0,0 +1,21 @@ +[Unit] +Description=Koha SIP server for %i +PartOf=koha@%i.target +After=koha@%i.target +ConditionPathExists=/var/lib/koha/%i/sip.enabled +ConditionPathExists=/etc/koha/sites/%i/SIPconfig.xml + +[Service] +Type=simple +User=%i-koha +Group=%i-koha +WorkingDirectory=/var/lib/koha/%i +Environment=KOHA_CONF=/etc/koha/sites/%i/koha-conf.xml +Environment=KOHA_HOME=/usr/share/koha +Environment=PERL5LIB=/usr/share/koha/lib +ExecStart=/usr/bin/perl /usr/share/koha/lib/C4/SIP/SIPServer.pm /etc/koha/sites/%i/SIPconfig.xml +Restart=on-failure +RestartSec=30s + +[Install] +WantedBy=koha@%i.target diff --git a/debian/systemd/koha-systemd-ctl b/debian/systemd/koha-systemd-ctl new file mode 100755 index 0000000000..4f9f95d773 --- /dev/null +++ b/debian/systemd/koha-systemd-ctl @@ -0,0 +1,56 @@ +#!/bin/bash +# koha-systemd-ctl - Helper for managing Koha instances via systemd + +set -e + +usage() { + cat < [service] + +Commands: + enable Enable all services for instance + disable Disable all services for instance + start Start all services for instance + stop Stop all services for instance + restart Restart all services for instance + status Show status of all services for instance + + enable Enable specific service for instance + disable Disable specific service for instance + start Start specific service for instance + stop Stop specific service for instance + restart Restart specific service for instance + status Show status of specific service for instance + +Services: plack, zebra, sip, z3950, worker, worker-long, indexer, es-indexer + +Examples: + $(basename $0) enable library + $(basename $0) start library plack + $(basename $0) status library + $(basename $0) restart library worker +EOF + exit 1 +} + +[ $# -lt 2 ] && usage + +CMD=$1 +INSTANCE=$2 +SERVICE=${3:-} + +if [ -n "$SERVICE" ]; then + UNIT="koha-${SERVICE}@${INSTANCE}.service" +else + UNIT="koha@${INSTANCE}.target" +fi + +case "$CMD" in + enable|disable|start|stop|restart|status) + systemctl "$CMD" "$UNIT" + ;; + *) + echo "Unknown command: $CMD" + usage + ;; +esac diff --git a/debian/systemd/koha-worker-long@.service b/debian/systemd/koha-worker-long@.service new file mode 100644 index 0000000000..77d1c5a9c0 --- /dev/null +++ b/debian/systemd/koha-worker-long@.service @@ -0,0 +1,21 @@ +[Unit] +Description=Koha background worker (long_tasks queue) for %i +PartOf=koha@%i.target +After=koha@%i.target +StartLimitIntervalSec=60 +StartLimitBurst=3 + +[Service] +Type=simple +User=%i-koha +Group=%i-koha +WorkingDirectory=/var/lib/koha/%i +Environment=KOHA_CONF=/etc/koha/sites/%i/koha-conf.xml +Environment=KOHA_HOME=/usr/share/koha +Environment=PERL5LIB=/usr/share/koha/lib +ExecStart=/usr/share/koha/bin/workers/background_jobs_worker.pl --queue long_tasks +Restart=on-failure +RestartSec=5s + +[Install] +WantedBy=koha@%i.target diff --git a/debian/systemd/koha-worker@.service b/debian/systemd/koha-worker@.service new file mode 100644 index 0000000000..bd0874f91e --- /dev/null +++ b/debian/systemd/koha-worker@.service @@ -0,0 +1,21 @@ +[Unit] +Description=Koha background worker (default queue) for %i +PartOf=koha@%i.target +After=koha@%i.target +StartLimitIntervalSec=60 +StartLimitBurst=3 + +[Service] +Type=simple +User=%i-koha +Group=%i-koha +WorkingDirectory=/var/lib/koha/%i +Environment=KOHA_CONF=/etc/koha/sites/%i/koha-conf.xml +Environment=KOHA_HOME=/usr/share/koha +Environment=PERL5LIB=/usr/share/koha/lib +ExecStart=/usr/share/koha/bin/workers/background_jobs_worker.pl --queue default +Restart=on-failure +RestartSec=5s + +[Install] +WantedBy=koha@%i.target diff --git a/debian/systemd/koha-z3950@.service b/debian/systemd/koha-z3950@.service new file mode 100644 index 0000000000..62cfc69f1d --- /dev/null +++ b/debian/systemd/koha-z3950@.service @@ -0,0 +1,21 @@ +[Unit] +Description=Koha Z39.50/SRU server for %i +PartOf=koha@%i.target +After=koha@%i.target +ConditionPathExists=/etc/koha/sites/%i/z3950/config.xml + +[Service] +Type=forking +User=%i-koha +Group=%i-koha +WorkingDirectory=/var/lib/koha/%i +Environment=KOHA_CONF=/etc/koha/sites/%i/koha-conf.xml +Environment=KOHA_HOME=/usr/share/koha +Environment=PERL5LIB=/usr/share/koha/lib +PIDFile=/var/run/koha/%i/z3950-responder.pid +ExecStart=/usr/share/koha/bin/z3950_responder.pl -c /etc/koha/sites/%i/z3950 -u %i-koha -p /var/run/koha/%i/z3950-responder.pid -D -d %i-koha-z3950 -l /var/log/koha/%i/z3950.log +Restart=on-failure +RestartSec=30s + +[Install] +WantedBy=koha@%i.target diff --git a/debian/systemd/koha-zebra@.service b/debian/systemd/koha-zebra@.service new file mode 100644 index 0000000000..61fd60c397 --- /dev/null +++ b/debian/systemd/koha-zebra@.service @@ -0,0 +1,19 @@ +[Unit] +Description=Koha Zebra indexing server for %i +PartOf=koha@%i.target +After=koha@%i.target + +[Service] +Type=forking +User=%i-koha +Group=%i-koha +WorkingDirectory=/var/lib/koha/%i +Environment=KOHA_CONF=/etc/koha/sites/%i/koha-conf.xml +Environment=KOHA_HOME=/usr/share/koha +PIDFile=/var/run/koha/%i/zebra.pid +ExecStart=/usr/bin/zebrasrv -f /etc/koha/sites/%i/koha-conf.xml -p /var/run/koha/%i/zebra.pid -D +Restart=on-failure +RestartSec=30s + +[Install] +WantedBy=koha@%i.target diff --git a/debian/systemd/koha.target b/debian/systemd/koha.target new file mode 100644 index 0000000000..37ba78919d --- /dev/null +++ b/debian/systemd/koha.target @@ -0,0 +1,6 @@ +[Unit] +Description=Koha ILS - All instances +After=network.target memcached.service mysql.service + +[Install] +WantedBy=multi-user.target diff --git a/debian/systemd/koha@.target b/debian/systemd/koha@.target new file mode 100644 index 0000000000..4fc988e0d6 --- /dev/null +++ b/debian/systemd/koha@.target @@ -0,0 +1,7 @@ +[Unit] +Description=Koha ILS instance %i +After=network.target memcached.service mysql.service +StopWhenUnneeded=yes + +[Install] +WantedBy=koha.target -- 2.50.1 (Apple Git-155)