Init project

This commit is contained in:
Benoit S 2021-11-15 22:23:45 +09:00
parent de5a8de641
commit 88bdb77e83
10 changed files with 261 additions and 1 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
pyinfra-debug.log

View file

@ -1,3 +1,47 @@
# linkding # linkding
Pyinfra that deploy linkding un-dockerized. Mostly to be used in LXD/C. Pyinfra that deploy linkding un-dockerized on a Debian 11 LXD container.
# Deployment
```
# lxc launch images:debian/11 <name>
# lxec exec <name> bash
# apt update && apt install python3-pip git
# pip install pyinfra
# git clone https://git.benpro.fr/pyinfra/linkding.git
# cd linkding
# ###!!!### Edit group_data/production.py
# pyinfra inventories/production.py deploy.py
```
## Upgrade
Run `remove.py` then `deploy.py`.
```
# pyinfra inventories/production.py remove.py
# pyinfra inventories/production.py deploy.py
```
# Attach a pictures volume
If required, you can mount external volumes. Example:
```
# lxc config device add <name> <name>_disk disk source=/dev/vdf path=/mnt/pictures readonly=true raw.mount.options=noload
```
Then add it to `group_data/production.py`:
```
photoprism_originals_src='/mnt/pictures'
```
# Run photoprism command
A systemd-run wrapper is installed and you can use it via `/usr/local/bin/photoprism`.
```
# /usr/local/bin/photoprism config
```

124
deploy.py Normal file
View file

@ -0,0 +1,124 @@
from pyinfra import host
from pyinfra.operations import apt, server, files, systemd, mysql
apt.update(
name='Update apt repositories',
)
apt.upgrade(
name='Upgrade apt packages',
)
apt.packages(
name='Install dependencies',
packages=host.data.app['deps'],
update=False,
)
server.user(
name='Create UNIX user',
user=host.data.unix_account['user'],
home=host.data.unix_account['home'],
shell=host.data.unix_account['shell'],
ensure_home=True,
system=True,
comment=f"{host.data.unix_account['user']} system user",
present=True,
)
for directory in host.data.data_directories:
files.directory(
name=f'Make required directory {directory}',
path=directory,
user=host.data.unix_account['user'],
group=host.data.unix_account['group'],
mode=755
)
files.download(
name='Download undocker',
src=host.data.undocker['url'],
dest=host.data.undocker['bin_path'],
user='root',
group='root',
mode='755',
sha256sum=host.data.undocker['sha256'],
)
files.directory(
name='Create undocker cache',
path=host.data.undocker['cache'],
user='root',
group='root',
mode=755
)
if not host.fact.file(f"{host.data.undocker['cache']}/{host.data.app['name']}.tar"):
server.shell(
name='Download Docker image',
chdir=host.data.undocker['cache'],
commands=[
f"skopeo copy {host.data.app['image']} docker-archive:{host.data.app['name']}.tar"
],
)
files.directory(
name='Create undocker app destination',
path=host.data.undocker['app_dst'],
user='root',
group='root',
mode=755
)
# If the bootstrap file is here, undockerized image should be fine, don't extract again
if not host.fact.file(f"{host.data.undocker['app_dst']}/etc/linkding/bootstrap.sh"):
server.shell(
name='Undocker the Docker image',
chdir=host.data.undocker['app_dst'],
commands=[
f"undocker {host.data.undocker['cache']}/{host.data.app['name']}.tar - | tar -xv"
],
)
# Since the app is badly Dockerized we need to do a chown
files.directory(
name=f"Ensure {host.data.undocker['app_dst']}/etc/linkding has correct rights",
path=f"{host.data.undocker['app_dst']}/etc/linkding",
user=host.data.unix_account['user'],
group=host.data.unix_account['group'],
)
files.template(
name='Set env file',
src='templates/env.j2',
dest=host.data.systemd['EnvironmentFile'],
mode='600',
)
files.template(
name='Set systemd service file',
src=f'templates/systemd.service.j2',
dest=f"/etc/systemd/system/{host.data.app['name']}.service",
mode='644',
)
systemd.daemon_reload(
name='Reload systemd',
user_mode=False,
)
systemd.service(
name='Enable systemd service',
service=f"{host.data.app['name']}.service",
running=True,
restarted=True,
enabled=True,
)
files.template(
name='Set systemd-run wrapper',
src='templates/systemd-run.sh.j2',
dest=f"/usr/local/bin/{host.data.app['name']}",
mode='755',
)

