forked from lab-in-a-box/liab-deployments
222 lines
5.4 KiB
Python
222 lines
5.4 KiB
Python
#
|
|
# Deploy OwnTracks (https://owntracks.org)
|
|
#
|
|
# An example inventory may look like this:
|
|
#
|
|
# group = [
|
|
# (
|
|
# 'edu.example.org',
|
|
# {
|
|
# 'owntracks': {
|
|
# 'sites': [
|
|
# {
|
|
# 'serve_address': "geo.example.org",
|
|
# 'container_tag': "docker.io/owntracks/recorder",
|
|
# 'user': ('owntracks', 1008),
|
|
# 'host_port': 8083,
|
|
# 'card_assets': 'assets/owntracks/geo.example.org-cards',
|
|
# 'config_assets': 'assets/owntracks/geo.example.org-config',
|
|
# 'auth': [
|
|
# ('usr1', '$2a$14$CWSpO...'),
|
|
# ('usr2', '$2a$14$rHlbr...'),
|
|
# ],
|
|
# }
|
|
# ],
|
|
# },
|
|
# ...
|
|
#
|
|
|
|
|
|
from pyinfra.api import deploy
|
|
from pyinfra import (
|
|
host,
|
|
)
|
|
from pyinfra.operations import (
|
|
files,
|
|
server,
|
|
systemd,
|
|
)
|
|
from liab_deployments.operations import (
|
|
caddy,
|
|
user,
|
|
user_systemd,
|
|
)
|
|
|
|
owntracks_container_setup = \
|
|
"--rm " \
|
|
"--name owntracks-recorder " \
|
|
"-v {user_home}/config:/config:Z " \
|
|
"-v {user_home}/store:/store:Z " \
|
|
"-v /etc/localtime:/etc/localtime:ro "
|
|
|
|
service_unit_tmpl = """\
|
|
[Unit]
|
|
Description=Podman-managed owntracks 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 \\
|
|
--sdnotify=conmon \\
|
|
-d \\
|
|
--replace \\
|
|
--pull always \\
|
|
-p {host_port}:8083 \\
|
|
--rm \\
|
|
--network=slirp4netns \\
|
|
--name owntracks-recorder \\
|
|
{container_setup} \\
|
|
{container_tag} --port 0
|
|
# --port 0 above disable the use of MQTT in favor of direct HTTP
|
|
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} {{
|
|
{auth}
|
|
reverse_proxy localhost:{host_port}
|
|
}}
|
|
"""
|
|
|
|
|
|
@deploy("Deploy OwnTracks")
|
|
def deploy_sites():
|
|
if not hasattr(host.data, 'owntracks'):
|
|
return
|
|
for spec in host.data.owntracks.get('sites', []):
|
|
_deploy_site(
|
|
spec['serve_address'],
|
|
spec['container_tag'],
|
|
spec['card_assets'],
|
|
spec['config_assets'],
|
|
spec['user'],
|
|
spec['host_port'],
|
|
spec['auth'],
|
|
name=spec.get('name', 'owntracks'),
|
|
caddyfile_block_tmpl=spec.get(
|
|
'caddyfile_block_tmpl', caddyfile_block_tmpl
|
|
),
|
|
)
|
|
|
|
|
|
def _deploy_site(
|
|
serve_address,
|
|
container_tag,
|
|
card_assets,
|
|
config_assets,
|
|
user_spec: tuple[str, int],
|
|
host_port,
|
|
auth: list[tuple[str, str]],
|
|
*,
|
|
name,
|
|
caddyfile_block_tmpl,
|
|
):
|
|
user_name, uid = user_spec
|
|
user_home = f'/home/{user_name}'
|
|
|
|
user.systemd_service(
|
|
user_name,
|
|
uid,
|
|
user_home,
|
|
)
|
|
|
|
for i in ['store', 'config']:
|
|
files.directory(
|
|
path=f'{user_home}/{i}',
|
|
present=True,
|
|
_sudo_user=user_name,
|
|
)
|
|
|
|
user_systemd.service_unit(
|
|
user_name,
|
|
user_home,
|
|
name,
|
|
service_unit_tmpl.format(
|
|
user_home=user_home,
|
|
container_tag=container_tag,
|
|
host_port=host_port,
|
|
container_setup=owntracks_container_setup.format(
|
|
user_home=user_home,
|
|
),
|
|
),
|
|
)
|
|
|
|
files.sync(
|
|
name='Deposit OwnTracks user cards',
|
|
src=card_assets,
|
|
dest=f'{user_home}/store/cards',
|
|
user=user_name,
|
|
)
|
|
|
|
files.sync(
|
|
name='Deposit OwnTracks recorder config',
|
|
src=config_assets,
|
|
dest=f'{user_home}/config',
|
|
user=user_name,
|
|
)
|
|
|
|
systemd.service(
|
|
name='Stop OwnTracks to load friends',
|
|
service='owntracks.service',
|
|
running=False,
|
|
daemon_reload=True,
|
|
user_mode=True,
|
|
user_name=user_name,
|
|
)
|
|
|
|
server.shell(
|
|
name='OwnTracks load friends',
|
|
commands=[
|
|
f'cd {user_home}; podman container run '
|
|
f'-it {owntracks_container_setup.format(user_home=user_home)} '
|
|
f'--entrypoint /bin/sh {container_tag} '
|
|
"-c '[ -d /store/ghash ] || ot-recorder --initialize; ocat --load=friends < /config/friends.txt'",
|
|
],
|
|
_sudo_user=user_name,
|
|
)
|
|
|
|
user_systemd.run_service(
|
|
user_name,
|
|
uid,
|
|
'owntracks',
|
|
)
|
|
|
|
server.wait(
|
|
name=f"Wait for OwnTracks {serve_address!r} to start",
|
|
port=host_port,
|
|
)
|
|
|
|
auth_indent = ' '
|
|
auth_spec = ['basicauth {']
|
|
for usr, passwd in auth:
|
|
auth_spec.append(f'{auth_indent}{usr} {passwd}')
|
|
auth_spec.append('}')
|
|
|
|
caddy.caddyfile_block(
|
|
marker=f'OWNTRACKS {serve_address}',
|
|
content=caddyfile_block_tmpl.format(
|
|
serve_address=serve_address,
|
|
host_port=host_port,
|
|
auth='\n'.join(f'{auth_indent}{line}'
|
|
for line in auth_spec),
|
|
),
|
|
)
|