From 7ae62fe78cf86a3bdc097a0177074984d8bed68f Mon Sep 17 00:00:00 2001 From: Ramon Date: Mon, 27 Jul 2026 09:46:01 +0200 Subject: [PATCH] v0.6.10-beta - ARR-stack met een schakelaar per onderdeel De ARR-stack installeerde altijd dezelfde zeven containers. Nu kies je per onderdeel uit twintig: - Media: sonarr, radarr, lidarr, readarr, whisparr - Indexers: prowlarr, jackett, flaresolverr, bazarr - Downloaden: qbittorrent, sabnzbd, nzbget, gluetun (VPN) - Aanvullend: jellyseerr, recyclarr, unpackerr, tdarr, autobrr, maintainerr, huntarr Standaard aan: sonarr, radarr, prowlarr, bazarr, qbittorrent, jellyseerr. Gluetun: - Staat die aan, dan draaien de downloadclients in diens netwerknamespace zonder eigen poortmapping; anders lekt hun verkeer om de VPN heen. Hun webinterfaces komen op de poorten van de Gluetun-container. - qBittorrent en SABnzbd luisteren allebei standaard op 8080 en botsten daardoor achter een gedeelde namespace. qBittorrent draait nu intern op 8090. Groepsschakelaars werkten niet: - Een `toggle` op een groep in template.json was zelf geen variabele en kreeg dus nooit een startwaarde, waardoor elk schakelbaar onderdeel standaard uit stond en een stack met schakelaars leeg binnenkwam. fields() geeft de schakelaar nu mee als synthetisch bool-veld met een instelbare standaardstand (toggle_default), en de UI toont hem alleen in de kop van de groep in plaats van er ook nog eens onder. Tests: elk onderdeel levert precies een service op als het aan staat en geen spoor als het uit staat, de downloadclients zitten achter de VPN zonder eigen poorten, en de interne poorten achter Gluetun botsen niet. Poortbotsingen met bestaande apps rechtgezet (8090 -> 8097, 8095 -> 8098); 6881 en 5055 blijven gedeeld met de losse variant van dezelfde app. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb --- CHANGELOG.md | 40 ++++ VERSION | 2 +- apps/arr-stack/files/compose.yaml | 291 +++++++++++++++++++++-- apps/arr-stack/template.json | 381 ++++++++++++++++++++++++++---- server-up/core/boilerplates.py | 13 + server-up/templates/index.html | 4 +- tests/test_apps.py | 84 +++++++ 7 files changed, 754 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99502ed..4f06830 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,43 @@ +# v0.6.10-beta — ARR-stack met een schakelaar per onderdeel + +De ARR-stack installeerde altijd dezelfde zeven containers. Nu kies je per +onderdeel wat je wilt, uit twintig: + +**Media beheren** — Sonarr (series), Radarr (films), Lidarr (muziek), Readarr +(boeken), Whisparr + +**Indexers en ondersteuning** — Prowlarr, Jackett, FlareSolverr, Bazarr +(ondertitels) + +**Downloaden** — qBittorrent, SABnzbd, NZBGet, en Gluetun om al het +downloadverkeer door een VPN te leiden + +**Verzoeken en aanvullingen** — Jellyseerr, Recyclarr (TRaSH-profielen), +Unpackerr, Tdarr (hercoderen), Autobrr, Maintainerr, Huntarr + +Standaard staan Sonarr, Radarr, Prowlarr, Bazarr, qBittorrent en Jellyseerr aan; +de rest zet je zelf bij. + +## Gluetun schakelt de downloadclients om + +Zet je Gluetun aan, dan verhuizen qBittorrent, SABnzbd en NZBGet naar diens +netwerknamespace en verliezen ze hun eigen poortmapping — precies zoals het +hoort, want anders lekt hun verkeer om de VPN heen. Hun webinterfaces bereik je +dan via de poorten van de Gluetun-container. + +Daarbij zat een val: qBittorrent en SABnzbd luisteren allebei standaard op 8080, +en achter één VPN-container botsen ze. qBittorrent draait nu intern op 8090. + +## Groepsschakelaars werkten niet + +Een groepsschakelaar in template.json was zelf geen variabele en kreeg dus nooit +een startwaarde. Elk schakelbaar onderdeel stond daardoor standaard uit — een +stack met schakelaars zou leeg binnenkomen. Ze worden nu als veld meegegeven met +een instelbare standaardstand, en de interface toont ze alleen als schakelaar in +de kop van de groep. + +--- + # v0.6.00-beta — 29 apps erbij, en een bug die zes bestaande apps onstartbaar maakte ## 🐛 Named volumes verdwenen uit het compose-bestand diff --git a/VERSION b/VERSION index 465f593..56cbdd8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.00-beta +0.6.10-beta diff --git a/apps/arr-stack/files/compose.yaml b/apps/arr-stack/files/compose.yaml index 049f146..04a0cd1 100644 --- a/apps/arr-stack/files/compose.yaml +++ b/apps/arr-stack/files/compose.yaml @@ -1,19 +1,13 @@ +# ARR-stack — kies per onderdeel of je het wilt. +# +# Aandachtspunten: +# * Zet de download- en mediamap op hetzelfde bestandssysteem, anders kopieert +# elke voltooide download in plaats van te verplaatsen (traag, dubbele opslag). +# * Draai je met Gluetun, dan zitten de downloadclients in het netwerk van die +# container en bereik je hun webinterface via de Gluetun-poorten. services: - << service_name >>-radarr: - image: lscr.io/linuxserver/radarr:latest - container_name: << service_name >>-radarr - environment: - - PUID=<< puid >> - - PGID=<< pgid >> - - TZ=<< timezone >> - volumes: - - << data_dir >>/<< service_name >>/radarr:/config - - << media_dir >>/films:/movies - - << downloads_dir >>:/downloads - ports: - - "<< port_radarr >>:7878" - restart: unless-stopped +<%- if enable_sonarr %> << service_name >>-sonarr: image: lscr.io/linuxserver/sonarr:latest container_name: << service_name >>-sonarr @@ -28,7 +22,26 @@ services: ports: - "<< port_sonarr >>:8989" restart: unless-stopped +<%- endif %> +<%- if enable_radarr %> + << service_name >>-radarr: + image: lscr.io/linuxserver/radarr:latest + container_name: << service_name >>-radarr + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/radarr:/config + - << media_dir >>/films:/movies + - << downloads_dir >>:/downloads + ports: + - "<< port_radarr >>:7878" + restart: unless-stopped +<%- endif %> + +<%- if enable_lidarr %> << service_name >>-lidarr: image: lscr.io/linuxserver/lidarr:latest container_name: << service_name >>-lidarr @@ -43,7 +56,9 @@ services: ports: - "<< port_lidarr >>:8686" restart: unless-stopped +<%- endif %> +<%- if enable_readarr %> << service_name >>-readarr: image: lscr.io/linuxserver/readarr:develop container_name: << service_name >>-readarr @@ -58,7 +73,26 @@ services: ports: - "<< port_readarr >>:8787" restart: unless-stopped +<%- endif %> +<%- if enable_whisparr %> + << service_name >>-whisparr: + image: ghcr.io/hotio/whisparr:latest + container_name: << service_name >>-whisparr + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/whisparr:/config + - << media_dir >>/volwassen:/adult + - << downloads_dir >>:/downloads + ports: + - "<< port_whisparr >>:6969" + restart: unless-stopped +<%- endif %> + +<%- if enable_prowlarr %> << service_name >>-prowlarr: image: lscr.io/linuxserver/prowlarr:latest container_name: << service_name >>-prowlarr @@ -71,7 +105,24 @@ services: ports: - "<< port_prowlarr >>:9696" restart: unless-stopped +<%- endif %> +<%- if enable_jackett %> + << service_name >>-jackett: + image: lscr.io/linuxserver/jackett:latest + container_name: << service_name >>-jackett + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/jackett:/config + ports: + - "<< port_jackett >>:9117" + restart: unless-stopped +<%- endif %> + +<%- if enable_bazarr %> << service_name >>-bazarr: image: lscr.io/linuxserver/bazarr:latest container_name: << service_name >>-bazarr @@ -86,14 +137,226 @@ services: ports: - "<< port_bazarr >>:6767" restart: unless-stopped +<%- endif %> +<%- if enable_flaresolverr %> + << service_name >>-flaresolverr: + image: ghcr.io/flaresolverr/flaresolverr:latest + container_name: << service_name >>-flaresolverr + environment: + - TZ=<< timezone >> + - LOG_LEVEL=info + ports: + - "<< port_flaresolverr >>:8191" + restart: unless-stopped +<%- endif %> + +<%- if enable_gluetun %> + << service_name >>-gluetun: + image: qmcgaw/gluetun:latest + container_name: << service_name >>-gluetun + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + environment: + - TZ=<< timezone >> + - VPN_SERVICE_PROVIDER=<< vpn_provider >> + - VPN_TYPE=<< vpn_type >> + - WIREGUARD_PRIVATE_KEY=<< wireguard_private_key >> + - WIREGUARD_ADDRESSES=<< wireguard_addresses >> + - OPENVPN_USER=<< openvpn_user >> + - OPENVPN_PASSWORD=<< openvpn_password >> + ports: + # De downloadclients delen dit netwerk, dus hun poorten staan hier. +<%- if enable_qbittorrent %> + - "<< port_qbittorrent >>:8090" + - "<< port_qbittorrent_tcp >>:6881" + - "<< port_qbittorrent_tcp >>:6881/udp" +<%- endif %> +<%- if enable_sabnzbd %> + - "<< port_sabnzbd >>:8080" +<%- endif %> +<%- if enable_nzbget %> + - "<< port_nzbget >>:6789" +<%- endif %> + volumes: + - << data_dir >>/<< service_name >>/gluetun:/gluetun + restart: unless-stopped +<%- endif %> + +<%- if enable_qbittorrent %> + << service_name >>-qbittorrent: + image: lscr.io/linuxserver/qbittorrent:latest + container_name: << service_name >>-qbittorrent + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + - WEBUI_PORT=8090 + volumes: + - << data_dir >>/<< service_name >>/qbittorrent:/config + - << downloads_dir >>:/downloads +<%- if enable_gluetun %> + network_mode: "service:<< service_name >>-gluetun" + depends_on: + - << service_name >>-gluetun +<%- endif %> +<%- if not enable_gluetun %> + ports: + - "<< port_qbittorrent >>:8090" + - "<< port_qbittorrent_tcp >>:6881" + - "<< port_qbittorrent_tcp >>:6881/udp" +<%- endif %> + restart: unless-stopped +<%- endif %> + +<%- if enable_sabnzbd %> + << service_name >>-sabnzbd: + image: lscr.io/linuxserver/sabnzbd:latest + container_name: << service_name >>-sabnzbd + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/sabnzbd:/config + - << downloads_dir >>:/downloads +<%- if enable_gluetun %> + network_mode: "service:<< service_name >>-gluetun" + depends_on: + - << service_name >>-gluetun +<%- endif %> +<%- if not enable_gluetun %> + ports: + - "<< port_sabnzbd >>:8080" +<%- endif %> + restart: unless-stopped +<%- endif %> + +<%- if enable_nzbget %> + << service_name >>-nzbget: + image: lscr.io/linuxserver/nzbget:latest + container_name: << service_name >>-nzbget + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/nzbget:/config + - << downloads_dir >>:/downloads +<%- if enable_gluetun %> + network_mode: "service:<< service_name >>-gluetun" + depends_on: + - << service_name >>-gluetun +<%- endif %> +<%- if not enable_gluetun %> + ports: + - "<< port_nzbget >>:6789" +<%- endif %> + restart: unless-stopped +<%- endif %> + +<%- if enable_jellyseerr %> << service_name >>-jellyseerr: image: fallenbagel/jellyseerr:latest container_name: << service_name >>-jellyseerr environment: - TZ=<< timezone >> + - LOG_LEVEL=info volumes: - << data_dir >>/<< service_name >>/jellyseerr:/app/config ports: - "<< port_jellyseerr >>:5055" restart: unless-stopped +<%- endif %> + +<%- if enable_recyclarr %> + << service_name >>-recyclarr: + image: ghcr.io/recyclarr/recyclarr:latest + container_name: << service_name >>-recyclarr + user: << puid >>:<< pgid >> + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/recyclarr:/config + restart: unless-stopped +<%- endif %> + +<%- if enable_unpackerr %> + << service_name >>-unpackerr: + image: ghcr.io/unpackerr/unpackerr:latest + container_name: << service_name >>-unpackerr + user: << puid >>:<< pgid >> + environment: + - TZ=<< timezone >> + - UN_SONARR_0_URL=http://<< service_name >>-sonarr:8989 + - UN_RADARR_0_URL=http://<< service_name >>-radarr:7878 + volumes: + - << data_dir >>/<< service_name >>/unpackerr:/config + - << downloads_dir >>:/downloads + restart: unless-stopped +<%- endif %> + +<%- if enable_tdarr %> + << service_name >>-tdarr: + image: ghcr.io/haveagitgat/tdarr:latest + container_name: << service_name >>-tdarr + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + - serverIP=0.0.0.0 + - serverPort=8266 + - webUIPort=8265 + - internalNode=true + volumes: + - << data_dir >>/<< service_name >>/tdarr/server:/app/server + - << data_dir >>/<< service_name >>/tdarr/configs:/app/configs + - << media_dir >>:/media + - << downloads_dir >>/tdarr-cache:/temp + ports: + - "<< port_tdarr >>:8265" + - "<< port_tdarr_server >>:8266" + restart: unless-stopped +<%- endif %> + +<%- if enable_autobrr %> + << service_name >>-autobrr: + image: ghcr.io/autobrr/autobrr:latest + container_name: << service_name >>-autobrr + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/autobrr:/config + ports: + - "<< port_autobrr >>:7474" + restart: unless-stopped +<%- endif %> + +<%- if enable_maintainerr %> + << service_name >>-maintainerr: + image: ghcr.io/jorenn92/maintainerr:latest + container_name: << service_name >>-maintainerr + user: << puid >>:<< pgid >> + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/maintainerr:/opt/data + ports: + - "<< port_maintainerr >>:6246" + restart: unless-stopped +<%- endif %> + +<%- if enable_huntarr %> + << service_name >>-huntarr: + image: ghcr.io/plexguide/huntarr:latest + container_name: << service_name >>-huntarr + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/huntarr:/config + ports: + - "<< port_huntarr >>:9705" + restart: unless-stopped +<%- endif %> diff --git a/apps/arr-stack/template.json b/apps/arr-stack/template.json index 0af6830..4c7045a 100644 --- a/apps/arr-stack/template.json +++ b/apps/arr-stack/template.json @@ -2,10 +2,21 @@ "kind": "compose", "metadata": { "name": "ARR-stack", - "description": "Complete media-automatiseringsstack: Radarr (films), Sonarr (series), Lidarr (muziek), Readarr (boeken), Prowlarr (indexers), Bazarr (ondertitels) en Jellyseerr (verzoeken).", - "tags": ["media", "automatisering", "radarr", "sonarr", "prowlarr", "bazarr", "jellyseerr"], - "icon": {"provider": "selfhst", "id": "radarr"}, - "version": {"name": "latest"} + "description": "Media-automatisering met een schakelaar per onderdeel: Sonarr, Radarr, Lidarr, Readarr, Whisparr, Prowlarr, Jackett, Bazarr, FlareSolverr, qBittorrent, SABnzbd, NZBGet, Gluetun (VPN), Jellyseerr, Recyclarr, Unpackerr, Tdarr, Autobrr, Maintainerr en Huntarr.", + "tags": [ + "media", + "automatisering", + "films", + "series", + "downloaden" + ], + "icon": { + "provider": "selfhst", + "id": "sonarr" + }, + "version": { + "name": "latest" + } }, "variables": [ { @@ -14,34 +25,33 @@ { "name": "service_name", "type": "str", - "title": "Servicenaam (prefix)", + "title": "Naam van de stack", "default": "arr", "required": true, - "description": "Prefix voor alle containers in de stack, bijv. 'arr' geeft arr-radarr, arr-sonarr, etc." + "description": "Wordt het voorvoegsel van elke container, bv. arr-sonarr" }, { "name": "data_dir", "type": "str", - "title": "Config directory", + "title": "Configuratiemap", "default": "/opt/serverup/appdata", - "required": true, - "description": "Basismap voor configuratiebestanden van alle ARR-apps" + "required": true }, { "name": "media_dir", "type": "str", - "title": "Media directory", + "title": "Mediamap", "default": "/mnt/media", "required": true, - "description": "Map voor films, series en muziek. Moet ook zichtbaar zijn voor de download-client." + "description": "Hier komen films/, series/, muziek/ en boeken/ onder te staan" }, { "name": "downloads_dir", "type": "str", - "title": "Downloads directory", + "title": "Downloadmap", "default": "/mnt/downloads", "required": true, - "description": "Map waar de download-client bestanden neerzet (qBittorrent of SABnzbd). Moet overeenkomen met het pad in de download-client." + "description": "Zet deze op hetzelfde bestandssysteem als de mediamap, anders kopieert elke download in plaats van te verplaatsen" }, { "name": "timezone", @@ -49,84 +59,365 @@ "title": "Tijdzone", "default": "Europe/Amsterdam", "required": true - } - ] - }, - { - "title": "Gebruiker", - "items": [ + }, { "name": "puid", "type": "int", - "title": "PUID", + "title": "Gebruikers-ID (PUID)", "default": 1000, "required": true, - "description": "User ID van de systeemgebruiker (id -u)" + "description": "`id -u` op je host; bepaalt de eigenaar van bestanden" }, { "name": "pgid", "type": "int", - "title": "PGID", + "title": "Groeps-ID (PGID)", "default": 1000, - "required": true, - "description": "Group ID van de systeemgebruiker (id -g)" + "required": true } ] }, { - "title": "Poorten", + "title": "Sonarr — series", + "items": [ + { + "name": "port_sonarr", + "type": "int", + "title": "Poort", + "default": 8989, + "required": true + } + ], + "toggle": "enable_sonarr", + "toggle_default": true, + "description": "Zoekt, downloadt en hernoemt series" + }, + { + "title": "Radarr — films", "items": [ { "name": "port_radarr", "type": "int", - "title": "Radarr poort", + "title": "Poort", "default": 7878, "required": true - }, - { - "name": "port_sonarr", - "type": "int", - "title": "Sonarr poort", - "default": 8989, - "required": true - }, + } + ], + "toggle": "enable_radarr", + "toggle_default": true, + "description": "Zoekt, downloadt en hernoemt films" + }, + { + "title": "Lidarr — muziek", + "items": [ { "name": "port_lidarr", "type": "int", - "title": "Lidarr poort", + "title": "Poort", "default": 8686, "required": true - }, + } + ], + "toggle": "enable_lidarr", + "toggle_default": false + }, + { + "title": "Readarr — boeken", + "items": [ { "name": "port_readarr", "type": "int", - "title": "Readarr poort", + "title": "Poort", "default": 8787, "required": true - }, + } + ], + "toggle": "enable_readarr", + "toggle_default": false, + "description": "Let op: de ontwikkeling van Readarr is stilgelegd; het draait nog wel" + }, + { + "title": "Whisparr — volwassenen", + "items": [ + { + "name": "port_whisparr", + "type": "int", + "title": "Poort", + "default": 6969, + "required": true + } + ], + "toggle": "enable_whisparr", + "toggle_default": false + }, + { + "title": "Prowlarr — indexerbeheer", + "items": [ { "name": "port_prowlarr", "type": "int", - "title": "Prowlarr poort", + "title": "Poort", "default": 9696, "required": true - }, + } + ], + "toggle": "enable_prowlarr", + "toggle_default": true, + "description": "Beheert je indexers centraal en duwt ze naar de andere *arr-apps" + }, + { + "title": "Jackett — indexerproxy", + "items": [ + { + "name": "port_jackett", + "type": "int", + "title": "Poort", + "default": 9117, + "required": true + } + ], + "toggle": "enable_jackett", + "toggle_default": false, + "description": "Ouder alternatief voor Prowlarr; meestal heb je er maar één nodig" + }, + { + "title": "FlareSolverr — Cloudflare omzeilen", + "items": [ + { + "name": "port_flaresolverr", + "type": "int", + "title": "Poort", + "default": 8191, + "required": true + } + ], + "toggle": "enable_flaresolverr", + "toggle_default": false, + "description": "Nodig voor indexers die achter een Cloudflare-controle zitten" + }, + { + "title": "Bazarr — ondertitels", + "items": [ { "name": "port_bazarr", "type": "int", - "title": "Bazarr poort", + "title": "Poort", "default": 6767, "required": true + } + ], + "toggle": "enable_bazarr", + "toggle_default": true + }, + { + "title": "qBittorrent — torrents", + "items": [ + { + "name": "port_qbittorrent", + "type": "int", + "title": "Webinterface", + "default": 8097, + "required": true }, + { + "name": "port_qbittorrent_tcp", + "type": "int", + "title": "Inkomende poort", + "default": 6881, + "required": true + } + ], + "toggle": "enable_qbittorrent", + "toggle_default": true, + "description": "Torrentclient met webinterface" + }, + { + "title": "SABnzbd — usenet", + "items": [ + { + "name": "port_sabnzbd", + "type": "int", + "title": "Poort", + "default": 8098, + "required": true + } + ], + "toggle": "enable_sabnzbd", + "toggle_default": false + }, + { + "title": "NZBGet — usenet (lichter)", + "items": [ + { + "name": "port_nzbget", + "type": "int", + "title": "Poort", + "default": 6789, + "required": true + } + ], + "toggle": "enable_nzbget", + "toggle_default": false, + "description": "Zuiniger alternatief voor SABnzbd" + }, + { + "title": "Gluetun — VPN voor de downloadclient", + "items": [ + { + "name": "vpn_provider", + "type": "str", + "title": "VPN-aanbieder", + "default": "mullvad", + "required": true, + "description": "Bijvoorbeeld mullvad, nordvpn, protonvpn of surfshark" + }, + { + "name": "vpn_type", + "type": "enum", + "title": "Protocol", + "default": "wireguard", + "required": true, + "config": { + "options": [ + "wireguard", + "openvpn" + ] + } + }, + { + "name": "wireguard_private_key", + "type": "str", + "title": "WireGuard privésleutel", + "default": "", + "required": false, + "config": { + "placeholder": "alleen bij wireguard" + } + }, + { + "name": "wireguard_addresses", + "type": "str", + "title": "WireGuard adressen", + "default": "", + "required": false, + "config": { + "placeholder": "10.64.0.2/32" + } + }, + { + "name": "openvpn_user", + "type": "str", + "title": "OpenVPN gebruiker", + "default": "", + "required": false + }, + { + "name": "openvpn_password", + "type": "str", + "title": "OpenVPN wachtwoord", + "default": "", + "required": false + } + ], + "toggle": "enable_gluetun", + "toggle_default": false, + "description": "Leidt al je downloadverkeer door een VPN. De downloadclients delen dan het netwerk van deze container, dus hun poorten komen hier te liggen." + }, + { + "title": "Jellyseerr — verzoeken", + "items": [ { "name": "port_jellyseerr", "type": "int", - "title": "Jellyseerr poort", + "title": "Poort", "default": 5055, - "required": true, - "description": "Webinterface voor gebruikers om films en series aan te vragen" + "required": true } - ] + ], + "toggle": "enable_jellyseerr", + "toggle_default": true, + "description": "Laat huisgenoten films en series aanvragen" + }, + { + "title": "Recyclarr — TRaSH-instellingen", + "items": [], + "toggle": "enable_recyclarr", + "toggle_default": false, + "description": "Synchroniseert kwaliteitsprofielen uit de TRaSH-gidsen naar Sonarr en Radarr" + }, + { + "title": "Unpackerr — archieven uitpakken", + "items": [], + "toggle": "enable_unpackerr", + "toggle_default": false, + "description": "Pakt gedownloade rar-archieven automatisch uit" + }, + { + "title": "Tdarr — hercoderen", + "items": [ + { + "name": "port_tdarr", + "type": "int", + "title": "Webinterface", + "default": 8265, + "required": true + }, + { + "name": "port_tdarr_server", + "type": "int", + "title": "Serverpoort", + "default": 8266, + "required": true + } + ], + "toggle": "enable_tdarr", + "toggle_default": false, + "description": "Zet je bibliotheek om naar een zuiniger formaat" + }, + { + "title": "Autobrr — automatisch grijpen", + "items": [ + { + "name": "port_autobrr", + "type": "int", + "title": "Poort", + "default": 7474, + "required": true + } + ], + "toggle": "enable_autobrr", + "toggle_default": false, + "description": "Reageert direct op aankondigingen in plaats van periodiek te zoeken" + }, + { + "title": "Maintainerr — opruimen", + "items": [ + { + "name": "port_maintainerr", + "type": "int", + "title": "Poort", + "default": 6246, + "required": true + } + ], + "toggle": "enable_maintainerr", + "toggle_default": false, + "description": "Ruimt media op volgens regels die je zelf instelt" + }, + { + "title": "Huntarr — gaten opvullen", + "items": [ + { + "name": "port_huntarr", + "type": "int", + "title": "Poort", + "default": 9705, + "required": true + } + ], + "toggle": "enable_huntarr", + "toggle_default": false, + "description": "Zoekt gericht naar ontbrekende en te verbeteren afleveringen" } ] } diff --git a/server-up/core/boilerplates.py b/server-up/core/boilerplates.py index d5ce5ae..aed4d45 100644 --- a/server-up/core/boilerplates.py +++ b/server-up/core/boilerplates.py @@ -81,6 +81,19 @@ def fields(d: Path) -> list[dict]: for grp in t.get("variables", []) or []: gname = grp.get("title") or grp.get("name", "") toggle = grp.get("toggle") + if toggle: + # De groepsschakelaar is zelf geen item in template.json, waardoor + # hij nergens een startwaarde kreeg en dus altijd uit stond. Als + # synthetisch veld krijgt hij die wel; de UI toont hem als schakelaar + # in de kop en slaat hem over in de lijst eronder. + out.append({ + "name": toggle, "type": "bool", + "title": gname, "group": gname, "group_toggle": toggle, + "default": bool(grp.get("toggle_default", True)), + "required": False, "options": [], "needs": [], + "placeholder": "", "description": grp.get("description", ""), + "is_group_toggle": True, + }) for item in grp.get("items", []) or []: cfg = item.get("config") or {} out.append({ diff --git a/server-up/templates/index.html b/server-up/templates/index.html index 18e8e6f..c2f90ab 100644 --- a/server-up/templates/index.html +++ b/server-up/templates/index.html @@ -1156,7 +1156,9 @@ tailwind.config = {