37
group_data/all.py Normal file
View file

@ -0,0 +1,37 @@
app = {
'name': 'linkding',
'deps': ['skopeo', 'curl'],
'image': 'docker://sissbruecker/linkding:latest',
}
undocker = {
'url': 'https://git.sr.ht/~motiejus/undocker/refs/download/v1.0.2/undocker-linux-amd64-v1.0.2',
'sha256': 'b937e69e774c530c080c1f6685763ca7db4dc58520a5a2054d111e1504f47688',
'bin_path': '/usr/local/bin/undocker',
'app_dst': f"/opt/{app['name']}",
'cache': '/var/cache/undocker',
}
unix_account = {
'user': app['name'],
'group': app['name'],
'home': f"/home/{app['name']}",
'shell': '/bin/false',
}
data_directories = [
f"{unix_account['home']}/data"
]
systemd = {
'Description': app['name'],
'User': unix_account['user'],
'Group': unix_account['group'],
'EnvironmentFile': f"/etc/{app['name']}.env",
'WorkingDirectory': f"/etc/{app['name']}",
'RootDirectory': f"{undocker['app_dst']}",
'ReadWritePaths': '+/etc/linkding',
'BindPaths': f"{data_directories[0]}:/etc/linkding/data",
'BindReadOnlyPaths': '/etc/resolv.conf /etc/hosts',
'ExecStart': '/etc/linkding/bootstrap.sh',
}

1
inventories/dev.py Normal file
View file

@ -0,0 +1 @@
dev_servers = ['@ssh/debian11.home.arpa']

View file

@ -0,0 +1 @@
production_servers = ['@local']

16
remove.py Normal file
View file

@ -0,0 +1,16 @@
from pyinfra import host
from pyinfra.operations import server, files
if host.fact.file(host.data.undocker_cache+'/photoprism.tar'):
server.shell(
name='Remove photoprism Docker image',
chdir=host.data.undocker_cache,
commands=['rm photoprism.tar'],
)
if host.fact.directory(host.data.undocker_dst):
server.shell(
name='Remove undocker destination',
commands=['rm -rf {}'.format(host.data.undocker_dst)],
)

3
templates/env.j2 Normal file
View file

@ -0,0 +1,3 @@
# From Dockerfile
VIRTUAL_ENV=/opt/venv
PATH=/opt/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

View file

@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
systemd-run \
--pty \
--property=User={{ host.data.systemd['User'] }} \
--property=Group={{ host.data.systemd['Group'] }} \
--property=EnvironmentFile={{ host.data.systemd['EnvironmentFile'] }} \
--property=WorkingDirectory={{ host.data.systemd['WorkingDirectory'] }} \
--property=RootDirectory={{ host.data.systemd['RootDirectory'] }} \
--property='BindPaths={{ host.data.systemd['BindPaths'] }}' \
--property='BindReadOnlyPaths={{ host.data.systemd['BindReadOnlyPaths'] }}' \
"$@"

View file

@ -0,0 +1,20 @@
[Unit]
Description={{ host.data.systemd['Description'] }}
After=network.target
[Service]
Type=simple
User={{ host.data.systemd['User'] }}
Group={{ host.data.systemd['Group'] }}
EnvironmentFile={{ host.data.systemd['EnvironmentFile'] }}
WorkingDirectory={{ host.data.systemd['WorkingDirectory'] }}
RootDirectory={{ host.data.systemd['RootDirectory'] }}
ReadWritePaths={{ host.data.systemd['ReadWritePaths'] }}
BindPaths={{ host.data.systemd['BindPaths'] }}
BindReadOnlyPaths={{ host.data.systemd['BindReadOnlyPaths'] }}
ExecStart={{ host.data.systemd['ExecStart'] }}
KillSignal=SIGQUIT
Restart=on-failure
[Install]
WantedBy=multi-user.target