forked from lab-in-a-box/liab-deployments
187 lines
4.4 KiB
Python
187 lines
4.4 KiB
Python
#
|
|
# Deploy ntfy.sh server (https://ntfy.sh) pub-sub notification service
|
|
#
|
|
# An example inventory may look like this:
|
|
#
|
|
# group = [
|
|
# (
|
|
# 'edu.datalad.org',
|
|
# {
|
|
# 'ntfy': [
|
|
# {
|
|
# 'serve_address': 'ntfy.example.org',
|
|
# 'container_tag': 'binwiederhier/ntfy',
|
|
# # user name and numerical ID
|
|
# 'user': ('ntfy', '4000'),
|
|
# 'host_port': 30030,
|
|
# 'config_file_asset': 'assets/status-example-config.yaml',
|
|
# #'data_dir': 'data',
|
|
# },
|
|
# ...
|
|
#
|
|
from pyinfra.api import deploy
|
|
from pyinfra import (
|
|
host,
|
|
)
|
|
from pyinfra.operations import (
|
|
files,
|
|
server,
|
|
)
|
|
from liab_deployments.operations import (
|
|
caddy,
|
|
user,
|
|
user_systemd,
|
|
)
|
|
|
|
|
|
service_unit_tmpl = """\
|
|
[Unit]
|
|
Description=Podman-managed ntfy service
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
RequiresMountsFor=%t/containers
|
|
|
|
[Service]
|
|
Environment=PODMAN_SYSTEMD_UNIT=%n
|
|
Restart=always
|
|
TimeoutStopSec=300
|
|
ExecStartPre=/bin/rm \\
|
|
-f %t/%n.ctr-id
|
|
|
|
ExecStart=/usr/bin/podman container run \\
|
|
--cidfile=%t/%n.ctr-id \\
|
|
--cgroups=no-conmon \\
|
|
--rm \\
|
|
--sdnotify=conmon \\
|
|
-d \\
|
|
--replace \\
|
|
--pull newer \\
|
|
--name ntfy \\
|
|
-e "NTFY_BASE_URL=https://{serve_address}" \\
|
|
-e "NTFY_CACHE_FILE=/data/cache.db" \\
|
|
-e "NTFY_AUTH_FILE=/data/auth.db" \\
|
|
-e "NTFY_AUTH_DEFAULT_ACCESS=deny-all" \\
|
|
-e "NTFY_BEHIND_PROXY=true" \\
|
|
-e "NTFY_ATTACHMENT_CACHE_DIR=/data/attachments" \\
|
|
-p {host_port}:80 \\
|
|
-v {user_home}/data:/data:rw \\
|
|
-v {user_home}/config:/etc/ntfy:ro \\
|
|
{container_tag} \\
|
|
serve
|
|
ExecStop=/usr/bin/podman stop \\
|
|
--ignore -t 10 \\
|
|
--cidfile=%t/%n.ctr-id
|
|
ExecStopPost=/usr/bin/podman rm \\
|
|
-f \\
|
|
--ignore -t 10 \\
|
|
--cidfile=%t/%n.ctr-id
|
|
Type=notify
|
|
NotifyAccess=all
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
"""
|
|
|
|
caddyfile_block_tmpl = """\
|
|
{serve_address} {{
|
|
reverse_proxy localhost:{host_port}
|
|
|
|
# Redirect HTTP to HTTPS, but only for GET topic addresses, since we want
|
|
# it to work with curl without the annoying https:// prefix
|
|
@httpget {{
|
|
protocol http
|
|
method GET
|
|
path_regexp ^/([-_a-z0-9]{{0,64}}$|docs/|static/)
|
|
}}
|
|
redir @httpget https://{{host}}{{uri}}
|
|
}}
|
|
"""
|
|
|
|
|
|
@deploy("Deploy ntfy")
|
|
def deploy_sites():
|
|
if not hasattr(host.data, 'ntfy'):
|
|
return
|
|
for spec in host.data.ntfy.get('sites', []):
|
|
_deploy_site(
|
|
spec['serve_address'],
|
|
spec['container_tag'],
|
|
spec['user'],
|
|
spec['host_port'],
|
|
name=spec.get('name', 'ntfy'),
|
|
caddyfile_block_tmpl=spec.get(
|
|
'caddyfile_block_tmpl', caddyfile_block_tmpl
|
|
),
|
|
config_file_asset=spec.get('config_file_asset'),
|
|
data_dir=spec.get('data_dir'),
|
|
)
|
|
|
|
|
|
def _deploy_site(
|
|
serve_address,
|
|
container_tag,
|
|
user_spec: tuple[str, int],
|
|
host_port,
|
|
*,
|
|
name,
|
|
caddyfile_block_tmpl,
|
|
config_file_asset=None,
|
|
data_dir=None,
|
|
):
|
|
user_name, uid = user_spec
|
|
user_home = f'/home/{user_name}'
|
|
|
|
user.systemd_service(
|
|
user_name,
|
|
uid,
|
|
user_home,
|
|
)
|
|
|
|
if data_dir is None:
|
|
data_dir = f'{user_home}/data'
|
|
|
|
for i in [f'{user_home}/config', data_dir]:
|
|
files.directory(
|
|
path=i,
|
|
present=True,
|
|
_sudo_user=user_name,
|
|
)
|
|
|
|
user_systemd.service_unit(
|
|
user_name,
|
|
user_home,
|
|
name,
|
|
service_unit_tmpl.format(
|
|
serve_address=serve_address,
|
|
user_home=user_home,
|
|
container_tag=container_tag,
|
|
host_port=host_port,
|
|
),
|
|
)
|
|
|
|
if config_file_asset:
|
|
files.put(
|
|
name='ntfy config',
|
|
src=config_file_asset,
|
|
dest=f'{user_home}/config/server.yml',
|
|
_sudo_user=user_name,
|
|
)
|
|
|
|
user_systemd.run_service(
|
|
user_name,
|
|
uid,
|
|
'ntfy',
|
|
)
|
|
|
|
server.wait(
|
|
name=f"Wait for ntfy {serve_address!r} to start",
|
|
port=host_port,
|
|
)
|
|
|
|
caddy.caddyfile_block(
|
|
marker=f'NTFY {serve_address}',
|
|
content=caddyfile_block_tmpl.format(
|
|
serve_address=serve_address,
|
|
host_port=host_port,
|
|
),
|
|
)
|