From 7d178a68b0d4d5b36db6399ea25f15f6535e911d Mon Sep 17 00:00:00 2001 From: Ramon Date: Fri, 31 Jul 2026 23:47:41 +0200 Subject: [PATCH] v0.8.00-beta - 55 apps erbij, en drie kapotte images gevonden - Catalogus van 142 naar 197 apps. Het zwaartepunt lag na het ARR-werk op media (42 apps) terwijl communicatie er 4 had, AI 4, financien 3 en foto's 2 - Drie nieuwe categorieen: Statistiek, Zakelijk en Spellen - Homelab-gereedschap: Dockge, Komodo, Glance, Gatus, Scrutiny, Backrest, Headscale, Zoraxy, CrowdSec, NetAlertX, Pocket ID, Authentik - Communicatie van 4 naar 12: Mattermost, Synapse, Element, Listmonk, Mumble, Roundcube, Stalwart - Notities: Outline, Trilium, SilverBullet, Readeck, Docmost, Kiwix - Verder LibreChat, AnythingLLM, LocalAI, Ghostfolio, Wallos, Maybe, Lychee, Piwigo, Homebox, wger, Donetick, Dawarich, Gitea, Adminer, code-server, Woodpecker, Semaphore, Opengist, MinIO, Pingvin Share, Umami, Matomo, Odoo, FreeScout, EspoCRM, RomM, Minecraft, Leantime, PrivateBin, Emby, ConvertX - Drie bestaande apps waren niet installeerbaar: Forgejo wees naar een latest-tag die dat project niet publiceert, Planka naar een tag 1 die niet bestaat, en Baby Buddy naar een ghcr-pad dat er niet is. Gevonden door alle 213 images in de catalogus langs de registries te halen - Twee testregels waren te krap: een config.yaml in files/ die geen compose is telde niet mee voor "veld wordt gebruikt", en geheimen die de gebruiker zelf aanlevert stonden in een handmatige namenlijst. Dat laatste is nu een vlag in het sjabloon: "eigen_invoer": true - Nieuwe controles voor de 36 apps met een eigen database: elke extra container draagt de servicenaam als voorvoegsel, geen vaste databasewachtwoorden, en er wacht altijd iemand met depends_on op de database Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Q9eqpADJSRs49SoGGr4NAy --- CHANGELOG.md | 41 +++++++ README.md | 2 +- VERSION | 2 +- apps/adminer/files/compose.yaml | 9 ++ apps/adminer/template.json | 51 +++++++++ apps/anythingllm/files/compose.yaml | 14 +++ apps/anythingllm/template.json | 61 ++++++++++ apps/authentik/files/compose.yaml | 58 ++++++++++ apps/authentik/template.json | 86 ++++++++++++++ apps/baby-buddy/files/compose.yaml | 4 +- apps/backrest/files/compose.yaml | 14 +++ apps/backrest/template.json | 72 ++++++++++++ apps/code-server/files/compose.yaml | 16 +++ apps/code-server/template.json | 93 +++++++++++++++ apps/convertx/files/compose.yaml | 13 +++ apps/convertx/template.json | 73 ++++++++++++ apps/crowdsec/files/compose.yaml | 14 +++ apps/crowdsec/template.json | 72 ++++++++++++ apps/dawarich/files/compose.yaml | 40 +++++++ apps/dawarich/template.json | 97 ++++++++++++++++ apps/dockge/files/compose.yaml | 14 +++ apps/dockge/template.json | 73 ++++++++++++ apps/docmost/files/compose.yaml | 35 ++++++ apps/docmost/template.json | 96 ++++++++++++++++ apps/donetick/files/compose.yaml | 14 +++ apps/donetick/template.json | 74 ++++++++++++ apps/element/files/compose.yaml | 11 ++ apps/element/files/config.json | 10 ++ apps/element/template.json | 77 +++++++++++++ apps/emby/files/compose.yaml | 14 +++ apps/emby/template.json | 89 +++++++++++++++ apps/espocrm/files/compose.yaml | 31 +++++ apps/espocrm/template.json | 102 +++++++++++++++++ apps/forgejo/files/compose.yaml | 2 +- apps/freescout/files/compose.yaml | 33 ++++++ apps/freescout/template.json | 104 +++++++++++++++++ apps/gatus/files/compose.yaml | 12 ++ apps/gatus/files/config.yaml | 6 + apps/gatus/template.json | 59 ++++++++++ apps/ghostfolio/files/compose.yaml | 37 ++++++ apps/ghostfolio/template.json | 92 +++++++++++++++ apps/gitea/files/compose.yaml | 17 +++ apps/gitea/template.json | 100 +++++++++++++++++ apps/glance/files/compose.yaml | 13 +++ apps/glance/files/glance.yml | 7 ++ apps/glance/template.json | 59 ++++++++++ apps/headscale/files/compose.yaml | 14 +++ apps/headscale/files/config.yaml | 11 ++ apps/headscale/template.json | 74 ++++++++++++ apps/homebox/files/compose.yaml | 13 +++ apps/homebox/template.json | 59 ++++++++++ apps/kiwix/files/compose.yaml | 12 ++ apps/kiwix/template.json | 59 ++++++++++ apps/leantime/files/compose.yaml | 30 +++++ apps/leantime/template.json | 96 ++++++++++++++++ apps/librechat/files/compose.yaml | 29 +++++ apps/librechat/template.json | 110 ++++++++++++++++++ apps/listmonk/files/compose.yaml | 33 ++++++ apps/listmonk/template.json | 97 ++++++++++++++++ apps/localai/files/compose.yaml | 13 +++ apps/localai/template.json | 59 ++++++++++ apps/lychee/files/compose.yaml | 15 +++ apps/lychee/template.json | 71 ++++++++++++ apps/matomo/files/compose.yaml | 28 +++++ apps/matomo/template.json | 74 ++++++++++++ apps/mattermost/files/compose.yaml | 29 +++++ apps/mattermost/template.json | 88 +++++++++++++++ apps/maybe/files/compose.yaml | 31 +++++ apps/maybe/template.json | 83 ++++++++++++++ apps/minecraft/files/compose.yaml | 14 +++ apps/minecraft/template.json | 96 ++++++++++++++++ apps/minio/files/compose.yaml | 15 +++ apps/minio/template.json | 94 ++++++++++++++++ apps/mumble/files/compose.yaml | 14 +++ apps/mumble/template.json | 86 ++++++++++++++ apps/netalertx/files/compose.yaml | 12 ++ apps/netalertx/template.json | 52 +++++++++ apps/odoo/files/compose.yaml | 26 +++++ apps/odoo/template.json | 75 +++++++++++++ apps/opengist/files/compose.yaml | 15 +++ apps/opengist/template.json | 79 +++++++++++++ apps/outline/files/compose.yaml | 47 ++++++++ apps/outline/template.json | 156 ++++++++++++++++++++++++++ apps/pingvin-share/files/compose.yaml | 12 ++ apps/pingvin-share/template.json | 59 ++++++++++ apps/piwigo/files/compose.yaml | 27 +++++ apps/piwigo/template.json | 93 +++++++++++++++ apps/planka/files/compose.yaml | 2 +- apps/pocket-id/files/compose.yaml | 13 +++ apps/pocket-id/template.json | 74 ++++++++++++ apps/privatebin/files/compose.yaml | 11 ++ apps/privatebin/template.json | 60 ++++++++++ apps/readeck/files/compose.yaml | 13 +++ apps/readeck/template.json | 72 ++++++++++++ apps/romm/files/compose.yaml | 32 ++++++ apps/romm/template.json | 93 +++++++++++++++ apps/roundcube/files/compose.yaml | 14 +++ apps/roundcube/template.json | 79 +++++++++++++ apps/scrutiny/files/compose.yaml | 17 +++ apps/scrutiny/template.json | 61 ++++++++++ apps/semaphore/files/compose.yaml | 34 ++++++ apps/semaphore/template.json | 112 ++++++++++++++++++ apps/silverbullet/files/compose.yaml | 12 ++ apps/silverbullet/template.json | 86 ++++++++++++++ apps/stalwart/files/compose.yaml | 15 +++ apps/stalwart/template.json | 92 +++++++++++++++ apps/synapse/files/compose.yaml | 13 +++ apps/synapse/template.json | 74 ++++++++++++ apps/trilium/files/compose.yaml | 11 ++ apps/trilium/template.json | 60 ++++++++++ apps/umami/files/compose.yaml | 24 ++++ apps/umami/template.json | 83 ++++++++++++++ apps/wallos/files/compose.yaml | 12 ++ apps/wallos/template.json | 60 ++++++++++ apps/wger/files/compose.yaml | 17 +++ apps/wger/template.json | 85 ++++++++++++++ apps/woodpecker/files/compose.yaml | 31 +++++ apps/woodpecker/template.json | 122 ++++++++++++++++++++ apps/zoraxy/files/compose.yaml | 13 +++ apps/zoraxy/template.json | 74 ++++++++++++ docs/apps-maken.md | 22 ++++ server-up/core/boilerplates.py | 5 + server-up/core/categories.py | 9 +- tests/test_app_templates.py | 13 ++- tests/test_apps.py | 69 +++++++++++- 125 files changed, 5789 insertions(+), 13 deletions(-) create mode 100644 apps/adminer/files/compose.yaml create mode 100644 apps/adminer/template.json create mode 100644 apps/anythingllm/files/compose.yaml create mode 100644 apps/anythingllm/template.json create mode 100644 apps/authentik/files/compose.yaml create mode 100644 apps/authentik/template.json create mode 100644 apps/backrest/files/compose.yaml create mode 100644 apps/backrest/template.json create mode 100644 apps/code-server/files/compose.yaml create mode 100644 apps/code-server/template.json create mode 100644 apps/convertx/files/compose.yaml create mode 100644 apps/convertx/template.json create mode 100644 apps/crowdsec/files/compose.yaml create mode 100644 apps/crowdsec/template.json create mode 100644 apps/dawarich/files/compose.yaml create mode 100644 apps/dawarich/template.json create mode 100644 apps/dockge/files/compose.yaml create mode 100644 apps/dockge/template.json create mode 100644 apps/docmost/files/compose.yaml create mode 100644 apps/docmost/template.json create mode 100644 apps/donetick/files/compose.yaml create mode 100644 apps/donetick/template.json create mode 100644 apps/element/files/compose.yaml create mode 100644 apps/element/files/config.json create mode 100644 apps/element/template.json create mode 100644 apps/emby/files/compose.yaml create mode 100644 apps/emby/template.json create mode 100644 apps/espocrm/files/compose.yaml create mode 100644 apps/espocrm/template.json create mode 100644 apps/freescout/files/compose.yaml create mode 100644 apps/freescout/template.json create mode 100644 apps/gatus/files/compose.yaml create mode 100644 apps/gatus/files/config.yaml create mode 100644 apps/gatus/template.json create mode 100644 apps/ghostfolio/files/compose.yaml create mode 100644 apps/ghostfolio/template.json create mode 100644 apps/gitea/files/compose.yaml create mode 100644 apps/gitea/template.json create mode 100644 apps/glance/files/compose.yaml create mode 100644 apps/glance/files/glance.yml create mode 100644 apps/glance/template.json create mode 100644 apps/headscale/files/compose.yaml create mode 100644 apps/headscale/files/config.yaml create mode 100644 apps/headscale/template.json create mode 100644 apps/homebox/files/compose.yaml create mode 100644 apps/homebox/template.json create mode 100644 apps/kiwix/files/compose.yaml create mode 100644 apps/kiwix/template.json create mode 100644 apps/leantime/files/compose.yaml create mode 100644 apps/leantime/template.json create mode 100644 apps/librechat/files/compose.yaml create mode 100644 apps/librechat/template.json create mode 100644 apps/listmonk/files/compose.yaml create mode 100644 apps/listmonk/template.json create mode 100644 apps/localai/files/compose.yaml create mode 100644 apps/localai/template.json create mode 100644 apps/lychee/files/compose.yaml create mode 100644 apps/lychee/template.json create mode 100644 apps/matomo/files/compose.yaml create mode 100644 apps/matomo/template.json create mode 100644 apps/mattermost/files/compose.yaml create mode 100644 apps/mattermost/template.json create mode 100644 apps/maybe/files/compose.yaml create mode 100644 apps/maybe/template.json create mode 100644 apps/minecraft/files/compose.yaml create mode 100644 apps/minecraft/template.json create mode 100644 apps/minio/files/compose.yaml create mode 100644 apps/minio/template.json create mode 100644 apps/mumble/files/compose.yaml create mode 100644 apps/mumble/template.json create mode 100644 apps/netalertx/files/compose.yaml create mode 100644 apps/netalertx/template.json create mode 100644 apps/odoo/files/compose.yaml create mode 100644 apps/odoo/template.json create mode 100644 apps/opengist/files/compose.yaml create mode 100644 apps/opengist/template.json create mode 100644 apps/outline/files/compose.yaml create mode 100644 apps/outline/template.json create mode 100644 apps/pingvin-share/files/compose.yaml create mode 100644 apps/pingvin-share/template.json create mode 100644 apps/piwigo/files/compose.yaml create mode 100644 apps/piwigo/template.json create mode 100644 apps/pocket-id/files/compose.yaml create mode 100644 apps/pocket-id/template.json create mode 100644 apps/privatebin/files/compose.yaml create mode 100644 apps/privatebin/template.json create mode 100644 apps/readeck/files/compose.yaml create mode 100644 apps/readeck/template.json create mode 100644 apps/romm/files/compose.yaml create mode 100644 apps/romm/template.json create mode 100644 apps/roundcube/files/compose.yaml create mode 100644 apps/roundcube/template.json create mode 100644 apps/scrutiny/files/compose.yaml create mode 100644 apps/scrutiny/template.json create mode 100644 apps/semaphore/files/compose.yaml create mode 100644 apps/semaphore/template.json create mode 100644 apps/silverbullet/files/compose.yaml create mode 100644 apps/silverbullet/template.json create mode 100644 apps/stalwart/files/compose.yaml create mode 100644 apps/stalwart/template.json create mode 100644 apps/synapse/files/compose.yaml create mode 100644 apps/synapse/template.json create mode 100644 apps/trilium/files/compose.yaml create mode 100644 apps/trilium/template.json create mode 100644 apps/umami/files/compose.yaml create mode 100644 apps/umami/template.json create mode 100644 apps/wallos/files/compose.yaml create mode 100644 apps/wallos/template.json create mode 100644 apps/wger/files/compose.yaml create mode 100644 apps/wger/template.json create mode 100644 apps/woodpecker/files/compose.yaml create mode 100644 apps/woodpecker/template.json create mode 100644 apps/zoraxy/files/compose.yaml create mode 100644 apps/zoraxy/template.json diff --git a/CHANGELOG.md b/CHANGELOG.md index b4b6b95..a691a58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,44 @@ +# v0.8.00-beta — 55 apps erbij, en drie kapotte images gevonden + +**De catalogus stond scheef.** Na het ARR-werk telde media 42 apps en downloaden +19, terwijl communicatie er 4 had, AI 4, financiën 3 en foto's 2. Wie de store +opende voor iets anders dan media, vond het vaak niet. Er zijn nu 55 apps bij, van +142 naar 197, gekozen op wat er in 2026 daadwerkelijk gedraaid wordt. + +**Drie nieuwe categorieën:** Statistiek (Umami, Matomo), Zakelijk (Odoo, +FreeScout, EspoCRM) en Spellen (RomM, Minecraft) — hoeken die er helemaal niet +waren. + +**Homelab-gereedschap:** Dockge, Komodo, Glance, Gatus, Scrutiny, Backrest, +Headscale, Zoraxy, CrowdSec, NetAlertX, Pocket ID en Authentik. +**Communicatie** gaat van 4 naar 12 met Mattermost, Synapse, Element, Listmonk, +Mumble, Roundcube en Stalwart. **Notities en documenten:** Outline, Trilium, +SilverBullet, Readeck, Docmost en Kiwix. Verder LibreChat, AnythingLLM, LocalAI, +Ghostfolio, Wallos, Maybe, Lychee, Piwigo, Homebox, wger, Donetick, Dawarich, +Gitea, Adminer, code-server, Woodpecker, Semaphore, Opengist, MinIO, Pingvin +Share, Leantime, PrivateBin, Emby en ConvertX. + +**Drie apps in de catalogus waren niet te installeren.** De controle die bij het +ARR-werk Huntarr ontmaskerde, is nu over alle 213 images in de catalogus gehaald. +Daaruit kwamen drie stille fouten: Forgejo wees naar `:latest` terwijl dat project +helemaal geen latest-tag publiceert, Planka naar een tag `1` die niet bestaat, en +Baby Buddy naar `ghcr.io/babybuddy/babybuddy` — een pad dat er niet is, terwijl +het sjabloon met zijn PUID/PGID al voor de linuxserver-variant geschreven was. Alle +drie rechtgezet. + +**Twee testregels waren te krap.** Een `config.yaml` in `files/` die geen +compose-bestand is, viel tussen wal en schip: hij werd niet als compose gescand en +overgeslagen omdat hij op `.yaml` eindigt — velden die alleen dáár gebruikt werden, +gingen door voor ongebruikt. En een verplicht geheim dat de gebruiker ergens anders +vandaan haalt, stond in een handmatige lijst met veldnamen. Dat is nu een vlag in +het sjabloon zelf: `"eigen_invoer": true`. + +**Nieuwe controles.** Zesendertig apps brengen inmiddels hun eigen database mee. +Daarvoor geldt nu: elke extra container draagt de servicenaam als voorvoegsel +(anders botsen twee installaties van dezelfde app), geen enkel databasewachtwoord +staat vast in een sjabloon, en er wacht altijd iemand met `depends_on` op de +database. + # v0.7.90-beta — De ARR-stack uit elkaar, en netwerkopties per container **Elk *arr-onderdeel is nu een losse app.** Wie alleen Sonarr wil, hoefde eerst diff --git a/README.md b/README.md index 1f8fd45..e32b564 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ IP-adres in je netwerk geven. | | | |---|---| -| **App-catalogus** | 96 kant-en-klare apps, ingedeeld in categorieën met kleur. Zoeken, filteren en installeren met een formulier in plaats van YAML. | +| **App-catalogus** | 197 kant-en-klare apps, ingedeeld in categorieën met kleur. Zoeken, filteren en installeren met een formulier in plaats van YAML. | | **Stacks beheren** | Starten, stoppen, bijwerken en herstarten — per stack of per losse container, met logs en live CPU-/geheugengebruik. | | **Apps koppelen** | Stacks komen op een gedeeld netwerk, zodat ze elkaar op naam bereiken. Een veld dat naar een andere app verwijst toont een keuzelijst met wat je al draait. | | **Eigen IP per stack** | Met macvlan of ipvlan krijgt een app een eigen adres in je LAN in plaats van poorten op de host. | diff --git a/VERSION b/VERSION index 8d57ee5..752fcfd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.7.90-beta +0.8.00-beta diff --git a/apps/adminer/files/compose.yaml b/apps/adminer/files/compose.yaml new file mode 100644 index 0000000..6b42604 --- /dev/null +++ b/apps/adminer/files/compose.yaml @@ -0,0 +1,9 @@ +services: + << service_name >>: + image: adminer:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + ports: + - "<< port >>:8080" + restart: unless-stopped diff --git a/apps/adminer/template.json b/apps/adminer/template.json new file mode 100644 index 0000000..85d89a2 --- /dev/null +++ b/apps/adminer/template.json @@ -0,0 +1,51 @@ +{ + "kind": "compose", + "metadata": { + "name": "Adminer", + "description": "Databasebeheer in één bestand: MySQL, PostgreSQL, SQLite en meer, zonder installatie per database. Let op: Adminer geeft volledige toegang tot elke database die hij kan bereiken. Zet hem niet zomaar op internet.", + "tags": [ + "database", + "beheer", + "ontwikkeling" + ], + "icon": { + "provider": "selfhst", + "id": "adminer" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ontwikkeling" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "adminer", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8160, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/anythingllm/files/compose.yaml b/apps/anythingllm/files/compose.yaml new file mode 100644 index 0000000..3320684 --- /dev/null +++ b/apps/anythingllm/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: mintplexlabs/anythingllm:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - STORAGE_DIR=/app/server/storage + volumes: + - << appdata_dir >>/<< service_name >>:/app/server/storage + ports: + - "<< port >>:3001" + cap_add: + - SYS_ADMIN + restart: unless-stopped diff --git a/apps/anythingllm/template.json b/apps/anythingllm/template.json new file mode 100644 index 0000000..a085536 --- /dev/null +++ b/apps/anythingllm/template.json @@ -0,0 +1,61 @@ +{ + "kind": "compose", + "metadata": { + "name": "AnythingLLM", + "description": "Praat met je eigen documenten: laadt bestanden in een vectordatabase en gebruikt die als context. Werkt met Ollama.", + "tags": [ + "ai", + "llm", + "rag", + "documenten" + ], + "icon": { + "provider": "selfhst", + "id": "anythingllm" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ai", + "documenten" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "anythingllm", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8142, + "required": true, + "description": "Standaard 3001; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/authentik/files/compose.yaml b/apps/authentik/files/compose.yaml new file mode 100644 index 0000000..d473e6f --- /dev/null +++ b/apps/authentik/files/compose.yaml @@ -0,0 +1,58 @@ +services: + << service_name >>: + image: ghcr.io/goauthentik/server:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - AUTHENTIK_SECRET_KEY=<< secret_key >> + - AUTHENTIK_POSTGRESQL__HOST=<< service_name >>-db + - AUTHENTIK_POSTGRESQL__USER=authentik + - AUTHENTIK_POSTGRESQL__NAME=authentik + - AUTHENTIK_POSTGRESQL__PASSWORD=<< db_password >> + - AUTHENTIK_REDIS__HOST=<< service_name >>-redis + volumes: + - << appdata_dir >>/<< service_name >>:/media + - << appdata_dir >>/<< service_name >>-templates:/templates + command: server + ports: + - "<< port >>:9000" + depends_on: + - << service_name >>-db + - << service_name >>-redis + restart: unless-stopped + << service_name >>-worker: + image: ghcr.io/goauthentik/server:latest + container_name: << service_name >>-worker + command: worker + environment: + - AUTHENTIK_SECRET_KEY=<< secret_key >> + - AUTHENTIK_POSTGRESQL__HOST=<< service_name >>-db + - AUTHENTIK_POSTGRESQL__USER=authentik + - AUTHENTIK_POSTGRESQL__NAME=authentik + - AUTHENTIK_POSTGRESQL__PASSWORD=<< db_password >> + - AUTHENTIK_REDIS__HOST=<< service_name >>-redis + volumes: + - << appdata_dir >>/<< service_name >>/media:/media + - << appdata_dir >>/<< service_name >>-templates:/templates + - /var/run/docker.sock:/var/run/docker.sock + depends_on: + - << service_name >>-db + - << service_name >>-redis + restart: unless-stopped + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=authentik + - POSTGRES_USER=authentik + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped + << service_name >>-redis: + image: valkey/valkey:8-alpine + container_name: << service_name >>-redis + command: valkey-server --save 60 1 + volumes: + - << appdata_dir >>/<< service_name >>-redis:/data + restart: unless-stopped diff --git a/apps/authentik/template.json b/apps/authentik/template.json new file mode 100644 index 0000000..7579807 --- /dev/null +++ b/apps/authentik/template.json @@ -0,0 +1,86 @@ +{ + "kind": "compose", + "metadata": { + "name": "Authentik", + "description": "Volledige identiteitsserver: OIDC, SAML, LDAP en passkeys, met een visuele opbouw van je inlogstappen. De zwaardere broer van Authelia.", + "tags": [ + "sso", + "oidc", + "saml", + "ldap", + "authenticatie" + ], + "icon": { + "provider": "selfhst", + "id": "authentik" + }, + "version": { + "name": "latest" + }, + "categories": [ + "beveiliging" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "authentik", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8133, + "required": true, + "description": "Standaard 9000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "secret_key", + "type": "str", + "title": "Geheime sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Ondertekent de sessies; verlies je hem, dan moet iedereen opnieuw inloggen" + } + ] + } + ] +} diff --git a/apps/baby-buddy/files/compose.yaml b/apps/baby-buddy/files/compose.yaml index 04b966f..2ac12d8 100644 --- a/apps/baby-buddy/files/compose.yaml +++ b/apps/baby-buddy/files/compose.yaml @@ -1,6 +1,6 @@ services: << service_name >>: - image: ghcr.io/babybuddy/babybuddy:latest + image: lscr.io/linuxserver/babybuddy:latest container_name: << service_name >> ports: - "<< port >>:8000" @@ -12,5 +12,5 @@ services: - ALLOWED_HOSTS=<< allowed_hosts >> - CSRF_TRUSTED_ORIGINS=http://<< allowed_hosts >> volumes: - - << appdata_dir >>/<< service_name >>/config:/app/data + - << appdata_dir >>/<< service_name >>:/config restart: unless-stopped diff --git a/apps/backrest/files/compose.yaml b/apps/backrest/files/compose.yaml new file mode 100644 index 0000000..df4b601 --- /dev/null +++ b/apps/backrest/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: garethgeorge/backrest:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/config + - << appdata_dir >>/<< service_name >>-data:/data + - << appdata_dir >>/<< service_name >>-cache:/cache + - << bron_dir >>:/userdata:ro + ports: + - "<< port >>:9898" + restart: unless-stopped diff --git a/apps/backrest/template.json b/apps/backrest/template.json new file mode 100644 index 0000000..91ad7a0 --- /dev/null +++ b/apps/backrest/template.json @@ -0,0 +1,72 @@ +{ + "kind": "compose", + "metadata": { + "name": "Backrest", + "description": "Webinterface voor restic: back-upschema's, snapshots doorbladeren en terugzetten, zonder de commandoregel.", + "tags": [ + "backup", + "restic", + "opslag" + ], + "icon": { + "provider": "selfhst", + "id": "backrest" + }, + "version": { + "name": "latest" + }, + "categories": [ + "opslag" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "backrest", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8127, + "required": true, + "description": "Standaard 9898; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "bron_dir", + "type": "str", + "title": "Map om te back-uppen", + "default": "/opt/serverup", + "required": true, + "description": "Wordt alleen-lezen gekoppeld als /userdata" + } + ] + } + ] +} diff --git a/apps/code-server/files/compose.yaml b/apps/code-server/files/compose.yaml new file mode 100644 index 0000000..781f96c --- /dev/null +++ b/apps/code-server/files/compose.yaml @@ -0,0 +1,16 @@ +services: + << service_name >>: + image: lscr.io/linuxserver/code-server:latest + container_name: << service_name >> + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + - UMASK=002 + - PASSWORD=<< wachtwoord >> + - DEFAULT_WORKSPACE=/config/workspace + volumes: + - << appdata_dir >>/<< service_name >>:/config + ports: + - "<< port >>:8443" + restart: unless-stopped diff --git a/apps/code-server/template.json b/apps/code-server/template.json new file mode 100644 index 0000000..cf5be6c --- /dev/null +++ b/apps/code-server/template.json @@ -0,0 +1,93 @@ +{ + "kind": "compose", + "metadata": { + "name": "code-server", + "description": "Visual Studio Code in je browser, draaiend op de server. Handig om vanaf een tablet of een andere machine te werken.", + "tags": [ + "editor", + "ontwikkeling", + "code" + ], + "icon": { + "provider": "selfhst", + "id": "vscode" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ontwikkeling" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "codeserver", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8161, + "required": true, + "description": "Standaard 8443; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Gebruiker", + "items": [ + { + "name": "puid", + "type": "int", + "title": "Gebruikers-ID (PUID)", + "default": 1000, + "required": true, + "description": "`id -u` op je server; bepaalt de eigenaar van de bestanden" + }, + { + "name": "pgid", + "type": "int", + "title": "Groeps-ID (PGID)", + "default": 1000, + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "wachtwoord", + "type": "str", + "title": "Wachtwoord voor de editor", + "default": "", + "required": true, + "secret": true, + "eigen_invoer": true + } + ] + } + ] +} diff --git a/apps/convertx/files/compose.yaml b/apps/convertx/files/compose.yaml new file mode 100644 index 0000000..2bd9b6a --- /dev/null +++ b/apps/convertx/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: ghcr.io/c4illin/convertx:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - JWT_SECRET=<< jwt_secret >> + - ACCOUNT_REGISTRATION=false + volumes: + - << appdata_dir >>/<< service_name >>:/app/data + ports: + - "<< port >>:3000" + restart: unless-stopped diff --git a/apps/convertx/template.json b/apps/convertx/template.json new file mode 100644 index 0000000..2ff62ca --- /dev/null +++ b/apps/convertx/template.json @@ -0,0 +1,73 @@ +{ + "kind": "compose", + "metadata": { + "name": "ConvertX", + "description": "Zet bestanden om naar een ander formaat in je browser: afbeeldingen, documenten, video en geluid, zonder uploaddienst van derden.", + "tags": [ + "conversie", + "bestanden", + "gereedschap" + ], + "icon": { + "provider": "selfhst", + "id": "convertx" + }, + "version": { + "name": "latest" + }, + "categories": [ + "productiviteit" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "convertx", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8176, + "required": true, + "description": "Standaard 3000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "jwt_secret", + "type": "str", + "title": "JWT-sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/crowdsec/files/compose.yaml b/apps/crowdsec/files/compose.yaml new file mode 100644 index 0000000..27eef0d --- /dev/null +++ b/apps/crowdsec/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: crowdsecurity/crowdsec:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - COLLECTIONS=crowdsecurity/linux crowdsecurity/nginx + volumes: + - << appdata_dir >>/<< service_name >>:/etc/crowdsec + - << appdata_dir >>/<< service_name >>-data:/var/lib/crowdsec/data + - << log_dir >>:/var/log/host:ro + ports: + - "<< port >>:8080" + restart: unless-stopped diff --git a/apps/crowdsec/template.json b/apps/crowdsec/template.json new file mode 100644 index 0000000..d89201a --- /dev/null +++ b/apps/crowdsec/template.json @@ -0,0 +1,72 @@ +{ + "kind": "compose", + "metadata": { + "name": "CrowdSec", + "description": "Leest je logbestanden mee en blokkeert aanvallers, met een blocklijst die door alle gebruikers samen wordt opgebouwd.", + "tags": [ + "beveiliging", + "firewall", + "logs" + ], + "icon": { + "provider": "selfhst", + "id": "crowdsec" + }, + "version": { + "name": "latest" + }, + "categories": [ + "beveiliging" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "crowdsec", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "API-poort", + "default": 8130, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "log_dir", + "type": "str", + "title": "Logmap van de host", + "default": "/var/log", + "required": true, + "description": "Wordt alleen-lezen gekoppeld; hier leest CrowdSec in mee" + } + ] + } + ] +} diff --git a/apps/dawarich/files/compose.yaml b/apps/dawarich/files/compose.yaml new file mode 100644 index 0000000..09dd6b5 --- /dev/null +++ b/apps/dawarich/files/compose.yaml @@ -0,0 +1,40 @@ +services: + << service_name >>: + image: freikin/dawarich:latest + container_name: << service_name >> + environment: + - RAILS_ENV=development + - DATABASE_HOST=<< service_name >>-db + - DATABASE_USERNAME=dawarich + - DATABASE_PASSWORD=<< db_password >> + - DATABASE_NAME=dawarich + - REDIS_URL=redis://<< service_name >>-redis:6379 + - APPLICATION_HOSTS=<< app_hosts >> + - TIME_ZONE=<< timezone >> + - SECRET_KEY_BASE=<< secret_key_base >> + volumes: + - << appdata_dir >>/<< service_name >>:/var/app/public + command: ["web-entrypoint.sh", "bin/rails", "server", "-p", "3000", "-b", "::"] + ports: + - "<< port >>:3000" + depends_on: + - << service_name >>-db + - << service_name >>-redis + restart: unless-stopped + << service_name >>-db: + image: postgis/postgis:16-3.4-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=dawarich + - POSTGRES_USER=dawarich + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped + << service_name >>-redis: + image: valkey/valkey:8-alpine + container_name: << service_name >>-redis + command: valkey-server --save 60 1 + volumes: + - << appdata_dir >>/<< service_name >>-redis:/data + restart: unless-stopped diff --git a/apps/dawarich/template.json b/apps/dawarich/template.json new file mode 100644 index 0000000..f0c2937 --- /dev/null +++ b/apps/dawarich/template.json @@ -0,0 +1,97 @@ +{ + "kind": "compose", + "metadata": { + "name": "Dawarich", + "description": "Je eigen locatiegeschiedenis, als vervanging van Google Maps Timeline. Importeert je oude Google-export.", + "tags": [ + "locatie", + "kaart", + "privacy" + ], + "icon": { + "provider": "selfhst", + "id": "dawarich" + }, + "version": { + "name": "latest" + }, + "categories": [ + "gezin", + "beveiliging" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "dawarich", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8152, + "required": true, + "description": "Standaard 3000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "app_hosts", + "type": "str", + "title": "Toegestane adressen", + "default": "localhost", + "required": true, + "description": "Komma-gescheiden; Rails weigert verzoeken van andere namen" + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "secret_key_base", + "type": "str", + "title": "Rails-sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/dockge/files/compose.yaml b/apps/dockge/files/compose.yaml new file mode 100644 index 0000000..82c8724 --- /dev/null +++ b/apps/dockge/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: louislam/dockge:1 + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - DOCKGE_STACKS_DIR=/opt/stacks + volumes: + - << appdata_dir >>/<< service_name >>:/app/data + - /var/run/docker.sock:/var/run/docker.sock + - << stacks_dir >>:/opt/stacks + ports: + - "<< port >>:5001" + restart: unless-stopped diff --git a/apps/dockge/template.json b/apps/dockge/template.json new file mode 100644 index 0000000..e1118d3 --- /dev/null +++ b/apps/dockge/template.json @@ -0,0 +1,73 @@ +{ + "kind": "compose", + "metadata": { + "name": "Dockge", + "description": "Beheert je compose-stacks met een interface die het compose-bestand laat zien in plaats van te verstoppen. Lichter dan Portainer.", + "tags": [ + "docker", + "beheer", + "containers" + ], + "icon": { + "provider": "selfhst", + "id": "dockge" + }, + "version": { + "name": "latest" + }, + "categories": [ + "beheer" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "dockge", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8121, + "required": true, + "description": "Standaard 5001; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "stacks_dir", + "type": "str", + "title": "Stacks-map", + "default": "/opt/stacks", + "required": true, + "description": "Waar Dockge de compose-bestanden neerzet", + "help": "Dockge bewaart hier zijn eigen stacks. Wijs dit niet naar de library van Server Up: dan beheren twee programma's dezelfde mappen en overschrijven ze elkaars werk." + } + ] + } + ] +} diff --git a/apps/docmost/files/compose.yaml b/apps/docmost/files/compose.yaml new file mode 100644 index 0000000..1fcee05 --- /dev/null +++ b/apps/docmost/files/compose.yaml @@ -0,0 +1,35 @@ +services: + << service_name >>: + image: docmost/docmost:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - APP_URL=<< app_url >> + - APP_SECRET=<< app_secret >> + - DATABASE_URL=postgresql://docmost:<< db_password >>@<< service_name >>-db:5432/docmost?schema=public + - REDIS_URL=redis://<< service_name >>-redis:6379 + volumes: + - << appdata_dir >>/<< service_name >>:/app/data/storage + ports: + - "<< port >>:3000" + depends_on: + - << service_name >>-db + - << service_name >>-redis + restart: unless-stopped + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=docmost + - POSTGRES_USER=docmost + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped + << service_name >>-redis: + image: valkey/valkey:8-alpine + container_name: << service_name >>-redis + command: valkey-server --save 60 1 + volumes: + - << appdata_dir >>/<< service_name >>-redis:/data + restart: unless-stopped diff --git a/apps/docmost/template.json b/apps/docmost/template.json new file mode 100644 index 0000000..75c5232 --- /dev/null +++ b/apps/docmost/template.json @@ -0,0 +1,96 @@ +{ + "kind": "compose", + "metadata": { + "name": "Docmost", + "description": "Documenten samen bewerken in realtime, met werkruimtes en rechten. Vergelijkbaar met Confluence of Notion.", + "tags": [ + "wiki", + "documenten", + "samenwerken" + ], + "icon": { + "provider": "selfhst", + "id": "docmost" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten", + "productiviteit" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "docmost", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8157, + "required": true, + "description": "Standaard 3000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "app_url", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8157", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "app_secret", + "type": "str", + "title": "Geheime sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/donetick/files/compose.yaml b/apps/donetick/files/compose.yaml new file mode 100644 index 0000000..afdb1c9 --- /dev/null +++ b/apps/donetick/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: donetick/donetick:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - DT_ENV=selfhosted + - DT_SQLITE_PATH=/donetick-data/donetick.db + - DT_JWT_SECRET=<< jwt_secret >> + volumes: + - << appdata_dir >>/<< service_name >>:/donetick-data + ports: + - "<< port >>:2021" + restart: unless-stopped diff --git a/apps/donetick/template.json b/apps/donetick/template.json new file mode 100644 index 0000000..85a3597 --- /dev/null +++ b/apps/donetick/template.json @@ -0,0 +1,74 @@ +{ + "kind": "compose", + "metadata": { + "name": "Donetick", + "description": "Terugkerende klusjes verdelen in huis, met beurten die doorschuiven en een melding als jij aan de beurt bent.", + "tags": [ + "taken", + "huishouden", + "klusjes" + ], + "icon": { + "provider": "selfhst", + "id": "donetick" + }, + "version": { + "name": "latest" + }, + "categories": [ + "gezin", + "productiviteit" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "donetick", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8151, + "required": true, + "description": "Standaard 2021; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "jwt_secret", + "type": "str", + "title": "JWT-sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/element/files/compose.yaml b/apps/element/files/compose.yaml new file mode 100644 index 0000000..d705ac5 --- /dev/null +++ b/apps/element/files/compose.yaml @@ -0,0 +1,11 @@ +services: + << service_name >>: + image: vectorim/element-web:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - ./config.json:/app/config.json:ro + ports: + - "<< port >>:80" + restart: unless-stopped diff --git a/apps/element/files/config.json b/apps/element/files/config.json new file mode 100644 index 0000000..4e01b03 --- /dev/null +++ b/apps/element/files/config.json @@ -0,0 +1,10 @@ +{ + "default_server_config": { + "m.homeserver": { + "base_url": "<< homeserver >>", + "server_name": "<< server_name >>" + } + }, + "brand": "Element", + "disable_guests": true +} diff --git a/apps/element/template.json b/apps/element/template.json new file mode 100644 index 0000000..59780a5 --- /dev/null +++ b/apps/element/template.json @@ -0,0 +1,77 @@ +{ + "kind": "compose", + "metadata": { + "name": "Element", + "description": "Webclient voor Matrix. Wijst standaard naar matrix.org; koppel hem aan je eigen Synapse.", + "tags": [ + "matrix", + "chat", + "communicatie" + ], + "icon": { + "provider": "selfhst", + "id": "element" + }, + "version": { + "name": "latest" + }, + "categories": [ + "communicatie" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "element", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8136, + "required": true, + "description": "Standaard 80; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "homeserver", + "type": "str", + "title": "Adres van je homeserver", + "default": "https://matrix.example.com", + "required": true, + "connect": { + "app": "synapse", + "scheme": "http", + "port": 8008 + }, + "help": "Het adres van de Matrix-server waar deze client op inlogt. Draai je Synapse zelf, kies die dan hier." + }, + { + "name": "server_name", + "type": "str", + "title": "Servernaam", + "default": "matrix.example.com", + "required": true, + "description": "Wordt getoond op het inlogscherm" + } + ] + } + ] +} diff --git a/apps/emby/files/compose.yaml b/apps/emby/files/compose.yaml new file mode 100644 index 0000000..e5e575a --- /dev/null +++ b/apps/emby/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: emby/embyserver:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - UID=<< puid >> + - GID=<< pgid >> + volumes: + - << appdata_dir >>/<< service_name >>:/config + - << data_root >>/media:/data/media:ro + ports: + - "<< port >>:8096" + restart: unless-stopped diff --git a/apps/emby/template.json b/apps/emby/template.json new file mode 100644 index 0000000..c93acd1 --- /dev/null +++ b/apps/emby/template.json @@ -0,0 +1,89 @@ +{ + "kind": "compose", + "metadata": { + "name": "Emby", + "description": "Mediaserver voor films, series en muziek, met eigen apps voor tv en telefoon. Alternatief voor Jellyfin en Plex.", + "tags": [ + "media", + "streaming", + "films", + "series" + ], + "icon": { + "provider": "selfhst", + "id": "emby" + }, + "version": { + "name": "latest" + }, + "categories": [ + "media" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "emby", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8175, + "required": true, + "description": "Standaard 8096; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "data_root", + "type": "str", + "title": "Gedeelde datamap", + "default": "/mnt/data", + "required": true, + "description": "Eén map met je media, gekoppeld als /data", + "help": "Media en downloads horen onder één map te staan, die als /data in elke container komt. Alleen dan kan een voltooide download met een hardlink naar je bibliotheek: geen kopie, geen dubbele opslag, en je torrent blijft seeden. Zet je ze op gescheiden paden, dan kopieert elke download opnieuw. Eronder: media/films, media/series, torrents/ en usenet/." + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Gebruiker", + "items": [ + { + "name": "puid", + "type": "int", + "title": "Gebruikers-ID (PUID)", + "default": 1000, + "required": true, + "description": "`id -u` op je server; bepaalt de eigenaar van de bestanden" + }, + { + "name": "pgid", + "type": "int", + "title": "Groeps-ID (PGID)", + "default": 1000, + "required": true + } + ] + } + ] +} diff --git a/apps/espocrm/files/compose.yaml b/apps/espocrm/files/compose.yaml new file mode 100644 index 0000000..96588fb --- /dev/null +++ b/apps/espocrm/files/compose.yaml @@ -0,0 +1,31 @@ +services: + << service_name >>: + image: espocrm/espocrm:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - ESPOCRM_DATABASE_HOST=<< service_name >>-db + - ESPOCRM_DATABASE_NAME=espocrm + - ESPOCRM_DATABASE_USER=espocrm + - ESPOCRM_DATABASE_PASSWORD=<< db_password >> + - ESPOCRM_ADMIN_USERNAME=<< admin_user >> + - ESPOCRM_ADMIN_PASSWORD=<< admin_password >> + - ESPOCRM_SITE_URL=<< app_url >> + volumes: + - << appdata_dir >>/<< service_name >>:/var/www/html + ports: + - "<< port >>:80" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: mariadb:11 + container_name: << service_name >>-db + environment: + - MARIADB_DATABASE=espocrm + - MARIADB_USER=espocrm + - MARIADB_PASSWORD=<< db_password >> + - MARIADB_ROOT_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/mysql + restart: unless-stopped diff --git a/apps/espocrm/template.json b/apps/espocrm/template.json new file mode 100644 index 0000000..7547291 --- /dev/null +++ b/apps/espocrm/template.json @@ -0,0 +1,102 @@ +{ + "kind": "compose", + "metadata": { + "name": "EspoCRM", + "description": "Klantrelatiebeheer: contacten, kansen, offertes en e-mail op één plek, met eigen velden en schermen.", + "tags": [ + "crm", + "klanten", + "verkoop" + ], + "icon": { + "provider": "selfhst", + "id": "espocrm" + }, + "version": { + "name": "latest" + }, + "categories": [ + "zakelijk" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "espocrm", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8171, + "required": true, + "description": "Standaard 80; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "admin_user", + "type": "str", + "title": "Beheerdersnaam", + "default": "admin", + "required": true + }, + { + "name": "app_url", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8171", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "admin_password", + "type": "str", + "title": "Beheerderswachtwoord", + "default": "", + "required": true, + "secret": true, + "eigen_invoer": true + } + ] + } + ] +} diff --git a/apps/forgejo/files/compose.yaml b/apps/forgejo/files/compose.yaml index 6d96d0a..2b8ce42 100644 --- a/apps/forgejo/files/compose.yaml +++ b/apps/forgejo/files/compose.yaml @@ -1,6 +1,6 @@ services: << service_name >>: - image: codeberg.org/forgejo/forgejo:latest + image: codeberg.org/forgejo/forgejo:13 container_name: << service_name >> ports: - "<< port_web >>:3000" diff --git a/apps/freescout/files/compose.yaml b/apps/freescout/files/compose.yaml new file mode 100644 index 0000000..5013bb3 --- /dev/null +++ b/apps/freescout/files/compose.yaml @@ -0,0 +1,33 @@ +services: + << service_name >>: + image: tiredofit/freescout:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - SITE_URL=<< app_url >> + - DB_TYPE=mariadb + - DB_HOST=<< service_name >>-db + - DB_NAME=freescout + - DB_USER=freescout + - DB_PASS=<< db_password >> + - ADMIN_EMAIL=<< admin_email >> + - ADMIN_PASS=<< admin_password >> + - DISPLAY_ERRORS=FALSE + volumes: + - << appdata_dir >>/<< service_name >>:/data + ports: + - "<< port >>:80" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: mariadb:11 + container_name: << service_name >>-db + environment: + - MARIADB_DATABASE=freescout + - MARIADB_USER=freescout + - MARIADB_PASSWORD=<< db_password >> + - MARIADB_ROOT_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/mysql + restart: unless-stopped diff --git a/apps/freescout/template.json b/apps/freescout/template.json new file mode 100644 index 0000000..1126828 --- /dev/null +++ b/apps/freescout/template.json @@ -0,0 +1,104 @@ +{ + "kind": "compose", + "metadata": { + "name": "FreeScout", + "description": "Gedeelde postbus voor klantvragen: e-mails worden tickets, met notities en toewijzing per medewerker.", + "tags": [ + "helpdesk", + "tickets", + "e-mail", + "klanten" + ], + "icon": { + "provider": "selfhst", + "id": "freescout" + }, + "version": { + "name": "latest" + }, + "categories": [ + "zakelijk", + "communicatie" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "freescout", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8170, + "required": true, + "description": "Standaard 80; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "app_url", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8170", + "required": true + }, + { + "name": "admin_email", + "type": "str", + "title": "E-mailadres beheerder", + "default": "admin@example.com", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "admin_password", + "type": "str", + "title": "Beheerderswachtwoord", + "default": "", + "required": true, + "secret": true, + "eigen_invoer": true + } + ] + } + ] +} diff --git a/apps/gatus/files/compose.yaml b/apps/gatus/files/compose.yaml new file mode 100644 index 0000000..c185b38 --- /dev/null +++ b/apps/gatus/files/compose.yaml @@ -0,0 +1,12 @@ +services: + << service_name >>: + image: twinproduction/gatus:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/config + - ./config.yaml:/config/config.yaml + ports: + - "<< port >>:8080" + restart: unless-stopped diff --git a/apps/gatus/files/config.yaml b/apps/gatus/files/config.yaml new file mode 100644 index 0000000..a7d805f --- /dev/null +++ b/apps/gatus/files/config.yaml @@ -0,0 +1,6 @@ +endpoints: + - name: server-up + url: "http://<< service_name >>:8080/health" + interval: 60s + conditions: + - "[STATUS] == 200" diff --git a/apps/gatus/template.json b/apps/gatus/template.json new file mode 100644 index 0000000..9677644 --- /dev/null +++ b/apps/gatus/template.json @@ -0,0 +1,59 @@ +{ + "kind": "compose", + "metadata": { + "name": "Gatus", + "description": "Bewaakt je diensten en toont per dienst een statuspagina met geschiedenis. Stuurt bericht als iets eruit ligt.", + "tags": [ + "monitoring", + "status", + "uptime" + ], + "icon": { + "provider": "selfhst", + "id": "gatus" + }, + "version": { + "name": "latest" + }, + "categories": [ + "monitoring" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "gatus", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8125, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/ghostfolio/files/compose.yaml b/apps/ghostfolio/files/compose.yaml new file mode 100644 index 0000000..9d56f22 --- /dev/null +++ b/apps/ghostfolio/files/compose.yaml @@ -0,0 +1,37 @@ +services: + << service_name >>: + image: ghostfolio/ghostfolio:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - DATABASE_URL=postgresql://ghostfolio:<< db_password >>@<< service_name >>-db:5432/ghostfolio?sslmode=prefer + - REDIS_HOST=<< service_name >>-redis + - REDIS_PORT=6379 + - ACCESS_TOKEN_SALT=<< access_token_salt >> + - JWT_SECRET_KEY=<< jwt_secret >> + - NODE_ENV=production + volumes: + - << appdata_dir >>/<< service_name >>:/tmp/ghostfolio + ports: + - "<< port >>:3333" + depends_on: + - << service_name >>-db + - << service_name >>-redis + restart: unless-stopped + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=ghostfolio + - POSTGRES_USER=ghostfolio + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped + << service_name >>-redis: + image: valkey/valkey:8-alpine + container_name: << service_name >>-redis + command: valkey-server --save 60 1 + volumes: + - << appdata_dir >>/<< service_name >>-redis:/data + restart: unless-stopped diff --git a/apps/ghostfolio/template.json b/apps/ghostfolio/template.json new file mode 100644 index 0000000..491062b --- /dev/null +++ b/apps/ghostfolio/template.json @@ -0,0 +1,92 @@ +{ + "kind": "compose", + "metadata": { + "name": "Ghostfolio", + "description": "Houdt je beleggingen bij over meerdere rekeningen heen, met spreiding, rendement en een tijdlijn.", + "tags": [ + "beleggen", + "portefeuille", + "financien" + ], + "icon": { + "provider": "selfhst", + "id": "ghostfolio" + }, + "version": { + "name": "latest" + }, + "categories": [ + "financien" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "ghostfolio", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8144, + "required": true, + "description": "Standaard 3333; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "access_token_salt", + "type": "str", + "title": "Salt voor toegangstokens", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + }, + { + "name": "jwt_secret", + "type": "str", + "title": "JWT-sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/gitea/files/compose.yaml b/apps/gitea/files/compose.yaml new file mode 100644 index 0000000..ac9e2e7 --- /dev/null +++ b/apps/gitea/files/compose.yaml @@ -0,0 +1,17 @@ +services: + << service_name >>: + image: gitea/gitea:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - USER_UID=<< puid >> + - USER_GID=<< pgid >> + - GITEA__database__DB_TYPE=sqlite3 + - GITEA__server__ROOT_URL=<< root_url >> + - GITEA__server__SSH_PORT=<< port_ssh >> + volumes: + - << appdata_dir >>/<< service_name >>:/data + ports: + - "<< port >>:3000" + - "<< port_ssh >>:22" + restart: unless-stopped diff --git a/apps/gitea/template.json b/apps/gitea/template.json new file mode 100644 index 0000000..d19af93 --- /dev/null +++ b/apps/gitea/template.json @@ -0,0 +1,100 @@ +{ + "kind": "compose", + "metadata": { + "name": "Gitea", + "description": "Git-hosting met issues, pull requests en een ingebouwde registry. Het project waar Forgejo uit voortkwam.", + "tags": [ + "git", + "code", + "ontwikkeling" + ], + "icon": { + "provider": "selfhst", + "id": "gitea" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ontwikkeling" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "gitea", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8159, + "required": true, + "description": "Standaard 3000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "port_ssh", + "type": "int", + "title": "SSH-poort", + "default": 2223, + "required": true, + "description": "Voor git via ssh" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Gebruiker", + "items": [ + { + "name": "puid", + "type": "int", + "title": "Gebruikers-ID (PUID)", + "default": 1000, + "required": true, + "description": "`id -u` op je server; bepaalt de eigenaar van de bestanden" + }, + { + "name": "pgid", + "type": "int", + "title": "Groeps-ID (PGID)", + "default": 1000, + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "root_url", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8159/", + "required": true, + "description": "Met een schuine streep aan het eind" + } + ] + } + ] +} diff --git a/apps/glance/files/compose.yaml b/apps/glance/files/compose.yaml new file mode 100644 index 0000000..036f784 --- /dev/null +++ b/apps/glance/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: glanceapp/glance:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/app/config + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./glance.yml:/app/config/glance.yml + ports: + - "<< port >>:8080" + restart: unless-stopped diff --git a/apps/glance/files/glance.yml b/apps/glance/files/glance.yml new file mode 100644 index 0000000..542e317 --- /dev/null +++ b/apps/glance/files/glance.yml @@ -0,0 +1,7 @@ +pages: + - name: Start + columns: + - size: full + widgets: + - type: docker-containers + - type: server-stats diff --git a/apps/glance/template.json b/apps/glance/template.json new file mode 100644 index 0000000..56a46db --- /dev/null +++ b/apps/glance/template.json @@ -0,0 +1,59 @@ +{ + "kind": "compose", + "metadata": { + "name": "Glance", + "description": "Startpagina die je feeds, servercijfers, weer en agenda's op één scherm zet. Volledig in te richten met een configuratiebestand.", + "tags": [ + "dashboard", + "startpagina", + "overzicht" + ], + "icon": { + "provider": "selfhst", + "id": "glance" + }, + "version": { + "name": "latest" + }, + "categories": [ + "beheer" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "glance", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8124, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/headscale/files/compose.yaml b/apps/headscale/files/compose.yaml new file mode 100644 index 0000000..2257590 --- /dev/null +++ b/apps/headscale/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: headscale/headscale:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/etc/headscale + - << appdata_dir >>/<< service_name >>-lib:/var/lib/headscale + - ./config.yaml:/etc/headscale/config.yaml + command: serve + ports: + - "<< port >>:8080" + restart: unless-stopped diff --git a/apps/headscale/files/config.yaml b/apps/headscale/files/config.yaml new file mode 100644 index 0000000..fe2ae48 --- /dev/null +++ b/apps/headscale/files/config.yaml @@ -0,0 +1,11 @@ +server_url: http://<< server_url >> +listen_addr: 0.0.0.0:8080 +metrics_listen_addr: 127.0.0.1:9090 +noise: + private_key_path: /var/lib/headscale/noise_private.key +prefixes: + v4: 100.64.0.0/10 +database: + type: sqlite + sqlite: + path: /var/lib/headscale/db.sqlite diff --git a/apps/headscale/template.json b/apps/headscale/template.json new file mode 100644 index 0000000..7ccdd62 --- /dev/null +++ b/apps/headscale/template.json @@ -0,0 +1,74 @@ +{ + "kind": "compose", + "metadata": { + "name": "Headscale", + "description": "Eigen coördinatieserver voor Tailscale-clients, zodat je mesh-VPN niet van een externe dienst afhangt. Let op: Zet Headscale niet achter een andere reverse proxy van jezelf zonder websockets door te laten; de clients houden een verbinding open.", + "tags": [ + "vpn", + "netwerk", + "tailscale", + "wireguard" + ], + "icon": { + "provider": "selfhst", + "id": "headscale" + }, + "version": { + "name": "latest" + }, + "categories": [ + "netwerk", + "beveiliging" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "headscale", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8128, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "server_url", + "type": "str", + "title": "Publiek adres", + "default": "headscale.example.com:8128", + "required": true, + "description": "Het adres waarop je clients Headscale bereiken" + } + ] + } + ] +} diff --git a/apps/homebox/files/compose.yaml b/apps/homebox/files/compose.yaml new file mode 100644 index 0000000..4b5f979 --- /dev/null +++ b/apps/homebox/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: ghcr.io/sysadminsmedia/homebox:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - HBOX_LOG_LEVEL=info + - HBOX_OPTIONS_ALLOW_REGISTRATION=false + volumes: + - << appdata_dir >>/<< service_name >>:/data + ports: + - "<< port >>:7745" + restart: unless-stopped diff --git a/apps/homebox/template.json b/apps/homebox/template.json new file mode 100644 index 0000000..dad2fda --- /dev/null +++ b/apps/homebox/template.json @@ -0,0 +1,59 @@ +{ + "kind": "compose", + "metadata": { + "name": "Homebox", + "description": "Houdt bij wat je in huis hebt: waar het ligt, wat het kostte, wanneer de garantie afloopt. Met etiketten en QR-codes.", + "tags": [ + "inventaris", + "huishouden", + "spullen" + ], + "icon": { + "provider": "selfhst", + "id": "homebox" + }, + "version": { + "name": "latest" + }, + "categories": [ + "gezin" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "homebox", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8149, + "required": true, + "description": "Standaard 7745; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/kiwix/files/compose.yaml b/apps/kiwix/files/compose.yaml new file mode 100644 index 0000000..c0c44ac --- /dev/null +++ b/apps/kiwix/files/compose.yaml @@ -0,0 +1,12 @@ +services: + << service_name >>: + image: ghcr.io/kiwix/kiwix-serve:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/data + command: "*.zim" + ports: + - "<< port >>:8080" + restart: unless-stopped diff --git a/apps/kiwix/template.json b/apps/kiwix/template.json new file mode 100644 index 0000000..9ff4204 --- /dev/null +++ b/apps/kiwix/template.json @@ -0,0 +1,59 @@ +{ + "kind": "compose", + "metadata": { + "name": "Kiwix", + "description": "Serveert offline kopieën van Wikipedia, Stack Overflow en meer uit zim-bestanden. Werkt zonder internet. Let op: Zet eerst een of meer .zim-bestanden in de datamap; download ze op library.kiwix.org. Zonder bestand start de container niet.", + "tags": [ + "offline", + "wikipedia", + "naslag" + ], + "icon": { + "provider": "selfhst", + "id": "kiwix" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "kiwix", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8158, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/leantime/files/compose.yaml b/apps/leantime/files/compose.yaml new file mode 100644 index 0000000..273ed80 --- /dev/null +++ b/apps/leantime/files/compose.yaml @@ -0,0 +1,30 @@ +services: + << service_name >>: + image: leantime/leantime:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - LEAN_DB_HOST=<< service_name >>-db + - LEAN_DB_USER=leantime + - LEAN_DB_PASSWORD=<< db_password >> + - LEAN_DB_DATABASE=leantime + - LEAN_APP_URL=<< app_url >> + - LEAN_SESSION_PASSWORD=<< session_password >> + volumes: + - << appdata_dir >>/<< service_name >>:/var/www/html/public/userfiles + ports: + - "<< port >>:8080" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: mariadb:11 + container_name: << service_name >>-db + environment: + - MARIADB_DATABASE=leantime + - MARIADB_USER=leantime + - MARIADB_PASSWORD=<< db_password >> + - MARIADB_ROOT_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/mysql + restart: unless-stopped diff --git a/apps/leantime/template.json b/apps/leantime/template.json new file mode 100644 index 0000000..b720bed --- /dev/null +++ b/apps/leantime/template.json @@ -0,0 +1,96 @@ +{ + "kind": "compose", + "metadata": { + "name": "Leantime", + "description": "Projectbeheer voor kleine teams: doelen, taken, tijdregistratie en een planbord, zonder de overdaad van de grote pakketten.", + "tags": [ + "projecten", + "taken", + "planning" + ], + "icon": { + "provider": "selfhst", + "id": "leantime" + }, + "version": { + "name": "latest" + }, + "categories": [ + "productiviteit", + "zakelijk" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "leantime", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8173, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "app_url", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8173", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "session_password", + "type": "str", + "title": "Sleutel voor de sessies", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/librechat/files/compose.yaml b/apps/librechat/files/compose.yaml new file mode 100644 index 0000000..88e7a1e --- /dev/null +++ b/apps/librechat/files/compose.yaml @@ -0,0 +1,29 @@ +services: + << service_name >>: + image: ghcr.io/danny-avila/librechat:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - HOST=0.0.0.0 + - PORT=3080 + - MONGO_URI=mongodb://app:<< db_password >>@<< service_name >>-db:27017/LibreChat?authSource=admin + - CREDS_KEY=<< creds_key >> + - CREDS_IV=<< creds_iv >> + - JWT_SECRET=<< jwt_secret >> + - JWT_REFRESH_SECRET=<< jwt_refresh_secret >> + volumes: + - << appdata_dir >>/<< service_name >>:/app/client/public/images + ports: + - "<< port >>:3080" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: mongo:8 + container_name: << service_name >>-db + environment: + - MONGO_INITDB_ROOT_USERNAME=app + - MONGO_INITDB_ROOT_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/data/db + restart: unless-stopped diff --git a/apps/librechat/template.json b/apps/librechat/template.json new file mode 100644 index 0000000..66741d4 --- /dev/null +++ b/apps/librechat/template.json @@ -0,0 +1,110 @@ +{ + "kind": "compose", + "metadata": { + "name": "LibreChat", + "description": "Chatinterface voor meerdere AI-aanbieders tegelijk, met gesprekken, presets en gedeelde prompts.", + "tags": [ + "ai", + "llm", + "chat" + ], + "icon": { + "provider": "selfhst", + "id": "librechat" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ai" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "librechat", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8141, + "required": true, + "description": "Standaard 3080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "creds_key", + "type": "str", + "title": "Sleutel voor opgeslagen gegevens", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + }, + { + "name": "creds_iv", + "type": "str", + "title": "Beginwaarde voor de versleuteling", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + }, + { + "name": "jwt_secret", + "type": "str", + "title": "JWT-sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + }, + { + "name": "jwt_refresh_secret", + "type": "str", + "title": "JWT-vernieuwsleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/listmonk/files/compose.yaml b/apps/listmonk/files/compose.yaml new file mode 100644 index 0000000..c16888e --- /dev/null +++ b/apps/listmonk/files/compose.yaml @@ -0,0 +1,33 @@ +services: + << service_name >>: + image: listmonk/listmonk:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - LISTMONK_app__address=0.0.0.0:9000 + - LISTMONK_db__host=<< service_name >>-db + - LISTMONK_db__port=5432 + - LISTMONK_db__user=listmonk + - LISTMONK_db__password=<< db_password >> + - LISTMONK_db__database=listmonk + - LISTMONK_db__ssl_mode=disable + - LISTMONK_app__admin_username=<< admin_user >> + - LISTMONK_app__admin_password=<< admin_password >> + volumes: + - << appdata_dir >>/<< service_name >>:/listmonk/uploads + command: sh -c "./listmonk --install --idempotent --yes --config '' && ./listmonk --config ''" + ports: + - "<< port >>:9000" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=listmonk + - POSTGRES_USER=listmonk + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped diff --git a/apps/listmonk/template.json b/apps/listmonk/template.json new file mode 100644 index 0000000..f762da0 --- /dev/null +++ b/apps/listmonk/template.json @@ -0,0 +1,97 @@ +{ + "kind": "compose", + "metadata": { + "name": "Listmonk", + "description": "Nieuwsbrieven en mailinglijsten versturen, met sjablonen, segmenten en statistieken per campagne.", + "tags": [ + "nieuwsbrief", + "e-mail", + "campagnes" + ], + "icon": { + "provider": "selfhst", + "id": "listmonk" + }, + "version": { + "name": "latest" + }, + "categories": [ + "communicatie", + "zakelijk" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "listmonk", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8137, + "required": true, + "description": "Standaard 9000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "admin_user", + "type": "str", + "title": "Beheerdersnaam", + "default": "admin", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "admin_password", + "type": "str", + "title": "Beheerderswachtwoord", + "default": "", + "required": true, + "secret": true, + "eigen_invoer": true, + "description": "Minimaal 8 tekens" + } + ] + } + ] +} diff --git a/apps/localai/files/compose.yaml b/apps/localai/files/compose.yaml new file mode 100644 index 0000000..fbbb692 --- /dev/null +++ b/apps/localai/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: localai/localai:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - MODELS_PATH=/models + - THREADS=4 + volumes: + - << appdata_dir >>/<< service_name >>:/models + ports: + - "<< port >>:8080" + restart: unless-stopped diff --git a/apps/localai/template.json b/apps/localai/template.json new file mode 100644 index 0000000..cea9ff9 --- /dev/null +++ b/apps/localai/template.json @@ -0,0 +1,59 @@ +{ + "kind": "compose", + "metadata": { + "name": "LocalAI", + "description": "Draait taalmodellen lokaal achter een API die dezelfde vorm heeft als die van OpenAI, zodat bestaande tools er zo op aansluiten.", + "tags": [ + "ai", + "llm", + "api" + ], + "icon": { + "provider": "selfhst", + "id": "localai" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ai" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "localai", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8143, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/lychee/files/compose.yaml b/apps/lychee/files/compose.yaml new file mode 100644 index 0000000..5993bd5 --- /dev/null +++ b/apps/lychee/files/compose.yaml @@ -0,0 +1,15 @@ +services: + << service_name >>: + image: lycheeorg/lychee:latest + container_name: << service_name >> + environment: + - DB_CONNECTION=sqlite + - APP_URL=<< app_url >> + - TIMEZONE=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/conf + - << appdata_dir >>/<< service_name >>-uploads:/uploads + - << appdata_dir >>/<< service_name >>-sym:/sym + ports: + - "<< port >>:80" + restart: unless-stopped diff --git a/apps/lychee/template.json b/apps/lychee/template.json new file mode 100644 index 0000000..d8abca8 --- /dev/null +++ b/apps/lychee/template.json @@ -0,0 +1,71 @@ +{ + "kind": "compose", + "metadata": { + "name": "Lychee", + "description": "Fotoalbums die je kunt delen, met wachtwoorden per album en een importmap. Lichter dan Immich als je geen telefoonsynchronisatie nodig hebt.", + "tags": [ + "fotos", + "albums", + "delen" + ], + "icon": { + "provider": "selfhst", + "id": "lychee" + }, + "version": { + "name": "latest" + }, + "categories": [ + "fotos" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "lychee", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8147, + "required": true, + "description": "Standaard 80; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "app_url", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8147", + "required": true + } + ] + } + ] +} diff --git a/apps/matomo/files/compose.yaml b/apps/matomo/files/compose.yaml new file mode 100644 index 0000000..70cfbba --- /dev/null +++ b/apps/matomo/files/compose.yaml @@ -0,0 +1,28 @@ +services: + << service_name >>: + image: matomo:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - MATOMO_DATABASE_HOST=<< service_name >>-db + - MATOMO_DATABASE_USERNAME=matomo + - MATOMO_DATABASE_PASSWORD=<< db_password >> + - MATOMO_DATABASE_DBNAME=matomo + volumes: + - << appdata_dir >>/<< service_name >>:/var/www/html + ports: + - "<< port >>:80" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: mariadb:11 + container_name: << service_name >>-db + environment: + - MARIADB_DATABASE=matomo + - MARIADB_USER=matomo + - MARIADB_PASSWORD=<< db_password >> + - MARIADB_ROOT_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/mysql + restart: unless-stopped diff --git a/apps/matomo/template.json b/apps/matomo/template.json new file mode 100644 index 0000000..7904a1e --- /dev/null +++ b/apps/matomo/template.json @@ -0,0 +1,74 @@ +{ + "kind": "compose", + "metadata": { + "name": "Matomo", + "description": "Uitgebreide webstatistieken met trechters, doelen en heatmaps, waarbij de gegevens bij jou blijven.", + "tags": [ + "analytics", + "bezoekers", + "privacy" + ], + "icon": { + "provider": "selfhst", + "id": "matomo" + }, + "version": { + "name": "latest" + }, + "categories": [ + "analytics" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "matomo", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8168, + "required": true, + "description": "Standaard 80; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + } + ] + } + ] +} diff --git a/apps/mattermost/files/compose.yaml b/apps/mattermost/files/compose.yaml new file mode 100644 index 0000000..228d249 --- /dev/null +++ b/apps/mattermost/files/compose.yaml @@ -0,0 +1,29 @@ +services: + << service_name >>: + image: mattermost/mattermost-team-edition:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - MM_SQLSETTINGS_DRIVERNAME=postgres + - MM_SQLSETTINGS_DATASOURCE=postgres://mattermost:<< db_password >>@<< service_name >>-db:5432/mattermost?sslmode=disable + - MM_SERVICESETTINGS_SITEURL=<< site_url >> + volumes: + - << appdata_dir >>/<< service_name >>:/mattermost/config + - << appdata_dir >>/<< service_name >>-data:/mattermost/data + - << appdata_dir >>/<< service_name >>-logs:/mattermost/logs + - << appdata_dir >>/<< service_name >>-plugins:/mattermost/plugins + ports: + - "<< port >>:8065" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=mattermost + - POSTGRES_USER=mattermost + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped diff --git a/apps/mattermost/template.json b/apps/mattermost/template.json new file mode 100644 index 0000000..a86787f --- /dev/null +++ b/apps/mattermost/template.json @@ -0,0 +1,88 @@ +{ + "kind": "compose", + "metadata": { + "name": "Mattermost", + "description": "Teamchat in kanalen, met threads, zoeken en koppelingen. Het zelfgehoste alternatief voor Slack.", + "tags": [ + "chat", + "team", + "communicatie" + ], + "icon": { + "provider": "selfhst", + "id": "mattermost" + }, + "version": { + "name": "latest" + }, + "categories": [ + "communicatie", + "productiviteit" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "mattermost", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8134, + "required": true, + "description": "Standaard 8065; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "site_url", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8134", + "required": true, + "description": "Nodig voor uitnodigingen en meldingen" + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + } + ] + } + ] +} diff --git a/apps/maybe/files/compose.yaml b/apps/maybe/files/compose.yaml new file mode 100644 index 0000000..56050fd --- /dev/null +++ b/apps/maybe/files/compose.yaml @@ -0,0 +1,31 @@ +services: + << service_name >>: + image: ghcr.io/maybe-finance/maybe:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - SELF_HOSTED=true + - RAILS_FORCE_SSL=false + - RAILS_ASSUME_SSL=false + - SECRET_KEY_BASE=<< secret_key_base >> + - DB_HOST=<< service_name >>-db + - POSTGRES_DB=maybe + - POSTGRES_USER=maybe + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>:/rails/storage + ports: + - "<< port >>:3000" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=maybe + - POSTGRES_USER=maybe + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped diff --git a/apps/maybe/template.json b/apps/maybe/template.json new file mode 100644 index 0000000..de23230 --- /dev/null +++ b/apps/maybe/template.json @@ -0,0 +1,83 @@ +{ + "kind": "compose", + "metadata": { + "name": "Maybe", + "description": "Persoonlijke financiën op één plek: rekeningen, uitgaven, vermogen en waar het naartoe gaat.", + "tags": [ + "budget", + "vermogen", + "financien" + ], + "icon": { + "provider": "selfhst", + "id": "maybe" + }, + "version": { + "name": "latest" + }, + "categories": [ + "financien" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "maybe", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8146, + "required": true, + "description": "Standaard 3000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "secret_key_base", + "type": "str", + "title": "Rails-sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/minecraft/files/compose.yaml b/apps/minecraft/files/compose.yaml new file mode 100644 index 0000000..538db09 --- /dev/null +++ b/apps/minecraft/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: itzg/minecraft-server:latest + container_name: << service_name >> + environment: + - EULA=<< eula >> + - TYPE=<< server_type >> + - MEMORY=<< geheugen >> + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/data + ports: + - "<< port >>:25565" + restart: unless-stopped diff --git a/apps/minecraft/template.json b/apps/minecraft/template.json new file mode 100644 index 0000000..7ac389f --- /dev/null +++ b/apps/minecraft/template.json @@ -0,0 +1,96 @@ +{ + "kind": "compose", + "metadata": { + "name": "Minecraft-server", + "description": "Eigen Minecraft-server, met keuze uit vanilla, Paper, Fabric en Forge. Werkt met mods en plugins.", + "tags": [ + "spellen", + "minecraft", + "gameserver" + ], + "icon": { + "provider": "selfhst", + "id": "minecraft" + }, + "version": { + "name": "latest" + }, + "categories": [ + "spellen" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "minecraft", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Serverpoort", + "default": 25565, + "required": true, + "description": "Zet deze poort open in je router als je van buitenaf wilt spelen" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "eula", + "type": "bool", + "title": "Ik ga akkoord met de Minecraft-EULA", + "default": false, + "required": false, + "description": "Zonder akkoord start de server niet — zie minecraft.net/eula" + }, + { + "name": "server_type", + "type": "enum", + "title": "Serversoort", + "default": "PAPER", + "required": true, + "config": { + "options": [ + "VANILLA", + "PAPER", + "FABRIC", + "FORGE", + "SPIGOT" + ] + } + }, + { + "name": "geheugen", + "type": "str", + "title": "Geheugen", + "default": "2G", + "required": true, + "description": "Bijvoorbeeld 2G of 4G" + } + ] + } + ] +} diff --git a/apps/minio/files/compose.yaml b/apps/minio/files/compose.yaml new file mode 100644 index 0000000..380b007 --- /dev/null +++ b/apps/minio/files/compose.yaml @@ -0,0 +1,15 @@ +services: + << service_name >>: + image: minio/minio:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - MINIO_ROOT_USER=<< root_user >> + - MINIO_ROOT_PASSWORD=<< root_password >> + volumes: + - << appdata_dir >>/<< service_name >>:/data + command: server /data --console-address ":9001" + ports: + - "<< port >>:9000" + - "<< port_console >>:9001" + restart: unless-stopped diff --git a/apps/minio/template.json b/apps/minio/template.json new file mode 100644 index 0000000..a5be599 --- /dev/null +++ b/apps/minio/template.json @@ -0,0 +1,94 @@ +{ + "kind": "compose", + "metadata": { + "name": "MinIO", + "description": "Objectopslag die de S3-API spreekt, zodat back-uptools en applicaties er zonder aanpassing op aansluiten.", + "tags": [ + "opslag", + "s3", + "objecten" + ], + "icon": { + "provider": "selfhst", + "id": "minio" + }, + "version": { + "name": "latest" + }, + "categories": [ + "opslag", + "ontwikkeling" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "minio", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "API-poort", + "default": 8164, + "required": true, + "description": "Standaard 9000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "port_console", + "type": "int", + "title": "Beheerinterface", + "default": 8165, + "required": true + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "root_user", + "type": "str", + "title": "Beheerdersnaam", + "default": "minioadmin", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "root_password", + "type": "str", + "title": "Beheerderswachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Minimaal 8 tekens" + } + ] + } + ] +} diff --git a/apps/mumble/files/compose.yaml b/apps/mumble/files/compose.yaml new file mode 100644 index 0000000..69cdbd1 --- /dev/null +++ b/apps/mumble/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: mumblevoip/mumble-server:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - MUMBLE_CONFIG_welcometext=<< welkomsttekst >> + - MUMBLE_SUPERUSER_PASSWORD=<< superuser_password >> + volumes: + - << appdata_dir >>/<< service_name >>:/data + ports: + - "<< port >>:64738" + - "<< port >>:64738/udp" + restart: unless-stopped diff --git a/apps/mumble/template.json b/apps/mumble/template.json new file mode 100644 index 0000000..bfce8de --- /dev/null +++ b/apps/mumble/template.json @@ -0,0 +1,86 @@ +{ + "kind": "compose", + "metadata": { + "name": "Mumble", + "description": "Spraakserver met lage vertraging, oorspronkelijk voor gamers maar prima voor elk gesprek waar geluid telt.", + "tags": [ + "spraak", + "voip", + "communicatie" + ], + "icon": { + "provider": "selfhst", + "id": "mumble" + }, + "version": { + "name": "latest" + }, + "categories": [ + "communicatie" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "mumble", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Serverpoort", + "default": 64738, + "required": true, + "description": "TCP en UDP op hetzelfde nummer" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "welkomsttekst", + "type": "str", + "title": "Welkomsttekst", + "default": "Welkom op deze Mumble-server", + "required": false + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "superuser_password", + "type": "str", + "title": "SuperUser-wachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Waarmee je de server beheert" + } + ] + } + ] +} diff --git a/apps/netalertx/files/compose.yaml b/apps/netalertx/files/compose.yaml new file mode 100644 index 0000000..b6491c0 --- /dev/null +++ b/apps/netalertx/files/compose.yaml @@ -0,0 +1,12 @@ +services: + << service_name >>: + image: jokobsk/netalertx:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - PORT=20211 + volumes: + - << appdata_dir >>/<< service_name >>:/app/config + - << appdata_dir >>/<< service_name >>-db:/app/db + network_mode: host + restart: unless-stopped diff --git a/apps/netalertx/template.json b/apps/netalertx/template.json new file mode 100644 index 0000000..856b89c --- /dev/null +++ b/apps/netalertx/template.json @@ -0,0 +1,52 @@ +{ + "kind": "compose", + "metadata": { + "name": "NetAlertX", + "description": "Scant je netwerk en meldt het zodra er een apparaat bijkomt dat je niet kent. Let op: Draait op het netwerk van de host, want anders ziet de scanner alleen het Docker-netwerk. Bereikbaar op poort 20211 van je server.", + "tags": [ + "netwerk", + "monitoring", + "beveiliging" + ], + "icon": { + "provider": "selfhst", + "id": "netalertx" + }, + "version": { + "name": "latest" + }, + "categories": [ + "netwerk", + "monitoring" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "netalertx", + "required": true + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/odoo/files/compose.yaml b/apps/odoo/files/compose.yaml new file mode 100644 index 0000000..2acac30 --- /dev/null +++ b/apps/odoo/files/compose.yaml @@ -0,0 +1,26 @@ +services: + << service_name >>: + image: odoo:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - HOST=<< service_name >>-db + - USER=odoo + - PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>:/var/lib/odoo + ports: + - "<< port >>:8069" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=postgres + - POSTGRES_USER=odoo + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped diff --git a/apps/odoo/template.json b/apps/odoo/template.json new file mode 100644 index 0000000..de90a35 --- /dev/null +++ b/apps/odoo/template.json @@ -0,0 +1,75 @@ +{ + "kind": "compose", + "metadata": { + "name": "Odoo", + "description": "Bedrijfssoftware in modules: verkoop, voorraad, facturen, CRM en boekhouding. Je zet aan wat je nodig hebt.", + "tags": [ + "erp", + "crm", + "facturen", + "boekhouding" + ], + "icon": { + "provider": "selfhst", + "id": "odoo" + }, + "version": { + "name": "latest" + }, + "categories": [ + "zakelijk" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "odoo", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8169, + "required": true, + "description": "Standaard 8069; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + } + ] + } + ] +} diff --git a/apps/opengist/files/compose.yaml b/apps/opengist/files/compose.yaml new file mode 100644 index 0000000..0cab4c4 --- /dev/null +++ b/apps/opengist/files/compose.yaml @@ -0,0 +1,15 @@ +services: + << service_name >>: + image: ghcr.io/thomiceli/opengist:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - OG_EXTERNAL_URL=<< app_url >> + - OG_SSH_GIT_ENABLED=true + - OG_SSH_GIT_PORT=<< port_ssh >> + volumes: + - << appdata_dir >>/<< service_name >>:/opengist + ports: + - "<< port >>:6157" + - "<< port_ssh >>:2222" + restart: unless-stopped diff --git a/apps/opengist/template.json b/apps/opengist/template.json new file mode 100644 index 0000000..50200fa --- /dev/null +++ b/apps/opengist/template.json @@ -0,0 +1,79 @@ +{ + "kind": "compose", + "metadata": { + "name": "Opengist", + "description": "Eigen plek voor codefragmenten, met versiegeschiedenis via git. Zelfgehoste GitHub Gist.", + "tags": [ + "code", + "snippets", + "git" + ], + "icon": { + "provider": "selfhst", + "id": "opengist" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ontwikkeling" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "opengist", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8177, + "required": true, + "description": "Standaard 6157; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "port_ssh", + "type": "int", + "title": "SSH-poort", + "default": 2224, + "required": true, + "description": "Voor git via ssh" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "app_url", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8177", + "required": true + } + ] + } + ] +} diff --git a/apps/outline/files/compose.yaml b/apps/outline/files/compose.yaml new file mode 100644 index 0000000..17d7476 --- /dev/null +++ b/apps/outline/files/compose.yaml @@ -0,0 +1,47 @@ +services: + << service_name >>: + image: outlinewiki/outline:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - NODE_ENV=production + - URL=<< app_url >> + - PORT=3000 + - SECRET_KEY=<< secret_key >> + - UTILS_SECRET=<< utils_secret >> + - DATABASE_URL=postgres://outline:<< db_password >>@<< service_name >>-db:5432/outline + - PGSSLMODE=disable + - REDIS_URL=redis://<< service_name >>-redis:6379 + - FILE_STORAGE=local + - FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data + - OIDC_CLIENT_ID=<< oidc_client_id >> + - OIDC_CLIENT_SECRET=<< oidc_client_secret >> + - OIDC_AUTH_URI=<< oidc_url_inloggen >> + - OIDC_TOKEN_URI=<< oidc_url_uitwisselen >> + - OIDC_USERINFO_URI=<< oidc_url_profiel >> + - OIDC_DISPLAY_NAME=<< oidc_naam >> + volumes: + - << appdata_dir >>/<< service_name >>:/var/lib/outline/data + ports: + - "<< port >>:3000" + depends_on: + - << service_name >>-db + - << service_name >>-redis + restart: unless-stopped + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=outline + - POSTGRES_USER=outline + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped + << service_name >>-redis: + image: valkey/valkey:8-alpine + container_name: << service_name >>-redis + command: valkey-server --save 60 1 + volumes: + - << appdata_dir >>/<< service_name >>-redis:/data + restart: unless-stopped diff --git a/apps/outline/template.json b/apps/outline/template.json new file mode 100644 index 0000000..608d240 --- /dev/null +++ b/apps/outline/template.json @@ -0,0 +1,156 @@ +{ + "kind": "compose", + "metadata": { + "name": "Outline", + "description": "Kennisbank voor teams: gedeelde documenten met versies, rechten per collectie en goed zoeken. Let op: Outline kent geen eigen wachtwoorden. Zonder werkende OIDC-instellingen kom je niet voorbij het inlogscherm.", + "tags": [ + "wiki", + "kennis", + "documenten", + "samenwerken" + ], + "icon": { + "provider": "selfhst", + "id": "outline" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten", + "productiviteit" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "outline", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8153, + "required": true, + "description": "Standaard 3000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "app_url", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8153", + "required": true + }, + { + "name": "oidc_naam", + "type": "str", + "title": "Naam van je inlogdienst", + "default": "Authentik", + "required": true + }, + { + "name": "oidc_client_id", + "type": "str", + "title": "OIDC client-id", + "default": "", + "required": true, + "connect": { + "app": "authentik", + "scheme": "http", + "port": 9000 + }, + "help": "Outline heeft geen eigen accounts: je logt altijd in via een externe dienst. Maak in Authentik, Keycloak of Pocket ID een OIDC-toepassing aan en neem de gegevens hier over." + }, + { + "name": "oidc_url_inloggen", + "type": "str", + "title": "OIDC-adres om in te loggen", + "default": "", + "required": true + }, + { + "name": "oidc_url_uitwisselen", + "type": "str", + "title": "OIDC-adres om de code in te wisselen", + "default": "", + "required": true + }, + { + "name": "oidc_url_profiel", + "type": "str", + "title": "OIDC-adres met de profielgegevens", + "default": "", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "secret_key", + "type": "str", + "title": "Geheime sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + }, + { + "name": "utils_secret", + "type": "str", + "title": "Sleutel voor hulpfuncties", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + }, + { + "name": "oidc_client_secret", + "type": "str", + "title": "OIDC client-secret", + "default": "", + "required": true, + "secret": true, + "eigen_invoer": true + } + ] + } + ] +} diff --git a/apps/pingvin-share/files/compose.yaml b/apps/pingvin-share/files/compose.yaml new file mode 100644 index 0000000..db1464f --- /dev/null +++ b/apps/pingvin-share/files/compose.yaml @@ -0,0 +1,12 @@ +services: + << service_name >>: + image: stonith404/pingvin-share:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/opt/app/backend/data + - << appdata_dir >>/<< service_name >>-img:/opt/app/frontend/public/img + ports: + - "<< port >>:3000" + restart: unless-stopped diff --git a/apps/pingvin-share/template.json b/apps/pingvin-share/template.json new file mode 100644 index 0000000..7dab939 --- /dev/null +++ b/apps/pingvin-share/template.json @@ -0,0 +1,59 @@ +{ + "kind": "compose", + "metadata": { + "name": "Pingvin Share", + "description": "Bestanden delen via een link die vanzelf verloopt, met een limiet op het aantal downloads.", + "tags": [ + "bestanden", + "delen", + "opslag" + ], + "icon": { + "provider": "selfhst", + "id": "pingvin-share" + }, + "version": { + "name": "latest" + }, + "categories": [ + "opslag" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "pingvinshare", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8166, + "required": true, + "description": "Standaard 3000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/piwigo/files/compose.yaml b/apps/piwigo/files/compose.yaml new file mode 100644 index 0000000..52e735e --- /dev/null +++ b/apps/piwigo/files/compose.yaml @@ -0,0 +1,27 @@ +services: + << service_name >>: + image: lscr.io/linuxserver/piwigo:latest + container_name: << service_name >> + environment: + - PUID=<< puid >> + - PGID=<< pgid >> + - TZ=<< timezone >> + - UMASK=002 + volumes: + - << appdata_dir >>/<< service_name >>:/config + ports: + - "<< port >>:80" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: mariadb:11 + container_name: << service_name >>-db + environment: + - MARIADB_DATABASE=piwigo + - MARIADB_USER=piwigo + - MARIADB_PASSWORD=<< db_password >> + - MARIADB_ROOT_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/mysql + restart: unless-stopped diff --git a/apps/piwigo/template.json b/apps/piwigo/template.json new file mode 100644 index 0000000..9c8ca01 --- /dev/null +++ b/apps/piwigo/template.json @@ -0,0 +1,93 @@ +{ + "kind": "compose", + "metadata": { + "name": "Piwigo", + "description": "Fotobibliotheek met een eigen database, tags, gebruikersrechten en een groot aanbod aan uitbreidingen.", + "tags": [ + "fotos", + "albums" + ], + "icon": { + "provider": "selfhst", + "id": "piwigo" + }, + "version": { + "name": "latest" + }, + "categories": [ + "fotos" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "piwigo", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8148, + "required": true, + "description": "Standaard 80; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Gebruiker", + "items": [ + { + "name": "puid", + "type": "int", + "title": "Gebruikers-ID (PUID)", + "default": 1000, + "required": true, + "description": "`id -u` op je server; bepaalt de eigenaar van de bestanden" + }, + { + "name": "pgid", + "type": "int", + "title": "Groeps-ID (PGID)", + "default": 1000, + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + } + ] + } + ] +} diff --git a/apps/planka/files/compose.yaml b/apps/planka/files/compose.yaml index b2a3653..91fa3d6 100644 --- a/apps/planka/files/compose.yaml +++ b/apps/planka/files/compose.yaml @@ -1,6 +1,6 @@ services: << service_name >>: - image: ghcr.io/plankanban/planka:1 + image: ghcr.io/plankanban/planka:latest container_name: << service_name >> ports: - "<< port >>:1337" diff --git a/apps/pocket-id/files/compose.yaml b/apps/pocket-id/files/compose.yaml new file mode 100644 index 0000000..86fd5c6 --- /dev/null +++ b/apps/pocket-id/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: ghcr.io/pocket-id/pocket-id:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - APP_URL=<< app_url >> + - TRUST_PROXY=true + volumes: + - << appdata_dir >>/<< service_name >>:/app/data + ports: + - "<< port >>:1411" + restart: unless-stopped diff --git a/apps/pocket-id/template.json b/apps/pocket-id/template.json new file mode 100644 index 0000000..fb1b103 --- /dev/null +++ b/apps/pocket-id/template.json @@ -0,0 +1,74 @@ +{ + "kind": "compose", + "metadata": { + "name": "Pocket ID", + "description": "Inloggen met passkeys voor al je apps. Eenvoudiger dan Authentik of Keycloak als je alleen OIDC nodig hebt.", + "tags": [ + "sso", + "oidc", + "passkeys", + "authenticatie" + ], + "icon": { + "provider": "selfhst", + "id": "pocket-id" + }, + "version": { + "name": "latest" + }, + "categories": [ + "beveiliging" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "pocketid", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8132, + "required": true, + "description": "Standaard 1411; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "app_url", + "type": "str", + "title": "Publiek adres", + "default": "https://id.example.com", + "required": true, + "description": "Passkeys zijn aan het exacte adres gebonden", + "help": "Een passkey wordt vastgelegd op het domein waar je hem aanmaakt. Verandert dit adres later, dan werken bestaande passkeys niet meer en moet iedereen opnieuw registreren." + } + ] + } + ] +} diff --git a/apps/privatebin/files/compose.yaml b/apps/privatebin/files/compose.yaml new file mode 100644 index 0000000..ed6549c --- /dev/null +++ b/apps/privatebin/files/compose.yaml @@ -0,0 +1,11 @@ +services: + << service_name >>: + image: privatebin/nginx-fpm-alpine:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/srv/data + ports: + - "<< port >>:8080" + restart: unless-stopped diff --git a/apps/privatebin/template.json b/apps/privatebin/template.json new file mode 100644 index 0000000..9130411 --- /dev/null +++ b/apps/privatebin/template.json @@ -0,0 +1,60 @@ +{ + "kind": "compose", + "metadata": { + "name": "PrivateBin", + "description": "Tekst delen die in je browser versleuteld wordt, zodat de server zelf niet kan lezen wat erin staat.", + "tags": [ + "pastebin", + "delen", + "privacy" + ], + "icon": { + "provider": "selfhst", + "id": "privatebin" + }, + "version": { + "name": "latest" + }, + "categories": [ + "productiviteit", + "beveiliging" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "privatebin", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8174, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/readeck/files/compose.yaml b/apps/readeck/files/compose.yaml new file mode 100644 index 0000000..4fc2d5c --- /dev/null +++ b/apps/readeck/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: codeberg.org/readeck/readeck:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - READECK_LOG_LEVEL=info + - READECK_ALLOWED_HOSTS=<< toegestane_hosts >> + volumes: + - << appdata_dir >>/<< service_name >>:/readeck + ports: + - "<< port >>:8000" + restart: unless-stopped diff --git a/apps/readeck/template.json b/apps/readeck/template.json new file mode 100644 index 0000000..0fdae70 --- /dev/null +++ b/apps/readeck/template.json @@ -0,0 +1,72 @@ +{ + "kind": "compose", + "metadata": { + "name": "Readeck", + "description": "Bewaart artikelen om later te lezen, ontdaan van reclame en opmaak. Met markeringen en eigen labels.", + "tags": [ + "lezen", + "artikelen", + "bladwijzers" + ], + "icon": { + "provider": "selfhst", + "id": "readeck" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "readeck", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8156, + "required": true, + "description": "Standaard 8000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "toegestane_hosts", + "type": "str", + "title": "Toegestane adressen", + "default": "localhost", + "required": true, + "description": "Komma-gescheiden lijst van namen waarop je Readeck opent" + } + ] + } + ] +} diff --git a/apps/romm/files/compose.yaml b/apps/romm/files/compose.yaml new file mode 100644 index 0000000..9fd3203 --- /dev/null +++ b/apps/romm/files/compose.yaml @@ -0,0 +1,32 @@ +services: + << service_name >>: + image: rommapp/romm:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - DB_HOST=<< service_name >>-db + - DB_NAME=romm + - DB_USER=romm + - DB_PASSWD=<< db_password >> + - ROMM_AUTH_SECRET_KEY=<< auth_secret >> + volumes: + - << appdata_dir >>/<< service_name >>:/romm/config + - << data_root >>:/data + - << appdata_dir >>/<< service_name >>-resources:/romm/resources + - << appdata_dir >>/<< service_name >>-redis:/redis-data + ports: + - "<< port >>:8080" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: mariadb:11 + container_name: << service_name >>-db + environment: + - MARIADB_DATABASE=romm + - MARIADB_USER=romm + - MARIADB_PASSWORD=<< db_password >> + - MARIADB_ROOT_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/mysql + restart: unless-stopped diff --git a/apps/romm/template.json b/apps/romm/template.json new file mode 100644 index 0000000..73840cd --- /dev/null +++ b/apps/romm/template.json @@ -0,0 +1,93 @@ +{ + "kind": "compose", + "metadata": { + "name": "RomM", + "description": "Beheert je verzameling retro-spellen, haalt er omslagen en gegevens bij, en laat je ze in de browser spelen. Let op: Zet je roms onder /data/roms, met een submap per platform (bijvoorbeeld /data/roms/snes).", + "tags": [ + "retro", + "spellen", + "emulator" + ], + "icon": { + "provider": "selfhst", + "id": "romm" + }, + "version": { + "name": "latest" + }, + "categories": [ + "spellen", + "media" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "romm", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8172, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "data_root", + "type": "str", + "title": "Gedeelde datamap", + "default": "/mnt/data", + "required": true, + "description": "Eén map met je media, gekoppeld als /data", + "help": "Media en downloads horen onder één map te staan, die als /data in elke container komt. Alleen dan kan een voltooide download met een hardlink naar je bibliotheek: geen kopie, geen dubbele opslag, en je torrent blijft seeden. Zet je ze op gescheiden paden, dan kopieert elke download opnieuw. Eronder: media/films, media/series, torrents/ en usenet/." + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "auth_secret", + "type": "str", + "title": "Sleutel voor de inlogsessies", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/roundcube/files/compose.yaml b/apps/roundcube/files/compose.yaml new file mode 100644 index 0000000..b998afc --- /dev/null +++ b/apps/roundcube/files/compose.yaml @@ -0,0 +1,14 @@ +services: + << service_name >>: + image: roundcube/roundcubemail:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - ROUNDCUBEMAIL_DB_TYPE=sqlite + - ROUNDCUBEMAIL_DEFAULT_HOST=<< imap_server >> + - ROUNDCUBEMAIL_SMTP_SERVER=<< smtp_server >> + volumes: + - << appdata_dir >>/<< service_name >>:/var/www/html + ports: + - "<< port >>:80" + restart: unless-stopped diff --git a/apps/roundcube/template.json b/apps/roundcube/template.json new file mode 100644 index 0000000..0778c1c --- /dev/null +++ b/apps/roundcube/template.json @@ -0,0 +1,79 @@ +{ + "kind": "compose", + "metadata": { + "name": "Roundcube", + "description": "Webmail voor een bestaande mailserver. Geen mailserver zelf: je logt in op je eigen IMAP-account.", + "tags": [ + "e-mail", + "webmail", + "imap" + ], + "icon": { + "provider": "selfhst", + "id": "roundcube" + }, + "version": { + "name": "latest" + }, + "categories": [ + "communicatie" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "roundcube", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8139, + "required": true, + "description": "Standaard 80; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "imap_server", + "type": "str", + "title": "IMAP-server", + "default": "ssl://imap.example.com", + "required": true, + "description": "Met ssl:// of tls:// ervoor" + }, + { + "name": "smtp_server", + "type": "str", + "title": "SMTP-server", + "default": "tls://smtp.example.com", + "required": true + } + ] + } + ] +} diff --git a/apps/scrutiny/files/compose.yaml b/apps/scrutiny/files/compose.yaml new file mode 100644 index 0000000..6bdfc25 --- /dev/null +++ b/apps/scrutiny/files/compose.yaml @@ -0,0 +1,17 @@ +services: + << service_name >>: + image: ghcr.io/analogj/scrutiny:master-omnibus + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/opt/scrutiny/config + - << appdata_dir >>/<< service_name >>-influxdb:/opt/scrutiny/influxdb + - /run/udev:/run/udev:ro + ports: + - "<< port >>:8080" + cap_add: + - SYS_RAWIO + devices: + - /dev/sda:/dev/sda + restart: unless-stopped diff --git a/apps/scrutiny/template.json b/apps/scrutiny/template.json new file mode 100644 index 0000000..e8c7e93 --- /dev/null +++ b/apps/scrutiny/template.json @@ -0,0 +1,61 @@ +{ + "kind": "compose", + "metadata": { + "name": "Scrutiny", + "description": "Leest de SMART-gegevens van je schijven uit en waarschuwt vóórdat er een stukgaat, in plaats van erna. Let op: Pas de lijst onder `devices` aan naar de schijven in jouw server; zonder toegang tot het apparaat zelf kan Scrutiny niets uitlezen.", + "tags": [ + "schijven", + "smart", + "monitoring", + "hardware" + ], + "icon": { + "provider": "selfhst", + "id": "scrutiny" + }, + "version": { + "name": "latest" + }, + "categories": [ + "monitoring", + "opslag" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "scrutiny", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8126, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/semaphore/files/compose.yaml b/apps/semaphore/files/compose.yaml new file mode 100644 index 0000000..b5fa26a --- /dev/null +++ b/apps/semaphore/files/compose.yaml @@ -0,0 +1,34 @@ +services: + << service_name >>: + image: semaphoreui/semaphore:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - SEMAPHORE_DB_DIALECT=postgres + - SEMAPHORE_DB_HOST=<< service_name >>-db + - SEMAPHORE_DB_PORT=5432 + - SEMAPHORE_DB_USER=semaphore + - SEMAPHORE_DB_PASS=<< db_password >> + - SEMAPHORE_DB=semaphore + - SEMAPHORE_ADMIN=<< admin_user >> + - SEMAPHORE_ADMIN_PASSWORD=<< admin_password >> + - SEMAPHORE_ADMIN_NAME=Beheerder + - SEMAPHORE_ADMIN_EMAIL=<< admin_email >> + - SEMAPHORE_ACCESS_KEY_ENCRYPTION=<< access_key_encryption >> + volumes: + - << appdata_dir >>/<< service_name >>:/etc/semaphore + ports: + - "<< port >>:3000" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=semaphore + - POSTGRES_USER=semaphore + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped diff --git a/apps/semaphore/template.json b/apps/semaphore/template.json new file mode 100644 index 0000000..5211f50 --- /dev/null +++ b/apps/semaphore/template.json @@ -0,0 +1,112 @@ +{ + "kind": "compose", + "metadata": { + "name": "Semaphore UI", + "description": "Webinterface voor Ansible: playbooks draaien, inventarissen beheren en zien wie wat wanneer uitvoerde.", + "tags": [ + "ansible", + "automatisering", + "ontwikkeling" + ], + "icon": { + "provider": "selfhst", + "id": "semaphore" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ontwikkeling", + "beheer" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "semaphore", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8163, + "required": true, + "description": "Standaard 3000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "admin_user", + "type": "str", + "title": "Beheerdersnaam", + "default": "admin", + "required": true + }, + { + "name": "admin_email", + "type": "str", + "title": "E-mailadres beheerder", + "default": "admin@example.com", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "access_key_encryption", + "type": "str", + "title": "Sleutel voor opgeslagen inloggegevens", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + }, + { + "name": "admin_password", + "type": "str", + "title": "Beheerderswachtwoord", + "default": "", + "required": true, + "secret": true, + "eigen_invoer": true + } + ] + } + ] +} diff --git a/apps/silverbullet/files/compose.yaml b/apps/silverbullet/files/compose.yaml new file mode 100644 index 0000000..5c041bb --- /dev/null +++ b/apps/silverbullet/files/compose.yaml @@ -0,0 +1,12 @@ +services: + << service_name >>: + image: ghcr.io/silverbulletmd/silverbullet:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - SB_USER=<< gebruiker >>:<< wachtwoord >> + volumes: + - << appdata_dir >>/<< service_name >>:/space + ports: + - "<< port >>:3000" + restart: unless-stopped diff --git a/apps/silverbullet/template.json b/apps/silverbullet/template.json new file mode 100644 index 0000000..0af56d4 --- /dev/null +++ b/apps/silverbullet/template.json @@ -0,0 +1,86 @@ +{ + "kind": "compose", + "metadata": { + "name": "SilverBullet", + "description": "Notitieprogramma dat gewone markdown-bestanden op schijf gebruikt en offline doorwerkt in je browser.", + "tags": [ + "notities", + "markdown", + "documenten" + ], + "icon": { + "provider": "selfhst", + "id": "silverbullet" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten", + "productiviteit" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "silverbullet", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8155, + "required": true, + "description": "Standaard 3000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "gebruiker", + "type": "str", + "title": "Gebruikersnaam", + "default": "admin", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "wachtwoord", + "type": "str", + "title": "Wachtwoord", + "default": "", + "required": true, + "secret": true, + "eigen_invoer": true + } + ] + } + ] +} diff --git a/apps/stalwart/files/compose.yaml b/apps/stalwart/files/compose.yaml new file mode 100644 index 0000000..f906b50 --- /dev/null +++ b/apps/stalwart/files/compose.yaml @@ -0,0 +1,15 @@ +services: + << service_name >>: + image: stalwartlabs/stalwart:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/opt/stalwart + ports: + - "<< port >>:8080" + - "<< port_smtp >>:25" + - "<< port_submission >>:587" + - "<< port_imap >>:143" + - "<< port_imaps >>:993" + restart: unless-stopped diff --git a/apps/stalwart/template.json b/apps/stalwart/template.json new file mode 100644 index 0000000..5ee0a9c --- /dev/null +++ b/apps/stalwart/template.json @@ -0,0 +1,92 @@ +{ + "kind": "compose", + "metadata": { + "name": "Stalwart", + "description": "Complete mailserver in één container: IMAP, JMAP, SMTP, spamfilter en een webinterface om het te beheren. Let op: Een mailserver draaien vraagt meer dan een container: je hebt een vast IP-adres nodig, kloppende SPF-, DKIM- en DMARC-records, en een reverse-DNS die op je domein uitkomt. Zonder dat komt je post niet aan.", + "tags": [ + "e-mail", + "mailserver", + "imap", + "smtp" + ], + "icon": { + "provider": "selfhst", + "id": "stalwart" + }, + "version": { + "name": "latest" + }, + "categories": [ + "communicatie" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "stalwart", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Beheerinterface", + "default": 8140, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "port_smtp", + "type": "int", + "title": "SMTP", + "default": 25, + "required": true, + "advanced": true + }, + { + "name": "port_submission", + "type": "int", + "title": "SMTP (submission)", + "default": 587, + "required": true, + "advanced": true + }, + { + "name": "port_imap", + "type": "int", + "title": "IMAP", + "default": 143, + "required": true, + "advanced": true + }, + { + "name": "port_imaps", + "type": "int", + "title": "IMAP (TLS)", + "default": 993, + "required": true, + "advanced": true + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/synapse/files/compose.yaml b/apps/synapse/files/compose.yaml new file mode 100644 index 0000000..57d412d --- /dev/null +++ b/apps/synapse/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: ghcr.io/element-hq/synapse:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - SYNAPSE_SERVER_NAME=<< server_name >> + - SYNAPSE_REPORT_STATS=no + volumes: + - << appdata_dir >>/<< service_name >>:/data + ports: + - "<< port >>:8008" + restart: unless-stopped diff --git a/apps/synapse/template.json b/apps/synapse/template.json new file mode 100644 index 0000000..421fb20 --- /dev/null +++ b/apps/synapse/template.json @@ -0,0 +1,74 @@ +{ + "kind": "compose", + "metadata": { + "name": "Synapse (Matrix)", + "description": "Matrix-homeserver: versleutelde chat die met elke andere Matrix-server praat. Combineer met Element als webclient. Let op: Bij de eerste start maakt Synapse zelf een configuratiebestand aan in de datamap. Maak daarna een gebruiker met `docker exec -it register_new_matrix_user`.", + "tags": [ + "matrix", + "chat", + "federatie", + "communicatie" + ], + "icon": { + "provider": "selfhst", + "id": "matrix" + }, + "version": { + "name": "latest" + }, + "categories": [ + "communicatie" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "synapse", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8135, + "required": true, + "description": "Standaard 8008; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "server_name", + "type": "str", + "title": "Servernaam", + "default": "matrix.example.com", + "required": true, + "description": "Het domein in je Matrix-adressen (@jij:dit-domein)", + "help": "Dit staat vast zodra er accounts zijn aangemaakt: het zit in het adres van elke gebruiker en in elke kamer-id. Later wijzigen betekent opnieuw beginnen." + } + ] + } + ] +} diff --git a/apps/trilium/files/compose.yaml b/apps/trilium/files/compose.yaml new file mode 100644 index 0000000..0753efd --- /dev/null +++ b/apps/trilium/files/compose.yaml @@ -0,0 +1,11 @@ +services: + << service_name >>: + image: triliumnext/notes:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/home/node/trilium-data + ports: + - "<< port >>:8080" + restart: unless-stopped diff --git a/apps/trilium/template.json b/apps/trilium/template.json new file mode 100644 index 0000000..ccb3eb8 --- /dev/null +++ b/apps/trilium/template.json @@ -0,0 +1,60 @@ +{ + "kind": "compose", + "metadata": { + "name": "Trilium Notes", + "description": "Notities in een boomstructuur, met onderlinge verwijzingen, versies en scripts. Sterk als je archief groot wordt.", + "tags": [ + "notities", + "kennis", + "documenten" + ], + "icon": { + "provider": "selfhst", + "id": "trilium" + }, + "version": { + "name": "latest" + }, + "categories": [ + "documenten", + "productiviteit" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "trilium", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8154, + "required": true, + "description": "Standaard 8080; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/umami/files/compose.yaml b/apps/umami/files/compose.yaml new file mode 100644 index 0000000..ec29546 --- /dev/null +++ b/apps/umami/files/compose.yaml @@ -0,0 +1,24 @@ +services: + << service_name >>: + image: ghcr.io/umami-software/umami:postgresql-latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - DATABASE_URL=postgresql://umami:<< db_password >>@<< service_name >>-db:5432/umami + - DATABASE_TYPE=postgresql + - APP_SECRET=<< app_secret >> + ports: + - "<< port >>:3000" + depends_on: + - << service_name >>-db + restart: unless-stopped + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_DB=umami + - POSTGRES_USER=umami + - POSTGRES_PASSWORD=<< db_password >> + volumes: + - << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data + restart: unless-stopped diff --git a/apps/umami/template.json b/apps/umami/template.json new file mode 100644 index 0000000..a6d304f --- /dev/null +++ b/apps/umami/template.json @@ -0,0 +1,83 @@ +{ + "kind": "compose", + "metadata": { + "name": "Umami", + "description": "Bezoekersstatistieken voor je websites zonder cookies en zonder persoonsgegevens. Lichtgewicht alternatief voor Google Analytics.", + "tags": [ + "analytics", + "bezoekers", + "privacy" + ], + "icon": { + "provider": "selfhst", + "id": "umami" + }, + "version": { + "name": "latest" + }, + "categories": [ + "analytics" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "umami", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8167, + "required": true, + "description": "Standaard 3000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "db_password", + "type": "str", + "title": "Databasewachtwoord", + "default": "", + "required": true, + "secret": true, + "generate": "auto", + "description": "Wordt automatisch ingevuld en in .env bewaard" + }, + { + "name": "app_secret", + "type": "str", + "title": "Geheime sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/wallos/files/compose.yaml b/apps/wallos/files/compose.yaml new file mode 100644 index 0000000..c599cae --- /dev/null +++ b/apps/wallos/files/compose.yaml @@ -0,0 +1,12 @@ +services: + << service_name >>: + image: bellamy/wallos:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/var/www/html/db + - << appdata_dir >>/<< service_name >>-logos:/var/www/html/images/uploads/logos + ports: + - "<< port >>:80" + restart: unless-stopped diff --git a/apps/wallos/template.json b/apps/wallos/template.json new file mode 100644 index 0000000..56a9c43 --- /dev/null +++ b/apps/wallos/template.json @@ -0,0 +1,60 @@ +{ + "kind": "compose", + "metadata": { + "name": "Wallos", + "description": "Houdt bij op welke abonnementen je zit, wat ze kosten en wanneer ze verlengen. Waarschuwt vóór de verlenging.", + "tags": [ + "abonnementen", + "kosten", + "financien" + ], + "icon": { + "provider": "selfhst", + "id": "wallos" + }, + "version": { + "name": "latest" + }, + "categories": [ + "financien", + "gezin" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "wallos", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8145, + "required": true, + "description": "Standaard 80; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/apps/wger/files/compose.yaml b/apps/wger/files/compose.yaml new file mode 100644 index 0000000..a601d6d --- /dev/null +++ b/apps/wger/files/compose.yaml @@ -0,0 +1,17 @@ +services: + << service_name >>: + image: wger/server:latest + container_name: << service_name >> + environment: + - SECRET_KEY=<< secret_key >> + - DJANGO_DB_ENGINE=django.db.backends.sqlite3 + - DJANGO_DB_DATABASE=/home/wger/media/db.sqlite3 + - TIME_ZONE=<< timezone >> + - ALLOW_REGISTRATION=False + - ALLOW_GUEST_USERS=False + - CSRF_TRUSTED_ORIGINS=<< app_url >> + volumes: + - << appdata_dir >>/<< service_name >>:/home/wger/media + ports: + - "<< port >>:8000" + restart: unless-stopped diff --git a/apps/wger/template.json b/apps/wger/template.json new file mode 100644 index 0000000..fa50043 --- /dev/null +++ b/apps/wger/template.json @@ -0,0 +1,85 @@ +{ + "kind": "compose", + "metadata": { + "name": "wger", + "description": "Trainingsschema's, gewicht en voeding bijhouden, met een oefeningendatabase die je zelf aanvult.", + "tags": [ + "fitness", + "gezondheid", + "training" + ], + "icon": { + "provider": "selfhst", + "id": "wger" + }, + "version": { + "name": "latest" + }, + "categories": [ + "gezin" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "wger", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8150, + "required": true, + "description": "Standaard 8000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "app_url", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8150", + "required": true + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "secret_key", + "type": "str", + "title": "Django-sleutel", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + } + ] + } + ] +} diff --git a/apps/woodpecker/files/compose.yaml b/apps/woodpecker/files/compose.yaml new file mode 100644 index 0000000..7f5b2d1 --- /dev/null +++ b/apps/woodpecker/files/compose.yaml @@ -0,0 +1,31 @@ +services: + << service_name >>: + image: woodpeckerci/woodpecker-server:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + - WOODPECKER_OPEN=false + - WOODPECKER_HOST=<< host >> + - WOODPECKER_AGENT_SECRET=<< agent_secret >> + - WOODPECKER_FORGEJO=true + - WOODPECKER_FORGEJO_URL=<< forgejo_url >> + - WOODPECKER_FORGEJO_CLIENT=<< forgejo_client >> + - WOODPECKER_FORGEJO_SECRET=<< forgejo_secret >> + - WOODPECKER_ADMIN=<< beheerder >> + volumes: + - << appdata_dir >>/<< service_name >>:/var/lib/woodpecker + ports: + - "<< port >>:8000" + restart: unless-stopped + << service_name >>-agent: + image: woodpeckerci/woodpecker-agent:latest + container_name: << service_name >>-agent + command: agent + environment: + - WOODPECKER_SERVER=<< service_name >>:9000 + - WOODPECKER_AGENT_SECRET=<< agent_secret >> + volumes: + - /var/run/docker.sock:/var/run/docker.sock + depends_on: + - << service_name >> + restart: unless-stopped diff --git a/apps/woodpecker/template.json b/apps/woodpecker/template.json new file mode 100644 index 0000000..631cca9 --- /dev/null +++ b/apps/woodpecker/template.json @@ -0,0 +1,122 @@ +{ + "kind": "compose", + "metadata": { + "name": "Woodpecker CI", + "description": "Bouwserver die je pipelines uit de repo leest. Werkt samen met Forgejo, Gitea en GitHub.", + "tags": [ + "ci", + "bouwen", + "ontwikkeling" + ], + "icon": { + "provider": "selfhst", + "id": "woodpecker" + }, + "version": { + "name": "latest" + }, + "categories": [ + "ontwikkeling" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "woodpecker", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Webinterface", + "default": 8162, + "required": true, + "description": "Standaard 8000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + }, + { + "title": "Instellingen", + "items": [ + { + "name": "host", + "type": "str", + "title": "Publiek adres", + "default": "http://localhost:8162", + "required": true + }, + { + "name": "forgejo_url", + "type": "str", + "title": "Adres van Forgejo", + "default": "http://forgejo:3000", + "required": true, + "connect": { + "app": "forgejo", + "scheme": "http", + "port": 3000 + }, + "help": "Woodpecker logt in via je git-server. Maak daar een OAuth2-toepassing aan en neem client-id en secret hier over." + }, + { + "name": "forgejo_client", + "type": "str", + "title": "OAuth2 client-id", + "default": "", + "required": true + }, + { + "name": "beheerder", + "type": "str", + "title": "Beheerdersaccount", + "default": "", + "required": true, + "description": "Gebruikersnaam in Forgejo die beheerder wordt" + } + ] + }, + { + "title": "Toegang", + "items": [ + { + "name": "agent_secret", + "type": "str", + "title": "Sleutel tussen server en agent", + "default": "", + "required": true, + "secret": true, + "generate": "auto" + }, + { + "name": "forgejo_secret", + "type": "str", + "title": "OAuth2 client-secret", + "default": "", + "required": true, + "secret": true, + "eigen_invoer": true + } + ] + } + ] +} diff --git a/apps/zoraxy/files/compose.yaml b/apps/zoraxy/files/compose.yaml new file mode 100644 index 0000000..1f896f6 --- /dev/null +++ b/apps/zoraxy/files/compose.yaml @@ -0,0 +1,13 @@ +services: + << service_name >>: + image: zoraxydocker/zoraxy:latest + container_name: << service_name >> + environment: + - TZ=<< timezone >> + volumes: + - << appdata_dir >>/<< service_name >>:/opt/zoraxy/config + ports: + - "<< port >>:8000" + - "<< port_http >>:80" + - "<< port_https >>:443" + restart: unless-stopped diff --git a/apps/zoraxy/template.json b/apps/zoraxy/template.json new file mode 100644 index 0000000..2c396b7 --- /dev/null +++ b/apps/zoraxy/template.json @@ -0,0 +1,74 @@ +{ + "kind": "compose", + "metadata": { + "name": "Zoraxy", + "description": "Reverse proxy met een webinterface in plaats van configuratiebestanden. Regelt zelf certificaten en heeft ingebouwde toegangsregels. Let op: Draai dit niet naast een andere reverse proxy op dezelfde poorten: 80 en 443 kunnen maar door één programma tegelijk gebruikt worden.", + "tags": [ + "proxy", + "https", + "netwerk", + "certificaten" + ], + "icon": { + "provider": "selfhst", + "id": "zoraxy" + }, + "version": { + "name": "latest" + }, + "categories": [ + "netwerk" + ] + }, + "variables": [ + { + "title": "Algemeen", + "items": [ + { + "name": "service_name", + "type": "str", + "title": "Servicenaam", + "default": "zoraxy", + "required": true + }, + { + "name": "port", + "type": "int", + "title": "Beheerinterface", + "default": 8129, + "required": true, + "description": "Standaard 8000; hier verplaatst omdat die poort al bezet is" + }, + { + "name": "port_http", + "type": "int", + "title": "HTTP", + "default": 80, + "required": true + }, + { + "name": "port_https", + "type": "int", + "title": "HTTPS", + "default": 443, + "required": true + }, + { + "name": "appdata_dir", + "type": "str", + "title": "Appdata-map", + "default": "/opt/serverup/appdata", + "required": true, + "description": "Basismap voor de gegevens van deze app" + }, + { + "name": "timezone", + "type": "str", + "title": "Tijdzone", + "default": "Europe/Amsterdam", + "required": true + } + ] + } + ] +} diff --git a/docs/apps-maken.md b/docs/apps-maken.md index 098f612..7915c2c 100644 --- a/docs/apps-maken.md +++ b/docs/apps-maken.md @@ -356,6 +356,28 @@ delen; die staan in een allowlist in `tests/test_apps.py`. Een onderdeel van de ARR-stack mag dezelfde poort hebben als zijn losse sjabloon — dat is dezelfde container, alleen anders verpakt. +**Een app met een eigen database.** Zet de database als tweede service in +hetzelfde compose-bestand, met het voorvoegsel van de app ervoor: + +```yaml + << service_name >>-db: + image: postgres:16-alpine + container_name: << service_name >>-db + environment: + - POSTGRES_PASSWORD=<< db_password >> +``` + +Dat voorvoegsel is geen opmaak: installeer je de app twee keer, dan botsen de +containernamen zonder. Het wachtwoord is een veld met `"secret": true` en +`"generate": "auto"`, zodat het formulier het invult en de waarde in `.env` +belandt in plaats van in het compose-bestand. Vergeet `depends_on` niet, anders +start de app vóór zijn database en valt hij om op de eerste verbinding. + +**Een geheim dat je nergens vandaan kunt genereren** — het client-secret van een +OIDC-toepassing, een wachtwoord dat de gebruiker zelf kiest — markeer je met +`"eigen_invoer": true`. Anders klaagt de testsuite terecht dat er een verplicht +geheim zonder waarde en zonder generator in staat. + **De appdata-map heet `appdata_dir`, de gedeelde datamap `data_root`.** De eerste is de plek waar déze app zijn instellingen bewaart (`/config`), de tweede is de gedeelde berg met media en downloads die als `/data` in elke container komt. Zit diff --git a/server-up/core/boilerplates.py b/server-up/core/boilerplates.py index 4f9fff2..d7943cc 100644 --- a/server-up/core/boilerplates.py +++ b/server-up/core/boilerplates.py @@ -152,6 +152,11 @@ def fields(d: Path) -> list[dict]: # willekeurigs. "auto" = ook meteen invullen, True = alleen een # knop (voor wachtwoorden waarmee je zelf inlogt). "generate": item.get("generate") or "", + # Een geheim dat de gebruiker ergens anders vandaan haalt: het + # client-secret van een OIDC-toepassing, een wachtwoord dat hij + # zelf kiest. Daar valt niets voor te genereren, en het is geen + # vergeten instelling. + "eigen_invoer": bool(item.get("eigen_invoer")), # In welke stap van het invulmenu dit veld thuishoort. "step": _stap_van(item, toggle), # "username" of "password": wordt getoond in het paneel diff --git a/server-up/core/categories.py b/server-up/core/categories.py index 4312416..d969c74 100644 --- a/server-up/core/categories.py +++ b/server-up/core/categories.py @@ -26,6 +26,9 @@ CATEGORIES: dict[str, dict] = { "financien": {"nl": "Financiën", "en": "Finance", "color": "#10b981", "icon": "mdi-cash-multiple"}, "gezin": {"nl": "Gezin & huishouden", "en": "Family & home", "color": "#f472b6", "icon": "mdi-home-heart"}, "monitoring": {"nl": "Monitoring", "en": "Monitoring", "color": "#f97316", "icon": "mdi-chart-line"}, + "analytics": {"nl": "Statistiek", "en": "Analytics", "color": "#d946ef", "icon": "mdi-chart-box-outline"}, + "zakelijk": {"nl": "Zakelijk", "en": "Business", "color": "#0d9488", "icon": "mdi-briefcase-outline"}, + "spellen": {"nl": "Spellen", "en": "Games", "color": "#e11d48", "icon": "mdi-gamepad-variant-outline"}, "ontwikkeling": {"nl": "Ontwikkeling", "en": "Development", "color": "#06b6d4", "icon": "mdi-code-braces"}, "ai": {"nl": "AI", "en": "AI", "color": "#a855f7", "icon": "mdi-brain"}, "beheer": {"nl": "Systeembeheer", "en": "System management", "color": "#64748b", "icon": "mdi-cog-outline"}, @@ -54,8 +57,12 @@ _TREFWOORDEN: list[tuple[tuple[str, ...], str]] = [ (("meldingen", "push", "chat", "communicatie", "e-mail"), "communicatie"), (("financien", "budget", "administratie"), "financien"), (("gezin", "huishouden", "recepten", "voorraad", "gezondheid", "logboek"), "gezin"), - (("monitoring", "metrics", "systeem", "dashboard", "statistiek", + (("monitoring", "metrics", "systeem", "dashboard", "realtime", "rapportage"), "monitoring"), + (("analytics", "bezoekers", "webstatistiek", "statistiek"), "analytics"), + (("crm", "helpdesk", "tickets", "facturen", "boekhouding", "assetbeheer", + "voorraadbeheer", "klanten"), "zakelijk"), + (("spellen", "games", "retro", "emulator", "gameserver", "minecraft"), "spellen"), (("git", "ontwikkelaar", "code", "ci", "database", "spreadsheet", "no-code", "encoding"), "ontwikkeling"), (("ai", "llm", "machine-learning"), "ai"), diff --git a/tests/test_app_templates.py b/tests/test_app_templates.py index e79275e..be28005 100644 --- a/tests/test_app_templates.py +++ b/tests/test_app_templates.py @@ -92,9 +92,13 @@ def test_geen_velden_die_nergens_gebruikt_worden(app): gebruikt |= set(VAR_RE.findall(ruw)) for blok in BLOK_RE.findall(ruw): gebruikt |= set(re.findall(r"[a-zA-Z_][a-zA-Z0-9_]*", blok)) - # Ook andere bestanden in files/ mogen variabelen gebruiken. + # Ook andere bestanden in files/ mogen variabelen gebruiken — inclusief + # YAML dat geen compose is, zoals de config.yaml die Headscale en Gatus + # meekrijgen. Die vielen eerder tussen wal en schip: niet gescand als + # compose, en overgeslagen omdat ze op .yaml eindigen. + composes = set(_compose_bestanden(app)) for p in (app / "files").rglob("*"): - if p.is_file() and p.suffix not in (".yaml", ".yml"): + if p.is_file() and p not in composes: try: gebruikt |= set(VAR_RE.findall(p.read_text(encoding="utf-8"))) except (UnicodeDecodeError, OSError): @@ -211,7 +215,8 @@ def test_verplichte_geheimen_zijn_invulbaar_of_worden_gegenereerd(app): worden, óf iets zijn dat de gebruiker zelf aanlevert. Wat overblijft is een veld waar niemand een geldige waarde voor kan verzinnen.""" # Wachtwoorden waarmee je zelf inlogt en tokens die je elders ophaalt vult - # de gebruiker bewust zelf in. + # de gebruiker bewust zelf in. Nieuwe sjablonen zeggen dat met + # `"eigen_invoer": true`; de namen hieronder zijn van vóór die vlag. eigen_invoer = ("admin_password", "web_password", "ui_password", "superuser_password", "password_hash", "hass_token", "forgejo_token", "adminpass") @@ -220,6 +225,8 @@ def test_verplichte_geheimen_zijn_invulbaar_of_worden_gegenereerd(app): continue if str(f.get("default") or "").strip(): continue + if f.get("eigen_invoer"): + continue # Een API-sleutel komt per definitie uit de app waar je naartoe wijst; # die kun je hier niet verzinnen, alleen overtypen. if f["name"].endswith(("_apikey", "_api_key")): diff --git a/tests/test_apps.py b/tests/test_apps.py index 53bce5f..576f009 100644 --- a/tests/test_apps.py +++ b/tests/test_apps.py @@ -32,7 +32,7 @@ def _render(d: Path, tmp: Path) -> dict: def test_er_zijn_apps(): - assert len(APPS) >= 60 + assert len(APPS) >= 190 @pytest.mark.parametrize("app", APPS, ids=NAMEN) @@ -86,11 +86,74 @@ def test_geen_onvervangen_variabelen(app): assert "<<" not in tekst and ">>" not in tekst, "onvervangen variabele" +# ── Apps die hun eigen database meebrengen ─────────────────────────────────── + +_DATABASE_IMAGES = ("postgres", "postgis", "mariadb", "mysql", "mongo", + "redis", "valkey") + + +def _bron(app: Path) -> str: + return (app / "files" / "compose.yaml").read_text(encoding="utf-8") + + +@pytest.mark.parametrize("app", APPS, ids=NAMEN) +def test_extra_containers_dragen_de_servicenaam(app): + """Een tweede container moet `-…` heten. + + De instantienaam is het enige wat een gebruiker kiest als hij een app twee + keer installeert. Heet de database dan gewoon `db`, dan botsen de twee + installaties op de containernaam en start de tweede niet. + """ + snaam = next((f.get("default") for f in bp.fields(app) + if f["name"] == "service_name"), None) or app.name + with tempfile.TemporaryDirectory() as t: + doc = _render(app, Path(t)) + for naam in doc["services"]: + assert naam == snaam or naam.startswith(f"{snaam}-"), \ + f"'{naam}' draagt de servicenaam '{snaam}' niet" + + +@pytest.mark.parametrize("app", APPS, ids=NAMEN) +def test_bijgeleverde_database_heeft_geen_vast_wachtwoord(app): + """Een database met een wachtwoord dat in het sjabloon staat, heeft bij + iedereen hetzelfde wachtwoord. Dat is geen wachtwoord.""" + ruw = _bron(app) + heeft_db = any(f"image: {i}" in ruw for i in _DATABASE_IMAGES) + if not heeft_db: + return + for regel in ruw.splitlines(): + r = regel.strip() + if not any(r.startswith(f"- {k}") for k in + ("POSTGRES_PASSWORD", "MARIADB_PASSWORD", "MARIADB_ROOT_PASSWORD", + "MYSQL_PASSWORD", "MYSQL_ROOT_PASSWORD", + "MONGO_INITDB_ROOT_PASSWORD")): + continue + waarde = r.split("=", 1)[1] if "=" in r else "" + assert "<<" in waarde, f"vast databasewachtwoord: {r}" + + +@pytest.mark.parametrize("app", APPS, ids=NAMEN) +def test_bijgeleverde_database_wordt_afgewacht(app): + """Zonder depends_on start de app vóór zijn database en valt hij om op de + eerste verbinding.""" + with tempfile.TemporaryDirectory() as t: + doc = _render(app, Path(t)) + diensten = doc["services"] + dbs = {n for n, s in diensten.items() + if isinstance(s, dict) + and any(str(s.get("image", "")).startswith(i) for i in _DATABASE_IMAGES)} + if not dbs: + return + wacht = {d for s in diensten.values() if isinstance(s, dict) + for d in (s.get("depends_on") or [])} + assert dbs <= wacht, f"niemand wacht op {sorted(dbs - wacht)}" + + # 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", "caddy"}, # reverse proxies - 443: {"nginx-proxy-manager", "traefik", "caddy"}, + 80: {"nginx-proxy-manager", "traefik", "caddy", "zoraxy"}, # reverse proxies + 443: {"nginx-proxy-manager", "traefik", "caddy", "zoraxy"}, 53: {"adguard-home", "pihole"}, # dns-blokkers # Hieronder: botsingen die er al waren vóór deze testsuite. De # vrije-poortsuggestie bij installeren vangt ze op, dus ze zijn hinderlijk