--- debug: false # set to true to print debug info log_level: "info" rebuild: true # rebuild images quadlets_deploy_configs: true # deploy quadlet service configs maintainer: "Bryan C. Roessler" tz: "America/New_York" alpine_base_image: "docker.io/alpine:3.23" alpine_mirror: "https://mirror.pilotfiber.com/alpinelinux" # Directories config_root: "{{ lookup('env', 'HOME') }}/.config" quadlet_root: "{{ lookup('env', 'HOME') }}/.config/containers/systemd" backup_root: "{{ lookup('env', 'HOME') }}/.config/containers/systemd/backup" download_root: "{{ lookup('env', 'HOME') }}/downloads" monitor_root: "{{ lookup('env', 'HOME') }}/downloads" media_root: "{{ lookup('env', 'HOME') }}/media" # linux-system-roles.podman podman_create_host_directories: true podman_host_directories: DEFAULT: owner: "{{ lookup('env', 'USER') }}" group: "{{ lookup('env', 'USER') }}" mode: "0755" podman_activate_systemd_units: true podman_run_as_user: "{{ lookup('env', 'USER') }}" podman_run_as_group: "{{ lookup('env', 'USER') }}" podman_systemd_unit_scope: user podman_prune_images: true podman_pull_image: false podman_continue_if_pull_fails: false podman_quadlet_specs: # Pods - name: htpc type: pod network: pasta publish: - "8080:80" - "8443:443" # Build images - name: htpc_sabnzbd type: build image: localhost/htpc_sabnzbd:latest pull: missing format: oci force_rm: true container_file: | FROM {{ alpine_base_image }} LABEL maintainer="{{ maintainer }}" RUN \ rm -rf /etc/apk/repositories \ && apk add --no-cache \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/main" \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/community" \ python3 py3-pip git unzip ca-certificates par2cmdline 7zip \ && apk add --no-cache --virtual=.build-deps \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/main" \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/community" \ autoconf automake build-base openssl-dev libffi-dev python3-dev \ && apk add --no-cache -X '{{ alpine_mirror }}/v3.14/main' unrar \ && git clone --depth 1 --branch master https://github.com/sabnzbd/sabnzbd /app \ && python3 -m venv /venv \ && . /venv/bin/activate \ && pip install --no-cache-dir -r /app/requirements.txt \ && apk del --purge .build-deps - name: htpc_qbittorrent type: build image: localhost/htpc_qbittorrent:latest pull: missing format: oci force_rm: true container_file: | FROM {{ alpine_base_image }} LABEL maintainer="{{ maintainer }}" RUN apk add --no-cache \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/main" \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/community" \ qbittorrent-nox \ && mkdir -p /app \ && ln -s /usr/bin/qbittorrent-nox /app/qbittorrent-nox WORKDIR /app - name: htpc_sonarr type: build image: localhost/htpc_sonarr:latest pull: missing format: oci force_rm: true container_file: | FROM {{ alpine_base_image }} LABEL maintainer="{{ maintainer }}" RUN apk add --no-cache \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/main" \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/community" \ libintl sqlite-libs icu-libs curl jq \ && url=$(curl -sL "https://api.github.com/repos/Sonarr/Sonarr/releases/latest" \ | jq -r '.assets[] | select(.name | test("linux-musl-x64.tar.gz$")) | .browser_download_url') \ && curl -L -o /tmp/Sonarr.tar.gz "$url" \ && mkdir -p /app && tar -xzf /tmp/Sonarr.tar.gz -C /app --strip-components=1 WORKDIR /app - name: htpc_radarr type: build image: localhost/htpc_radarr:latest pull: missing format: oci force_rm: true container_file: | FROM {{ alpine_base_image }} LABEL maintainer="{{ maintainer }}" RUN apk add --no-cache \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/main" \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/community" \ icu-libs libintl sqlite-libs curl libmediainfo xmlstarlet jq \ && url=$(curl -sL "https://api.github.com/repos/Radarr/Radarr/releases/latest" \ | jq -r '.assets[] | select(.name | test("linux-musl-core-x64.tar.gz$")) | .browser_download_url') \ && curl -L -o /tmp/radarr.tar.gz "$url" \ && mkdir -p /app \ && tar -xzf /tmp/radarr.tar.gz --strip-components=1 -C /app \ && chmod +x /app/Radarr \ && rm -rf /app/Radarr.Update WORKDIR /app - name: htpc_lidarr type: build image: localhost/htpc_lidarr:latest pull: missing format: oci force_rm: true container_file: | FROM {{ alpine_base_image }} LABEL maintainer="{{ maintainer }}" RUN apk add --no-cache \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/main" \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/community" \ icu-libs libintl sqlite-libs curl libmediainfo xmlstarlet jq \ && url=$(curl -sL "https://api.github.com/repos/Lidarr/Lidarr/releases/latest" \ | jq -r '.assets[] | select(.name | test("linux-musl-core-x64.tar.gz$")) | .browser_download_url') \ && [ -n "$url" ] \ && curl -L -o /tmp/Lidarr.tar.gz "$url" \ && mkdir -p /app && tar -xzf /tmp/Lidarr.tar.gz --strip-components=1 -C /app \ && chmod +x /app/Lidarr \ && rm /tmp/Lidarr.tar.gz WORKDIR /app - name: htpc_prowlarr type: build image: localhost/htpc_prowlarr:latest pull: missing format: oci force_rm: true container_file: | FROM {{ alpine_base_image }} LABEL maintainer="{{ maintainer }}" RUN apk add --no-cache \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/main" \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/community" \ libintl icu-libs sqlite-libs curl jq \ && url=$(curl -sL "https://api.github.com/repos/Prowlarr/Prowlarr/releases/latest" \ | jq -r '.assets[] | select(.name | test("linux-musl-core-x64.tar.gz$")) | .browser_download_url') \ && [ -n "$url" ] \ && curl -L -o /tmp/Prowlarr.tar.gz "$url" \ && mkdir -p /app \ && tar -xzf /tmp/Prowlarr.tar.gz -C /app --strip-components=1 \ && rm /tmp/Prowlarr.tar.gz WORKDIR /app - name: htpc_unpackerr type: build image: localhost/htpc_unpackerr:latest pull: missing format: oci force_rm: true container_file: | FROM {{ alpine_base_image }} LABEL maintainer="{{ maintainer }}" RUN apk add --no-cache \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/main" \ -X "{{ alpine_mirror }}/v{{ alpine_base_image.split(':')[-1] }}/community" \ curl tar jq \ && url=$(curl -sL "https://api.github.com/repos/davidnewhall/Unpackerr/releases/latest" \ | jq -r '.assets[] | select(.name == "unpackerr.amd64.linux.gz") | .browser_download_url') \ && [ -n "$url" ] \ && curl -L -o /tmp/unpackerr.gz "$url" \ && mkdir -p /app \ && gunzip -c /tmp/unpackerr.gz > /app/unpackerr \ && chmod +x /app/unpackerr \ && rm /tmp/unpackerr.gz WORKDIR /app # Containers - name: htpc_traefik type: container pod: htpc image: docker.io/traefik:latest pull: newer volumes: - "{{ config_root }}/traefik:/etc/traefik:Z" env: TZ: "{{ tz }}" command: - "--api.dashboard=true" - "--api.insecure=true" - "--providers.file.directory=/etc/traefik/dynamic" - "--providers.file.watch=true" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--entrypoints.websecure.http.tls.certFile=/etc/traefik/server.crt" - "--entrypoints.websecure.http.tls.keyFile=/etc/traefik/server.key" - "--log.level=INFO" restart_policy: on-failure - name: htpc_sabnzbd type: container pod: htpc image: localhost/htpc_sabnzbd:latest volumes: - "{{ config_root }}/sabnzbd:/config:Z" - "{{ download_root }}/htpc:/downloads:z" - "{{ monitor_root }}/nzbs:/nzbs:Z" env: TZ: "{{ tz }}" command: - "/venv/bin/python" - "-OO" - "/app/SABnzbd.py" - "--config-file=/config/sabnzbd.ini" - "--browser=0" restart_policy: on-failure - name: htpc_qbittorrent type: container pod: htpc image: localhost/htpc_qbittorrent:latest volumes: - "{{ config_root }}/qbittorrent:/config:Z" - "{{ download_root }}/htpc:/downloads:z" - "{{ monitor_root }}/torrents:/torrents:Z" env: TZ: "{{ tz }}" command: - "qbittorrent-nox" - "--profile=/config" restart_policy: on-failure - name: htpc_sonarr type: container pod: htpc image: localhost/htpc_sonarr:latest volumes: - "{{ config_root }}/sonarr:/config:Z" - "{{ download_root }}/htpc:/downloads:z" - "{{ media_root }}/tv:/tv:Z" env: TZ: "{{ tz }}" SONARR__APP__LAUNCHBROWSER: false SONARR__APP__INSTANCENAME: "{{ SONARR__APP__INSTANCENAME | default('Sonarr') }}" SONARR__AUTH__METHOD: "{{ SONARR__AUTH__METHOD | default('Forms') }}" SONARR__AUTH__APIKEY: "{{ SONARR__AUTH__APIKEY | default(lookup('password', '/dev/null length=32 chars=ascii_letters,digits')) }}" SONARR__SERVER__ENABLESSL: "{{ SONARR__SERVER__ENABLESSL | default(false) }}" SONARR__SERVER__SSLPORT: "{{ SONARR__SERVER__SSLPORT | default('9898') }}" SONARR__SERVER__PORT: "{{ SONARR__SERVER__PORT | default('8989') }}" SONARR__SERVER__BINDADDRESS: "{{ SONARR__SERVER__BINDADDRESS | default('*') }}" SONARR__SERVER__SSLCERTPATH: "{{ SONARR__SERVER__SSLCERTPATH | default('/config/ssl/server.crt') }}" SONARR__SERVER__SSLCERTPASSWORD: "{{ SONARR__SERVER__SSLCERTPASSWORD | default('/config/ssl/server.key') }}" SONARR__LOG__ANALYTICSENABLED: "{{ SONARR__LOG__ANALYTICSENABLED | default(false) }}" SONARR__UPDATE__AUTOMATICALLY: "{{ SONARR__UPDATE__AUTOMATICALLY | default(false) }}" SONARR__LOG__LEVEL: "{{ SONARR__LOG__LEVEL | default('info') }}" command: ["/app/Sonarr", "-data=/config"] restart_policy: on-failure - name: htpc_radarr type: container pod: htpc image: localhost/htpc_radarr:latest volumes: - "{{ config_root }}/radarr:/config:Z" - "{{ download_root }}/htpc:/downloads:z" - "{{ media_root }}/movies:/movies:Z" env: TZ: "{{ tz }}" RADARR__APP__LAUNCHBROWSER: false RADARR__APP__INSTANCENAME: "{{ RADARR__APP__INSTANCENAME | default('Radarr') }}" RADARR__AUTH__METHOD: "{{ RADARR__AUTH__METHOD | default('Forms') }}" RADARR__AUTH__APIKEY: "{{ RADARR__AUTH__APIKEY | default(lookup('password', '/dev/null length=32 chars=ascii_letters,digits')) }}" RADARR__AUTH__ENABLED: "{{ RADARR__AUTH__ENABLED | default(true) }}" RADARR__AUTH__REQUIRED: "{{ RADARR__AUTH__REQUIRED | default('DisabledForLocalAddresses') }}" RADARR__SERVER__ENABLESSL: "{{ RADARR__SERVER__ENABLESSL | default(false) }}" RADARR__SERVER__PORT: "{{ RADARR__SERVER__PORT | default('7878') }}" RADARR__SERVER__BINDADDRESS: "{{ RADARR__SERVER__BINDADDRESS | default('*') }}" RADARR__LOG__ANALYTICSENABLED: "{{ RADARR__LOG__ANALYTICSENABLED | default(false) }}" RADARR__LOG__LEVEL: "{{ RADARR__LOG__LEVEL | default('info') }}" RADARR__UPDATE__AUTOMATICALLY: "{{ RADARR__UPDATE__AUTOMATICALLY | default(false) }}" command: ["/app/Radarr", "--nobrowser", "--data=/config"] restart_policy: on-failure - name: htpc_lidarr type: container pod: htpc image: localhost/htpc_lidarr:latest volumes: - "{{ config_root }}/lidarr:/config:Z" - "{{ download_root }}/htpc:/downloads:z" - "{{ media_root }}/music:/music:Z" env: TZ: "{{ tz }}" LIDARR__APP__LAUNCHBROWSER: false LIDARR__APP__INSTANCENAME: "{{ LIDARR__APP__INSTANCENAME | default('Lidarr') }}" LIDARR__AUTH__METHOD: "{{ LIDARR__AUTH__METHOD | default('Forms') }}" LIDARR__AUTH__APIKEY: "{{ LIDARR__AUTH__APIKEY | default(lookup('password', '/dev/null length=32 chars=ascii_letters,digits')) }}" LIDARR__AUTH__ENABLED: "{{ LIDARR__AUTH__ENABLED | default(true) }}" LIDARR__AUTH__REQUIRED: "{{ LIDARR__AUTH__REQUIRED | default('DisabledForLocalAddresses') }}" LIDARR__SERVER__ENABLESSL: "{{ LIDARR__SERVER__ENABLESSL | default(false) }}" LIDARR__SERVER__PORT: "{{ LIDARR__SERVER__PORT | default('8686') }}" LIDARR__SERVER__SSLPORT: "{{ LIDARR__SERVER__SSLPORT | default('6868') }}" LIDARR__SERVER__BINDADDRESS: "{{ LIDARR__SERVER__BINDADDRESS | default('*') }}" LIDARR__SERVER__SSLCERTPATH: "{{ LIDARR__SERVER__SSLCERTPATH | default('/config/ssl/server.crt') }}" LIDARR__SERVER__SSLCERTPASSWORD: "{{ LIDARR__SERVER__SSLCERTPASSWORD | default('/config/ssl/server.key') }}" LIDARR__LOG__ANALYTICSENABLED: "{{ LIDARR__LOG__ANALYTICSENABLED | default(false) }}" LIDARR__LOG__LEVEL: "{{ LIDARR__LOG__LEVEL | default('info') }}" LIDARR__UPDATE__AUTOMATICALLY: "{{ LIDARR__UPDATE__AUTOMATICALLY | default(false) }}" command: ["/app/Lidarr", "-nobrowser", "--data=/config"] restart_policy: on-failure - name: htpc_lazylibrarian type: container pod: htpc image: localhost/htpc_lazylibrarian:latest volumes: - "{{ config_root }}/lazylibrarian:/config:Z" - "{{ download_root }}/htpc:/downloads:z" - "{{ media_root }}/ebooks:/ebooks:Z" env: TZ: "{{ tz }}" command: ["/venv/bin/python", "/app/LazyLibrarian.py", "--nolaunch", "--port", "{{ lazylibrarian_port | default('5299') }}", "--datadir=/config"] restart_policy: on-failure - name: htpc_prowlarr type: container pod: htpc image: localhost/htpc_prowlarr:latest volumes: - "{{ config_root }}/prowlarr:/config:Z" - "{{ download_root }}/htpc:/downloads:z" env: TZ: "{{ tz }}" PROWLARR__APP__LAUNCHBROWSER: false PROWLARR__APP__INSTANCENAME: "{{ PROWLARR__APP__INSTANCENAME | default('Prowlarr') }}" PROWLARR__AUTH__METHOD: "{{ PROWLARR__AUTH__METHOD | default('Forms') }}" PROWLARR__AUTH__REQUIRED: "{{ PROWLARR__AUTH__REQUIRED | default('DisabledForLocalAddresses') }}" PROWLARR__AUTH__APIKEY: "{{ PROWLARR__AUTH__APIKEY | default(lookup('password', '/dev/null length=32 chars=ascii_letters,digits')) }}" PROWLARR__SERVER__ENABLESSL: "{{ PROWLARR__SERVER__ENABLESSL | default(false) }}" PROWLARR__SERVER__SSLPORT: "{{ PROWLARR__SERVER__PORT | default('6969') }}" PROWLARR__SERVER__PORT: "{{ PROWLARR__SERVER__PORT | default('9696') }}" PROWLARR__SERVER__BINDADDRESS: "{{ PROWLARR__SERVER__BINDADDRESS | default('*') }}" PROWLARR__LOG__ANALYTICSENABLED: "{{ PROWLARR__LOG__ANALYTICSENABLED | default(false) }}" PROWLARR__LOG__LEVEL: "{{ PROWLARR__LOG__LEVEL | default('info') }}" PROWLARR__UPDATE__AUTOMATICALLY: "{{ PROWLARR__UPDATE__AUTOMATICALLY | default(false) }}" command: ["/app/Prowlarr", "--nobrowser", "--data=/config"] restart_policy: on-failure - name: htpc_unpackerr type: container pod: htpc image: localhost/htpc_unpackerr:latest volumes: - "{{ config_root }}/unpackerr:/config:Z" - "{{ download_root }}/htpc:/downloads:z" env: TZ: "{{ tz }}" UNPACKERR__LOG__ANALYTICSENABLED: "{{ UNPACKERR__LOG__ANALYTICSENABLED | default(false) }}" UNPACKERR__UPDATE__AUTOMATICALLY: "{{ UNPACKERR__UPDATE__AUTOMATICALLY | default(false) }}" UNPACKERR__LOG__LEVEL: "{{ UNPACKERR__LOG__LEVEL | default('info') }}" command: ["/app/unpackerr"] restart_policy: on-failure