Add elwig-backend.service to .deb package

This commit is contained in:
2025-04-30 16:56:35 +02:00
parent 60be49d31d
commit fbb1a62284
8 changed files with 98 additions and 16 deletions

2
.gitignore vendored
View File

@ -3,3 +3,5 @@
*.sql
*.sqlite3
*.deb
*.ini
!*.sample.ini

9
backend.sample.ini Normal file
View File

@ -0,0 +1,9 @@
[general]
domain = wg.example.com
database = database.sqlite3
users = users.txt
#port = 8084
[jwt]
secret = key
#invalidate_before = 1970-01-01T00:00:00Z

View File

@ -8,6 +8,12 @@ mkdir -p build/
mkdir -p build/usr/bin/
cp src/elwig-backend build/usr/bin
mkdir -p build/lib/systemd/system/
cp pkg/elwig-backend.service build/lib/systemd/system
mkdir -p build/etc/elwig
cp backend.sample.ini build/etc/elwig/backend.ini
mkdir -p build/DEBIAN/
echo -n "\
Package: elwig-backend
@ -17,11 +23,15 @@ Priority: optional
Essential: no
Architecture: all
Depends: python3
Installed-Size: $(du -ks build/usr/bin/ | cut -f 1)
Installed-Size: $(du -ks build/usr/bin/ build/etc/ build/lib/systemd/system/ | cut -f 1 | paste -sd+ | bc)
Maintainer: Lorenz Stechauner <lorenz.stechauner@necronda.net>
Homepage: https://git.necronda.net/winzer/elwig-backend
Description: Local backend for Elwig's REST API
" > build/DEBIAN/control
echo -n "\
/etc/elwig/backend.ini
" > build/DEBIAN/conffiles
cp pkg/postinst pkg/prerm pkg/postrm build/DEBIAN
chmod 0755 build/usr/bin/*
sudo chown root:root -R build/

13
pkg/elwig-backend.service Normal file
View File

@ -0,0 +1,13 @@
[Unit]
Description=Elwig backend
After=network.target
[Service]
RestartSec=5s
Type=simple
User=nobody
ExecStart=/usr/bin/elwig-backend /etc/elwig/backend.ini
Restart=on-failure
[Install]
WantedBy=multi-user.target

25
pkg/postinst Executable file
View File

@ -0,0 +1,25 @@
#!/bin/sh
set -e
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
# This will only remove masks created by d-s-h on package removal.
deb-systemd-helper unmask 'elwig-backend.service' >/dev/null || true
# was-enabled defaults to true, so new installations run enable.
if deb-systemd-helper --quiet was-enabled 'elwig-backend.service'; then
# Enables the unit on first installation, creates new
# symlinks on upgrades if the unit file has changed.
deb-systemd-helper enable 'elwig-backend.service' >/dev/null || true
else
# Update the statefile to add new symlinks (if any), which need to be
# cleaned up on purge. Also remove old symlinks.
deb-systemd-helper update-state 'elwig-backend.service' >/dev/null || true
fi
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true
if [ -n "$2" ]; then
_dh_action=restart
else
_dh_action=start
fi
deb-systemd-invoke $_dh_action 'elwig-backend.service' >/dev/null || true
fi
fi

16
pkg/postrm Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh
set -e
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true
fi
if [ "$1" = "remove" ]; then
if [ -x "/usr/bin/deb-systemd-helper" ]; then
deb-systemd-helper mask 'elwig-backend.service' >/dev/null || true
fi
fi
if [ "$1" = "purge" ]; then
if [ -x "/usr/bin/deb-systemd-helper" ]; then
deb-systemd-helper purge 'elwig-backend.service' >/dev/null || true
deb-systemd-helper unmask 'elwig-backend.service' >/dev/null || true
fi
fi

5
pkg/prerm Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
set -e
if [ -d /run/systemd/system ] && [ "$1" = remove ]; then
deb-systemd-invoke stop 'elwig-backend.service' >/dev/null || true
fi

View File

@ -4,6 +4,8 @@
from __future__ import annotations
from typing import Callable, Optional
from http.server import BaseHTTPRequestHandler, HTTPServer
import configparser
import os.path
import argparse
import datetime
import time
@ -18,7 +20,7 @@ import hashlib
import hmac
VERSION: str = '0.0.4'
VERSION: str = '0.0.6'
CNX: sqlite3.Cursor
USER_FILE: str
@ -176,7 +178,7 @@ class ElwigApi(BaseHTTPRequestHandler):
self.send(f'{{"message":{jdmp(message)}}}\n', status_code=status_code)
def see_other(self, url: str) -> None:
self.send(f'{{"url": {jdmp(url)}}}\n', status_code=303, url=url)
self.send(f'{{"url":{jdmp(url)}}}\n', status_code=303, url=url)
def authorize(self) -> tuple[str, str, str]:
auth = self.headers.get('Authorization')
@ -488,29 +490,29 @@ def main() -> None:
sqlite3.register_adapter(datetime.time, lambda t: t.strftime('%H:%M:%S'))
parser = argparse.ArgumentParser()
parser.add_argument('db', type=str, metavar='DB')
parser.add_argument('jwt_file', type=str, metavar='JWT-FILE')
parser.add_argument('user_file', type=str, metavar='USER-FILE')
parser.add_argument('-p', '--port', type=int, default=8080)
parser.add_argument('config_file', type=str, metavar='CONFIG_FILE')
parser.add_argument('-p', '--port', type=int)
args = parser.parse_args()
jwt_file = args.jwt_file
with open(jwt_file, 'rb') as file:
iss, dt, JWT_SECRET = file.readline().strip().split(b':', 2)
JWT_ISSUER = iss.decode('utf-8')
JWT_INVALIDATE_BEFORE = int(datetime.datetime.fromisoformat(dt.decode('ascii')).timestamp()) if dt else 0
config = configparser.ConfigParser()
config.read(args.config_file)
JWT_ISSUER = config['general']['domain']
JWT_INVALIDATE_BEFORE = int(datetime.datetime.fromisoformat(config['jwt'].get('invalidate_before', '1970-01-01T00:00:00Z')).timestamp())
JWT_SECRET = config['jwt']['secret'].encode('utf-8')
USER_FILE = args.user_file
USER_FILE = os.path.join(os.path.dirname(os.path.abspath(args.config_file)), config['general']['users'])
with open(USER_FILE, 'r') as file:
for line in file:
(u, r, i, p) = line.strip().split(':', 3)
JWT_USER_INVALIDATE_BEFORE[u.strip()] = int(datetime.datetime.fromisoformat(i).timestamp()) if i else 0
CNX = sqlite3.connect(f'file:{args.db}?mode=ro', uri=True)
db_file = os.path.join(os.path.dirname(os.path.abspath(args.config_file)), config['general']['database'])
CNX = sqlite3.connect(f'file:{db_file}?mode=ro', uri=True)
CNX.create_function('REGEXP', 2, sqlite_regexp, deterministic=True)
server = HTTPServer(('localhost', args.port), ElwigApi)
print(f'Listening on http://localhost:{args.port}')
port = args.port or int(config['general'].get('port', '8084'))
server = HTTPServer(('localhost', port), ElwigApi)
print(f'Listening on http://localhost:{port}')
try:
server.serve_forever()
except InterruptedError | KeyboardInterrupt: