Compare commits

...

8 Commits

  1. 6
      cookbooks/base/centos-stream10.image
  2. 16
      cookbooks/base/discover-virtiofs-tags.service
  3. 1
      cookbooks/base/tmpfiles.d/base.conf
  4. 7
      cookbooks/base/var-lib-virtiofs-data.mount
  5. 3
      cookbooks/lego/Makefile
  6. 2
      cookbooks/lego/config/examples/config.env
  7. 19
      cookbooks/lego/config/examples/lego-dev.sh
  8. 18
      cookbooks/lego/config/process-hooks.sh
  9. 0
      cookbooks/lego/config/renew-hook/flag-as-renewed.sh
  10. 7
      cookbooks/lego/dropins/lego-renew.container.d/lego-dev.conf
  11. 7
      cookbooks/lego/dropins/lego-run.container.d/lego-dev.conf
  12. 5
      cookbooks/lego/hooks.mk
  13. 12
      cookbooks/lego/lego-renew-hooks.service
  14. 2
      cookbooks/lego/lego-renew.container
  15. 2
      cookbooks/ntfy/ntfy.container
  16. 12
      cookbooks/quay/config/quay_load_tls_certs.sh
  17. 6
      cookbooks/quay/other/lego/quay.sh
  18. 9
      cookbooks/quay/quay-app.container
  19. 15
      cookbooks/quay/quay-init-certificate.service
  20. 17
      cookbooks/quay/quay-load-renewed-certificate.service
  21. 4
      cookbooks/quay/quay.target
  22. 9
      cookbooks/redis/overlay.bu
  23. 19
      cookbooks/samba/config/examples/smb.conf.d/10-shares.conf
  24. 3
      cookbooks/samba/samba.build
  25. 7
      cookbooks/samba/samba.container
  26. 14
      cookbooks/seedbox/README.md
  27. 33
      cookbooks/seedbox/cross-seed.container
  28. 6
      cookbooks/seedbox/cross-seed.image
  29. 6
      cookbooks/seedbox/dropins/samba.container.d/seedbox.conf
  30. 4
      cookbooks/seedbox/flaresolverr.container
  31. 12
      cookbooks/seedbox/jellyfin.container
  32. 12
      cookbooks/seedbox/lidarr.container
  33. 6
      cookbooks/seedbox/other/samba/10-shares.conf
  34. 13
      cookbooks/seedbox/other/traefik/cross-seed.yaml
  35. 3
      cookbooks/seedbox/other/traefik/jellyfin.yaml
  36. 3
      cookbooks/seedbox/other/traefik/lidarr.yaml
  37. 3
      cookbooks/seedbox/other/traefik/prowlarr.yaml
  38. 3
      cookbooks/seedbox/other/traefik/qbittorrent.yaml
  39. 3
      cookbooks/seedbox/other/traefik/radarr.yaml
  40. 3
      cookbooks/seedbox/other/traefik/sonarr.yaml
  41. 12
      cookbooks/seedbox/prowlarr.container
  42. 16
      cookbooks/seedbox/qbittorrent.container
  43. 12
      cookbooks/seedbox/radarr.container
  44. 4
      cookbooks/seedbox/seedbox.target
  45. 12
      cookbooks/seedbox/sonarr.container
  46. 47
      cookbooks/seedbox/tmpfiles.d/seedbox.conf
  47. 16
      cookbooks/seedbox/var-lib-virtiofs-hdd.mount
  48. 16
      cookbooks/seedbox/var-lib-virtiofs-ssd.mount
  49. 12
      cookbooks/smtprelay/Makefile
  50. 68
      cookbooks/smtprelay/README.md
  51. 73
      cookbooks/smtprelay/SPECS.md
  52. 22
      cookbooks/smtprelay/config/container/Containerfile
  53. 9
      cookbooks/smtprelay/config/container/install-smtprelay.sh
  54. 16
      cookbooks/smtprelay/config/examples/allowed_users.txt
  55. 42
      cookbooks/smtprelay/config/examples/smtprelay.ini
  56. 6
      cookbooks/smtprelay/other/lego/smtprelay.sh
  57. 9
      cookbooks/smtprelay/overlay.bu
  58. 10
      cookbooks/smtprelay/smtprelay-build.timer
  59. 10
      cookbooks/smtprelay/smtprelay.build
  60. 49
      cookbooks/smtprelay/smtprelay.container
  61. 11
      cookbooks/smtprelay/smtprelay.target
  62. 2
      cookbooks/smtprelay/tmpfiles.d/smtprelay.conf
  63. 86
      cookbooks/traefik/README.md
  64. 6
      cookbooks/vsftpd/other/lego/vsftpd.sh
  65. 17
      cookbooks/vsftpd/vsftpd-load-renewed-certificate.service

6
cookbooks/base/centos-stream10.image

@ -0,0 +1,6 @@
[Unit]
Description=Pull quay.io/centos/centos:stream10
Documentation=https://quay.io/centos/centos
[Image]
Image=quay.io/centos/centos:stream10

16
cookbooks/base/discover-virtiofs-tags.service

@ -0,0 +1,16 @@
[Unit]
Description=Discover the virtiofs tags made available by the hypervisor
RequiresMountsFor=/run
ConditionPathIsMountPoint=/run
# Unless DefaultDependencies= is set to false, service units will implicitly
# have dependencies of type Requires= and After= on basic.target as well as
# dependencies of type Conflicts= and Before= on shutdown.target.
#
# So, we need to set DefaultDependencies to "no" to break the ordering cycle.
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/bin/bash -Eeuo pipefail -c 'shopt -s nullglob; mkdir -p /run/quadlets/base/virtiofs; for tagfile in /sys/fs/virtiofs/*/tag; do tag=$(<"$tagfile"); echo -n > "/run/quadlets/base/virtiofs/$tag"; done'
RemainAfterExit=yes

1
cookbooks/base/tmpfiles.d/base.conf

@ -1,2 +1 @@
d /var/lib/virtiofs 0755 0 0 -
d /var/lib/virtiofs/data 0755 0 0 -

7
cookbooks/base/var-lib-virtiofs-data.mount

@ -1,9 +1,10 @@
[Unit]
Description=Mount the "data" virtio filesystem
Requires=discover-virtiofs-tags.service
After=discover-virtiofs-tags.service
# Only run on Fedora CoreOS
ConditionOSRelease=ID=fedora
ConditionOSRelease=VARIANT_ID=coreos
# Only run if the "data" tag is present (as discovered by discover-virtiofs-tags.service)
ConditionPathExists=/run/quadlets/base/virtiofs/data
[Mount]
What=data

3
cookbooks/lego/Makefile

@ -9,3 +9,6 @@ PROJECT_GID = 10000
# Include common Makefile
include ../../scripts/common.mk
TARGET_FILES += $(TARGET_CHROOT)/etc/quadlets/lego/renew-hooks.d
$(TARGET_CHROOT)/etc/quadlets/lego/renew-hooks.d:
install -m 0700 -o root -g root -D -d $@

2
cookbooks/lego/config/examples/config.env

@ -1,3 +1,3 @@
LEGO_GLOBAL_ARGS=-a -m nicolas.masse@itix.fr -d changeme.example.tld --http
LEGO_RUN_ARGS=
LEGO_RENEW_ARGS=--days 30 --renew-hook=/etc/lego/hooks/flag-as-renewed.sh
LEGO_RENEW_ARGS=--days 30 --renew-hook=/etc/lego/renew-hook/flag-as-renewed.sh

19
cookbooks/lego/config/examples/lego-dev.sh

@ -0,0 +1,19 @@
#!/bin/bash
set -Eeuo pipefail
# In development mode, it is not possible to get a certificate from Let's Encrypt, so we just create a self-signed certificate for localhost, so that other services can still use it.
mkdir -p /var/lib/quadlets/lego/certificates
if [ -f /var/lib/quadlets/lego/certificates/localhost.crt ] && [ -f /var/lib/quadlets/lego/certificates/localhost.key ]; then
renewal="yes"
else
renewal="no"
fi
echo "Generating self-signed certificate for localhost..."
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /var/lib/quadlets/lego/certificates/localhost.key -out /var/lib/quadlets/lego/certificates/localhost.crt -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost"
if [[ "$renewal" == "yes" ]]; then
echo "Flagging certificate as renewed..."
touch /var/lib/quadlets/lego/certificates/localhost.renewed
fi

18
cookbooks/lego/config/process-hooks.sh

@ -0,0 +1,18 @@
#!/bin/bash
set -Eeuo pipefail
for hook in /etc/quadlets/lego/renew-hooks.d/*.sh; do
if [[ -x "$hook" ]]; then
echo "Running renew hook: $hook"
if ! "$hook"; then
echo "Error: Renew hook failed: $hook" >&2
fi
else
echo "Skipping non-executable hook: $hook"
fi
done
rm -f /var/lib/quadlets/lego/certificates/*.renewed
exit 0

0
cookbooks/lego/config/hooks/flag-as-renewed.sh → cookbooks/lego/config/renew-hook/flag-as-renewed.sh

7
cookbooks/lego/dropins/lego-renew.container.d/lego-dev.conf

@ -0,0 +1,7 @@
[Container]
# When in development mode, it is not possible to renew a certificate from Let's Encrypt, so we just skip the entrypoint.
Entrypoint=/bin/true
[Service]
# And we update the self-signed certificate and flag it as renewed.
ExecStartPost=/etc/quadlets/lego/lego-dev.sh

7
cookbooks/lego/dropins/lego-run.container.d/lego-dev.conf

@ -0,0 +1,7 @@
[Container]
# When in development mode, it is not possible to get a certificate from Let's Encrypt, so we just skip the entrypoint.
Entrypoint=/bin/true
[Service]
# And we create a self-signed certificate for localhost, so that other services can still use it.
ExecStartPost=/etc/quadlets/lego/lego-dev.sh

5
cookbooks/lego/hooks.mk

@ -0,0 +1,5 @@
# Lego renewal hooks
TARGET_LEGO_FILES = $(patsubst other/lego/%.sh, $(TARGET_CHROOT)/etc/quadlets/lego/renew-hooks.d/%.sh, $(wildcard other/lego/*.sh))
TARGET_FILES += $(TARGET_LEGO_FILES)
$(TARGET_CHROOT)/etc/quadlets/lego/renew-hooks.d/%.sh: other/lego/%.sh
install -D -m 0755 -o root -g root $< $@

12
cookbooks/lego/lego-renew-hooks.service

@ -0,0 +1,12 @@
[Unit]
Description=Process Lego certificate renewal hooks
# Lego touches .renewed files when renewed certificates are available
ConditionPathExistsGlob=/var/lib/quadlets/lego/certificates/*.renewed
After=lego-renew.service
[Service]
Type=oneshot
ExecStart=/etc/quadlets/lego/process-hooks.sh
[Install]
WantedBy=lego-renew.service

2
cookbooks/lego/lego-renew.container

@ -27,7 +27,7 @@ EnvironmentFile=/etc/quadlets/lego/config.env
# Volume mounts
Volume=/var/lib/quadlets/lego:/.lego:z
Volume=/etc/quadlets/lego/hooks:/etc/lego/hooks:ro
Volume=/etc/quadlets/lego/renew-hook:/etc/lego/renew-hook:ro
# Be safe, set the umask to 0077 so that private keys are not world-readable
PodmanArgs=--umask=0077

2
cookbooks/ntfy/ntfy.container

@ -30,7 +30,7 @@ Volume=/etc/quadlets/ntfy/server.yml:/etc/ntfy/server.yml:ro,z
Volume=/var/lib/virtiofs/data/ntfy:/var/cache/ntfy:Z
# Health check
HealthCmd=wget -q --tries=1 http://localhost:8080/v1/health -O - | grep -Eo '"healthy"\s*:\s*true' || exit 1
HealthCmd=wget -q --tries=1 http://127.0.0.1:8080/v1/health -O - | grep -qEo '"healthy"\s*:\s*true'
HealthInterval=60s
HealthTimeout=10s
HealthStartPeriod=40s

12
cookbooks/quay/config/quay_load_tls_certs.sh

@ -2,13 +2,5 @@
set -Eeuo pipefail
if ls /var/lib/quadlets/lego/certificates/*.crt &> /dev/null; then
echo "Lego-issued certificates found, loading them for Quay..."
install -o 10026 -g 10000 -m 0600 $(ls /var/lib/quadlets/lego/certificates/*.crt | head -1) /etc/quadlets/quay/app/ssl.cert
install -o 10026 -g 10000 -m 0600 $(ls /var/lib/quadlets/lego/certificates/*.key | head -1) /etc/quadlets/quay/app/ssl.key
elif [ ! -f /etc/quadlets/quay/app/ssl.cert ] && [ ! -f /etc/quadlets/quay/app/ssl.key ]; then
echo "No Lego-issued certificates found, generating self-signed certificates for Quay..."
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/quadlets/quay/app/ssl.key -out /etc/quadlets/quay/app/ssl.cert -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost"
chown 10026:10000 /etc/quadlets/quay/app/ssl.{key,cert}
chmod 0600 /etc/quadlets/quay/app/ssl.{key,cert}
fi
install -o 10026 -g 10000 -m 0600 $(ls /var/lib/quadlets/lego/certificates/*.crt | head -1) /run/quadlets/quay/tls/ssl.cert
install -o 10026 -g 10000 -m 0600 $(ls /var/lib/quadlets/lego/certificates/*.key | head -1) /run/quadlets/quay/tls/ssl.key

6
cookbooks/quay/other/lego/quay.sh

@ -0,0 +1,6 @@
#!/bin/bash
set -Eeuo pipefail
/etc/quadlets/quay/quay_load_tls_certs.sh
systemctl --no-block restart quay-app.service

9
cookbooks/quay/quay-app.container

@ -1,8 +1,8 @@
[Unit]
Description=Quay Container Registry Application
Documentation=https://docs.projectquay.io/
After=network.target redis-server.service quay-init-certificate.service var-lib-virtiofs-data.mount
Requires=redis-server.service quay-init-certificate.service var-lib-virtiofs-data.mount
After=network.target redis-server.service var-lib-virtiofs-data.mount
Requires=redis-server.service var-lib-virtiofs-data.mount
# Only start if Quay has been configured
ConditionPathExists=/etc/quadlets/quay/app/config.yaml
@ -32,6 +32,8 @@ Volume=/var/lib/virtiofs/data/quay/storage:/datastorage:Z
# Configuration
Volume=/etc/quadlets/quay/app:/quay-registry/conf/stack:Z,ro
Volume=/run/quadlets/quay/tls/ssl.cert:/quay-registry/conf/stack/ssl.cert:Z,ro
Volume=/run/quadlets/quay/tls/ssl.key:/quay-registry/conf/stack/ssl.key:Z,ro
# Health check
HealthCmd=curl -sk https://localhost:8443/health/instance
@ -46,6 +48,9 @@ RestartSec=10
TimeoutStartSec=120
TimeoutStopSec=30
# Load TLS certificates from Lego before starting the container
ExecStartPre=/etc/quadlets/quay/quay_load_tls_certs.sh
# Wait for PostgreSQL to be ready on localhost
ExecStartPre=/bin/sh -c 'exec 2>/dev/null; for try in $(seq 0 12); do if ! /bin/true 5<> /dev/tcp/127.0.0.1/5432; then echo "Waiting for PostgreSQL to be available..."; sleep 5; else exit 0; fi; done; exit 1'

15
cookbooks/quay/quay-init-certificate.service

@ -1,15 +0,0 @@
[Unit]
Description=Initialize Quay TLS certificates if not already present
Before=quay-app.service
After=lego.target
# Start/stop this unit when the target is started/stopped
PartOf=quay.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/etc/quadlets/quay/quay_load_tls_certs.sh
[Install]
WantedBy=quay.target

17
cookbooks/quay/quay-load-renewed-certificate.service

@ -1,17 +0,0 @@
[Unit]
Description=Reload Quay TLS certificate after Lego renewal
# Lego touches .renewed files when renewed certificates are available
ConditionPathExistsGlob=/var/lib/quadlets/lego/certificates/*.renewed
After=lego-renew.service
[Service]
Type=oneshot
# Copy the renewed certificates to the Quay TLS directory
ExecStart=/etc/quadlets/quay/quay_load_tls_certs.sh
# Restart Quay to load the new certificate
ExecStart=systemctl --no-block restart quay-app.service
# Remove the flag files after restarting Quay
ExecStartPost=/bin/sh -Eeuo pipefail -c 'rm -f /var/lib/quadlets/lego/certificates/*.renewed'
[Install]
WantedBy=lego-renew.service

4
cookbooks/quay/quay.target

@ -1,8 +1,8 @@
[Unit]
Description=Quay Container Registry Target
Documentation=https://docs.projectquay.io/
Requires=postgresql.target redis.target quay-clair.service quay-app.service quay-init-certificate.service
After=postgresql.target redis.target quay-clair.service quay-app.service quay-init-certificate.service
Requires=postgresql.target redis.target lego.target quay-clair.service quay-app.service
After=postgresql.target redis.target lego.target quay-clair.service quay-app.service
# Allow isolation - can stop/start this target independently
AllowIsolate=yes

9
cookbooks/redis/overlay.bu

@ -0,0 +1,9 @@
variant: fcos
version: 1.4.0
passwd:
users:
- name: redis
uid: 10021
gecos: Redis server
home_dir: /var/lib/quadlets/redis
primary_group: itix-svc

19
cookbooks/samba/config/examples/smb.conf.d/10-shares.conf

@ -1,19 +0,0 @@
server string = Storage
[foo]
path = /data/foo
comment = Foo
valid users = @itix
write list = @itix
group = itix
directory mask = 0770
create mask = 0660
[bar]
path = /data/bar
comment = Bar
valid users = @itix
write list = @itix
group = itix
directory mask = 0775
create mask = 0664

3
cookbooks/samba/samba.build

@ -1,7 +1,8 @@
[Unit]
Description=Build of the Samba daemon
Wants=network-online.target
After=network-online.target
After=network-online.target centos-stream10-image.service
Requires=centos-stream10-image.service
[Build]
File=/etc/quadlets/samba/container/Containerfile

7
cookbooks/samba/samba.container

@ -1,8 +1,7 @@
[Unit]
Description=Samba
After=samba-build.service
Wants=samba-build.service
Requires=var-lib-virtiofs-data.mount
After=network.target samba-build.service
Wants=network.target samba-build.service
# Start/stop this unit when the target is started/stopped
PartOf=samba.target
@ -23,11 +22,11 @@ User=0
# Storage
Volume=/var/lib/quadlets/samba/data:/var/lib/samba:Z
Volume=/var/lib/quadlets/samba/log:/var/log/samba:Z
Volume=/var/lib/virtiofs/data/storage:/data
Volume=/etc/quadlets/samba/smb.conf.d:/etc/samba/smb.conf.d:Z
Volume=/run/quadlets/samba/passwd:/etc/passwd:Z
Volume=/run/quadlets/samba/group:/etc/group:Z
Volume=/run/quadlets/samba/shadow:/etc/shadow:Z
# Heads up ! You need to mount the volumes you want to share in a drop-in configuration file !
# Network
Network=host

14
cookbooks/seedbox/README.md

@ -13,6 +13,7 @@ This cookbook includes the following services:
- **Prowlarr**: Indexer manager for Radarr, Sonarr, and Lidarr.
- **Jellyfin**: Media server for streaming your collection.
- **FlareSolverr**: Proxy server to bypass Cloudflare protection for indexers.
- **cross-seed**: Automatically cross-seeds your torrents on other private trackers using your existing data.
All services:
@ -48,6 +49,19 @@ You should see all services starting up. Access the web interfaces:
- **Prowlarr**: `http://127.0.0.1:9696/`
- **Jellyfin**: `http://127.0.0.1:8096/`
- **FlareSolverr**: `http://127.0.0.1:8191/`
- **cross-seed**: `http://127.0.0.1:2468/`
On its first start, **cross-seed** generates a template configuration file at
`/var/lib/virtiofs/ssd/cross-seed/config/config.js`. Edit it by hand to set at
least:
- `torznab`: your Prowlarr Torznab indexer URL(s) (with their API keys), e.g. `http://prowlarr:9696/1/api?apikey=<key>`.
- `torrentClients`: the qBittorrent connection string, e.g. `qbittorrent:http://<user>:<pass>@localhost:8080`.
- `linkDirs`: `["/data/storage/seed"]`, so that cross-seed hardlinks matches into the dedicated `seed` directory shared with qBittorrent.
Then restart **cross-seed.service** for the changes to take effect. See the
[cross-seed documentation](https://www.cross-seed.org/docs/basics/getting-started)
for the full set of options.
Restart the **seedbox.target** unit.

33
cookbooks/seedbox/cross-seed.container

@ -0,0 +1,33 @@
[Unit]
Description=Fully automatic cross-seeding for torrent trackers
Documentation=https://www.cross-seed.org/docs/basics/getting-started
Wants=network.target
After=network.target
RequiresMountsFor=/var/lib/virtiofs/ssd
RequiresMountsFor=/var/lib/virtiofs/hdd
[Container]
ContainerName=cross-seed
# Image
Image=cross-seed.image
AutoUpdate=registry
# Security
User=10017
Group=10000
# Storage
Volume=/var/lib/virtiofs/ssd/cross-seed/config:/config:z
Volume=/var/lib/virtiofs/hdd:/data:z
# Network
AddCapability=CAP_NET_BIND_SERVICE
Network=host
# Configuration
Environment=TZ=Etc/UTC HOME=/config
Exec=daemon
[Install]
WantedBy=seedbox.target

6
cookbooks/seedbox/cross-seed.image

@ -0,0 +1,6 @@
[Unit]
Description=podman pull ghcr.io/cross-seed/cross-seed
Documentation=https://www.cross-seed.org/docs/basics/getting-started
[Image]
Image=ghcr.io/cross-seed/cross-seed:latest

6
cookbooks/seedbox/dropins/samba.container.d/seedbox.conf

@ -0,0 +1,6 @@
[Unit]
RequiresMountsFor=/var/lib/virtiofs/ssd
RequiresMountsFor=/var/lib/virtiofs/hdd
[Container]
Volume=/var/lib/virtiofs/hdd:/data:z

4
cookbooks/seedbox/flaresolverr.container

@ -1,8 +1,8 @@
[Unit]
Description=Proxy server to bypass Cloudflare protection
Documentation=https://github.com/FlareSolverr/FlareSolverr/
Wants=network-online.target
After=network-online.target
Wants=network.target
After=network.target
[Container]
ContainerName=flaresolverr

12
cookbooks/seedbox/jellyfin.container

@ -1,10 +1,10 @@
[Unit]
Description= The Free Software Media System
Documentation=https://docs.linuxserver.io/images/docker-jellyfin/
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/var/lib/virtiofs/data
ConditionPathIsMountPoint=/var/lib/virtiofs/data
Wants=network.target
After=network.target
RequiresMountsFor=/var/lib/virtiofs/ssd
RequiresMountsFor=/var/lib/virtiofs/hdd
[Container]
ContainerName=jellyfin
@ -18,8 +18,8 @@ User=10017
Group=10000
# Storage
Volume=/var/lib/virtiofs/data/jellyfin/config:/config:z
Volume=/var/lib/virtiofs/data/storage/media:/data:z
Volume=/var/lib/virtiofs/ssd/jellyfin/config:/config:z
Volume=/var/lib/virtiofs/hdd/media:/data:z
# Network
AddCapability=CAP_NET_BIND_SERVICE

12
cookbooks/seedbox/lidarr.container

@ -1,10 +1,10 @@
[Unit]
Description=Smart PVR for newsgroup and bittorrent users.
Documentation=https://docs.linuxserver.io/images/docker-lidarr/
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/var/lib/virtiofs/data
ConditionPathIsMountPoint=/var/lib/virtiofs/data
Wants=network.target
After=network.target
RequiresMountsFor=/var/lib/virtiofs/ssd
RequiresMountsFor=/var/lib/virtiofs/hdd
[Container]
ContainerName=lidarr
@ -18,8 +18,8 @@ User=10017
Group=10000
# Storage
Volume=/var/lib/virtiofs/data/lidarr/config:/config:z
Volume=/var/lib/virtiofs/data/storage:/data:z
Volume=/var/lib/virtiofs/ssd/lidarr/config:/config:z
Volume=/var/lib/virtiofs/hdd:/data:z
# Network
AddCapability=CAP_NET_BIND_SERVICE

6
cookbooks/seedbox/other/samba/10-shares.conf

@ -1,7 +1,7 @@
server string = Seedbox
[media]
path = /data/storage/media
path = /data/media
comment = Media
valid users = @itix
write list = @itix
@ -10,7 +10,7 @@ directory mask = 0775
create mask = 0664
[downloads]
path = /data/storage/downloads
path = /data/downloads
comment = Downloads
valid users = @itix
write list = @itix
@ -19,7 +19,7 @@ directory mask = 0775
create mask = 0664
[import]
path = /data/storage/import
path = /data/import
comment = Imports
valid users = @itix
write list = @itix

13
cookbooks/seedbox/other/traefik/cross-seed.yaml

@ -0,0 +1,13 @@
http:
routers:
cross-seed:
rule: "Host(`cross-seed`)"
entryPoints:
- http
middlewares:
service: "cross-seed"
services:
cross-seed:
loadBalancer:
servers:
- url: "http://127.0.0.1:2468"

3
cookbooks/seedbox/other/traefik/jellyfin.yaml

@ -3,12 +3,9 @@ http:
jellyfin:
rule: "Host(`jellyfin`)"
entryPoints:
#- https
- http
middlewares:
service: "jellyfin"
#tls:
# certResolver: le
services:
jellyfin:
loadBalancer:

3
cookbooks/seedbox/other/traefik/lidarr.yaml

@ -3,12 +3,9 @@ http:
lidarr:
rule: "Host(`lidarr`)"
entryPoints:
#- https
- http
middlewares:
service: "lidarr"
#tls:
# certResolver: le
services:
lidarr:
loadBalancer:

3
cookbooks/seedbox/other/traefik/prowlarr.yaml

@ -3,12 +3,9 @@ http:
prowlarr:
rule: "Host(`prowlarr`)"
entryPoints:
#- https
- http
middlewares:
service: "prowlarr"
#tls:
# certResolver: le
services:
prowlarr:
loadBalancer:

3
cookbooks/seedbox/other/traefik/qbittorrent.yaml

@ -3,12 +3,9 @@ http:
qbittorrent-webui:
rule: "Host(`qbittorrent`)"
entryPoints:
#- https
- http
middlewares:
service: "qbittorrent-webui"
#tls:
# certResolver: le
services:
qbittorrent-webui:
loadBalancer:

3
cookbooks/seedbox/other/traefik/radarr.yaml

@ -3,12 +3,9 @@ http:
radarr:
rule: "Host(`radarr`)"
entryPoints:
#- https
- http
middlewares:
service: "radarr"
#tls:
# certResolver: le
services:
radarr:
loadBalancer:

3
cookbooks/seedbox/other/traefik/sonarr.yaml

@ -3,12 +3,9 @@ http:
sonarr:
rule: "Host(`sonarr`)"
entryPoints:
#- https
- http
middlewares:
service: "sonarr"
#tls:
# certResolver: le
services:
sonarr:
loadBalancer:

12
cookbooks/seedbox/prowlarr.container

@ -1,10 +1,10 @@
[Unit]
Description=Prowlarr is an indexer manager/proxy built on the popular *arr .net/reactjs base stack to integrate with your various PVR apps.
Documentation=https://docs.linuxserver.io/images/docker-prowlarr/
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/var/lib/virtiofs/data
ConditionPathIsMountPoint=/var/lib/virtiofs/data
Wants=network.target
After=network.target
RequiresMountsFor=/var/lib/virtiofs/ssd
RequiresMountsFor=/var/lib/virtiofs/hdd
[Container]
ContainerName=prowlarr
@ -18,8 +18,8 @@ User=10017
Group=10000
# Storage
Volume=/var/lib/virtiofs/data/prowlarr/config:/config:z
Volume=/var/lib/virtiofs/data/storage:/data:z
Volume=/var/lib/virtiofs/ssd/prowlarr/config:/config:z
Volume=/var/lib/virtiofs/hdd:/data:z
# Network
AddCapability=CAP_NET_BIND_SERVICE

16
cookbooks/seedbox/qbittorrent.container

@ -1,9 +1,9 @@
[Unit]
Description=qBittorrent client
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/var/lib/virtiofs/data
ConditionPathIsMountPoint=/var/lib/virtiofs/data
Wants=network.target
After=network.target
RequiresMountsFor=/var/lib/virtiofs/ssd
RequiresMountsFor=/var/lib/virtiofs/hdd
[Container]
ContainerName=qbittorrent
@ -17,11 +17,9 @@ User=10017
Group=10000
# Storage
Volume=/var/lib/virtiofs/data/qbittorrent/config:/config:z
Volume=/var/lib/virtiofs/data/storage:/data:z
# This volume is required for torrents migrated from the old seedbox
Volume=/var/lib/virtiofs/data/storage/downloads:/downloads:z
Volume=/var/lib/virtiofs/ssd/qbittorrent/config:/config:z
Volume=/var/lib/virtiofs/ssd/qbittorrent/incomplete:/incomplete:z
Volume=/var/lib/virtiofs/hdd:/data:z
# Network
AddCapability=CAP_NET_BIND_SERVICE

12
cookbooks/seedbox/radarr.container

@ -1,10 +1,10 @@
[Unit]
Description=Radarr is a movie collection manager for Usenet and BitTorrent users.
Documentation=https://docs.linuxserver.io/images/docker-radarr/
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/var/lib/virtiofs/data
ConditionPathIsMountPoint=/var/lib/virtiofs/data
Wants=network.target
After=network.target
RequiresMountsFor=/var/lib/virtiofs/ssd
RequiresMountsFor=/var/lib/virtiofs/hdd
[Container]
ContainerName=radarr
@ -18,8 +18,8 @@ User=10017
Group=10000
# Storage
Volume=/var/lib/virtiofs/data/radarr/config:/config:z
Volume=/var/lib/virtiofs/data/storage:/data:z
Volume=/var/lib/virtiofs/ssd/radarr/config:/config:z
Volume=/var/lib/virtiofs/hdd:/data:z
# Network
AddCapability=CAP_NET_BIND_SERVICE

4
cookbooks/seedbox/seedbox.target

@ -1,8 +1,8 @@
[Unit]
Description=Seedbox Service Target
Documentation=man:systemd.target(5)
Requires=radarr.service sonarr.service lidarr.service prowlarr.service qbittorrent.service jellyfin.service flaresolverr.service
After=radarr.service sonarr.service lidarr.service prowlarr.service qbittorrent.service jellyfin.service flaresolverr.service
Requires=radarr.service sonarr.service lidarr.service prowlarr.service qbittorrent.service jellyfin.service flaresolverr.service cross-seed.service
After=radarr.service sonarr.service lidarr.service prowlarr.service qbittorrent.service jellyfin.service flaresolverr.service cross-seed.service
# Allow isolation - can stop/start this target independently
AllowIsolate=yes

12
cookbooks/seedbox/sonarr.container

@ -1,10 +1,10 @@
[Unit]
Description=Smart PVR for newsgroup and bittorrent users.
Documentation=https://docs.linuxserver.io/images/docker-sonarr/
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/var/lib/virtiofs/data
ConditionPathIsMountPoint=/var/lib/virtiofs/data
Wants=network.target
After=network.target
RequiresMountsFor=/var/lib/virtiofs/ssd
RequiresMountsFor=/var/lib/virtiofs/hdd
[Container]
ContainerName=sonarr
@ -18,8 +18,8 @@ User=10017
Group=10000
# Storage
Volume=/var/lib/virtiofs/data/sonarr/config:/config:z
Volume=/var/lib/virtiofs/data/storage:/data:z
Volume=/var/lib/virtiofs/ssd/sonarr/config:/config:z
Volume=/var/lib/virtiofs/hdd:/data:z
# Network
AddCapability=CAP_NET_BIND_SERVICE

47
cookbooks/seedbox/tmpfiles.d/seedbox.conf

@ -1,22 +1,25 @@
d$ /var/lib/virtiofs/data/storage 0755 0 0 -
d$ /var/lib/virtiofs/data/storage/media 0775 10017 10000 -
d$ /var/lib/virtiofs/data/storage/media/movies 0775 10017 10000 -
d$ /var/lib/virtiofs/data/storage/media/series 0775 10017 10000 -
d$ /var/lib/virtiofs/data/storage/media/music 0775 10017 10000 -
d$ /var/lib/virtiofs/data/storage/downloads 0775 10017 10000 -
d$ /var/lib/virtiofs/data/storage/torrents 0775 10017 10000 -
d$ /var/lib/virtiofs/data/storage/import 0775 10017 10000 -
d$ /var/lib/virtiofs/data/radarr 0700 10017 10000 -
d$ /var/lib/virtiofs/data/radarr/config 0700 10017 10000 -
d$ /var/lib/virtiofs/data/radarr/config/tmp 0700 10017 10000 -
d$ /var/lib/virtiofs/data/radarr/config/xdg 0700 10017 10000 -
d$ /var/lib/virtiofs/data/sonarr 0700 10017 10000 -
d$ /var/lib/virtiofs/data/sonarr/config 0700 10017 10000 -
d$ /var/lib/virtiofs/data/sonarr/config/tmp 0700 10017 10000 -
d$ /var/lib/virtiofs/data/sonarr/config/xdg 0700 10017 10000 -
d$ /var/lib/virtiofs/data/prowlarr 0700 10017 10000 -
d$ /var/lib/virtiofs/data/prowlarr/config 0700 10017 10000 -
d$ /var/lib/virtiofs/data/prowlarr/config/tmp 0700 10017 10000 -
d$ /var/lib/virtiofs/data/prowlarr/config/xdg 0700 10017 10000 -
d$ /var/lib/virtiofs/data/jellyfin 0700 10017 10000 -
d$ /var/lib/virtiofs/data/jellyfin/config 0700 10017 10000 -
d$ /var/lib/virtiofs/hdd/storage 0755 0 0 -
d$ /var/lib/virtiofs/hdd/storage/media 0775 10017 10000 -
d$ /var/lib/virtiofs/hdd/storage/media/movies 0775 10017 10000 -
d$ /var/lib/virtiofs/hdd/storage/media/series 0775 10017 10000 -
d$ /var/lib/virtiofs/hdd/storage/media/music 0775 10017 10000 -
d$ /var/lib/virtiofs/hdd/storage/downloads 0775 10017 10000 -
d$ /var/lib/virtiofs/hdd/storage/torrents 0775 10017 10000 -
d$ /var/lib/virtiofs/hdd/storage/seed 0775 10017 10000 -
d$ /var/lib/virtiofs/hdd/storage/import 0775 10017 10000 -
d$ /var/lib/virtiofs/ssd/radarr 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/radarr/config 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/radarr/config/tmp 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/radarr/config/xdg 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/sonarr 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/sonarr/config 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/sonarr/config/tmp 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/sonarr/config/xdg 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/prowlarr 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/prowlarr/config 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/prowlarr/config/tmp 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/prowlarr/config/xdg 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/jellyfin 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/jellyfin/config 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/cross-seed 0700 10017 10000 -
d$ /var/lib/virtiofs/ssd/cross-seed/config 0700 10017 10000 -

16
cookbooks/seedbox/var-lib-virtiofs-hdd.mount

@ -0,0 +1,16 @@
[Unit]
Description=Mount the "hdd" virtio filesystem
Requires=discover-virtiofs-tags.service
After=discover-virtiofs-tags.service
# Only run if the "hdd" tag is present (as discovered by discover-virtiofs-tags.service)
ConditionPathExists=/run/quadlets/base/virtiofs/hdd
[Mount]
What=hdd
Where=/var/lib/virtiofs/hdd
Type=virtiofs
Options=context=system_u:object_r:container_file_t:s0
[Install]
WantedBy=local-fs.target

16
cookbooks/seedbox/var-lib-virtiofs-ssd.mount

@ -0,0 +1,16 @@
[Unit]
Description=Mount the "ssd" virtio filesystem
Requires=discover-virtiofs-tags.service
After=discover-virtiofs-tags.service
# Only run if the "ssd" tag is present (as discovered by discover-virtiofs-tags.service)
ConditionPathExists=/run/quadlets/base/virtiofs/ssd
[Mount]
What=ssd
Where=/var/lib/virtiofs/ssd
Type=virtiofs
Options=context=system_u:object_r:container_file_t:s0
[Install]
WantedBy=local-fs.target

12
cookbooks/smtprelay/Makefile

@ -0,0 +1,12 @@
##
## Makefile for smtprelay quadlet
##
DEPENDENCIES = lego
# smtprelay quadlet is mapped to the 10030 user (smtprelay) and 10000 group (itix-svc)
PROJECT_UID = 10030
PROJECT_GID = 10000
# Include common Makefile
include ../../scripts/common.mk

68
cookbooks/smtprelay/README.md

@ -0,0 +1,68 @@
# Podman Quadlet: smtprelay
## Overview
[smtprelay](https://github.com/decke/smtprelay) is a small Golang based SMTP relay/proxy server that accepts mail via SMTP and forwards it to an upstream smarthost (ex: Mailgun, Gmail, ...).
This cookbook:
- Builds a custom smtprelay container image locally, from CentOS Stream 10.
- Runs smtprelay directly as a dedicated, unprivileged UID/GID (no user namespace mapping).
- Listens on the submission port (587) with STARTTLS, authenticating clients against a local user/password file.
- Loads TLS certificates issued by the `lego` cookbook and reloads them automatically when renewed.
- Includes a timer to periodically rebuild the container image.
## Prerequisites
- Configuration file `/etc/quadlets/smtprelay/smtprelay.ini` must exist.
- File `/etc/quadlets/smtprelay/allowed_users.txt` must exist, listing the users allowed to relay mail.
- The `lego` cookbook should be configured to provide TLS certificates.
## Usage
In a separate terminal, follow the logs.
```sh
sudo make tail-logs
```
Install the Podman Quadlets and start smtprelay.
```sh
sudo make clean install
```
You should see the **smtprelay-build.service** building the smtprelay container image.
Then, the **smtprelay.service** should start up.
Verify smtprelay is running:
```sh
sudo systemctl status smtprelay.service
```
Send a test mail with [swaks](https://www.jetmore.org/john/code/swaks/):
```sh
swaks --to youremail@example.com --from youremail@example.com --auth-user yourusername --auth-password yourpassword --port 587 --tls
```
When Let's Encrypt certificates are renewed, the renewal hook automatically restarts smtprelay so it picks up the new certificates.
Restart the **smtprelay.target** unit.
```sh
sudo systemctl restart smtprelay.target
```
Finally, remove the quadlets, their configuration and their data.
```sh
sudo make uninstall clean
```
## Integration tests
```sh
sudo make test
```

73
cookbooks/smtprelay/SPECS.md

@ -0,0 +1,73 @@
# Specification for smtprelay Quadlet Cookbook
You will have to develop a Quadlet cookbook for smtprelay, the mail transfer agent.
## Architecture
smtprelay is a mail transfer agent, deployed as a container image.
The container image will be built from the CentOS Stream 10 image (`quay.io/centos/centos:stream10`).
## Common requirements
- The `quay.io/centos/centos:stream10` docker image MUST have its own quadlet .image file.
- Each cookbook MUST have a dedicated unique UID. The GID is 10000.
## Security
Directly set the UID and GID in the quadlet file (no mapping).
Use the host network, like other quadlet cookbooks.
Let's Encrypt certificates will be handled by Traefik, so no need to worry about that in the smtprelay cookbook.
## Installation
Create the Containerfile for smtprelay, which will install the smtprelay binary.
The smtprelay binary can be obtained from the official releases on GitHub: https://github.com/decke/smtprelay.
Look at `cookbooks/base/config/install-fastfetch.sh` for an example of how to install a binary from a GitHub release in a Containerfile.
## Configuration
A sample configuration file for smtprelay:
```ini
; Hostname for this SMTP server
hostname = localhost
; File which contains username and password used for
; authentication before they can send mail.
allowed_users = /etc/smtprelay/allowed_users.txt
; Networks that are allowed to send mails to us
; Defaults to localhost. If set to "", then any address is allowed.
;allowed_nets = 0.0.0.0/0 ::/0
allowed_nets = 0.0.0.0/0
; Enable TLS for incoming connections on port 587
listen = starttls://0.0.0.0:587
local_cert = /etc/smtprelay/tls/localhost.crt
local_key = /etc/smtprelay/tls/localhost.key
; Enforce encrypted connection on STARTTLS ports before
; accepting mails from client.
local_forcetls = true
; Relay Config (ex: Mailgun)
remotes = starttls://user:pass@smtp.mailgun.org:587
```
## Entrypoint
```sh
smtprelay --config /etc/smtprelay/smtprelay.ini -logfile=/dev/stdout
```
## How to test
```sh
swaks --to youremail@example.com --from youremail@example.com --auth-user yourusername --auth-password yourpassword --port 587 --tls
```
## Useful examples
You can copy the structure of the `miniflux` cookbook.
Look at the `samba` cookbook for an example of how to handle the container image building.

22
cookbooks/smtprelay/config/container/Containerfile

@ -0,0 +1,22 @@
FROM quay.io/centos/centos:stream10 AS builder
# Tools needed to fetch and unpack the smtprelay release
RUN dnf install -y curl jq tar gzip \
&& dnf clean all
COPY install-smtprelay.sh /
RUN /install-smtprelay.sh
FROM quay.io/centos/centos:stream10
# CA certificates are required to establish TLS connections to the relay host
RUN dnf install -y ca-certificates \
&& dnf clean all
COPY --from=builder /usr/local/bin/smtprelay /usr/local/bin/smtprelay
# Submission port
EXPOSE 587
ENTRYPOINT [ "/usr/local/bin/smtprelay" ]
CMD [ "--config", "/etc/smtprelay/smtprelay.ini", "-logfile=/dev/stdout" ]

9
cookbooks/smtprelay/config/container/install-smtprelay.sh

@ -0,0 +1,9 @@
#!/bin/bash
set -Eeuo pipefail
SMTPRELAY_LATEST_VERSION="$(curl -sSfL https://api.github.com/repos/decke/smtprelay/releases | jq -r '.[] | select(.prerelease == false and .draft == false) | .tag_name' | sort -V | tail -1)"
SMTPRELAY_VERSION="${SMTPRELAY_VERSION:-$SMTPRELAY_LATEST_VERSION}"
declare -A ARCH_MAP=( ["x86_64"]="amd64" ["aarch64"]="arm64" )
arch="$(arch)"
arch=${ARCH_MAP[$arch]}
echo "Installing smtprelay $SMTPRELAY_VERSION for $arch..."
curl -sSfL https://github.com/decke/smtprelay/releases/download/$SMTPRELAY_VERSION/smtprelay-$SMTPRELAY_VERSION-linux-$arch.tar.gz | tar -zx -C /usr/local/bin --no-same-owner smtprelay

16
cookbooks/smtprelay/config/examples/allowed_users.txt

@ -0,0 +1,16 @@
# File which contains username and password used for authentication
# before clients can relay mail through this server.
#
# Format (one user per line, fields separated by spaces):
# username bcrypt-hash [email[,email[,...]]]
#
# username: the SMTP auth username
# bcrypt-hash: the bcrypt hash of the password
# email: comma-separated list of "from" addresses the user is
# allowed to send as (omit to allow any address)
#
# Generate the bcrypt hash of a password with:
# python3 -c "import bcrypt; print(bcrypt.hashpw(b'<password>', bcrypt.gensalt()).decode())"
#
# Example user "demo" (password "changeme") allowed to send from any address:
demo $2b$12$V3XmeosOSoI4B.2D8HLzWu7y2YQaoBeF2unnGopZ2ZJJpQ58sKToa

42
cookbooks/smtprelay/config/examples/smtprelay.ini

@ -0,0 +1,42 @@
# -----------------------------------------------------------------------
# smtprelay configuration - relay-only SMTP server
#
# Copy this file to /etc/quadlets/smtprelay/smtprelay.ini and adjust the
# values for your environment.
# -----------------------------------------------------------------------
; Hostname for this SMTP server
hostname = mail.example.com
; File which contains username and password used for
; authentication before they can send mail (see allowed_users.txt example).
allowed_users = /etc/smtprelay/allowed_users.txt
; Networks that are allowed to send mails to us.
; The container uses the host network, so clients connect from outside -
; allow any address and rely on SMTP authentication instead.
allowed_nets = 0.0.0.0/0
; -----------------------------------------------------------------------
; Inbound TLS (certificates provided by the lego cookbook)
;
; Replace "localhost" with the actual certificate filename from
; /var/lib/quadlets/lego/certificates/.
; -----------------------------------------------------------------------
; Enable TLS for incoming connections on port 587
listen = starttls://0.0.0.0:587
local_cert = /etc/smtprelay/tls/localhost.crt
local_key = /etc/smtprelay/tls/localhost.key
; Enforce encrypted connection on STARTTLS ports before
; accepting mails from client.
local_forcetls = true
; -----------------------------------------------------------------------
; Outbound relay
; -----------------------------------------------------------------------
; Relay all mail through an upstream smarthost (ex: Mailgun).
; Adjust the credentials and host for your provider.
remotes = starttls://user:pass@smtp.mailgun.org:587

6
cookbooks/smtprelay/other/lego/smtprelay.sh

@ -0,0 +1,6 @@
#!/bin/bash
set -Eeuo pipefail
install -o 10030 -g 10000 -m 0600 -t /run/quadlets/smtprelay/tls /var/lib/quadlets/lego/certificates/*.crt /var/lib/quadlets/lego/certificates/*.key
systemctl --no-block restart smtprelay.service

9
cookbooks/smtprelay/overlay.bu

@ -0,0 +1,9 @@
variant: fcos
version: 1.4.0
passwd:
users:
- name: smtprelay
uid: 10030
gecos: smtprelay MTA
home_dir: /var/lib/quadlets/smtprelay
primary_group: itix-svc

10
cookbooks/smtprelay/smtprelay-build.timer

@ -0,0 +1,10 @@
[Unit]
Description=Rebuild the smtprelay container image
PartOf=smtprelay.target
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=smtprelay.target

10
cookbooks/smtprelay/smtprelay.build

@ -0,0 +1,10 @@
[Unit]
Description=Build of the smtprelay MTA
Wants=network-online.target
After=network-online.target centos-stream10-image.service
Requires=centos-stream10-image.service
[Build]
File=/etc/quadlets/smtprelay/container/Containerfile
ImageTag=localhost/smtprelay:latest
SetWorkingDirectory=/etc/quadlets/smtprelay/container

49
cookbooks/smtprelay/smtprelay.container

@ -0,0 +1,49 @@
[Unit]
Description=smtprelay MTA
Documentation=https://github.com/decke/smtprelay
After=local-fs.target network.target smtprelay-build.service lego.target
Wants=smtprelay-build.service lego.target
# Only start if the main configuration file exists
ConditionPathExists=/etc/quadlets/smtprelay/smtprelay.ini
# Stop when the target is stopped
PartOf=smtprelay.target
[Container]
ContainerName=smtprelay
# Image
Image=localhost/smtprelay:latest
AutoUpdate=local
# Security - run directly as a dedicated, unprivileged UID/GID (no mapping)
User=10030
Group=10000
# Port 587 is a privileged port (< 1024); grant the capability to bind to it
AddCapability=CAP_NET_BIND_SERVICE
# Command and arguments
Entrypoint=/usr/local/bin/smtprelay
Exec=--config /etc/smtprelay/smtprelay.ini -logfile=/dev/stdout
# Storage
Volume=/etc/quadlets/smtprelay/smtprelay.ini:/etc/smtprelay/smtprelay.ini:ro,Z
Volume=/etc/quadlets/smtprelay/allowed_users.txt:/etc/smtprelay/allowed_users.txt:ro,Z
Volume=/run/quadlets/smtprelay/tls:/etc/smtprelay/tls:Z
# Network
Network=host
[Service]
Restart=always
RestartSec=10
TimeoutStartSec=120
TimeoutStopSec=30
# Get the TLS certificates in place before starting smtprelay
ExecStartPre=/bin/sh -c 'install -o 10030 -g 10000 -m 0600 -t /run/quadlets/smtprelay/tls /var/lib/quadlets/lego/certificates/*.crt /var/lib/quadlets/lego/certificates/*.key'
[Install]
WantedBy=smtprelay.target

11
cookbooks/smtprelay/smtprelay.target

@ -0,0 +1,11 @@
[Unit]
Description=smtprelay Service Target
Documentation=man:systemd.target(5)
Requires=smtprelay.service smtprelay-build.timer
After=smtprelay.service smtprelay-build.timer
# Allow isolation - can stop/start this target independently
AllowIsolate=yes
[Install]
WantedBy=multi-user.target

2
cookbooks/smtprelay/tmpfiles.d/smtprelay.conf

@ -0,0 +1,2 @@
d$ /run/quadlets/smtprelay 0700 10030 10000 -
d$ /run/quadlets/smtprelay/tls 0700 10030 10000 -

86
cookbooks/traefik/README.md

@ -82,3 +82,89 @@ sudo make uninstall clean
```sh
sudo make test
```
## What if I want to use a TLS certificate provided by the "lego" cookbook?
**/etc/containers/systemd/traefik.container.d/lego.conf**:
```ini
[Unit]
# Now, Traefik depends on the lego target, which will ensure that the TLS certificates are generated and available before Traefik starts
After=lego.target
Wants=lego.target
[Container]
# Mount the directory containing the TLS certificates generated by lego into the Traefik container
Volume=/run/quadlets/traefik/tls:/etc/traefik/tls:Z
# Health check on HTTPS
HealthCmd=wget -q -O /dev/null --no-check-certificate --header 'Host: ping' https://127.0.0.1/
[Service]
# Get the TLS certificates in place before starting traefik
ExecStartPre=/bin/sh -c 'install -o 10001 -g 10000 -m 0600 -t /run/quadlets/traefik/tls /var/lib/quadlets/lego/certificates/*.crt /var/lib/quadlets/lego/certificates/*.key'
```
**/etc/quadlets/traefik/conf.d/tls.yaml**:
```yaml
tls:
certificates:
- certFile: /etc/traefik/tls/f.q.d.n.crt
keyFile: /etc/traefik/tls/f.q.d.n.key
stores:
default:
defaultCertificate:
certFile: /etc/traefik/tls/f.q.d.n.crt
keyFile: /etc/traefik/tls/f.q.d.n.key
http:
routers:
traefik-ping-tls:
rule: Host(`ping`)
entryPoints:
- https
service: "ping@internal"
tls: {}
middlewares:
- localhost-only
middlewares:
localhost-only:
ipAllowList:
sourceRange:
- "127.0.0.1/32"
```
**/etc/quadlets/traefik/traefik.yaml**:
```yaml
entryPoints:
# <-- no http entrypoint here
https:
address: ":443"
```
**/etc/tmpfiles.d/traefik-lego.conf**:
```
d /run/quadlets/traefik 0755 10001 10000 -
d /run/quadlets/traefik/tls 0700 10001 10000 -
```
**/etc/quadlets/traefik/conf.d/$yoursite.yaml**:
```yaml
http:
routers:
example:
rule: "Host(`service.example.test`)"
entryPoints:
- https
service: "example"
tls: {} # <-- this tells Traefik to enable TLS and find a matching certificate by SNI
services:
example:
loadBalancer:
servers:
- url: "http://127.0.0.1:8080"
```

6
cookbooks/vsftpd/other/lego/vsftpd.sh

@ -0,0 +1,6 @@
#!/bin/bash
set -Eeuo pipefail
install -o 10015 -g 10000 -m 0600 -t /run/quadlets/vsftpd/tls /var/lib/quadlets/lego/certificates/*.crt /var/lib/quadlets/lego/certificates/*.key
systemctl --no-block restart vsftpd.service

17
cookbooks/vsftpd/vsftpd-load-renewed-certificate.service

@ -1,17 +0,0 @@
[Unit]
Description=Restart Vsftpd if a new TLS certificate is available
# Lego touch .renewed files when renewed certificates are available
ConditionPathExistsGlob=/var/lib/quadlets/lego/certificates/*.renewed
After=lego-renew.service
[Service]
Type=oneshot
# Copy the renewed certificates to the vsftpd /run directory
ExecStartPre=/bin/sh -Eeuo pipefail -c 'install -o 10015 -g 10000 -m 0600 -t /run/quadlets/vsftpd/tls /var/lib/quadlets/lego/certificates/*.crt /var/lib/quadlets/lego/certificates/*.key'
# Restart vsftpd to load the new certificates
ExecStart=systemctl --no-block restart vsftpd.service
# Remove the flag files after restarting vsftpd
ExecStartPost=/bin/sh -Eeuo pipefail -c 'rm -f /var/lib/quadlets/lego/certificates/*.renewed'
[Install]
WantedBy=lego-renew.service
Loading…
Cancel
Save