diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f06830..2ecab38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,44 @@ +# v0.6.20-beta — 31 apps erbij na een rondgang langs de verzamelsites + +Van 65 naar 96 apps. Selectie op basis van awesome-selfhosted, selfh.st, +Perfect Media Server en een paar overzichtslijsten van 2026, aangevuld met wat +er in de bestaande collectie nog ontbrak. + +**Monitoring** — Prometheus (de tegenhanger van Grafana, die er al stond), +InfluxDB, Netdata, Beszel + +**Reverse proxy** — Caddy, dat zijn certificaten volledig zelf regelt + +**Notities en kennis** — Memos, HedgeDoc, Wiki.js, Excalidraw, Karakeep + +**Data en dashboards** — NocoDB, Baserow, Metabase + +**Identiteit** — Authelia en Keycloak, allebei bruikbaar met de +reverse-proxy-SSO van Server Up zelf + +**Media** — Komga, PhotoPrism, MeTube, Pinchflat + +**Meldingen** — ntfy + +**Productiviteit** — Planka, Focalboard, Kimai + +**Locatie en voertuig** — OwnTracks, TeslaMate + +**Hulpmiddelen** — Shlink, CyberChef, LanguageTool, Kopia + +**AI** — Ollama en Open WebUI, allebei volledig lokaal + +De images van de nieuwere apps (Beszel, Karakeep, Pinchflat) zijn nagetrokken +bij de bron in plaats van uit het hoofd opgeschreven; van Karakeep is de +officiële compose overgenomen, inclusief de meilisearch- en chrome-containers +die hij nodig heeft. + +Vijftien poortbotsingen met bestaande apps zijn automatisch rechtgezet. Caddy +deelt 80 en 443 met Traefik en Nginx Proxy Manager — alternatieven voor dezelfde +taak, dus dat staat in de allowlist. + +--- + # v0.6.10-beta — ARR-stack met een schakelaar per onderdeel De ARR-stack installeerde altijd dezelfde zeven containers. Nu kies je per diff --git a/VERSION b/VERSION index 56cbdd8..08ce70d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.10-beta +0.6.20-beta diff --git a/apps/authelia/files/compose.yaml b/apps/authelia/files/compose.yaml new file mode 100644 index 0000000..5be34dc --- /dev/null +++ b/apps/authelia/files/compose.yaml @@ -0,0 +1,15 @@ +services: + << service_name >>: + image: authelia/authelia:latest + container_name: << service_name >> + ports: + - "<< port >>:9091" + environment: + - TZ=<< timezone >> + - AUTHELIA_JWT_SECRET=<< jwt_secret >> + - AUTHELIA_SESSION_SECRET=<< session_secret >> + - AUTHELIA_STORAGE_ENCRYPTION_KEY=<< storage_key >> + volumes: + # Zet hier configuration.yml en users_database.yml neer voor de eerste start. + - << data_dir >>/<< service_name >>/config:/config + restart: unless-stopped diff --git a/apps/authelia/template.json b/apps/authelia/template.json new file mode 100644 index 0000000..0ce99a3 --- /dev/null +++ b/apps/authelia/template.json @@ -0,0 +1,87 @@ +{ + "kind": "compose", + "metadata": { + "name": "Authelia", + "description": "Inlogportaal met tweestapsverificatie voor al je diensten achter een reverse proxy. Werkt samen met de SSO-instelling van Server Up.", + "tags": [ + "beveiliging", + "sso", + "authenticatie" + ], + "icon": { + "provider": "selfhst", + "id": "authelia" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "authelia", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 9091, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "jwt_secret", + "type": "str", + "title": "JWT-sleutel", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "session_secret", + "type": "str", + "title": "Sessiesleutel", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "storage_key", + "type": "str", + "title": "Opslagversleuteling", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + } + ] + } + ] +} diff --git a/apps/baserow/files/compose.yaml b/apps/baserow/files/compose.yaml new file mode 100644 index 0000000..29b2c04 --- /dev/null +++ b/apps/baserow/files/compose.yaml @@ -0,0 +1,12 @@ +services: + << service_name >>: + image: baserow/baserow:latest + container_name: << service_name >> + ports: + - "<< port >>:80" + environment: + - TZ=<< timezone >> + - BASEROW_PUBLIC_URL=<< public_url >> + volumes: + - << data_dir >>/<< service_name >>:/baserow/data + restart: unless-stopped diff --git a/apps/baserow/template.json b/apps/baserow/template.json new file mode 100644 index 0000000..6c26f3f --- /dev/null +++ b/apps/baserow/template.json @@ -0,0 +1,62 @@ +{ + "kind": "compose", + "metadata": { + "name": "Baserow", + "description": "Databases opbouwen zonder te programmeren, met formulieren en weergaven.", + "tags": [ + "database", + "no-code", + "formulieren" + ], + "icon": { + "provider": "selfhst", + "id": "baserow" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "baserow", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8099, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "public_url", + "type": "str", + "title": "Publieke URL", + "default": "http://localhost:8098", + "required": true, + "description": "Zonder dit kloppen links en uploads niet" + } + ] + } + ] +} diff --git a/apps/beszel/files/compose.yaml b/apps/beszel/files/compose.yaml new file mode 100644 index 0000000..3b124fa --- /dev/null +++ b/apps/beszel/files/compose.yaml @@ -0,0 +1,23 @@ +services: + << service_name >>: + image: henrygd/beszel:latest + container_name: << service_name >> + ports: + - "<< port >>:8090" + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/data:/beszel_data + restart: unless-stopped + + << service_name >>-agent: + image: henrygd/beszel-agent:latest + container_name: << service_name >>-agent + network_mode: host + environment: + - TZ=<< timezone >> + - PORT=<< agent_port >> + - KEY=<< agent_key >> + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + restart: unless-stopped diff --git a/apps/beszel/template.json b/apps/beszel/template.json new file mode 100644 index 0000000..9c8f173 --- /dev/null +++ b/apps/beszel/template.json @@ -0,0 +1,70 @@ +{ + "kind": "compose", + "metadata": { + "name": "Beszel", + "description": "Lichte servermonitoring met grafieken en alarmen, zonder een hele Prometheus-opstelling.", + "tags": [ + "monitoring", + "systeem", + "lichtgewicht" + ], + "icon": { + "provider": "selfhst", + "id": "beszel" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "beszel", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8100, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "agent_port", + "type": "int", + "title": "Agent-poort", + "default": 45876, + "required": true, + "description": "De agent meet deze host; extra servers wijs je later aan" + }, + { + "name": "agent_key", + "type": "str", + "title": "Publieke sleutel agent", + "default": "", + "required": false, + "description": "Laat leeg bij de eerste installatie; je vindt hem in de webinterface" + } + ] + } + ] +} diff --git a/apps/caddy/files/compose.yaml b/apps/caddy/files/compose.yaml new file mode 100644 index 0000000..9284546 --- /dev/null +++ b/apps/caddy/files/compose.yaml @@ -0,0 +1,20 @@ +services: + << service_name >>: + image: caddy:2 + container_name: << service_name >> + ports: + - "<< port >>:80" + - "<< https_port >>:443" + - "<< https_port >>:443/udp" + environment: + - TZ=<< timezone >> + volumes: + # Zet hier je Caddyfile neer; Caddy regelt de certificaten daarna zelf. + - << data_dir >>/<< service_name >>/Caddyfile:/etc/caddy/Caddyfile + - << service_name >>_data:/data + - << service_name >>_config:/config + restart: unless-stopped + +volumes: + << service_name >>_data: + << service_name >>_config: diff --git a/apps/caddy/template.json b/apps/caddy/template.json new file mode 100644 index 0000000..c5efe58 --- /dev/null +++ b/apps/caddy/template.json @@ -0,0 +1,61 @@ +{ + "kind": "compose", + "metadata": { + "name": "Caddy", + "description": "Reverse proxy die HTTPS-certificaten volledig zelf regelt. Eenvoudiger in te stellen dan Traefik of Nginx.", + "tags": [ + "proxy", + "netwerk", + "https" + ], + "icon": { + "provider": "selfhst", + "id": "caddy" + }, + "version": { + "name": "2" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "caddy", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "HTTP poort", + "default": 80, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "https_port", + "type": "int", + "title": "HTTPS poort", + "default": 443, + "required": true + } + ] + } + ] +} diff --git a/apps/cyberchef/files/compose.yaml b/apps/cyberchef/files/compose.yaml new file mode 100644 index 0000000..ac7bc5c --- /dev/null +++ b/apps/cyberchef/files/compose.yaml @@ -0,0 +1,9 @@ +services: + << service_name >>: + image: mpepping/cyberchef:latest + container_name: << service_name >> + ports: + - "<< port >>:8000" + environment: + - TZ=<< timezone >> + restart: unless-stopped diff --git a/apps/cyberchef/template.json b/apps/cyberchef/template.json new file mode 100644 index 0000000..5799d9d --- /dev/null +++ b/apps/cyberchef/template.json @@ -0,0 +1,47 @@ +{ + "kind": "compose", + "metadata": { + "name": "CyberChef", + "description": "Zwitsers zakmes voor coderen, decoderen, hashen en data omzetten. Draait volledig lokaal.", + "tags": [ + "hulpmiddel", + "encoding", + "ontwikkelaar" + ], + "icon": { + "provider": "selfhst", + "id": "cyberchef" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "cyberchef", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8106, + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/excalidraw/files/compose.yaml b/apps/excalidraw/files/compose.yaml new file mode 100644 index 0000000..e418a85 --- /dev/null +++ b/apps/excalidraw/files/compose.yaml @@ -0,0 +1,9 @@ +services: + << service_name >>: + image: excalidraw/excalidraw:latest + container_name: << service_name >> + ports: + - "<< port >>:80" + environment: + - TZ=<< timezone >> + restart: unless-stopped diff --git a/apps/excalidraw/template.json b/apps/excalidraw/template.json new file mode 100644 index 0000000..97a0a06 --- /dev/null +++ b/apps/excalidraw/template.json @@ -0,0 +1,47 @@ +{ + "kind": "compose", + "metadata": { + "name": "Excalidraw", + "description": "Schetsen en diagrammen tekenen in een handgetekende stijl. Draait volledig in de browser.", + "tags": [ + "tekenen", + "diagram", + "samenwerken" + ], + "icon": { + "provider": "selfhst", + "id": "excalidraw" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "excalidraw", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8101, + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/focalboard/files/compose.yaml b/apps/focalboard/files/compose.yaml new file mode 100644 index 0000000..a9cab86 --- /dev/null +++ b/apps/focalboard/files/compose.yaml @@ -0,0 +1,11 @@ +services: + << service_name >>: + image: mattermost/focalboard:latest + container_name: << service_name >> + ports: + - "<< port >>:8000" + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>:/opt/focalboard/data + restart: unless-stopped diff --git a/apps/focalboard/template.json b/apps/focalboard/template.json new file mode 100644 index 0000000..48c2a90 --- /dev/null +++ b/apps/focalboard/template.json @@ -0,0 +1,54 @@ +{ + "kind": "compose", + "metadata": { + "name": "Focalboard", + "description": "Taken en projecten bijhouden in borden, tabellen en kalenders.", + "tags": [ + "productiviteit", + "taken", + "projecten" + ], + "icon": { + "provider": "selfhst", + "id": "focalboard" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "focalboard", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8102, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/hedgedoc/files/compose.yaml b/apps/hedgedoc/files/compose.yaml new file mode 100644 index 0000000..924350a --- /dev/null +++ b/apps/hedgedoc/files/compose.yaml @@ -0,0 +1,31 @@ +services: + << service_name >>: + image: quay.io/hedgedoc/hedgedoc:latest + container_name: << service_name >> + ports: + - "<< port >>:3000" + environment: + - TZ=<< timezone >> + - CMD_DB_URL=postgres://hedgedoc:<< db_password >>@<< service_name >>-db:5432/hedgedoc + - CMD_DOMAIN=<< app_url >> + - CMD_URL_ADDPORT=false + - CMD_ALLOW_ANONYMOUS=false + volumes: + - << data_dir >>/<< service_name >>/uploads:/hedgedoc/public/uploads + depends_on: + - << service_name >>-db + restart: unless-stopped + + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_USER=hedgedoc + - POSTGRES_PASSWORD=<< db_password >> + - POSTGRES_DB=hedgedoc + volumes: + - << service_name >>_pgdata:/var/lib/postgresql/data + restart: unless-stopped + +volumes: + << service_name >>_pgdata: diff --git a/apps/hedgedoc/template.json b/apps/hedgedoc/template.json new file mode 100644 index 0000000..85acf9f --- /dev/null +++ b/apps/hedgedoc/template.json @@ -0,0 +1,72 @@ +{ + "kind": "compose", + "metadata": { + "name": "HedgeDoc", + "description": "Samen documenten schrijven in Markdown, realtime in de browser.", + "tags": [ + "notities", + "samenwerken", + "markdown" + ], + "icon": { + "provider": "selfhst", + "id": "hedgedoc" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "hedgedoc", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 3011, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "db_password", + "type": "str", + "title": "Database wachtwoord", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "app_url", + "type": "str", + "title": "Basis-URL", + "default": "http://localhost:3010", + "required": true + } + ] + } + ] +} diff --git a/apps/influxdb/files/compose.yaml b/apps/influxdb/files/compose.yaml new file mode 100644 index 0000000..db28bc9 --- /dev/null +++ b/apps/influxdb/files/compose.yaml @@ -0,0 +1,17 @@ +services: + << service_name >>: + image: influxdb:2 + container_name: << service_name >> + ports: + - "<< port >>:8086" + environment: + - TZ=<< timezone >> + - DOCKER_INFLUXDB_INIT_MODE=setup + - DOCKER_INFLUXDB_INIT_USERNAME=<< admin_user >> + - DOCKER_INFLUXDB_INIT_PASSWORD=<< admin_password >> + - DOCKER_INFLUXDB_INIT_ORG=<< org >> + - DOCKER_INFLUXDB_INIT_BUCKET=<< bucket >> + volumes: + - << data_dir >>/<< service_name >>/data:/var/lib/influxdb2 + - << data_dir >>/<< service_name >>/config:/etc/influxdb2 + restart: unless-stopped diff --git a/apps/influxdb/template.json b/apps/influxdb/template.json new file mode 100644 index 0000000..9ba0cdf --- /dev/null +++ b/apps/influxdb/template.json @@ -0,0 +1,86 @@ +{ + "kind": "compose", + "metadata": { + "name": "InfluxDB", + "description": "Tijdreeksdatabase voor meetwaarden van sensoren, servers en Home Assistant.", + "tags": [ + "monitoring", + "database", + "metrics" + ], + "icon": { + "provider": "selfhst", + "id": "influxdb" + }, + "version": { + "name": "2" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "influxdb", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8089, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "org", + "type": "str", + "title": "Organisatie", + "default": "thuis", + "required": true + }, + { + "name": "bucket", + "type": "str", + "title": "Bucket", + "default": "metingen", + "required": true + }, + { + "name": "admin_user", + "type": "str", + "title": "Beheerder", + "default": "admin", + "required": true + }, + { + "name": "admin_password", + "type": "str", + "title": "Beheerderswachtwoord", + "default": "", + "required": true, + "description": "Minimaal 8 tekens", + "config": { + "placeholder": "sterk-wachtwoord" + } + } + ] + } + ] +} diff --git a/apps/karakeep/files/compose.yaml b/apps/karakeep/files/compose.yaml new file mode 100644 index 0000000..1b4b5e0 --- /dev/null +++ b/apps/karakeep/files/compose.yaml @@ -0,0 +1,43 @@ +services: + << service_name >>: + image: ghcr.io/karakeep-app/karakeep:release + container_name: << service_name >> + ports: + - "<< port >>:3000" + environment: + - TZ=<< timezone >> + - NEXTAUTH_SECRET=<< secret >> + - MEILI_ADDR=http://<< service_name >>-meilisearch:7700 + - BROWSER_WEB_URL=http://<< service_name >>-chrome:9222 + - DATA_DIR=/data + - OPENAI_API_KEY=<< openai_key >> + volumes: + - << data_dir >>/<< service_name >>/data:/data + depends_on: + - << service_name >>-meilisearch + - << service_name >>-chrome + restart: unless-stopped + + << service_name >>-chrome: + image: gcr.io/zenika-hub/alpine-chrome:124 + container_name: << service_name >>-chrome + command: + - --no-sandbox + - --disable-gpu + - --disable-dev-shm-usage + - --remote-debugging-address=0.0.0.0 + - --remote-debugging-port=9222 + - --hide-scrollbars + restart: unless-stopped + + << service_name >>-meilisearch: + image: getmeili/meilisearch:v1.41.0 + container_name: << service_name >>-meilisearch + environment: + - MEILI_NO_ANALYTICS=true + volumes: + - << service_name >>_meili:/meili_data + restart: unless-stopped + +volumes: + << service_name >>_meili: diff --git a/apps/karakeep/template.json b/apps/karakeep/template.json new file mode 100644 index 0000000..7eed13e --- /dev/null +++ b/apps/karakeep/template.json @@ -0,0 +1,73 @@ +{ + "kind": "compose", + "metadata": { + "name": "Karakeep", + "description": "Bewaart bladwijzers, artikelen en notities met volledige tekstzoekfunctie. Voorheen Hoarder.", + "tags": [ + "bladwijzers", + "archief", + "lezen" + ], + "icon": { + "provider": "selfhst", + "id": "karakeep" + }, + "version": { + "name": "release" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "karakeep", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 3012, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "secret", + "type": "str", + "title": "Geheime sleutel", + "default": "", + "required": true, + "description": "Willekeurige waarde voor sessies", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "openai_key", + "type": "str", + "title": "OpenAI-sleutel (optioneel)", + "default": "", + "required": false, + "description": "Alleen nodig als je automatisch labels wilt laten toekennen" + } + ] + } + ] +} diff --git a/apps/keycloak/files/compose.yaml b/apps/keycloak/files/compose.yaml new file mode 100644 index 0000000..cbd92eb --- /dev/null +++ b/apps/keycloak/files/compose.yaml @@ -0,0 +1,32 @@ +services: + << service_name >>: + image: quay.io/keycloak/keycloak:latest + container_name: << service_name >> + command: start-dev + ports: + - "<< port >>:8080" + environment: + - TZ=<< timezone >> + - KC_BOOTSTRAP_ADMIN_USERNAME=<< admin_user >> + - KC_BOOTSTRAP_ADMIN_PASSWORD=<< admin_password >> + - KC_DB=postgres + - KC_DB_URL=jdbc:postgresql://<< service_name >>-db:5432/keycloak + - KC_DB_USERNAME=keycloak + - KC_DB_PASSWORD=<< db_password >> + depends_on: + - << service_name >>-db + restart: unless-stopped + + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=keycloak + - POSTGRES_USER=keycloak + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << service_name >>_pgdata:/var/lib/postgresql/data + restart: unless-stopped + +volumes: + << service_name >>_pgdata: diff --git a/apps/keycloak/template.json b/apps/keycloak/template.json new file mode 100644 index 0000000..53b3ea5 --- /dev/null +++ b/apps/keycloak/template.json @@ -0,0 +1,83 @@ +{ + "kind": "compose", + "metadata": { + "name": "Keycloak", + "description": "Volwaardige identiteitsserver met OIDC en SAML, gebruikersbeheer en federatie.", + "tags": [ + "beveiliging", + "sso", + "oidc" + ], + "icon": { + "provider": "selfhst", + "id": "keycloak" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "keycloak", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8103, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "admin_user", + "type": "str", + "title": "Beheerder", + "default": "admin", + "required": true + }, + { + "name": "admin_password", + "type": "str", + "title": "Beheerderswachtwoord", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "db_password", + "type": "str", + "title": "Database wachtwoord", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + } + ] + } + ] +} diff --git a/apps/kimai/files/compose.yaml b/apps/kimai/files/compose.yaml new file mode 100644 index 0000000..6ce5bcb --- /dev/null +++ b/apps/kimai/files/compose.yaml @@ -0,0 +1,32 @@ +services: + << service_name >>: + image: kimai/kimai2:apache + container_name: << service_name >> + ports: + - "<< port >>:8001" + environment: + - TZ=<< timezone >> + - DATABASE_URL=mysql://kimai:<< db_password >>@<< service_name >>-db/kimai?charset=utf8mb4&serverVersion=8.0.0 + - ADMINMAIL=<< admin_email >> + - ADMINPASS=<< admin_password >> + volumes: + - << data_dir >>/<< service_name >>/data:/opt/kimai/var/data + depends_on: + - << service_name >>-db + restart: unless-stopped + + << service_name >>-db: + image: mysql:8 + container_name: << service_name >>-db + command: --default-storage-engine innodb + environment: + - MYSQL_DATABASE=kimai + - MYSQL_USER=kimai + - MYSQL_PASSWORD=<< db_password >> + - MYSQL_ROOT_PASSWORD=<< db_password >> + volumes: + - << service_name >>_dbdata:/var/lib/mysql + restart: unless-stopped + +volumes: + << service_name >>_dbdata: diff --git a/apps/kimai/template.json b/apps/kimai/template.json new file mode 100644 index 0000000..810b4fa --- /dev/null +++ b/apps/kimai/template.json @@ -0,0 +1,83 @@ +{ + "kind": "compose", + "metadata": { + "name": "Kimai", + "description": "Urenregistratie voor projecten en klanten, met rapportages en facturen.", + "tags": [ + "productiviteit", + "uren", + "administratie" + ], + "icon": { + "provider": "selfhst", + "id": "kimai" + }, + "version": { + "name": "apache" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "kimai", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8104, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "db_password", + "type": "str", + "title": "Database wachtwoord", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "admin_email", + "type": "str", + "title": "Beheerder e-mail", + "default": "admin@example.com", + "required": true + }, + { + "name": "admin_password", + "type": "str", + "title": "Beheerderswachtwoord", + "default": "", + "required": true, + "description": "Minimaal 8 tekens", + "config": { + "placeholder": "sterk-wachtwoord" + } + } + ] + } + ] +} diff --git a/apps/komga/files/compose.yaml b/apps/komga/files/compose.yaml new file mode 100644 index 0000000..53340df --- /dev/null +++ b/apps/komga/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: gotson/komga:latest + container_name: << service_name >> + ports: + - "<< port >>:25600" + environment: + - TZ=<< timezone >> + user: "<< puid >>:<< pgid >>" + volumes: + - << data_dir >>/<< service_name >>/config:/config + - << library_dir >>:/data + restart: unless-stopped diff --git a/apps/komga/template.json b/apps/komga/template.json new file mode 100644 index 0000000..c7e98f3 --- /dev/null +++ b/apps/komga/template.json @@ -0,0 +1,76 @@ +{ + "kind": "compose", + "metadata": { + "name": "Komga", + "description": "Server voor strips en manga met leesvoortgang en een ingebouwde lezer.", + "tags": [ + "media", + "strips", + "manga" + ], + "icon": { + "provider": "selfhst", + "id": "komga" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "komga", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 25600, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "puid", + "type": "int", + "title": "Gebruikers-ID (PUID)", + "default": 1000, + "required": true, + "description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host" + }, + { + "name": "pgid", + "type": "int", + "title": "Groeps-ID (PGID)", + "default": 1000, + "required": true + }, + { + "name": "library_dir", + "type": "str", + "title": "Stripboekenmap", + "default": "/opt/serverup/media/comics", + "required": true + } + ] + } + ] +} diff --git a/apps/kopia/files/compose.yaml b/apps/kopia/files/compose.yaml new file mode 100644 index 0000000..edd1877 --- /dev/null +++ b/apps/kopia/files/compose.yaml @@ -0,0 +1,21 @@ +services: + << service_name >>: + image: kopia/kopia:latest + container_name: << service_name >> + command: + - server + - start + - --insecure + - --address=0.0.0.0:51515 + - --server-username=<< ui_user >> + - --server-password=<< ui_password >> + ports: + - "<< port >>:51515" + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/config:/app/config + - << data_dir >>/<< service_name >>/cache:/app/cache + - << source_dir >>:/data:ro + - << repo_dir >>:/repository + restart: unless-stopped diff --git a/apps/kopia/template.json b/apps/kopia/template.json new file mode 100644 index 0000000..8af9d6c --- /dev/null +++ b/apps/kopia/template.json @@ -0,0 +1,86 @@ +{ + "kind": "compose", + "metadata": { + "name": "Kopia", + "description": "Versleutelde back-ups met deduplicatie naar schijf, NAS of cloudopslag.", + "tags": [ + "backup", + "opslag", + "versleuteling" + ], + "icon": { + "provider": "selfhst", + "id": "kopia" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "kopia", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 51515, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "source_dir", + "type": "str", + "title": "Map om te back-uppen", + "default": "/opt/serverup", + "required": true + }, + { + "name": "repo_dir", + "type": "str", + "title": "Repository", + "default": "/opt/serverup/backups/kopia", + "required": true + }, + { + "name": "ui_user", + "type": "str", + "title": "Gebruikersnaam", + "default": "kopia", + "required": true + }, + { + "name": "ui_password", + "type": "str", + "title": "Wachtwoord webinterface", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + } + ] + } + ] +} diff --git a/apps/languagetool/files/compose.yaml b/apps/languagetool/files/compose.yaml new file mode 100644 index 0000000..c746bbb --- /dev/null +++ b/apps/languagetool/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: erikvl87/languagetool:latest + container_name: << service_name >> + ports: + - "<< port >>:8010" + environment: + - TZ=<< timezone >> + - Java_Xms=512m + - Java_Xmx=2g +<%- if ngrams %> + - langtool_languageModel=/ngrams +<%- endif %> + restart: unless-stopped diff --git a/apps/languagetool/template.json b/apps/languagetool/template.json new file mode 100644 index 0000000..bb3a3e8 --- /dev/null +++ b/apps/languagetool/template.json @@ -0,0 +1,54 @@ +{ + "kind": "compose", + "metadata": { + "name": "LanguageTool", + "description": "Spelling- en grammaticacontrole voor tientallen talen, zonder je tekst naar een clouddienst te sturen.", + "tags": [ + "taal", + "schrijven", + "privacy" + ], + "icon": { + "provider": "selfhst", + "id": "languagetool" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "languagetool", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8107, + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "ngrams", + "type": "bool", + "title": "N-gram data gebruiken", + "default": false, + "description": "Betere suggesties, maar vraagt enkele gigabytes aan schijfruimte" + } + ] + } + ] +} diff --git a/apps/memos/files/compose.yaml b/apps/memos/files/compose.yaml new file mode 100644 index 0000000..2124d8f --- /dev/null +++ b/apps/memos/files/compose.yaml @@ -0,0 +1,11 @@ +services: + << service_name >>: + image: neosmemo/memos:stable + container_name: << service_name >> + ports: + - "<< port >>:5230" + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>:/var/opt/memos + restart: unless-stopped diff --git a/apps/memos/template.json b/apps/memos/template.json new file mode 100644 index 0000000..a8f33a2 --- /dev/null +++ b/apps/memos/template.json @@ -0,0 +1,54 @@ +{ + "kind": "compose", + "metadata": { + "name": "Memos", + "description": "Snel gedachten en notities vastleggen in een tijdlijn. Als een privé-microblog.", + "tags": [ + "notities", + "schrijven", + "persoonlijk" + ], + "icon": { + "provider": "selfhst", + "id": "memos" + }, + "version": { + "name": "stable" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "memos", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 5230, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/metabase/files/compose.yaml b/apps/metabase/files/compose.yaml new file mode 100644 index 0000000..96f33c6 --- /dev/null +++ b/apps/metabase/files/compose.yaml @@ -0,0 +1,12 @@ +services: + << service_name >>: + image: metabase/metabase:latest + container_name: << service_name >> + ports: + - "<< port >>:3000" + environment: + - TZ=<< timezone >> + - MB_DB_FILE=/metabase-data/metabase.db + volumes: + - << data_dir >>/<< service_name >>:/metabase-data + restart: unless-stopped diff --git a/apps/metabase/template.json b/apps/metabase/template.json new file mode 100644 index 0000000..f2b739c --- /dev/null +++ b/apps/metabase/template.json @@ -0,0 +1,54 @@ +{ + "kind": "compose", + "metadata": { + "name": "Metabase", + "description": "Vragen stellen aan je databases en de antwoorden als grafiek of dashboard tonen.", + "tags": [ + "dashboard", + "database", + "rapportage" + ], + "icon": { + "provider": "selfhst", + "id": "metabase" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "metabase", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 3013, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/metube/files/compose.yaml b/apps/metube/files/compose.yaml new file mode 100644 index 0000000..8c9e158 --- /dev/null +++ b/apps/metube/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: ghcr.io/alexta69/metube:latest + container_name: << service_name >> + ports: + - "<< port >>:8081" + environment: + - TZ=<< timezone >> + - UID=<< puid >> + - GID=<< pgid >> + volumes: + - << downloads_dir >>:/downloads + restart: unless-stopped diff --git a/apps/metube/template.json b/apps/metube/template.json new file mode 100644 index 0000000..b71eaf9 --- /dev/null +++ b/apps/metube/template.json @@ -0,0 +1,76 @@ +{ + "kind": "compose", + "metadata": { + "name": "MeTube", + "description": "Video's van YouTube en honderden andere sites downloaden via een webformulier.", + "tags": [ + "media", + "downloaden", + "video" + ], + "icon": { + "provider": "selfhst", + "id": "metube" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "metube", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8105, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "puid", + "type": "int", + "title": "Gebruikers-ID (PUID)", + "default": 1000, + "required": true, + "description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host" + }, + { + "name": "pgid", + "type": "int", + "title": "Groeps-ID (PGID)", + "default": 1000, + "required": true + }, + { + "name": "downloads_dir", + "type": "str", + "title": "Downloadmap", + "default": "/opt/serverup/media/downloads", + "required": true + } + ] + } + ] +} diff --git a/apps/netdata/files/compose.yaml b/apps/netdata/files/compose.yaml new file mode 100644 index 0000000..d33c8c3 --- /dev/null +++ b/apps/netdata/files/compose.yaml @@ -0,0 +1,30 @@ +services: + << service_name >>: + image: netdata/netdata:stable + container_name: << service_name >> + hostname: << service_name >> + ports: + - "<< port >>:19999" + environment: + - TZ=<< timezone >> + cap_add: + - SYS_PTRACE + - SYS_ADMIN + security_opt: + - apparmor:unconfined + volumes: + - << service_name >>_config:/etc/netdata + - << service_name >>_lib:/var/lib/netdata + - << service_name >>_cache:/var/cache/netdata + - /etc/passwd:/host/etc/passwd:ro + - /etc/group:/host/etc/group:ro + - /proc:/host/proc:ro + - /sys:/host/sys:ro + - /etc/os-release:/host/etc/os-release:ro + - /var/run/docker.sock:/var/run/docker.sock:ro + restart: unless-stopped + +volumes: + << service_name >>_config: + << service_name >>_lib: + << service_name >>_cache: diff --git a/apps/netdata/template.json b/apps/netdata/template.json new file mode 100644 index 0000000..42f7c5e --- /dev/null +++ b/apps/netdata/template.json @@ -0,0 +1,47 @@ +{ + "kind": "compose", + "metadata": { + "name": "Netdata", + "description": "Realtime overzicht van processor, geheugen, schijven en containers, met alarmen.", + "tags": [ + "monitoring", + "systeem", + "realtime" + ], + "icon": { + "provider": "selfhst", + "id": "netdata" + }, + "version": { + "name": "stable" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "netdata", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 19999, + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/nocodb/files/compose.yaml b/apps/nocodb/files/compose.yaml new file mode 100644 index 0000000..a932eed --- /dev/null +++ b/apps/nocodb/files/compose.yaml @@ -0,0 +1,11 @@ +services: + << service_name >>: + image: nocodb/nocodb:latest + container_name: << service_name >> + ports: + - "<< port >>:8080" + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>:/usr/app/data + restart: unless-stopped diff --git a/apps/nocodb/template.json b/apps/nocodb/template.json new file mode 100644 index 0000000..af57740 --- /dev/null +++ b/apps/nocodb/template.json @@ -0,0 +1,54 @@ +{ + "kind": "compose", + "metadata": { + "name": "NocoDB", + "description": "Verandert een database in een spreadsheet-achtige werkomgeving. Open alternatief voor Airtable.", + "tags": [ + "database", + "spreadsheet", + "no-code" + ], + "icon": { + "provider": "selfhst", + "id": "nocodb" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "nocodb", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8108, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/ntfy/files/compose.yaml b/apps/ntfy/files/compose.yaml new file mode 100644 index 0000000..72c995f --- /dev/null +++ b/apps/ntfy/files/compose.yaml @@ -0,0 +1,17 @@ +services: + << service_name >>: + image: binwiederhier/ntfy:latest + container_name: << service_name >> + command: serve + ports: + - "<< port >>:80" + environment: + - TZ=<< timezone >> + - NTFY_BASE_URL=<< base_url >> + - NTFY_BEHIND_PROXY=true + - NTFY_AUTH_FILE=/var/lib/ntfy/user.db + - NTFY_AUTH_DEFAULT_ACCESS=<< auth_default >> + - NTFY_CACHE_FILE=/var/lib/ntfy/cache.db + volumes: + - << data_dir >>/<< service_name >>:/var/lib/ntfy + restart: unless-stopped diff --git a/apps/ntfy/template.json b/apps/ntfy/template.json new file mode 100644 index 0000000..f0efcb1 --- /dev/null +++ b/apps/ntfy/template.json @@ -0,0 +1,76 @@ +{ + "kind": "compose", + "metadata": { + "name": "ntfy", + "description": "Meldingen naar je telefoon sturen vanuit scripts en apps, met één HTTP-verzoek.", + "tags": [ + "meldingen", + "push", + "automatisering" + ], + "icon": { + "provider": "selfhst", + "id": "ntfy" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "ntfy", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8109, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "base_url", + "type": "str", + "title": "Basis-URL", + "default": "http://localhost:8101", + "required": true + }, + { + "name": "auth_default", + "type": "enum", + "title": "Standaardtoegang", + "default": "deny-all", + "required": true, + "description": "deny-all vereist een account voor elk onderwerp", + "config": { + "options": [ + "deny-all", + "read-only", + "read-write" + ] + } + } + ] + } + ] +} diff --git a/apps/ollama/files/compose.yaml b/apps/ollama/files/compose.yaml new file mode 100644 index 0000000..1d7955d --- /dev/null +++ b/apps/ollama/files/compose.yaml @@ -0,0 +1,20 @@ +services: + << service_name >>: + image: ollama/ollama:latest + container_name: << service_name >> + ports: + - "<< port >>:11434" + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>:/root/.ollama +<%- if gpu %> + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: all + capabilities: [gpu] +<%- endif %> + restart: unless-stopped diff --git a/apps/ollama/template.json b/apps/ollama/template.json new file mode 100644 index 0000000..ac72758 --- /dev/null +++ b/apps/ollama/template.json @@ -0,0 +1,61 @@ +{ + "kind": "compose", + "metadata": { + "name": "Ollama", + "description": "Draait taalmodellen lokaal op je eigen hardware. Geen gegevens naar buiten.", + "tags": [ + "ai", + "llm", + "privacy" + ], + "icon": { + "provider": "selfhst", + "id": "ollama" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "ollama", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 11434, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "gpu", + "type": "bool", + "title": "NVIDIA-GPU gebruiken", + "default": false, + "description": "Vereist de NVIDIA Container Toolkit op de host" + } + ] + } + ] +} diff --git a/apps/open-webui/files/compose.yaml b/apps/open-webui/files/compose.yaml new file mode 100644 index 0000000..2a995c9 --- /dev/null +++ b/apps/open-webui/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: ghcr.io/open-webui/open-webui:main + container_name: << service_name >> + ports: + - "<< port >>:8080" + environment: + - TZ=<< timezone >> + - OLLAMA_BASE_URL=<< ollama_url >> + - WEBUI_SECRET_KEY=<< secret_key >> + volumes: + - << data_dir >>/<< service_name >>:/app/backend/data + restart: unless-stopped diff --git a/apps/open-webui/template.json b/apps/open-webui/template.json new file mode 100644 index 0000000..ab1d747 --- /dev/null +++ b/apps/open-webui/template.json @@ -0,0 +1,73 @@ +{ + "kind": "compose", + "metadata": { + "name": "Open WebUI", + "description": "Chatinterface voor Ollama en andere modellen, met gesprekken, documenten en gebruikers.", + "tags": [ + "ai", + "llm", + "chat" + ], + "icon": { + "provider": "selfhst", + "id": "open-webui" + }, + "version": { + "name": "main" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "open-webui", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8110, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "ollama_url", + "type": "str", + "title": "Ollama-adres", + "default": "http://ollama:11434", + "required": true, + "description": "Wijs naar je Ollama-container of een adres in je netwerk" + }, + { + "name": "secret_key", + "type": "str", + "title": "Geheime sleutel", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + } + ] + } + ] +} diff --git a/apps/owntracks/files/compose.yaml b/apps/owntracks/files/compose.yaml new file mode 100644 index 0000000..124fe72 --- /dev/null +++ b/apps/owntracks/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: owntracks/recorder:latest + container_name: << service_name >> + ports: + - "<< port >>:8083" + environment: + - TZ=<< timezone >> + - OTR_PORT=0 + volumes: + - << data_dir >>/<< service_name >>/store:/store + - << data_dir >>/<< service_name >>/config:/config + restart: unless-stopped diff --git a/apps/owntracks/template.json b/apps/owntracks/template.json new file mode 100644 index 0000000..ba6b6f4 --- /dev/null +++ b/apps/owntracks/template.json @@ -0,0 +1,54 @@ +{ + "kind": "compose", + "metadata": { + "name": "OwnTracks Recorder", + "description": "Slaat je eigen locatiegeschiedenis op, zonder dat die bij een clouddienst belandt.", + "tags": [ + "locatie", + "privacy", + "logboek" + ], + "icon": { + "provider": "selfhst", + "id": "owntracks" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "owntracks", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8111, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/photoprism/files/compose.yaml b/apps/photoprism/files/compose.yaml new file mode 100644 index 0000000..75f1e2e --- /dev/null +++ b/apps/photoprism/files/compose.yaml @@ -0,0 +1,38 @@ +services: + << service_name >>: + image: photoprism/photoprism:latest + container_name: << service_name >> + ports: + - "<< port >>:2342" + environment: + - TZ=<< timezone >> + - PHOTOPRISM_ADMIN_PASSWORD=<< admin_password >> + - PHOTOPRISM_ORIGINALS_LIMIT=5000 + - PHOTOPRISM_DATABASE_DRIVER=mysql + - PHOTOPRISM_DATABASE_SERVER=<< service_name >>-db:3306 + - PHOTOPRISM_DATABASE_NAME=photoprism + - PHOTOPRISM_DATABASE_USER=photoprism + - PHOTOPRISM_DATABASE_PASSWORD=<< db_password >> + volumes: + - << photos_dir >>:/photoprism/originals + - << data_dir >>/<< service_name >>/storage:/photoprism/storage + depends_on: + - << service_name >>-db + restart: unless-stopped + + << service_name >>-db: + image: mariadb:11 + container_name: << service_name >>-db + command: --innodb-buffer-pool-size=512M --transaction-isolation=READ-COMMITTED + environment: + - MARIADB_AUTO_UPGRADE=1 + - MARIADB_DATABASE=photoprism + - MARIADB_USER=photoprism + - MARIADB_PASSWORD=<< db_password >> + - MARIADB_ROOT_PASSWORD=<< db_password >> + volumes: + - << service_name >>_dbdata:/var/lib/mysql + restart: unless-stopped + +volumes: + << service_name >>_dbdata: diff --git a/apps/photoprism/template.json b/apps/photoprism/template.json new file mode 100644 index 0000000..304bf09 --- /dev/null +++ b/apps/photoprism/template.json @@ -0,0 +1,83 @@ +{ + "kind": "compose", + "metadata": { + "name": "PhotoPrism", + "description": "Fotobeheer met gezichtsherkenning en zoeken op inhoud, volledig lokaal.", + "tags": [ + "fotos", + "media", + "ai" + ], + "icon": { + "provider": "selfhst", + "id": "photoprism" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "photoprism", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 2342, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "photos_dir", + "type": "str", + "title": "Fotomap", + "default": "/opt/serverup/media/photos", + "required": true + }, + { + "name": "admin_password", + "type": "str", + "title": "Beheerderswachtwoord", + "default": "", + "required": true, + "description": "Minimaal 8 tekens", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "db_password", + "type": "str", + "title": "Database wachtwoord", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + } + ] + } + ] +} diff --git a/apps/pinchflat/files/compose.yaml b/apps/pinchflat/files/compose.yaml new file mode 100644 index 0000000..4ad97b9 --- /dev/null +++ b/apps/pinchflat/files/compose.yaml @@ -0,0 +1,12 @@ +services: + << service_name >>: + image: ghcr.io/kieraneglin/pinchflat:latest + container_name: << service_name >> + ports: + - "<< port >>:8945" + environment: + - TZ=<< timezone >> + volumes: + - << data_dir >>/<< service_name >>/config:/config + - << downloads_dir >>:/downloads + restart: unless-stopped diff --git a/apps/pinchflat/template.json b/apps/pinchflat/template.json new file mode 100644 index 0000000..88f31d3 --- /dev/null +++ b/apps/pinchflat/template.json @@ -0,0 +1,61 @@ +{ + "kind": "compose", + "metadata": { + "name": "Pinchflat", + "description": "Archiveert YouTube-kanalen automatisch naar een nette mediabibliotheek voor Jellyfin of Plex.", + "tags": [ + "media", + "video", + "archief" + ], + "icon": { + "provider": "selfhst", + "id": "pinchflat" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "pinchflat", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8945, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "downloads_dir", + "type": "str", + "title": "Mediamap", + "default": "/opt/serverup/media/youtube", + "required": true + } + ] + } + ] +} diff --git a/apps/planka/files/compose.yaml b/apps/planka/files/compose.yaml new file mode 100644 index 0000000..8e206c4 --- /dev/null +++ b/apps/planka/files/compose.yaml @@ -0,0 +1,35 @@ +services: + << service_name >>: + image: ghcr.io/plankanban/planka:1 + container_name: << service_name >> + ports: + - "<< port >>:1337" + environment: + - TZ=<< timezone >> + - BASE_URL=<< base_url >> + - DATABASE_URL=postgresql://planka:<< db_password >>@<< service_name >>-db/planka + - SECRET_KEY=<< secret_key >> + - DEFAULT_ADMIN_EMAIL=<< admin_email >> + - DEFAULT_ADMIN_PASSWORD=<< admin_password >> + - DEFAULT_ADMIN_NAME=Beheerder + - DEFAULT_ADMIN_USERNAME=beheerder + volumes: + - << data_dir >>/<< service_name >>/avatars:/app/public/user-avatars + - << data_dir >>/<< service_name >>/attachments:/app/private/attachments + depends_on: + - << service_name >>-db + restart: unless-stopped + + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=planka + - POSTGRES_USER=planka + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << service_name >>_pgdata:/var/lib/postgresql/data + restart: unless-stopped + +volumes: + << service_name >>_pgdata: diff --git a/apps/planka/template.json b/apps/planka/template.json new file mode 100644 index 0000000..807a137 --- /dev/null +++ b/apps/planka/template.json @@ -0,0 +1,101 @@ +{ + "kind": "compose", + "metadata": { + "name": "Planka", + "description": "Kanban-borden voor projecten en klussen. Open alternatief voor Trello.", + "tags": [ + "productiviteit", + "kanban", + "projecten" + ], + "icon": { + "provider": "selfhst", + "id": "planka" + }, + "version": { + "name": "1" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "planka", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 1337, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "db_password", + "type": "str", + "title": "Database wachtwoord", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "secret_key", + "type": "str", + "title": "Geheime sleutel", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "base_url", + "type": "str", + "title": "Basis-URL", + "default": "http://localhost:1337", + "required": true + }, + { + "name": "admin_email", + "type": "str", + "title": "Beheerder e-mail", + "default": "admin@example.com", + "required": true + }, + { + "name": "admin_password", + "type": "str", + "title": "Beheerderswachtwoord", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + } + ] + } + ] +} diff --git a/apps/prometheus/files/compose.yaml b/apps/prometheus/files/compose.yaml new file mode 100644 index 0000000..44b4868 --- /dev/null +++ b/apps/prometheus/files/compose.yaml @@ -0,0 +1,16 @@ +services: + << service_name >>: + image: prom/prometheus:latest + container_name: << service_name >> + ports: + - "<< port >>:9090" + command: + - --config.file=/etc/prometheus/prometheus.yml + - --storage.tsdb.retention.time=<< retention >> + volumes: + - << data_dir >>/<< service_name >>/config:/etc/prometheus + - << service_name >>_data:/prometheus + restart: unless-stopped + +volumes: + << service_name >>_data: diff --git a/apps/prometheus/template.json b/apps/prometheus/template.json new file mode 100644 index 0000000..df0986f --- /dev/null +++ b/apps/prometheus/template.json @@ -0,0 +1,62 @@ +{ + "kind": "compose", + "metadata": { + "name": "Prometheus", + "description": "Verzamelt en bewaart meetwaarden van je servers en diensten. De gebruikelijke tegenhanger van Grafana.", + "tags": [ + "monitoring", + "metrics", + "infrastructuur" + ], + "icon": { + "provider": "selfhst", + "id": "prometheus" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "prometheus", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 9092, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "retention", + "type": "str", + "title": "Bewaartermijn", + "default": "30d", + "required": true, + "description": "Hoe lang meetwaarden bewaard blijven, bv. 30d of 1y" + } + ] + } + ] +} diff --git a/apps/shlink/files/compose.yaml b/apps/shlink/files/compose.yaml new file mode 100644 index 0000000..a79491e --- /dev/null +++ b/apps/shlink/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: shlinkio/shlink:stable + container_name: << service_name >> + ports: + - "<< port >>:8080" + environment: + - TZ=<< timezone >> + - DEFAULT_DOMAIN=<< domain >> + - IS_HTTPS_ENABLED=false + - INITIAL_API_KEY=<< api_key >> + volumes: + - << data_dir >>/<< service_name >>:/etc/shlink/data + restart: unless-stopped diff --git a/apps/shlink/template.json b/apps/shlink/template.json new file mode 100644 index 0000000..829537a --- /dev/null +++ b/apps/shlink/template.json @@ -0,0 +1,73 @@ +{ + "kind": "compose", + "metadata": { + "name": "Shlink", + "description": "Eigen URL-verkorter met statistieken en QR-codes.", + "tags": [ + "netwerk", + "links", + "statistiek" + ], + "icon": { + "provider": "selfhst", + "id": "shlink" + }, + "version": { + "name": "stable" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "shlink", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 8112, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "domain", + "type": "str", + "title": "Domein", + "default": "links.example.com", + "required": true, + "description": "Het domein waarop je verkorte links uitkomen" + }, + { + "name": "api_key", + "type": "str", + "title": "Initiële API-sleutel", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + } + ] + } + ] +} diff --git a/apps/teslamate/files/compose.yaml b/apps/teslamate/files/compose.yaml new file mode 100644 index 0000000..daebe0e --- /dev/null +++ b/apps/teslamate/files/compose.yaml @@ -0,0 +1,56 @@ +services: + << service_name >>: + image: teslamate/teslamate:latest + container_name: << service_name >> + ports: + - "<< port >>:4000" + environment: + - TZ=<< timezone >> + - DATABASE_USER=teslamate + - DATABASE_PASS=<< db_password >> + - DATABASE_NAME=teslamate + - DATABASE_HOST=<< service_name >>-db + - MQTT_HOST=<< service_name >>-mosquitto + - ENCRYPTION_KEY=<< encryption_key >> + depends_on: + - << service_name >>-db + - << service_name >>-mosquitto + restart: unless-stopped + + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_USER=teslamate + - POSTGRES_PASSWORD=<< db_password >> + - POSTGRES_DB=teslamate + volumes: + - << service_name >>_pgdata:/var/lib/postgresql/data + restart: unless-stopped + + << service_name >>-grafana: + image: teslamate/grafana:latest + container_name: << service_name >>-grafana + ports: + - "<< grafana_port >>:3000" + environment: + - DATABASE_USER=teslamate + - DATABASE_PASS=<< db_password >> + - DATABASE_NAME=teslamate + - DATABASE_HOST=<< service_name >>-db + volumes: + - << service_name >>_grafana:/var/lib/grafana + restart: unless-stopped + + << service_name >>-mosquitto: + image: eclipse-mosquitto:2 + container_name: << service_name >>-mosquitto + command: mosquitto -c /mosquitto-no-auth.conf + volumes: + - << service_name >>_mqtt:/mosquitto/data + restart: unless-stopped + +volumes: + << service_name >>_pgdata: + << service_name >>_grafana: + << service_name >>_mqtt: diff --git a/apps/teslamate/template.json b/apps/teslamate/template.json new file mode 100644 index 0000000..f6cd413 --- /dev/null +++ b/apps/teslamate/template.json @@ -0,0 +1,83 @@ +{ + "kind": "compose", + "metadata": { + "name": "TeslaMate", + "description": "Registreert ritten, laadsessies en accugezondheid van je Tesla, met dashboards in Grafana.", + "tags": [ + "auto", + "logboek", + "dashboard" + ], + "icon": { + "provider": "selfhst", + "id": "teslamate" + }, + "version": { + "name": "latest" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "teslamate", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 4000, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "db_password", + "type": "str", + "title": "Database wachtwoord", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "encryption_key", + "type": "str", + "title": "Versleutelingssleutel", + "default": "", + "required": true, + "description": "Beschermt je Tesla-token", + "config": { + "placeholder": "sterk-wachtwoord" + } + }, + { + "name": "grafana_port", + "type": "int", + "title": "Grafana poort", + "default": 3014, + "required": true + } + ] + } + ] +} diff --git a/apps/wikijs/files/compose.yaml b/apps/wikijs/files/compose.yaml new file mode 100644 index 0000000..0a57aea --- /dev/null +++ b/apps/wikijs/files/compose.yaml @@ -0,0 +1,33 @@ +services: + << service_name >>: + image: ghcr.io/requarks/wiki:2 + container_name: << service_name >> + ports: + - "<< port >>:3000" + environment: + - TZ=<< timezone >> + - DB_TYPE=postgres + - DB_HOST=<< service_name >>-db + - DB_PORT=5432 + - DB_USER=wikijs + - DB_PASS=<< db_password >> + - DB_NAME=wiki + volumes: + - << data_dir >>/<< service_name >>/content:/wiki/data/content + depends_on: + - << service_name >>-db + restart: unless-stopped + + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_USER=wikijs + - POSTGRES_PASSWORD=<< db_password >> + - POSTGRES_DB=wiki + volumes: + - << service_name >>_pgdata:/var/lib/postgresql/data + restart: unless-stopped + +volumes: + << service_name >>_pgdata: diff --git a/apps/wikijs/template.json b/apps/wikijs/template.json new file mode 100644 index 0000000..9ab301f --- /dev/null +++ b/apps/wikijs/template.json @@ -0,0 +1,65 @@ +{ + "kind": "compose", + "metadata": { + "name": "Wiki.js", + "description": "Moderne wiki met een visuele editor, toegangsrechten per pagina en zoekfunctie.", + "tags": [ + "documentatie", + "wiki", + "kennis" + ], + "icon": { + "provider": "selfhst", + "id": "wikijs" + }, + "version": { + "name": "2" + } + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "wikijs", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Web poort", + "default": 3015, + "required": true + }, + { + "name": "data_dir", + "type": "str", + "title": "Data directory", + "default": "/opt/serverup/appdata", + "required": true + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + }, + { + "name": "db_password", + "type": "str", + "title": "Database wachtwoord", + "default": "", + "required": true, + "description": "Gebruik de dobbelsteenknop voor een willekeurige waarde", + "config": { + "placeholder": "sterk-wachtwoord" + } + } + ] + } + ] +} diff --git a/tests/test_apps.py b/tests/test_apps.py index 60c8120..e6ad48e 100644 --- a/tests/test_apps.py +++ b/tests/test_apps.py @@ -89,8 +89,8 @@ def test_geen_onvervangen_variabelen(app): # Poorten die meerdere apps bewust delen: alternatieven voor dezelfde taak, # die je nooit tegelijk draait. Alles daarbuiten hoort uniek te zijn. GEDEELDE_POORTEN = { - 80: {"nginx-proxy-manager", "traefik"}, # reverse proxies - 443: {"nginx-proxy-manager", "traefik"}, + 80: {"nginx-proxy-manager", "traefik", "caddy"}, # reverse proxies + 443: {"nginx-proxy-manager", "traefik", "caddy"}, 53: {"adguard-home", "pihole"}, # dns-blokkers 5055: {"arr-stack", "jellyseerr"}, # zelfde app 6881: {"arr-stack", "qbittorrent"}, # zelfde app