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

Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This commit is contained in:
Tomás Cohen Arazi 2026-03-10 15:05:10 -03:00 committed by Pedro Amorim
parent 02e0b4dc9e
commit dc8cced6be
No known key found for this signature in database
GPG Key ID: 06B75BA7F3894D55
17 changed files with 366 additions and 0 deletions

16
debian/control.in vendored
View File

@ -3,6 +3,7 @@ Maintainer: Mason James <mtj@kohaaloha.com>
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.

88
debian/koha-systemd.README.Debian vendored Normal file
View File

@ -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

1
debian/koha-systemd.dirs vendored Normal file
View File

@ -0,0 +1 @@
usr/lib/systemd/system

3
debian/koha-systemd.install vendored Normal file
View File

@ -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

13
debian/koha-systemd.postinst vendored Normal file
View File

@ -0,0 +1,13 @@
#!/bin/sh
set -e
case "$1" in
configure)
# Reload systemd daemon
systemctl daemon-reload || true
;;
esac
#DEBHELPER#
exit 0

14
debian/koha-systemd.prerm vendored Normal file
View File

@ -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

19
debian/systemd/koha-es-indexer@.service vendored Normal file
View File

@ -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

19
debian/systemd/koha-indexer@.service vendored Normal file
View File

@ -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

21
debian/systemd/koha-plack@.service vendored Normal file
View File

@ -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

21
debian/systemd/koha-sip@.service vendored Normal file
View File

@ -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

56
debian/systemd/koha-systemd-ctl vendored Executable file
View File

@ -0,0 +1,56 @@
#!/bin/bash
# koha-systemd-ctl - Helper for managing Koha instances via systemd
set -e
usage() {
cat <<EOF
Usage: $(basename $0) <command> <instance> [service]
Commands:
enable <instance> Enable all services for instance
disable <instance> Disable all services for instance
start <instance> Start all services for instance
stop <instance> Stop all services for instance
restart <instance> Restart all services for instance
status <instance> Show status of all services for instance
enable <instance> <svc> Enable specific service for instance
disable <instance> <svc> Disable specific service for instance
start <instance> <svc> Start specific service for instance
stop <instance> <svc> Stop specific service for instance
restart <instance> <svc> Restart specific service for instance
status <instance> <svc> 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

View File

@ -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

21
debian/systemd/koha-worker@.service vendored Normal file
View File

@ -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

21
debian/systemd/koha-z3950@.service vendored Normal file
View File

@ -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

19
debian/systemd/koha-zebra@.service vendored Normal file
View File

@ -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

6
debian/systemd/koha.target vendored Normal file
View File

@ -0,0 +1,6 @@
[Unit]
Description=Koha ILS - All instances
After=network.target memcached.service mysql.service
[Install]
WantedBy=multi-user.target

7
debian/systemd/koha@.target vendored Normal file
View File

@ -0,0 +1,7 @@
[Unit]
Description=Koha ILS instance %i
After=network.target memcached.service mysql.service
StopWhenUnneeded=yes
[Install]
WantedBy=koha.target