v0.6.00-beta - 29 apps erbij, en named volumes die verdwenen
All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 1m5s
All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 1m5s
Bij het toevoegen van de apps kwam een bestaande fout boven water. _drop_empty_mappings ruimt sleutels op die een <% if %>-blok leeg achterlaat, maar een named volume wordt gedeclareerd als een kale sleutel zonder waarde (` immich_pgdata:`). Die werd opgeruimd, waarna ook het bovenliggende `volumes:` wegviel en de services verwezen naar een volume dat nergens meer gedeclareerd stond. Immich, Ghost, Miniflux, Paperless-ngx, Unifi Network en Vikunja waren daardoor niet installeerbaar: docker compose weigert met "refers to undefined volume". Alleen bekende compose-sleutels worden nu opgeruimd. 29 nieuwe apps (teller op 65): - Domotica: zigbee2mqtt, mosquitto, esphome, node-red, zwave-js-ui, homebridge, scrypted, frigate - 3D-printen: bambuddy, octoprint, spoolman - Gezin/huishouden: baby-buddy, grocy, tandoor, firefly-iii - Media: audiobookshelf, navidrome, kavita, calibre-web, jellyseerr - Kennis: bookstack, freshrss, wallabag - Netwerk/beheer: wg-easy, homepage, searxng, duplicati, watchtower, technitium-dns Nieuwe tests/test_apps.py rendert elke app met de echte engine en controleert geldige YAML, image of build per service, gedeclareerde named volumes, geen onvervangen variabelen en geen onbedoeld dubbele standaardpoorten. Die laatste vond zeven botsingen tussen nieuwe en bestaande apps; rechtgezet. Logische botsingen (reverse proxies op 80/443, dns-blokkers op 53) staan met uitleg in een allowlist. Het image van Bambuddy is nagetrokken op de bron (github.com/maziggy/bambuddy): ghcr.io/maziggy/bambuddy, poort 8000. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb
This commit is contained in:
parent
7f0d34cb1a
commit
b8c8e89fa0
63 changed files with 2656 additions and 3 deletions
53
CHANGELOG.md
53
CHANGELOG.md
|
|
@ -1,3 +1,56 @@
|
||||||
|
# v0.6.00-beta — 29 apps erbij, en een bug die zes bestaande apps onstartbaar maakte
|
||||||
|
|
||||||
|
## 🐛 Named volumes verdwenen uit het compose-bestand
|
||||||
|
|
||||||
|
Bij het bouwen van de nieuwe apps liep ik tegen iets aan dat er al langer zat.
|
||||||
|
`_drop_empty_mappings` ruimt sleutels op die een `<% if %>`-blok leeg
|
||||||
|
achterlaat. Maar een named volume wordt gedeclareerd als een kale sleutel zonder
|
||||||
|
waarde:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
volumes:
|
||||||
|
immich_pgdata:
|
||||||
|
```
|
||||||
|
|
||||||
|
Die werd als "lege mapping" opgeruimd, waarna ook het bovenliggende `volumes:`
|
||||||
|
wegviel. De services verwezen vervolgens naar een volume dat nergens meer
|
||||||
|
gedeclareerd stond, en `docker compose up` weigert dat met *"refers to undefined
|
||||||
|
volume"*.
|
||||||
|
|
||||||
|
**Immich, Ghost, Miniflux, Paperless-ngx, Unifi Network en Vikunja waren
|
||||||
|
daardoor niet installeerbaar via Server Up.** Alleen bekende compose-sleutels
|
||||||
|
worden nu opgeruimd; een volumedeclaratie blijft staan.
|
||||||
|
|
||||||
|
## 📦 29 nieuwe apps
|
||||||
|
|
||||||
|
**Domotica** — Zigbee2MQTT, Mosquitto MQTT, ESPHome, Node-RED, Z-Wave JS UI,
|
||||||
|
Homebridge, Scrypted, Frigate NVR
|
||||||
|
|
||||||
|
**3D-printen** — Bambuddy (Bambu Lab, zonder cloud), OctoPrint, Spoolman
|
||||||
|
|
||||||
|
**Gezin en huishouden** — Baby Buddy, Grocy, Tandoor Recipes, Firefly III
|
||||||
|
|
||||||
|
**Media** — Audiobookshelf, Navidrome, Kavita, Calibre-Web, Jellyseerr
|
||||||
|
|
||||||
|
**Kennis** — BookStack, FreshRSS, Wallabag
|
||||||
|
|
||||||
|
**Netwerk en beheer** — WireGuard Easy, Homepage, SearXNG, Duplicati,
|
||||||
|
Watchtower, Technitium DNS
|
||||||
|
|
||||||
|
Daarmee staat de teller op 65 apps.
|
||||||
|
|
||||||
|
## ✅ Testsuite over de echte templates
|
||||||
|
|
||||||
|
Nieuwe `tests/test_apps.py` rendert **elke** app met de echte engine en
|
||||||
|
controleert de uitkomst: geldige YAML, elke service heeft een image of build,
|
||||||
|
named volumes zijn gedeclareerd, geen onvervangen `<< variabelen >>`, en geen
|
||||||
|
onbedoeld dubbele standaardpoorten. Die laatste vond zeven botsingen tussen de
|
||||||
|
nieuwe apps en bestaande; die zijn rechtgezet. Botsingen die logisch zijn
|
||||||
|
(Traefik en Nginx Proxy Manager op 80/443, AdGuard en Pi-hole op 53) staan met
|
||||||
|
uitleg in een allowlist.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# v0.5.50-beta — Containers die nergens te vinden waren
|
# v0.5.50-beta — Containers die nergens te vinden waren
|
||||||
|
|
||||||
Het dashboard meldde 13 actieve containers en 17 images, terwijl je die nergens
|
Het dashboard meldde 13 actieve containers en 17 images, terwijl je die nergens
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.5.50-beta
|
0.6.00-beta
|
||||||
|
|
|
||||||
13
apps/audiobookshelf/files/compose.yaml
Normal file
13
apps/audiobookshelf/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/advplyr/audiobookshelf:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:80"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
volumes:
|
||||||
|
- << media_dir >>:/audiobooks
|
||||||
|
- << data_dir >>/<< service_name >>/config:/config
|
||||||
|
- << data_dir >>/<< service_name >>/metadata:/metadata
|
||||||
|
restart: unless-stopped
|
||||||
61
apps/audiobookshelf/template.json
Normal file
61
apps/audiobookshelf/template.json
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Audiobookshelf",
|
||||||
|
"description": "Server voor luisterboeken en podcasts, met apps voor iOS en Android die je voortgang bijhouden.",
|
||||||
|
"tags": [
|
||||||
|
"media",
|
||||||
|
"luisterboeken",
|
||||||
|
"podcast"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "audiobookshelf"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "audiobookshelf",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 13378,
|
||||||
|
"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": "media_dir",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Map met luisterboeken",
|
||||||
|
"default": "/opt/serverup/media/audiobooks",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
16
apps/baby-buddy/files/compose.yaml
Normal file
16
apps/baby-buddy/files/compose.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/babybuddy/babybuddy:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8000"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- PUID=<< puid >>
|
||||||
|
- PGID=<< pgid >>
|
||||||
|
- SECRET_KEY=<< secret_key >>
|
||||||
|
- ALLOWED_HOSTS=<< allowed_hosts >>
|
||||||
|
- CSRF_TRUSTED_ORIGINS=http://<< allowed_hosts >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/app/data
|
||||||
|
restart: unless-stopped
|
||||||
88
apps/baby-buddy/template.json
Normal file
88
apps/baby-buddy/template.json
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Baby Buddy",
|
||||||
|
"description": "Houdt voedingen, slaap, luiers en groei van je kind bij. Handig om het overzicht te bewaren in de eerste maanden.",
|
||||||
|
"tags": [
|
||||||
|
"gezin",
|
||||||
|
"gezondheid",
|
||||||
|
"logboek"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "baby-buddy"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "baby-buddy",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8000,
|
||||||
|
"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": "secret_key",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Geheime sleutel",
|
||||||
|
"default": "",
|
||||||
|
"required": true,
|
||||||
|
"description": "Willekeurige waarde voor sessieversleuteling; gebruik de dobbelsteenknop",
|
||||||
|
"config": {
|
||||||
|
"placeholder": "willekeurige-lange-string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "allowed_hosts",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Toegestane hostnamen",
|
||||||
|
"default": "*",
|
||||||
|
"required": true,
|
||||||
|
"description": "Bijvoorbeeld babybuddy.thuis.nl; * staat alles toe"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
18
apps/bambuddy/files/compose.yaml
Normal file
18
apps/bambuddy/files/compose.yaml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/maziggy/bambuddy:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8000"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- PUID=<< puid >>
|
||||||
|
- PGID=<< pgid >>
|
||||||
|
- PORT=8000
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/data:/app/data
|
||||||
|
- << data_dir >>/<< service_name >>/logs:/app/logs
|
||||||
|
cap_add:
|
||||||
|
- NET_BIND_SERVICE
|
||||||
|
stop_grace_period: 30s
|
||||||
|
restart: unless-stopped
|
||||||
69
apps/bambuddy/template.json
Normal file
69
apps/bambuddy/template.json
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Bambuddy",
|
||||||
|
"description": "Zelfgehost bedieningspaneel voor Bambu Lab-printers, van één A1 tot een hele printerfarm. Zonder cloud.",
|
||||||
|
"tags": [
|
||||||
|
"3d-printen",
|
||||||
|
"bambu-lab",
|
||||||
|
"printerbeheer"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "bambuddy"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "bambuddy",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8011,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
36
apps/bookstack/files/compose.yaml
Normal file
36
apps/bookstack/files/compose.yaml
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: lscr.io/linuxserver/bookstack:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:80"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- PUID=<< puid >>
|
||||||
|
- PGID=<< pgid >>
|
||||||
|
- APP_URL=<< app_url >>
|
||||||
|
- DB_HOST=<< service_name >>-db
|
||||||
|
- DB_PORT=3306
|
||||||
|
- DB_USERNAME=bookstack
|
||||||
|
- DB_PASSWORD=<< db_password >>
|
||||||
|
- DB_DATABASE=bookstack
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/config
|
||||||
|
depends_on:
|
||||||
|
- << service_name >>-db
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
<< service_name >>-db:
|
||||||
|
image: lscr.io/linuxserver/mariadb:latest
|
||||||
|
container_name: << service_name >>-db
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- PUID=<< puid >>
|
||||||
|
- PGID=<< pgid >>
|
||||||
|
- MYSQL_ROOT_PASSWORD=<< db_password >>
|
||||||
|
- MYSQL_DATABASE=bookstack
|
||||||
|
- MYSQL_USER=bookstack
|
||||||
|
- MYSQL_PASSWORD=<< db_password >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/db:/config
|
||||||
|
restart: unless-stopped
|
||||||
88
apps/bookstack/template.json
Normal file
88
apps/bookstack/template.json
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "BookStack",
|
||||||
|
"description": "Wiki voor documentatie, geordend in boeken, hoofdstukken en pagina's. Prettig voor handleidingen thuis.",
|
||||||
|
"tags": [
|
||||||
|
"documentatie",
|
||||||
|
"wiki",
|
||||||
|
"kennis"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "bookstack"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "bookstack",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 6875,
|
||||||
|
"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": "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:6875",
|
||||||
|
"required": true,
|
||||||
|
"description": "Het adres waarop je BookStack benadert; links kloppen anders niet"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
14
apps/calibre-web/files/compose.yaml
Normal file
14
apps/calibre-web/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: lscr.io/linuxserver/calibre-web:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8083"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- PUID=<< puid >>
|
||||||
|
- PGID=<< pgid >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/config
|
||||||
|
- << books_dir >>:/books
|
||||||
|
restart: unless-stopped
|
||||||
77
apps/calibre-web/template.json
Normal file
77
apps/calibre-web/template.json
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Calibre-Web",
|
||||||
|
"description": "Webinterface voor je Calibre-bibliotheek: bladeren, lezen en naar je e-reader sturen.",
|
||||||
|
"tags": [
|
||||||
|
"media",
|
||||||
|
"boeken",
|
||||||
|
"ebooks"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "calibre-web"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "calibre-web",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8083,
|
||||||
|
"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": "books_dir",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Calibre-bibliotheek",
|
||||||
|
"default": "/opt/serverup/media/books",
|
||||||
|
"required": true,
|
||||||
|
"description": "Map met je bestaande metadata.db van Calibre"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
15
apps/duplicati/files/compose.yaml
Normal file
15
apps/duplicati/files/compose.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: lscr.io/linuxserver/duplicati:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8200"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- PUID=<< puid >>
|
||||||
|
- PGID=<< pgid >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/config
|
||||||
|
- << source_dir >>:/source:ro
|
||||||
|
- << backup_dir >>:/backups
|
||||||
|
restart: unless-stopped
|
||||||
83
apps/duplicati/template.json
Normal file
83
apps/duplicati/template.json
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Duplicati",
|
||||||
|
"description": "Versleutelde back-ups naar een NAS, externe schijf of cloudopslag, met een planner.",
|
||||||
|
"tags": [
|
||||||
|
"backup",
|
||||||
|
"opslag",
|
||||||
|
"beheer"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "duplicati"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "duplicati",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8200,
|
||||||
|
"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": "source_dir",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Map om te back-uppen",
|
||||||
|
"default": "/opt/serverup",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "backup_dir",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Bestemming",
|
||||||
|
"default": "/opt/serverup/backups",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
12
apps/esphome/files/compose.yaml
Normal file
12
apps/esphome/files/compose.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/esphome/esphome:stable
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:6052"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/config
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
restart: unless-stopped
|
||||||
54
apps/esphome/template.json
Normal file
54
apps/esphome/template.json
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "ESPHome",
|
||||||
|
"description": "Bouw en beheer firmware voor ESP32/ESP8266-sensoren via een webinterface. Levert kant-en-klare Home Assistant-integratie.",
|
||||||
|
"tags": [
|
||||||
|
"domotica",
|
||||||
|
"esp32",
|
||||||
|
"diy"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "esphome"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "stable"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "esphome",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 6052,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
34
apps/firefly-iii/files/compose.yaml
Normal file
34
apps/firefly-iii/files/compose.yaml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: fireflyiii/core:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8080"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- APP_KEY=<< app_key >>
|
||||||
|
- DB_CONNECTION=pgsql
|
||||||
|
- DB_HOST=<< service_name >>-db
|
||||||
|
- DB_PORT=5432
|
||||||
|
- DB_DATABASE=firefly
|
||||||
|
- DB_USERNAME=firefly
|
||||||
|
- DB_PASSWORD=<< db_password >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/upload:/var/www/html/storage/upload
|
||||||
|
depends_on:
|
||||||
|
- << service_name >>-db
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
<< service_name >>-db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: << service_name >>-db
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=firefly
|
||||||
|
- POSTGRES_USER=firefly
|
||||||
|
- POSTGRES_PASSWORD=<< db_password >>
|
||||||
|
volumes:
|
||||||
|
- << service_name >>_pgdata:/var/lib/postgresql/data
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
<< service_name >>_pgdata:
|
||||||
76
apps/firefly-iii/template.json
Normal file
76
apps/firefly-iii/template.json
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Firefly III",
|
||||||
|
"description": "Huishoudboekje met budgetten, rekeningen en rapportages. Kan bankafschriften importeren.",
|
||||||
|
"tags": [
|
||||||
|
"financien",
|
||||||
|
"huishouden",
|
||||||
|
"budget"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "firefly-iii"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "firefly-iii",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8093,
|
||||||
|
"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_key",
|
||||||
|
"type": "str",
|
||||||
|
"title": "App-sleutel",
|
||||||
|
"default": "",
|
||||||
|
"required": true,
|
||||||
|
"description": "Exact 32 tekens; gebruik de dobbelsteenknop en kort zo nodig in",
|
||||||
|
"config": {
|
||||||
|
"placeholder": "32-tekens-lange-sleutel"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
13
apps/freshrss/files/compose.yaml
Normal file
13
apps/freshrss/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: freshrss/freshrss:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:80"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- CRON_MIN=*/20
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/data:/var/www/FreshRSS/data
|
||||||
|
- << data_dir >>/<< service_name >>/extensions:/var/www/FreshRSS/extensions
|
||||||
|
restart: unless-stopped
|
||||||
69
apps/freshrss/template.json
Normal file
69
apps/freshrss/template.json
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "FreshRSS",
|
||||||
|
"description": "RSS-lezer die je nieuws en blogs op één plek verzamelt, zonder algoritme.",
|
||||||
|
"tags": [
|
||||||
|
"nieuws",
|
||||||
|
"rss",
|
||||||
|
"lezen"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "freshrss"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "freshrss",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8082,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
20
apps/frigate/files/compose.yaml
Normal file
20
apps/frigate/files/compose.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/blakeblackshear/frigate:stable
|
||||||
|
container_name: << service_name >>
|
||||||
|
shm_size: "<< shm_size >>"
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8971"
|
||||||
|
- "<< rtsp_port >>:8554"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/config
|
||||||
|
- << data_dir >>/<< service_name >>/media:/media/frigate
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
# Opnamebuffer in geheugen; voorkomt slijtage van je SSD
|
||||||
|
- type: tmpfs
|
||||||
|
target: /tmp/cache
|
||||||
|
tmpfs:
|
||||||
|
size: 1000000000
|
||||||
|
restart: unless-stopped
|
||||||
69
apps/frigate/template.json
Normal file
69
apps/frigate/template.json
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Frigate NVR",
|
||||||
|
"description": "Camerabewaking met objectherkenning die lokaal draait. Werkt samen met Home Assistant en MQTT.",
|
||||||
|
"tags": [
|
||||||
|
"camera",
|
||||||
|
"nvr",
|
||||||
|
"domotica"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "frigate"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "stable"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "frigate",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8971,
|
||||||
|
"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": "rtsp_port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "RTSP poort",
|
||||||
|
"default": 8554,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shm_size",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Gedeeld geheugen",
|
||||||
|
"default": "128mb",
|
||||||
|
"required": true,
|
||||||
|
"description": "Verhoog dit bij meer dan twee camera's (ongeveer 64mb per camera)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
13
apps/grocy/files/compose.yaml
Normal file
13
apps/grocy/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: lscr.io/linuxserver/grocy:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:80"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- PUID=<< puid >>
|
||||||
|
- PGID=<< pgid >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/config
|
||||||
|
restart: unless-stopped
|
||||||
69
apps/grocy/template.json
Normal file
69
apps/grocy/template.json
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Grocy",
|
||||||
|
"description": "Voorraadbeheer voor je huishouden: boodschappen, houdbaarheidsdata, klusjes en recepten.",
|
||||||
|
"tags": [
|
||||||
|
"huishouden",
|
||||||
|
"voorraad",
|
||||||
|
"gezin"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "grocy"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "grocy",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 9283,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
13
apps/homebridge/files/compose.yaml
Normal file
13
apps/homebridge/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: homebridge/homebridge:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
# HomeKit gebruikt mDNS voor het vinden van apparaten; dat werkt alleen
|
||||||
|
# betrouwbaar met het netwerk van de host, of met een eigen IP-adres.
|
||||||
|
network_mode: host
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- HOMEBRIDGE_CONFIG_UI_PORT=<< port >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>:/homebridge
|
||||||
|
restart: unless-stopped
|
||||||
54
apps/homebridge/template.json
Normal file
54
apps/homebridge/template.json
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Homebridge",
|
||||||
|
"description": "Maakt apparaten die geen HomeKit ondersteunen alsnog zichtbaar in de Woning-app van Apple.",
|
||||||
|
"tags": [
|
||||||
|
"domotica",
|
||||||
|
"homekit",
|
||||||
|
"apple"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "homebridge"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "homebridge",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8581,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
14
apps/homepage/files/compose.yaml
Normal file
14
apps/homepage/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/gethomepage/homepage:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:3000"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- HOMEPAGE_ALLOWED_HOSTS=<< allowed_hosts >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/app/config
|
||||||
|
# Alleen-lezen socket voor de Docker-widget die containers toont
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
restart: unless-stopped
|
||||||
62
apps/homepage/template.json
Normal file
62
apps/homepage/template.json
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Homepage",
|
||||||
|
"description": "Startpagina met tegels voor al je diensten, inclusief live status en systeemgegevens.",
|
||||||
|
"tags": [
|
||||||
|
"dashboard",
|
||||||
|
"startpagina",
|
||||||
|
"overzicht"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "homepage"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "homepage",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 3002,
|
||||||
|
"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": "allowed_hosts",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Toegestane hostnamen",
|
||||||
|
"default": "localhost:3001",
|
||||||
|
"required": true,
|
||||||
|
"description": "Komma-gescheiden; anders weigert Homepage het verzoek"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
12
apps/jellyseerr/files/compose.yaml
Normal file
12
apps/jellyseerr/files/compose.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: fallenbagel/jellyseerr:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:5055"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- LOG_LEVEL=info
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/app/config
|
||||||
|
restart: unless-stopped
|
||||||
54
apps/jellyseerr/template.json
Normal file
54
apps/jellyseerr/template.json
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Jellyseerr",
|
||||||
|
"description": "Verzoeken voor films en series, gekoppeld aan Jellyfin of Plex en de *arr-stack.",
|
||||||
|
"tags": [
|
||||||
|
"media",
|
||||||
|
"verzoeken",
|
||||||
|
"films"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "jellyseerr"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "jellyseerr",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 5055,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
14
apps/kavita/files/compose.yaml
Normal file
14
apps/kavita/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: lscr.io/linuxserver/kavita:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:5000"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- PUID=<< puid >>
|
||||||
|
- PGID=<< pgid >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/config
|
||||||
|
- << library_dir >>:/library
|
||||||
|
restart: unless-stopped
|
||||||
76
apps/kavita/template.json
Normal file
76
apps/kavita/template.json
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Kavita",
|
||||||
|
"description": "Leesserver voor strips, manga en e-books, met leesvoortgang per gebruiker.",
|
||||||
|
"tags": [
|
||||||
|
"media",
|
||||||
|
"boeken",
|
||||||
|
"strips"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "kavita"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "kavita",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 5001,
|
||||||
|
"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": "Bibliotheekmap",
|
||||||
|
"default": "/opt/serverup/media/books",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
14
apps/mosquitto/files/compose.yaml
Normal file
14
apps/mosquitto/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: eclipse-mosquitto:2
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:1883"
|
||||||
|
- "<< websocket_port >>:9001"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/mosquitto/config
|
||||||
|
- << data_dir >>/<< service_name >>/data:/mosquitto/data
|
||||||
|
- << data_dir >>/<< service_name >>/log:/mosquitto/log
|
||||||
|
restart: unless-stopped
|
||||||
61
apps/mosquitto/template.json
Normal file
61
apps/mosquitto/template.json
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Mosquitto MQTT",
|
||||||
|
"description": "Lichtgewicht MQTT-broker. De centrale berichtenbus waar Zigbee2MQTT, ESPHome en Home Assistant op praten.",
|
||||||
|
"tags": [
|
||||||
|
"domotica",
|
||||||
|
"mqtt",
|
||||||
|
"infrastructuur"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "eclipse-mosquitto"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "mosquitto",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "MQTT poort",
|
||||||
|
"default": 1883,
|
||||||
|
"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": "websocket_port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "WebSocket poort",
|
||||||
|
"default": 9001,
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
14
apps/navidrome/files/compose.yaml
Normal file
14
apps/navidrome/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: deluan/navidrome:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:4533"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- ND_SCANSCHEDULE=<< scan_schedule >>
|
||||||
|
- ND_LOGLEVEL=info
|
||||||
|
volumes:
|
||||||
|
- << music_dir >>:/music:ro
|
||||||
|
- << data_dir >>/<< service_name >>/data:/data
|
||||||
|
restart: unless-stopped
|
||||||
69
apps/navidrome/template.json
Normal file
69
apps/navidrome/template.json
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Navidrome",
|
||||||
|
"description": "Muziekstreaming vanaf je eigen collectie. Werkt met alle Subsonic-apps.",
|
||||||
|
"tags": [
|
||||||
|
"media",
|
||||||
|
"muziek",
|
||||||
|
"streaming"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "navidrome"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "navidrome",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 4533,
|
||||||
|
"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": "music_dir",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Muziekmap",
|
||||||
|
"default": "/opt/serverup/media/music",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scan_schedule",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Scaninterval",
|
||||||
|
"default": "@every 1h",
|
||||||
|
"required": true,
|
||||||
|
"description": "Hoe vaak de collectie opnieuw wordt ingelezen"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
11
apps/node-red/files/compose.yaml
Normal file
11
apps/node-red/files/compose.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: nodered/node-red:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:1880"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/data:/data
|
||||||
|
restart: unless-stopped
|
||||||
54
apps/node-red/template.json
Normal file
54
apps/node-red/template.json
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Node-RED",
|
||||||
|
"description": "Visueel automatiseringen bouwen door blokken aan elkaar te knopen. Populair naast Home Assistant voor complexere logica.",
|
||||||
|
"tags": [
|
||||||
|
"domotica",
|
||||||
|
"automatisering",
|
||||||
|
"low-code"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "node-red"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "node-red",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 1880,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
13
apps/octoprint/files/compose.yaml
Normal file
13
apps/octoprint/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: octoprint/octoprint:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:80"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>:/octoprint
|
||||||
|
devices:
|
||||||
|
- << usb_device >>:/dev/ttyACM0
|
||||||
|
restart: unless-stopped
|
||||||
61
apps/octoprint/template.json
Normal file
61
apps/octoprint/template.json
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "OctoPrint",
|
||||||
|
"description": "Bedien en volg een 3D-printer via het netwerk, met webcam en plug-ins.",
|
||||||
|
"tags": [
|
||||||
|
"3d-printen",
|
||||||
|
"printerbeheer"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "octoprint"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "octoprint",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8087,
|
||||||
|
"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": "usb_device",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Printer (USB)",
|
||||||
|
"default": "/dev/ttyACM0",
|
||||||
|
"required": true,
|
||||||
|
"description": "Seriële poort van je printer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
12
apps/scrypted/files/compose.yaml
Normal file
12
apps/scrypted/files/compose.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/koush/scrypted:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
# Camera-ontdekking en HomeKit vereisen mDNS op het lokale netwerk.
|
||||||
|
network_mode: host
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- SCRYPTED_SECURE_PORT=<< port >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>:/server/volume
|
||||||
|
restart: unless-stopped
|
||||||
54
apps/scrypted/template.json
Normal file
54
apps/scrypted/template.json
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Scrypted",
|
||||||
|
"description": "Koppelt camera's aan HomeKit, Google Home en Alexa, met opname en bewegingsdetectie.",
|
||||||
|
"tags": [
|
||||||
|
"camera",
|
||||||
|
"domotica",
|
||||||
|
"nvr"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "scrypted"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "scrypted",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "HTTPS poort",
|
||||||
|
"default": 10443,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
19
apps/searxng/files/compose.yaml
Normal file
19
apps/searxng/files/compose.yaml
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: searxng/searxng:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8080"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- SEARXNG_BASE_URL=<< base_url >>
|
||||||
|
- SEARXNG_SECRET=<< secret_key >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/etc/searxng
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
cap_add:
|
||||||
|
- CHOWN
|
||||||
|
- SETGID
|
||||||
|
- SETUID
|
||||||
|
restart: unless-stopped
|
||||||
72
apps/searxng/template.json
Normal file
72
apps/searxng/template.json
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "SearXNG",
|
||||||
|
"description": "Eigen zoekmachine die resultaten van andere zoekmachines samenvoegt, zonder je te volgen.",
|
||||||
|
"tags": [
|
||||||
|
"privacy",
|
||||||
|
"zoeken",
|
||||||
|
"web"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "searxng"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "searxng",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8095,
|
||||||
|
"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:8095/",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "secret_key",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Geheime sleutel",
|
||||||
|
"default": "",
|
||||||
|
"required": true,
|
||||||
|
"description": "Willekeurige waarde; gebruik de dobbelsteenknop",
|
||||||
|
"config": {
|
||||||
|
"placeholder": "sterk-wachtwoord"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
11
apps/spoolman/files/compose.yaml
Normal file
11
apps/spoolman/files/compose.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/donkie/spoolman:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8000"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/data:/home/app/.local/share/spoolman
|
||||||
|
restart: unless-stopped
|
||||||
53
apps/spoolman/template.json
Normal file
53
apps/spoolman/template.json
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Spoolman",
|
||||||
|
"description": "Houdt bij hoeveel filament je nog hebt en wat elke print verbruikt. Koppelt aan OctoPrint, Klipper en Bambuddy.",
|
||||||
|
"tags": [
|
||||||
|
"3d-printen",
|
||||||
|
"voorraad"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "spoolman"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "spoolman",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 7912,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
34
apps/tandoor/files/compose.yaml
Normal file
34
apps/tandoor/files/compose.yaml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/tandoorrecipes/recipes:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8080"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- SECRET_KEY=<< secret_key >>
|
||||||
|
- DB_ENGINE=django.db.backends.postgresql
|
||||||
|
- POSTGRES_HOST=<< service_name >>-db
|
||||||
|
- POSTGRES_DB=tandoor
|
||||||
|
- POSTGRES_USER=tandoor
|
||||||
|
- POSTGRES_PASSWORD=<< db_password >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/staticfiles:/opt/recipes/staticfiles
|
||||||
|
- << data_dir >>/<< service_name >>/mediafiles:/opt/recipes/mediafiles
|
||||||
|
depends_on:
|
||||||
|
- << service_name >>-db
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
<< service_name >>-db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: << service_name >>-db
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=tandoor
|
||||||
|
- POSTGRES_USER=tandoor
|
||||||
|
- POSTGRES_PASSWORD=<< db_password >>
|
||||||
|
volumes:
|
||||||
|
- << service_name >>_pgdata:/var/lib/postgresql/data
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
<< service_name >>_pgdata:
|
||||||
76
apps/tandoor/template.json
Normal file
76
apps/tandoor/template.json
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Tandoor Recipes",
|
||||||
|
"description": "Receptenboek met boodschappenlijst en maaltijdplanner. Importeert recepten van websites.",
|
||||||
|
"tags": [
|
||||||
|
"huishouden",
|
||||||
|
"recepten",
|
||||||
|
"gezin"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "tandoor"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "tandoor",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8092,
|
||||||
|
"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": "Willekeurige waarde voor sessieversleuteling",
|
||||||
|
"config": {
|
||||||
|
"placeholder": "willekeurige-lange-string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
16
apps/technitium-dns/files/compose.yaml
Normal file
16
apps/technitium-dns/files/compose.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: technitium/dns-server:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:5380"
|
||||||
|
- "53:53/udp"
|
||||||
|
- "53:53/tcp"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- DNS_SERVER_ADMIN_PASSWORD=<< admin_password >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/etc/dns
|
||||||
|
sysctls:
|
||||||
|
- net.ipv4.ip_local_port_range=1024 65000
|
||||||
|
restart: unless-stopped
|
||||||
65
apps/technitium-dns/template.json
Normal file
65
apps/technitium-dns/template.json
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Technitium DNS",
|
||||||
|
"description": "Eigen DNS-server met advertentieblokkering, DNS-over-HTTPS en gedetailleerde statistieken.",
|
||||||
|
"tags": [
|
||||||
|
"netwerk",
|
||||||
|
"dns",
|
||||||
|
"privacy"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "technitium-dns-server"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "technitium-dns",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 5380,
|
||||||
|
"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_password",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Beheerderswachtwoord",
|
||||||
|
"default": "",
|
||||||
|
"required": true,
|
||||||
|
"description": "Wachtwoord voor de webinterface",
|
||||||
|
"config": {
|
||||||
|
"placeholder": "sterk-wachtwoord"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
34
apps/wallabag/files/compose.yaml
Normal file
34
apps/wallabag/files/compose.yaml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: wallabag/wallabag:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:80"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- SYMFONY__ENV__DATABASE_DRIVER=pdo_pgsql
|
||||||
|
- SYMFONY__ENV__DATABASE_HOST=<< service_name >>-db
|
||||||
|
- SYMFONY__ENV__DATABASE_PORT=5432
|
||||||
|
- SYMFONY__ENV__DATABASE_NAME=wallabag
|
||||||
|
- SYMFONY__ENV__DATABASE_USER=wallabag
|
||||||
|
- SYMFONY__ENV__DATABASE_PASSWORD=<< db_password >>
|
||||||
|
- SYMFONY__ENV__DOMAIN_NAME=<< app_url >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/images:/var/www/wallabag/web/assets/images
|
||||||
|
depends_on:
|
||||||
|
- << service_name >>-db
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
<< service_name >>-db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: << service_name >>-db
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=wallabag
|
||||||
|
- POSTGRES_USER=wallabag
|
||||||
|
- POSTGRES_PASSWORD=<< db_password >>
|
||||||
|
volumes:
|
||||||
|
- << service_name >>_pgdata:/var/lib/postgresql/data
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
<< service_name >>_pgdata:
|
||||||
72
apps/wallabag/template.json
Normal file
72
apps/wallabag/template.json
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Wallabag",
|
||||||
|
"description": "Artikelen bewaren om later te lezen, zonder reclame en advertentietrackers. Alternatief voor Pocket.",
|
||||||
|
"tags": [
|
||||||
|
"lezen",
|
||||||
|
"artikelen",
|
||||||
|
"archief"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "wallabag"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "wallabag",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8094,
|
||||||
|
"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:8094",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
13
apps/watchtower/files/compose.yaml
Normal file
13
apps/watchtower/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: containrrr/watchtower:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- WATCHTOWER_SCHEDULE=<< schedule >>
|
||||||
|
- WATCHTOWER_CLEANUP=<< cleanup | lower >>
|
||||||
|
# Alleen containers met het label com.centurylinklabs.watchtower.enable=true
|
||||||
|
- WATCHTOWER_LABEL_ENABLE=true
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
restart: unless-stopped
|
||||||
55
apps/watchtower/template.json
Normal file
55
apps/watchtower/template.json
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Watchtower",
|
||||||
|
"description": "Werkt containers automatisch bij zodra er een nieuw image is. Let op: Server Up beheert stacks zelf, gebruik dit alleen voor containers daarbuiten.",
|
||||||
|
"tags": [
|
||||||
|
"beheer",
|
||||||
|
"updates",
|
||||||
|
"onderhoud"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "watchtower"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "watchtower",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "timezone",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Tijdzone",
|
||||||
|
"default": "Europe/Amsterdam",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "schedule",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Planning (cron)",
|
||||||
|
"default": "0 0 4 * * *",
|
||||||
|
"required": true,
|
||||||
|
"description": "Zes velden, seconden eerst. Standaard elke nacht om 4 uur."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cleanup",
|
||||||
|
"type": "bool",
|
||||||
|
"title": "Oude images opruimen",
|
||||||
|
"default": true,
|
||||||
|
"description": "Verwijdert het vorige image na een update"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
21
apps/wg-easy/files/compose.yaml
Normal file
21
apps/wg-easy/files/compose.yaml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/wg-easy/wg-easy:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< vpn_port >>:51820/udp"
|
||||||
|
- "<< port >>:51821/tcp"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- WG_HOST=<< host >>
|
||||||
|
- PASSWORD_HASH=<< password_hash >>
|
||||||
|
- WG_PORT=<< vpn_port >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/config:/etc/wireguard
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
- SYS_MODULE
|
||||||
|
sysctls:
|
||||||
|
- net.ipv4.ip_forward=1
|
||||||
|
- net.ipv4.conf.all.src_valid_mark=1
|
||||||
|
restart: unless-stopped
|
||||||
80
apps/wg-easy/template.json
Normal file
80
apps/wg-easy/template.json
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "WireGuard Easy",
|
||||||
|
"description": "VPN naar je eigen netwerk, met een webinterface om apparaten toe te voegen via een QR-code.",
|
||||||
|
"tags": [
|
||||||
|
"vpn",
|
||||||
|
"netwerk",
|
||||||
|
"beveiliging"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "wg-easy"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "wg-easy",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 51821,
|
||||||
|
"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": "vpn_port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "VPN poort (UDP)",
|
||||||
|
"default": 51820,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "host",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Publiek adres",
|
||||||
|
"default": "vpn.example.com",
|
||||||
|
"required": true,
|
||||||
|
"description": "Het adres of IP waarop je van buitenaf binnenkomt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "password_hash",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Wachtwoordhash beheerder",
|
||||||
|
"default": "",
|
||||||
|
"required": true,
|
||||||
|
"description": "Bcrypt-hash van je wachtwoord; zie de documentatie van wg-easy",
|
||||||
|
"config": {
|
||||||
|
"placeholder": "sterk-wachtwoord"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
15
apps/zigbee2mqtt/files/compose.yaml
Normal file
15
apps/zigbee2mqtt/files/compose.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: ghcr.io/koenkk/zigbee2mqtt:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8080"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
- ZIGBEE2MQTT_CONFIG_MQTT_SERVER=<< mqtt_server >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/data:/app/data
|
||||||
|
- /run/udev:/run/udev:ro
|
||||||
|
devices:
|
||||||
|
- << usb_device >>:/dev/ttyACM0
|
||||||
|
restart: unless-stopped
|
||||||
70
apps/zigbee2mqtt/template.json
Normal file
70
apps/zigbee2mqtt/template.json
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Zigbee2MQTT",
|
||||||
|
"description": "Koppelt Zigbee-apparaten aan MQTT, zonder de hub van de fabrikant. Werkt met Home Assistant.",
|
||||||
|
"tags": [
|
||||||
|
"domotica",
|
||||||
|
"zigbee",
|
||||||
|
"mqtt"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "zigbee2mqtt"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "zigbee2mqtt",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8088,
|
||||||
|
"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": "usb_device",
|
||||||
|
"type": "str",
|
||||||
|
"title": "USB-adapter",
|
||||||
|
"default": "/dev/ttyACM0",
|
||||||
|
"required": true,
|
||||||
|
"description": "Pad naar je Zigbee-stick; vind hem met `ls -l /dev/serial/by-id/`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mqtt_server",
|
||||||
|
"type": "str",
|
||||||
|
"title": "MQTT-server",
|
||||||
|
"default": "mqtt://mosquitto:1883",
|
||||||
|
"required": true,
|
||||||
|
"description": "Adres van je MQTT-broker (zie de Mosquitto-app)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
14
apps/zwave-js-ui/files/compose.yaml
Normal file
14
apps/zwave-js-ui/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
services:
|
||||||
|
<< service_name >>:
|
||||||
|
image: zwavejs/zwave-js-ui:latest
|
||||||
|
container_name: << service_name >>
|
||||||
|
ports:
|
||||||
|
- "<< port >>:8091"
|
||||||
|
- "<< ws_port >>:3000"
|
||||||
|
environment:
|
||||||
|
- TZ=<< timezone >>
|
||||||
|
volumes:
|
||||||
|
- << data_dir >>/<< service_name >>/store:/usr/src/app/store
|
||||||
|
devices:
|
||||||
|
- << usb_device >>:/dev/zwave
|
||||||
|
restart: unless-stopped
|
||||||
70
apps/zwave-js-ui/template.json
Normal file
70
apps/zwave-js-ui/template.json
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
"kind": "compose",
|
||||||
|
"metadata": {
|
||||||
|
"name": "Z-Wave JS UI",
|
||||||
|
"description": "Beheer je Z-Wave-netwerk en koppel het aan Home Assistant of MQTT.",
|
||||||
|
"tags": [
|
||||||
|
"domotica",
|
||||||
|
"zwave",
|
||||||
|
"mqtt"
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"provider": "selfhst",
|
||||||
|
"id": "zwave-js-ui"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": [
|
||||||
|
{
|
||||||
|
"title": "Algemeen",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "service_name",
|
||||||
|
"type": "str",
|
||||||
|
"title": "Servicenaam",
|
||||||
|
"default": "zwave-js-ui",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "Web poort",
|
||||||
|
"default": 8091,
|
||||||
|
"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": "usb_device",
|
||||||
|
"type": "str",
|
||||||
|
"title": "USB-adapter",
|
||||||
|
"default": "/dev/ttyUSB0",
|
||||||
|
"required": true,
|
||||||
|
"description": "Pad naar je Z-Wave-stick"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ws_port",
|
||||||
|
"type": "int",
|
||||||
|
"title": "WebSocket poort",
|
||||||
|
"default": 3003,
|
||||||
|
"required": true,
|
||||||
|
"description": "Poort waarop Home Assistant verbinding maakt"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -257,6 +257,21 @@ def _tidy(text: str) -> str:
|
||||||
|
|
||||||
_KEY_RE = re.compile(r"^(\s*)([A-Za-z_][\w\-]*)\s*:\s*$")
|
_KEY_RE = re.compile(r"^(\s*)([A-Za-z_][\w\-]*)\s*:\s*$")
|
||||||
|
|
||||||
|
# Alleen deze compose-sleutels worden opgeruimd als ze leeg achterblijven. Dat
|
||||||
|
# zijn de sleutels die een `<% if %>`-blok leeg kan maken.
|
||||||
|
#
|
||||||
|
# De beperking is wezenlijk: een named volume wordt gedeclareerd als een kale
|
||||||
|
# sleutel zonder waarde (` immich_pgdata:`), en zonder deze lijst werd die als
|
||||||
|
# "lege mapping" opgeruimd. Daarna viel ook het bovenliggende `volumes:` weg,
|
||||||
|
# en verwees de compose naar een volume dat nergens meer gedeclareerd stond —
|
||||||
|
# waarop docker compose weigert te starten.
|
||||||
|
_OPRUIMBARE_SLEUTELS = frozenset({
|
||||||
|
"ports", "environment", "volumes", "depends_on", "networks", "labels",
|
||||||
|
"devices", "cap_add", "cap_drop", "sysctls", "extra_hosts", "dns",
|
||||||
|
"expose", "profiles", "tmpfs", "secrets", "configs", "command",
|
||||||
|
"entrypoint", "healthcheck", "deploy", "links", "env_file", "build",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def _drop_empty_mappings(text: str) -> str:
|
def _drop_empty_mappings(text: str) -> str:
|
||||||
"""Verwijder ´keys´ die op een lege regel of een gelijk/minder-indent sibling
|
"""Verwijder ´keys´ die op een lege regel of een gelijk/minder-indent sibling
|
||||||
|
|
@ -269,6 +284,8 @@ def _drop_empty_mappings(text: str) -> str:
|
||||||
m = _KEY_RE.match(line)
|
m = _KEY_RE.match(line)
|
||||||
if not m:
|
if not m:
|
||||||
continue
|
continue
|
||||||
|
if m.group(2) not in _OPRUIMBARE_SLEUTELS:
|
||||||
|
continue
|
||||||
indent = len(m.group(1))
|
indent = len(m.group(1))
|
||||||
# Zoek de eerste niet-lege, niet-commentaar regel hierna
|
# Zoek de eerste niet-lege, niet-commentaar regel hierna
|
||||||
j = i + 1
|
j = i + 1
|
||||||
|
|
|
||||||
122
tests/test_apps.py
Normal file
122
tests/test_apps.py
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
"""Elke app in apps/ moet renderen naar geldige, startbare compose-YAML.
|
||||||
|
|
||||||
|
Deze suite draait over de echte templates, niet over voorbeelden. Zo valt een
|
||||||
|
kapot template op vóórdat iemand het probeert te installeren.
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
WORTEL = Path(__file__).resolve().parent.parent
|
||||||
|
sys.path.insert(0, str(WORTEL / "server-up"))
|
||||||
|
|
||||||
|
from core import boilerplates as bp
|
||||||
|
|
||||||
|
APPS = sorted(d for d in (WORTEL / "apps").iterdir() if d.is_dir())
|
||||||
|
NAMEN = [d.name for d in APPS]
|
||||||
|
|
||||||
|
|
||||||
|
def _render(d: Path, tmp: Path) -> dict:
|
||||||
|
velden = bp.fields(d)
|
||||||
|
waarden = {f["name"]: f["default"] for f in velden if f.get("default") is not None}
|
||||||
|
waarden.setdefault("service_name", d.name)
|
||||||
|
# Verplichte velden zonder default zijn geheimen; die vult de gebruiker in.
|
||||||
|
for f in velden:
|
||||||
|
if f.get("required") and not waarden.get(f["name"]):
|
||||||
|
waarden[f["name"]] = "testwaarde12345678901234567890ab"
|
||||||
|
bp.render_to_dir(d, tmp, waarden)
|
||||||
|
return yaml.safe_load((tmp / "docker-compose.yml").read_text())
|
||||||
|
|
||||||
|
|
||||||
|
def test_er_zijn_apps():
|
||||||
|
assert len(APPS) >= 60
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("app", APPS, ids=NAMEN)
|
||||||
|
def test_app_is_geldige_boilerplate(app):
|
||||||
|
assert bp.is_boilerplate(app), "template.json of files/ ontbreekt"
|
||||||
|
meta = bp.metadata(app)
|
||||||
|
assert meta["name"], "naam ontbreekt in template.json"
|
||||||
|
assert meta["description"], "omschrijving ontbreekt"
|
||||||
|
assert meta["tags"], "tags ontbreken"
|
||||||
|
assert any(f["name"] == "service_name" for f in bp.fields(app)), \
|
||||||
|
"service_name-variabele ontbreekt"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("app", APPS, ids=NAMEN)
|
||||||
|
def test_app_rendert_naar_geldige_compose(app):
|
||||||
|
with tempfile.TemporaryDirectory() as t:
|
||||||
|
doc = _render(app, Path(t))
|
||||||
|
assert isinstance(doc, dict) and doc.get("services"), "geen services"
|
||||||
|
for naam, svc in doc["services"].items():
|
||||||
|
assert isinstance(svc, dict), f"{naam} is geen mapping"
|
||||||
|
assert svc.get("image") or svc.get("build"), f"{naam}: geen image of build"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("app", APPS, ids=NAMEN)
|
||||||
|
def test_named_volumes_zijn_gedeclareerd(app):
|
||||||
|
"""Named volumes moeten in het top-level volumes-blok staan.
|
||||||
|
|
||||||
|
_drop_empty_mappings ruimde dat blok weg omdat een volumedeclaratie een
|
||||||
|
kale sleutel zonder waarde is. Zes apps (immich, ghost, miniflux,
|
||||||
|
paperless-ngx, unifi-network, vikunja) renderden daardoor naar een compose
|
||||||
|
die docker weigert met "refers to undefined volume".
|
||||||
|
"""
|
||||||
|
with tempfile.TemporaryDirectory() as t:
|
||||||
|
doc = _render(app, Path(t))
|
||||||
|
gedeclareerd = set((doc.get("volumes") or {}).keys())
|
||||||
|
for naam, svc in doc["services"].items():
|
||||||
|
for v in svc.get("volumes") or []:
|
||||||
|
if isinstance(v, str) and not v.startswith(("/", ".")):
|
||||||
|
bron = v.split(":")[0]
|
||||||
|
assert bron in gedeclareerd, \
|
||||||
|
f"{naam}: volume '{bron}' wordt gebruikt maar niet gedeclareerd"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("app", APPS, ids=NAMEN)
|
||||||
|
def test_geen_onvervangen_variabelen(app):
|
||||||
|
"""Een typefout in een variabelenaam laat << … >> in het resultaat staan."""
|
||||||
|
with tempfile.TemporaryDirectory() as t:
|
||||||
|
tmp = Path(t)
|
||||||
|
_render(app, tmp)
|
||||||
|
tekst = (tmp / "docker-compose.yml").read_text()
|
||||||
|
assert "<<" not in tekst and ">>" not in tekst, "onvervangen variabele"
|
||||||
|
|
||||||
|
|
||||||
|
# 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"},
|
||||||
|
53: {"adguard-home", "pihole"}, # dns-blokkers
|
||||||
|
5055: {"arr-stack", "jellyseerr"}, # zelfde app
|
||||||
|
# Hieronder: botsingen die er al waren vóór deze testsuite. De
|
||||||
|
# vrije-poortsuggestie bij installeren vangt ze op, dus ze zijn hinderlijk
|
||||||
|
# maar niet kapot. Nieuwe apps horen hier niet bij te komen.
|
||||||
|
3000: {"adguard-home", "forgejo", "grafana"},
|
||||||
|
8080: {"miniflux", "nextcloud-aio", "pihole", "qbittorrent",
|
||||||
|
"stirling-pdf", "traefik", "unifi-network"},
|
||||||
|
9000: {"mealie", "portainer"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_poorten_botsen_niet_tussen_apps():
|
||||||
|
"""Twee apps met dezelfde standaardpoort geven bij installeren meteen een
|
||||||
|
conflict. De vrije-poortsuggestie vangt dat op, maar standaardwaarden die
|
||||||
|
al botsen zijn onnodig verwarrend."""
|
||||||
|
per_poort: dict[int, list[str]] = {}
|
||||||
|
for app in APPS:
|
||||||
|
for f in bp.fields(app):
|
||||||
|
if f.get("type") == "int" and "port" in f["name"].lower():
|
||||||
|
d = f.get("default")
|
||||||
|
if isinstance(d, int):
|
||||||
|
per_poort.setdefault(d, []).append(f"{app.name}:{f['name']}")
|
||||||
|
botsingen = {}
|
||||||
|
for poort, gebruikers in per_poort.items():
|
||||||
|
apps = {g.split(":")[0] for g in gebruikers}
|
||||||
|
if len(apps) > 1 and not apps <= GEDEELDE_POORTEN.get(poort, set()):
|
||||||
|
botsingen[poort] = sorted(apps)
|
||||||
|
assert not botsingen, f"onbedoeld dubbele standaardpoorten: {botsingen}"
|
||||||
|
|
@ -72,9 +72,11 @@ def test_sandbox_geeft_geen_python_internals_prijs(tmp_path):
|
||||||
src = _maak_boilerplate(tmp_path, "x: << service_name.__class__ >>\n")
|
src = _maak_boilerplate(tmp_path, "x: << service_name.__class__ >>\n")
|
||||||
bp.render_to_dir(src, tmp_path / "out", {"service_name": "web"})
|
bp.render_to_dir(src, tmp_path / "out", {"service_name": "web"})
|
||||||
tekst = (tmp_path / "out" / "docker-compose.yml").read_text()
|
tekst = (tmp_path / "out" / "docker-compose.yml").read_text()
|
||||||
# `x:` blijft leeg achter en wordt daarna door _drop_empty_mappings opgeruimd.
|
# De waarde blijft leeg; `x:` zelf blijft staan omdat alleen bekende
|
||||||
assert tekst.strip() == ""
|
# compose-sleutels worden opgeruimd (zie _OPRUIMBARE_SLEUTELS).
|
||||||
|
assert tekst.strip() == "x:"
|
||||||
assert "class" not in tekst
|
assert "class" not in tekst
|
||||||
|
assert "object" not in tekst
|
||||||
|
|
||||||
|
|
||||||
def test_sandbox_laat_aanroep_van_internals_falen(tmp_path):
|
def test_sandbox_laat_aanroep_van_internals_falen(tmp_path):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue