Compare commits
28 commits
7eee8ba8ca
...
2862f7844c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2862f7844c | ||
|
|
2ba15418ab | ||
|
|
ff1979ba51 | ||
|
|
4450b3c171 | ||
|
|
146d7ae79d | ||
|
|
7ae62fe78c | ||
|
|
b8c8e89fa0 | ||
|
|
7f0d34cb1a | ||
|
|
34a48fb74a | ||
|
|
cb04c4a7ad | ||
|
|
dea949a003 | ||
|
|
eb52c2ac41 | ||
|
|
8da53aba6f | ||
|
|
b30f83866f | ||
|
|
cbb232d63f | ||
|
|
923c8dabee | ||
|
|
4346fefe4d | ||
|
|
866c5b8c1e | ||
|
|
6d5453ed70 | ||
|
|
576ee17a61 | ||
|
|
a1fb5f5a8f | ||
|
|
342b2ee9e5 | ||
|
|
f40fd39ed9 | ||
|
|
ae99df2fc7 | ||
|
|
fe7abce95b | ||
|
|
8ff5f4b1d3 | ||
|
|
8b29553a71 | ||
|
|
916e54a229 |
220 changed files with 18378 additions and 494 deletions
48
.env.example
Normal file
48
.env.example
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Instellingen van deze Server Up-installatie.
|
||||
#
|
||||
# Kopieer naar `.env` in dezelfde map als docker-compose.yml. Het bestand staat
|
||||
# in .gitignore en wordt door de deploy-workflow met rust gelaten, dus wat je
|
||||
# hier zet blijft staan bij een update.
|
||||
#
|
||||
# cp .env.example .env
|
||||
|
||||
# ── Bereikbaarheid ───────────────────────────────────────────────────────────
|
||||
|
||||
# Op welk adres de poort wordt gepubliceerd.
|
||||
# 127.0.0.1 alleen vanaf de server zelf (standaard, veiligst)
|
||||
# 0.0.0.0 vanaf het hele netwerk — doe dit alleen achter een reverse proxy
|
||||
# met TLS, want Server Up beheert Docker als root
|
||||
BIND=127.0.0.1
|
||||
|
||||
# Poort op de host.
|
||||
PORT=5000
|
||||
|
||||
# ── Versie en bijwerken ──────────────────────────────────────────────────────
|
||||
|
||||
# Welke image-tag draait. De deploy-workflow schrijft deze waarde zelf; met de
|
||||
# hand aanpassen kan om terug te rollen naar een eerdere versie.
|
||||
#SU_TAG=0.5.40-beta
|
||||
|
||||
# Registry-image, zónder tag. Staat dit ingevuld, dan draait deze server vanaf
|
||||
# een registry en werkt de knop "Nu bijwerken" in de interface. Laat het leeg
|
||||
# als de server zelf bouwt na een push naar Git — dan is Git de update-route.
|
||||
# Zie docs/updates.md.
|
||||
#SU_IMAGE=git.example.com/bes-r/server-up
|
||||
|
||||
# ── Overig ───────────────────────────────────────────────────────────────────
|
||||
|
||||
# Waar de stacks, appdata en backups komen te staan. Dit pad wordt in de
|
||||
# container op hetzelfde pad gemount, zodat compose-bestanden kloppen.
|
||||
#BASE_DIR=/opt/serverup
|
||||
|
||||
# Zet op 1 zodra alles via HTTPS loopt: de sessiecookie krijgt dan de
|
||||
# Secure-vlag.
|
||||
#SU_HTTPS=1
|
||||
|
||||
# Extra app-repositories zonder de wizard, als JSON-array. Eenmalig ingelezen
|
||||
# en daarna opgeslagen in config.json.
|
||||
#SU_BOOT_REPOS=[{"id":"mijn-apps","name":"Mijn Apps","url":"https://…","branch":"main","subdir":"apps"}]
|
||||
|
||||
# Debug-endpoints (/api/debug/*) inschakelen. Alleen tijdelijk gebruiken:
|
||||
# /api/debug/config toont de volledige configuratie.
|
||||
#SU_DEBUG=1
|
||||
|
|
@ -1,52 +1,98 @@
|
|||
# Forgejo Actions — bouw + push image NAAR DE REGISTRY (optioneel, handmatig)
|
||||
# Forgejo Actions — bouw het image en push het naar de container-registry.
|
||||
#
|
||||
# UITGESCHAKELD voor automatische runs. Deze server bouwt zelf via
|
||||
# deploy-prod.yml / deploy.yml (rsync + `docker compose build`), dus een
|
||||
# registry-push is niet nodig. Stond dit op `push: tags: v*`, dan bleef de job
|
||||
# hangen omdat hij een runner met label `docker` zoekt die niet bestaat —
|
||||
# dat veroorzaakte de eindeloos "building" run in de Actions-tab.
|
||||
# Dit image is wat de "Nu bijwerken"-knop in Server Up ophaalt. Draait bij elke
|
||||
# v*-tag, zodat elke release (en pre-release) een image krijgt met dezelfde tag
|
||||
# als de release zelf: v0.5.10 → server-up:0.5.10.
|
||||
#
|
||||
# Wil je tóch naar de Forgejo container-registry publiceren: start deze workflow
|
||||
# handmatig via de Actions-tab (Run workflow) en zorg dat er een runner met
|
||||
# label `docker` bestaat (of pas `runs-on` aan naar je eigen runner-label).
|
||||
# Vereisten (Repository → Settings):
|
||||
# Variables → REGISTRY = git.example.com (host van je Forgejo)
|
||||
# OWNER = bes-r (gebruiker/organisatie)
|
||||
# Secrets → PACKAGE_TOKEN = <token met write:package>
|
||||
#
|
||||
# Vereisten (alleen voor handmatige runs):
|
||||
# Settings → Variables → REGISTRY=git.example.com, OWNER=bes-r
|
||||
# Settings → Secrets → PACKAGE_TOKEN=<token met write:package scope>
|
||||
# Zie docs/updates.md voor de complete instelling.
|
||||
|
||||
name: Build and push image (handmatig)
|
||||
name: Build en push image (handmatig)
|
||||
|
||||
# Alleen handmatig. Bij een v*-tag bouwt en pusht deploy-prod.yml het image al
|
||||
# in dezelfde job — zo kan er geen wachtrij ontstaan waarin de deploy op een
|
||||
# build wacht die zelf nog in de rij staat.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Versie om te bouwen (bv. 0.5.10). Leeg = VERSION-bestand"
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: docker
|
||||
runs-on: [self-hosted, prod]
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Extract versie uit tag
|
||||
id: tag
|
||||
run: echo "v=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Login op Forgejo registry
|
||||
- name: Versie en tags bepalen
|
||||
id: meta
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VERSION="${{ inputs.tag }}"
|
||||
if [ -z "$VERSION" ]; then
|
||||
VERSION="$(tr -d '[:space:]' < VERSION)"
|
||||
fi
|
||||
IMAGE="${{ vars.REGISTRY }}/${{ vars.OWNER }}/server-up"
|
||||
echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
|
||||
echo "IMAGE=${IMAGE}" >> "$GITHUB_ENV"
|
||||
|
||||
# Pre-release (tag met een streepje, bv. v0.5.10-beta1) krijgt géén
|
||||
# 'latest'-tag: die hoort bij het stable-kanaal.
|
||||
if [[ "$VERSION" == *-* ]]; then
|
||||
echo "EXTRA_TAG=beta" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "EXTRA_TAG=latest" >> "$GITHUB_ENV"
|
||||
fi
|
||||
echo "Bouwen: ${IMAGE}:${VERSION}"
|
||||
|
||||
- name: Tests draaien
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# In een container in plaats van een venv op de runner: die heeft
|
||||
# geen python3-venv, en zo draaien de tests bovendien op exact de
|
||||
# Python-versie waarop de app in productie draait.
|
||||
# PYTHONDONTWRITEBYTECODE + no:cacheprovider voorkomen dat er
|
||||
# root-eigen bestanden in de werkmap achterblijven.
|
||||
docker run --rm \
|
||||
-v "$PWD:/w" -w /w \
|
||||
-v su-pip-cache:/root/.cache/pip \
|
||||
-e PYTHONDONTWRITEBYTECODE=1 \
|
||||
python:3.12-slim \
|
||||
sh -c "pip install -q -r server-up/requirements.txt pytest \
|
||||
&& python -m pytest tests -q -p no:cacheprovider"
|
||||
|
||||
- name: Inloggen op de registry
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "${{ secrets.PACKAGE_TOKEN }}" \
|
||||
| docker login ${{ vars.REGISTRY }} \
|
||||
-u ${{ vars.OWNER }} \
|
||||
--password-stdin
|
||||
| docker login "${{ vars.REGISTRY }}" \
|
||||
-u "${{ vars.OWNER }}" --password-stdin
|
||||
|
||||
- name: Bouw image met versie ingebakken
|
||||
- name: Bouwen
|
||||
run: |
|
||||
set -euo pipefail
|
||||
docker build \
|
||||
--build-arg SU_VERSION=${{ steps.tag.outputs.v }} \
|
||||
-t ${{ vars.REGISTRY }}/${{ vars.OWNER }}/server-up:${{ steps.tag.outputs.v }} \
|
||||
-t ${{ vars.REGISTRY }}/${{ vars.OWNER }}/server-up:latest \
|
||||
--pull \
|
||||
--build-arg "SU_VERSION=${VERSION}" \
|
||||
-t "${IMAGE}:${VERSION}" \
|
||||
-t "${IMAGE}:${EXTRA_TAG}" \
|
||||
.
|
||||
|
||||
- name: Push image
|
||||
- name: Pushen
|
||||
run: |
|
||||
docker push ${{ vars.REGISTRY }}/${{ vars.OWNER }}/server-up:${{ steps.tag.outputs.v }}
|
||||
docker push ${{ vars.REGISTRY }}/${{ vars.OWNER }}/server-up:latest
|
||||
set -euo pipefail
|
||||
docker push "${IMAGE}:${VERSION}"
|
||||
docker push "${IMAGE}:${EXTRA_TAG}"
|
||||
echo "Gepusht: ${IMAGE}:${VERSION} en ${IMAGE}:${EXTRA_TAG}"
|
||||
|
||||
- name: Uitloggen
|
||||
if: always()
|
||||
run: docker logout "${{ vars.REGISTRY }}" || true
|
||||
|
|
|
|||
|
|
@ -41,32 +41,115 @@ jobs:
|
|||
echo "SU_VERSION=${VERSION}" >> "$GITHUB_ENV"
|
||||
echo "Deploying version: ${VERSION} (${CHANNEL})"
|
||||
|
||||
- name: Tests draaien
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# In een container in plaats van een venv op de runner: die heeft
|
||||
# geen python3-venv, en zo draaien de tests bovendien op exact de
|
||||
# Python-versie waarop de app in productie draait.
|
||||
# PYTHONDONTWRITEBYTECODE + no:cacheprovider voorkomen dat er
|
||||
# root-eigen bestanden in de werkmap achterblijven.
|
||||
docker run --rm \
|
||||
-v "$PWD:/w" -w /w \
|
||||
-v su-pip-cache:/root/.cache/pip \
|
||||
-e PYTHONDONTWRITEBYTECODE=1 \
|
||||
python:3.12-slim \
|
||||
sh -c "pip install -q -r server-up/requirements.txt pytest \
|
||||
&& python -m pytest tests -q -p no:cacheprovider"
|
||||
|
||||
- name: Sync code naar deploy-directory
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# .env staat in .gitignore, dus de checkout heeft er geen. Zonder deze
|
||||
# uitzondering wist --delete de lokale instellingen van de server
|
||||
# (BIND, SU_IMAGE, PORT) bij elke deploy.
|
||||
rsync -a --delete \
|
||||
--exclude='.git/' \
|
||||
--exclude='.forgejo/' \
|
||||
--exclude='.env' \
|
||||
./ "$DEPLOY_DIR/"
|
||||
|
||||
- name: Schrijf VERSION-bestand
|
||||
working-directory: ${{ env.DEPLOY_DIR }}
|
||||
run: echo "${VERSION}" > VERSION
|
||||
|
||||
- name: Build image
|
||||
working-directory: ${{ env.DEPLOY_DIR }}
|
||||
run: |
|
||||
docker compose build --pull
|
||||
# docker compose bouwt als server-up:latest; voeg versie- en channel-tags toe
|
||||
docker tag server-up:latest "server-up:${VERSION}"
|
||||
docker tag server-up:latest "server-up:${CHANNEL}"
|
||||
|
||||
- name: Deploy
|
||||
working-directory: ${{ env.DEPLOY_DIR }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Expliciet cd in plaats van 'working-directory:'; dat laatste wordt
|
||||
# niet door elke runner even betrouwbaar toegepast.
|
||||
cd "$DEPLOY_DIR"
|
||||
echo "${VERSION}" > VERSION
|
||||
echo "Werkmap: $(pwd)"
|
||||
|
||||
- name: Bouwen (en pushen naar de registry)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd "$DEPLOY_DIR"
|
||||
# SU_TAG vastleggen zodat compose en de "Nu bijwerken"-knop in de app
|
||||
# naar hetzelfde image wijzen (zie docs/updates.md).
|
||||
#
|
||||
# SU_TAG bepaalt welk image compose start. We schrijven dat bij
|
||||
# voorkeur in .env zodat het een handmatige `docker compose up`
|
||||
# overleeft, maar dat bestand kan van een andere gebruiker zijn (bv.
|
||||
# met sudo aangemaakt). Lukt schrijven niet, dan geven we SU_TAG mee
|
||||
# via de omgeving: compose gebruikt die en de deploy loopt gewoon door.
|
||||
if [ ! -f .env ] && [ -f .env.example ]; then
|
||||
cp .env.example .env 2>/dev/null \
|
||||
&& echo "Nieuwe .env aangemaakt vanuit .env.example" \
|
||||
|| echo "LET OP: kon geen .env aanmaken in $(pwd)"
|
||||
fi
|
||||
|
||||
if [ -w .env ] || { [ ! -e .env ] && [ -w . ]; }; then
|
||||
touch .env
|
||||
sed -i '/^SU_TAG=/d' .env
|
||||
echo "SU_TAG=${VERSION}" >> .env
|
||||
echo "Inhoud van $(pwd)/.env:"
|
||||
grep -vE '^\s*(#|$)' .env | sed 's/^/ /'
|
||||
else
|
||||
echo "LET OP: $(pwd)/.env is niet schrijfbaar voor $(id -un)."
|
||||
echo " Eigenaar: $(stat -c '%U:%G %a' .env 2>/dev/null || echo onbekend)"
|
||||
echo " Herstel eenmalig met:"
|
||||
echo " sudo chown $(stat -c '%U:%G' . ) $(pwd)/.env"
|
||||
echo " SU_TAG wordt nu via de omgeving meegegeven."
|
||||
fi
|
||||
|
||||
# Draait deze server vanaf de registry (SU_IMAGE in .env), dan bouwen
|
||||
# we hier én pushen we het resultaat, zodat de in-app updateknop het
|
||||
# image kan ophalen. Bouwen en pushen zitten bewust in dezelfde job:
|
||||
# een aparte build-workflow zou met deze deploy om de runner strijden.
|
||||
export SU_TAG="${VERSION}"
|
||||
SU_IMAGE="$(grep -E '^SU_IMAGE=' .env 2>/dev/null | cut -d= -f2- || true)"
|
||||
docker compose build --pull
|
||||
|
||||
if [ -n "$SU_IMAGE" ]; then
|
||||
echo "Registry-modus: ${SU_IMAGE}:${VERSION} pushen"
|
||||
echo "${{ secrets.PACKAGE_TOKEN }}" \
|
||||
| docker login "${{ vars.REGISTRY }}" -u "${{ vars.OWNER }}" --password-stdin
|
||||
docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:${CHANNEL}" || true
|
||||
docker push "${SU_IMAGE}:${VERSION}"
|
||||
# Pre-releases krijgen geen 'latest': dat hoort bij stable.
|
||||
case "$VERSION" in
|
||||
*-*) docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:beta"
|
||||
docker push "${SU_IMAGE}:beta" ;;
|
||||
*) docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:latest"
|
||||
docker push "${SU_IMAGE}:latest" ;;
|
||||
esac
|
||||
docker logout "${{ vars.REGISTRY }}" || true
|
||||
else
|
||||
echo "Lokale bouwmodus (geen SU_IMAGE ingesteld)"
|
||||
docker tag "server-up:${VERSION}" "server-up:${CHANNEL}" || true
|
||||
fi
|
||||
|
||||
- name: Deploy
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd "$DEPLOY_DIR"
|
||||
export SU_TAG="${VERSION}"
|
||||
docker compose up -d --remove-orphans
|
||||
docker compose ps
|
||||
echo "Compose-projectmap volgens de container:"
|
||||
docker inspect server-up \
|
||||
--format ' {{index .Config.Labels "com.docker.compose.project.working_dir"}}'
|
||||
echo "Poortbinding:"
|
||||
docker inspect server-up \
|
||||
--format ' {{range $p, $c := .NetworkSettings.Ports}}{{$p}} -> {{range $c}}{{.HostIp}}:{{.HostPort}}{{end}}{{"\n"}}{{end}}'
|
||||
|
||||
- name: Wachten op healthcheck
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -41,32 +41,93 @@ jobs:
|
|||
echo "SU_VERSION=${VERSION}" >> "$GITHUB_ENV"
|
||||
echo "Deploying version: ${VERSION} (${CHANNEL})"
|
||||
|
||||
- name: Tests draaien
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# In een container in plaats van een venv op de runner: die heeft
|
||||
# geen python3-venv, en zo draaien de tests bovendien op exact de
|
||||
# Python-versie waarop de app in productie draait.
|
||||
# PYTHONDONTWRITEBYTECODE + no:cacheprovider voorkomen dat er
|
||||
# root-eigen bestanden in de werkmap achterblijven.
|
||||
docker run --rm \
|
||||
-v "$PWD:/w" -w /w \
|
||||
-v su-pip-cache:/root/.cache/pip \
|
||||
-e PYTHONDONTWRITEBYTECODE=1 \
|
||||
python:3.12-slim \
|
||||
sh -c "pip install -q -r server-up/requirements.txt pytest \
|
||||
&& python -m pytest tests -q -p no:cacheprovider"
|
||||
|
||||
- name: Sync code naar deploy-directory
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# .env staat in .gitignore, dus de checkout heeft er geen. Zonder deze
|
||||
# uitzondering wist --delete de lokale instellingen van de server
|
||||
# (BIND, SU_IMAGE, PORT) bij elke deploy.
|
||||
rsync -a --no-group --delete \
|
||||
--exclude='.git/' \
|
||||
--exclude='.forgejo/' \
|
||||
--exclude='.env' \
|
||||
./ "$DEPLOY_DIR/"
|
||||
|
||||
- name: Schrijf VERSION-bestand
|
||||
working-directory: ${{ env.DEPLOY_DIR }}
|
||||
run: echo "${VERSION}" > VERSION
|
||||
|
||||
- name: Build image
|
||||
working-directory: ${{ env.DEPLOY_DIR }}
|
||||
run: |
|
||||
docker compose build --pull
|
||||
# docker compose bouwt als server-up:latest; voeg versie- en channel-tags toe
|
||||
docker tag server-up:latest "server-up:${VERSION}"
|
||||
docker tag server-up:latest "server-up:${CHANNEL}"
|
||||
|
||||
- name: Deploy
|
||||
working-directory: ${{ env.DEPLOY_DIR }}
|
||||
- name: Instellingen en versie klaarzetten
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Expliciet cd in plaats van 'working-directory:'. Dat laatste wordt
|
||||
# niet door elke runner-implementatie even betrouwbaar toegepast, en
|
||||
# als het misgaat belanden VERSION, .env en de container stilletjes in
|
||||
# de werkmap van de runner in plaats van in de deploy-map.
|
||||
cd "$DEPLOY_DIR"
|
||||
echo "Werkmap: $(pwd)"
|
||||
|
||||
echo "${VERSION}" > VERSION
|
||||
|
||||
# SU_TAG bepaalt welk image compose start. We schrijven dat bij
|
||||
# voorkeur in .env zodat het een handmatige `docker compose up`
|
||||
# overleeft, maar dat bestand kan van een andere gebruiker zijn (bv.
|
||||
# met sudo aangemaakt). Lukt schrijven niet, dan geven we SU_TAG mee
|
||||
# via de omgeving: compose gebruikt die en de deploy loopt gewoon door.
|
||||
if [ ! -f .env ] && [ -f .env.example ]; then
|
||||
cp .env.example .env 2>/dev/null \
|
||||
&& echo "Nieuwe .env aangemaakt vanuit .env.example" \
|
||||
|| echo "LET OP: kon geen .env aanmaken in $(pwd)"
|
||||
fi
|
||||
|
||||
if [ -w .env ] || { [ ! -e .env ] && [ -w . ]; }; then
|
||||
touch .env
|
||||
sed -i '/^SU_TAG=/d' .env
|
||||
echo "SU_TAG=${VERSION}" >> .env
|
||||
echo "Inhoud van $(pwd)/.env:"
|
||||
grep -vE '^\s*(#|$)' .env | sed 's/^/ /'
|
||||
else
|
||||
echo "LET OP: $(pwd)/.env is niet schrijfbaar voor $(id -un)."
|
||||
echo " Eigenaar: $(stat -c '%U:%G %a' .env 2>/dev/null || echo onbekend)"
|
||||
echo " Herstel eenmalig met:"
|
||||
echo " sudo chown $(stat -c '%U:%G' . ) $(pwd)/.env"
|
||||
echo " SU_TAG wordt nu via de omgeving meegegeven."
|
||||
fi
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd "$DEPLOY_DIR"
|
||||
export SU_TAG="${VERSION}"
|
||||
docker compose build --pull
|
||||
docker tag "server-up:${VERSION}" "server-up:${CHANNEL}" || true
|
||||
|
||||
- name: Deploy
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd "$DEPLOY_DIR"
|
||||
export SU_TAG="${VERSION}"
|
||||
docker compose up -d --remove-orphans
|
||||
docker compose ps
|
||||
# Waar draait de container vandaan, en op welk adres luistert hij?
|
||||
echo "Compose-projectmap volgens de container:"
|
||||
docker inspect server-up \
|
||||
--format ' {{index .Config.Labels "com.docker.compose.project.working_dir"}}'
|
||||
echo "Poortbinding:"
|
||||
docker inspect server-up \
|
||||
--format ' {{range $p, $c := .NetworkSettings.Ports}}{{$p}} -> {{range $c}}{{.HostIp}}:{{.HostPort}}{{end}}{{"\n"}}{{end}}'
|
||||
|
||||
- name: Wachten op healthcheck
|
||||
run: |
|
||||
|
|
|
|||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -2,3 +2,5 @@ __pycache__/
|
|||
*.pyc
|
||||
*.pyo
|
||||
.env
|
||||
.pytest_cache/
|
||||
venv/
|
||||
|
|
|
|||
754
CHANGELOG.md
754
CHANGELOG.md
|
|
@ -1,3 +1,757 @@
|
|||
# v0.7.30-beta — Installeren met één regel
|
||||
|
||||
```bash
|
||||
curl -fsSL https://git.ramonbesselink.nl/bes-r/server-up/raw/branch/main/install.sh | sh
|
||||
```
|
||||
|
||||
Het script controleert je systeem, biedt aan Docker te installeren als dat
|
||||
ontbreekt, haalt de code op, maakt `.env` aan, bouwt het image, start de
|
||||
container en wacht tot `/healthz` antwoordt. Daarna toont het waar je terecht
|
||||
kunt — met de waarschuwing dat je meteen een beheerdersaccount moet aanmaken.
|
||||
|
||||
Opties: `--dir`, `--port`, `--bind`, `--branch`, `--token`, `--update`,
|
||||
`--uninstall`, `--yes` en `--dry-run`.
|
||||
|
||||
**`--dry-run`** toont de hele gang van zaken zonder iets te wijzigen. Handig om
|
||||
te zien wat er gaat gebeuren voordat je een script met root-rechten loslaat op
|
||||
je server; `docs/installeren.md` zet die stap dan ook vooraan.
|
||||
|
||||
**Bijwerken** gaat met `sh /opt/server-up/install.sh --update`: nieuwe code
|
||||
ophalen, opnieuw bouwen, herstarten. Je `.env`, stacks en gegevens blijven staan.
|
||||
**Verwijderen** stopt de container maar laat je gegevens met rust, en vertelt
|
||||
daarna hoe je die alsnog opruimt.
|
||||
|
||||
Het script gebruikt alleen `sudo` waar dat nodig is: kun je zelf al in de
|
||||
doelmap schrijven én docker aanroepen, dan blijft alles onder je eigen account.
|
||||
|
||||
Nieuw: `README.md` verwijst er nu naar, plus `docs/installeren.md` met alle
|
||||
opties en een probleemoplostabel.
|
||||
|
||||
Getest onder `sh`, `dash` en `bash`, met een testsuite die controleert dat er
|
||||
geen bashismen in sluipen, dat een typefout in de opties netjes stopt, en dat
|
||||
een proefdraai echt niets aanmaakt. Twee dingen die daarbij naar boven kwamen:
|
||||
de wachtlus gaf anderhalve minuut lang geen enkel teken van leven (nu puntjes),
|
||||
en `docker compose --project-directory` zoekt zonder `-f` het compose-bestand
|
||||
alsnog in de huidige map — wat bij `curl | sh` je thuismap is.
|
||||
|
||||
---
|
||||
|
||||
# v0.7.20-beta — Instellingen wijzigen, koppelen achteraf, en een defect uit v0.7.00
|
||||
|
||||
## 🔴 Gedeeld netwerk botste met `network_mode`
|
||||
|
||||
De koppeling uit v0.7.00 hing élke service aan het gedeelde netwerk. Maar een
|
||||
service met `network_mode` deelt al andermans namespace, en docker compose
|
||||
weigert die combinatie. Met de standaardkeuze "Verbinden met andere apps" waren
|
||||
**Homebridge**, **Scrypted**, **Beszel** en de **ARR-stack met Gluetun** daardoor
|
||||
niet te installeren.
|
||||
|
||||
Services met `network_mode` worden nu overgeslagen. Een test past het gedeelde
|
||||
netwerk toe over alle 96 apps en controleert dat die combinatie nooit ontstaat.
|
||||
|
||||
## ⚙️ Instellingen wijzigen na installatie
|
||||
|
||||
Je koos bij het installeren netjes een poort, map en wachtwoord — maar daarna was
|
||||
er geen weg terug naar dat formulier. Voor een andere poort moest je het
|
||||
compose-bestand met de hand bewerken.
|
||||
|
||||
De knop **Instellingen** op elke stackkaart opent hetzelfde formulier, voorgevuld
|
||||
met wat je destijds hebt gekozen. Opslaan maakt eerst een backup, rendert de
|
||||
stack opnieuw, valideert en herstart. Loopt het valideren mis, dan wordt de
|
||||
backup automatisch teruggezet.
|
||||
|
||||
Stacks die zijn geïnstalleerd voordat Server Up die keuzes bewaarde, hebben de
|
||||
knop uit staan met uitleg waarom.
|
||||
|
||||
## 🔗 Bestaande stacks alsnog koppelen
|
||||
|
||||
Het gedeelde netwerk gold alleen voor nieuwe installaties. Een knop op de
|
||||
stackkaart zet een bestaande stack er alsnog op, valideert en herstart. Wordt de
|
||||
compose ongeldig, dan wordt de wijziging teruggedraaid.
|
||||
|
||||
## 🔍 Audit-log doorzoekbaar
|
||||
|
||||
Het log toonde de laatste tweehonderd regels zonder filter, terwijl er inmiddels
|
||||
logins, rolwijzigingen, backups en updates in landen. Nu filteren op bron, actie,
|
||||
status en periode, met vrij zoeken door referentie, details en IP-adres, en
|
||||
doorbladeren voorbij de eerste honderd.
|
||||
|
||||
## 📖 Documentatie
|
||||
|
||||
- **`README.md`** — die was er niet. Wat Server Up is, installeren, het eerste
|
||||
account, en waar je verder moet kijken.
|
||||
- **`docs/apps-maken.md`** — het volledige templateformaat: velden, geavanceerde
|
||||
opties, uitleg per veld, apps aan elkaar koppelen, onderdelen optioneel maken
|
||||
met groepsschakelaars, en de valkuilen (named volumes, poorten, `network_mode`).
|
||||
- **`docs/README.md`** — index over de zeven documenten.
|
||||
|
||||
De changelog-secties voor `v0.5.44`, `v0.5.45` en `v0.5.46` ontbraken; omdat
|
||||
`release.yml` de notes daaruit haalt, zou een tag op die versies een lege release
|
||||
opleveren. Aangevuld, met een test die afdwingt dat het huidige `VERSION` altijd
|
||||
een sectie heeft.
|
||||
|
||||
---
|
||||
|
||||
# v0.7.10-beta — Categorieën met kleur, in de app store en bij je apps
|
||||
|
||||
Alle 96 apps zijn ingedeeld in zeventien categorieën, elk met een eigen kleur en
|
||||
pictogram. Een app mag in meerdere categorieën zitten: Frigate staat onder
|
||||
Domotica én Media, Immich onder Foto's én Opslag, Kavita onder Media én
|
||||
Documenten. Negenendertig apps vallen onder meer dan één.
|
||||
|
||||
| | Categorie | | Categorie |
|
||||
|---|---|---|---|
|
||||
| 🟣 | Media | 🔵 | Netwerk |
|
||||
| 🩷 | Foto's | 🔴 | Beveiliging |
|
||||
| 🟢 | Downloaden | 🟠 | Opslag & backup |
|
||||
| 🟩 | Domotica | 🩵 | Documenten |
|
||||
| 🟦 | 3D-printen | 🟦 | Productiviteit |
|
||||
| 🔷 | Communicatie | 🟩 | Financiën |
|
||||
| 🌸 | Gezin & huishouden | 🟧 | Monitoring |
|
||||
| 🩵 | Ontwikkeling | 🟪 | AI |
|
||||
| ⬜ | Systeembeheer | | |
|
||||
|
||||
**In de app store** staat een gekleurde categoriebalk met per categorie het
|
||||
aantal apps. Klikken filtert; het bestaande zoekveld en de tagfilters werken
|
||||
ernaast gewoon door. Elke app-kaart toont zijn categorieën als gekleurde badge,
|
||||
en klikken op zo'n badge filtert er meteen op.
|
||||
|
||||
**Bij je geïnstalleerde apps** staat dezelfde balk, met alleen de categorieën die
|
||||
je daadwerkelijk draait. Elke stackkaart heeft een gekleurde rand in de kleur van
|
||||
zijn eerste categorie, plus dezelfde klikbare badges.
|
||||
|
||||
Apps uit externe repo's (zoals de ChristianLempa-boilerplates) geven geen
|
||||
categorieën op. Die worden afgeleid uit hun tags en omschrijving, zodat ook zij
|
||||
een kleur en een plek in het filter krijgen in plaats van als naamloze groep
|
||||
buiten de indeling te vallen.
|
||||
|
||||
Tests bewaken dat elke app minstens één geldige categorie heeft, dat de kleuren
|
||||
onderling verschillen, en dat er geen categorie in het filter staat waar geen
|
||||
enkele app onder valt.
|
||||
|
||||
---
|
||||
|
||||
# v0.7.00-beta — Apps koppelen, eenvoudiger instellen, geavanceerde opties verborgen
|
||||
|
||||
## 🔗 Apps kunnen elkaar nu bereiken
|
||||
|
||||
Elke stack draaide als eigen compose-project en kreeg daarmee zijn eigen
|
||||
netwerk. Twee stacks konden elkaar dus niet op naam vinden: Zigbee2MQTT zag de
|
||||
Mosquitto-broker uit een andere stack simpelweg niet.
|
||||
|
||||
Bij het installeren staat nu **"Verbinden met andere apps"** aan. De stack komt
|
||||
dan op een gedeeld bridge-netwerk (`serverup`), waar containers elkaar op naam
|
||||
oplossen. Het netwerk wordt aangemaakt zodra de eerste stack het nodig heeft.
|
||||
|
||||
## 🎯 Kiezen in plaats van typen
|
||||
|
||||
Een veld dat naar een andere app verwijst, toont voortaan een **keuzelijst met
|
||||
wat je al hebt draaien** in plaats van een leeg tekstveld. Installeer je
|
||||
Zigbee2MQTT en heb je Mosquitto al staan, dan staat `mqtt://mosquitto:1883` er
|
||||
meteen ingevuld. Hetzelfde voor Open WebUI dat je Ollama vindt.
|
||||
|
||||
Staat de app er nog niet, dan zegt het veld dat — met de mogelijkheid om alsnog
|
||||
handmatig een adres in te vullen.
|
||||
|
||||
## 💬 Uitleg per instelling
|
||||
|
||||
Achter elk veld met toelichting staat een **info-icoon**. Klikken opent een blok
|
||||
met de volledige uitleg en de standaardwaarde. Voor de instellingen die de
|
||||
meeste vragen oproepen is die uitleg uitgeschreven — waarom je downloadmap op
|
||||
hetzelfde bestandssysteem moet staan als je mediamap, wat `shm_size` bij Frigate
|
||||
doet, waarom Caddy poort 80 nodig heeft ook als je alles via HTTPS aanbiedt.
|
||||
|
||||
## 🎛️ Geavanceerde opties uit het zicht
|
||||
|
||||
Velden die je meestal met rust laat — database-wachtwoorden, PUID/PGID,
|
||||
USB-paden, bewaartermijnen — zitten nu achter een uitklapblok **"Geavanceerde
|
||||
opties"** met een teller erbij. Het installatieformulier begint daardoor met
|
||||
alleen de vragen die er echt toe doen.
|
||||
|
||||
Templates kunnen `advanced: true` op een veld of op een hele groep zetten. Een
|
||||
test bewaakt dat er per app altijd zichtbare velden overblijven, zodat niemand
|
||||
per ongeluk een volledig leeg formulier maakt.
|
||||
|
||||
---
|
||||
|
||||
# v0.6.20-beta — 31 apps erbij na een rondgang langs de verzamelsites
|
||||
|
||||
Van 65 naar 96 apps. Selectie op basis van awesome-selfhosted, selfh.st,
|
||||
Perfect Media Server en een paar overzichtslijsten van 2026, aangevuld met wat
|
||||
er in de bestaande collectie nog ontbrak.
|
||||
|
||||
**Monitoring** — Prometheus (de tegenhanger van Grafana, die er al stond),
|
||||
InfluxDB, Netdata, Beszel
|
||||
|
||||
**Reverse proxy** — Caddy, dat zijn certificaten volledig zelf regelt
|
||||
|
||||
**Notities en kennis** — Memos, HedgeDoc, Wiki.js, Excalidraw, Karakeep
|
||||
|
||||
**Data en dashboards** — NocoDB, Baserow, Metabase
|
||||
|
||||
**Identiteit** — Authelia en Keycloak, allebei bruikbaar met de
|
||||
reverse-proxy-SSO van Server Up zelf
|
||||
|
||||
**Media** — Komga, PhotoPrism, MeTube, Pinchflat
|
||||
|
||||
**Meldingen** — ntfy
|
||||
|
||||
**Productiviteit** — Planka, Focalboard, Kimai
|
||||
|
||||
**Locatie en voertuig** — OwnTracks, TeslaMate
|
||||
|
||||
**Hulpmiddelen** — Shlink, CyberChef, LanguageTool, Kopia
|
||||
|
||||
**AI** — Ollama en Open WebUI, allebei volledig lokaal
|
||||
|
||||
De images van de nieuwere apps (Beszel, Karakeep, Pinchflat) zijn nagetrokken
|
||||
bij de bron in plaats van uit het hoofd opgeschreven; van Karakeep is de
|
||||
officiële compose overgenomen, inclusief de meilisearch- en chrome-containers
|
||||
die hij nodig heeft.
|
||||
|
||||
Vijftien poortbotsingen met bestaande apps zijn automatisch rechtgezet. Caddy
|
||||
deelt 80 en 443 met Traefik en Nginx Proxy Manager — alternatieven voor dezelfde
|
||||
taak, dus dat staat in de allowlist.
|
||||
|
||||
---
|
||||
|
||||
# v0.6.10-beta — ARR-stack met een schakelaar per onderdeel
|
||||
|
||||
De ARR-stack installeerde altijd dezelfde zeven containers. Nu kies je per
|
||||
onderdeel wat je wilt, uit twintig:
|
||||
|
||||
**Media beheren** — Sonarr (series), Radarr (films), Lidarr (muziek), Readarr
|
||||
(boeken), Whisparr
|
||||
|
||||
**Indexers en ondersteuning** — Prowlarr, Jackett, FlareSolverr, Bazarr
|
||||
(ondertitels)
|
||||
|
||||
**Downloaden** — qBittorrent, SABnzbd, NZBGet, en Gluetun om al het
|
||||
downloadverkeer door een VPN te leiden
|
||||
|
||||
**Verzoeken en aanvullingen** — Jellyseerr, Recyclarr (TRaSH-profielen),
|
||||
Unpackerr, Tdarr (hercoderen), Autobrr, Maintainerr, Huntarr
|
||||
|
||||
Standaard staan Sonarr, Radarr, Prowlarr, Bazarr, qBittorrent en Jellyseerr aan;
|
||||
de rest zet je zelf bij.
|
||||
|
||||
## Gluetun schakelt de downloadclients om
|
||||
|
||||
Zet je Gluetun aan, dan verhuizen qBittorrent, SABnzbd en NZBGet naar diens
|
||||
netwerknamespace en verliezen ze hun eigen poortmapping — precies zoals het
|
||||
hoort, want anders lekt hun verkeer om de VPN heen. Hun webinterfaces bereik je
|
||||
dan via de poorten van de Gluetun-container.
|
||||
|
||||
Daarbij zat een val: qBittorrent en SABnzbd luisteren allebei standaard op 8080,
|
||||
en achter één VPN-container botsen ze. qBittorrent draait nu intern op 8090.
|
||||
|
||||
## Groepsschakelaars werkten niet
|
||||
|
||||
Een groepsschakelaar in template.json was zelf geen variabele en kreeg dus nooit
|
||||
een startwaarde. Elk schakelbaar onderdeel stond daardoor standaard uit — een
|
||||
stack met schakelaars zou leeg binnenkomen. Ze worden nu als veld meegegeven met
|
||||
een instelbare standaardstand, en de interface toont ze alleen als schakelaar in
|
||||
de kop van de groep.
|
||||
|
||||
---
|
||||
|
||||
# v0.6.00-beta — 29 apps erbij, en een bug die zes bestaande apps onstartbaar maakte
|
||||
|
||||
## 🐛 Named volumes verdwenen uit het compose-bestand
|
||||
|
||||
Bij het bouwen van de nieuwe apps liep ik tegen iets aan dat er al langer zat.
|
||||
`_drop_empty_mappings` ruimt sleutels op die een `<% if %>`-blok leeg
|
||||
achterlaat. Maar een named volume wordt gedeclareerd als een kale sleutel zonder
|
||||
waarde:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
immich_pgdata:
|
||||
```
|
||||
|
||||
Die werd als "lege mapping" opgeruimd, waarna ook het bovenliggende `volumes:`
|
||||
wegviel. De services verwezen vervolgens naar een volume dat nergens meer
|
||||
gedeclareerd stond, en `docker compose up` weigert dat met *"refers to undefined
|
||||
volume"*.
|
||||
|
||||
**Immich, Ghost, Miniflux, Paperless-ngx, Unifi Network en Vikunja waren
|
||||
daardoor niet installeerbaar via Server Up.** Alleen bekende compose-sleutels
|
||||
worden nu opgeruimd; een volumedeclaratie blijft staan.
|
||||
|
||||
## 📦 29 nieuwe apps
|
||||
|
||||
**Domotica** — Zigbee2MQTT, Mosquitto MQTT, ESPHome, Node-RED, Z-Wave JS UI,
|
||||
Homebridge, Scrypted, Frigate NVR
|
||||
|
||||
**3D-printen** — Bambuddy (Bambu Lab, zonder cloud), OctoPrint, Spoolman
|
||||
|
||||
**Gezin en huishouden** — Baby Buddy, Grocy, Tandoor Recipes, Firefly III
|
||||
|
||||
**Media** — Audiobookshelf, Navidrome, Kavita, Calibre-Web, Jellyseerr
|
||||
|
||||
**Kennis** — BookStack, FreshRSS, Wallabag
|
||||
|
||||
**Netwerk en beheer** — WireGuard Easy, Homepage, SearXNG, Duplicati,
|
||||
Watchtower, Technitium DNS
|
||||
|
||||
Daarmee staat de teller op 65 apps.
|
||||
|
||||
## ✅ Testsuite over de echte templates
|
||||
|
||||
Nieuwe `tests/test_apps.py` rendert **elke** app met de echte engine en
|
||||
controleert de uitkomst: geldige YAML, elke service heeft een image of build,
|
||||
named volumes zijn gedeclareerd, geen onvervangen `<< variabelen >>`, en geen
|
||||
onbedoeld dubbele standaardpoorten. Die laatste vond zeven botsingen tussen de
|
||||
nieuwe apps en bestaande; die zijn rechtgezet. Botsingen die logisch zijn
|
||||
(Traefik en Nginx Proxy Manager op 80/443, AdGuard en Pi-hole op 53) staan met
|
||||
uitleg in een allowlist.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.50-beta — Containers die nergens te vinden waren
|
||||
|
||||
Het dashboard meldde 13 actieve containers en 17 images, terwijl je die nergens
|
||||
terugzag. Dat kwam doordat de cijfers en de lijst uit twee verschillende bronnen
|
||||
komen:
|
||||
|
||||
* de **tellers** komen van `docker info` en gaan over de hele Docker-daemon
|
||||
* de **stacklijst** toont alleen mappen in `LIBRARY_DIR` met een compose-bestand
|
||||
|
||||
Alles wat je buiten Server Up om had gestart — je Forgejo, de act_runner,
|
||||
containers van vóór je Server Up ging gebruiken — telde dus wel mee maar was
|
||||
onzichtbaar en onbedienbaar. Een beheertool die dingen telt die hij niet toont,
|
||||
is verwarrend.
|
||||
|
||||
## Wat er nu is
|
||||
|
||||
- **Overzicht van alle containers op de host.** Onder de stacklijst staat een
|
||||
blok "Overige containers" met alles wat niet bij een beheerde stack hoort,
|
||||
inclusief image, poorten en compose-project. Starten, stoppen, herstarten en
|
||||
logs bekijken kan direct.
|
||||
- **De dashboardteller vertelt nu het hele verhaal**: onder "actief" staat
|
||||
hoeveel daarvan via Server Up loopt.
|
||||
- De eigen container is gemarkeerd als "deze app" en kan niet via dit blok
|
||||
gestopt worden — daarvoor is de herstartknop in de instellingen, die dat
|
||||
netjes afhandelt in plaats van zichzelf halverwege een verzoek te stoppen.
|
||||
- Een viewer ziet de lijst wel maar kan niets bedienen.
|
||||
|
||||
## Verholpen tijdens het bouwen
|
||||
|
||||
Containers zonder poorten én zonder compose-labels vielen weg uit de lijst als
|
||||
ze toevallig als laatste stonden: `strip()` haalde de lege velden aan het eind
|
||||
van de uitvoer weg, waarna die regel te weinig kolommen leek te hebben. Gevonden
|
||||
door de test die precies zo'n container als laatste zet.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.46-beta — Deploy strandde op een .env van een andere gebruiker
|
||||
|
||||
De stap die instellingen klaarzet faalde op `touch: cannot touch '.env':
|
||||
Permission denied`. Het bestand was met sudo aangemaakt en dus van root, terwijl
|
||||
de runner als gewone gebruiker draait — waarmee de hele deploy afbrak op iets
|
||||
dat geen blokkade hoort te zijn.
|
||||
|
||||
- `SU_TAG` gaat nu altijd via de omgeving naar `docker compose`. Wegschrijven in
|
||||
`.env` blijft de voorkeur omdat het een handmatige `docker compose up`
|
||||
overleeft, maar is niet meer nodig om te kunnen deployen.
|
||||
- Is `.env` niet schrijfbaar, dan meldt de log wie de eigenaar is en welk
|
||||
`chown`-commando dat rechtzet, en loopt de deploy door.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.45-beta — Wizard-knop toegevoegd
|
||||
|
||||
De wizard was alleen zichtbaar bij een verse installatie: zodra hij een keer was
|
||||
afgerond, was er geen enkele manier meer om hem te openen. De vertaalsleutels
|
||||
`wizard_open` en `wizard_reset` bestonden al en `/api/wizard/reset` werkte ook,
|
||||
maar de knop is nooit gebouwd — ook niet in v0.4.60.
|
||||
|
||||
- Blok **Setup Wizard** onder Instellingen met "Wizard openen" en "Opnieuw
|
||||
uitvoeren".
|
||||
- Sluitknop in de wizard zelf; die kon je eerder alleen verlaten door hem
|
||||
helemaal af te ronden.
|
||||
- De staptitels lopen nu via `t()` in plaats van harde Nederlandse teksten.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.44-beta — Gedetecteerd netwerk verdween uit het formulier
|
||||
|
||||
Zodra je een netwerk had toegevoegd, was het blok "gevonden op deze server" leeg
|
||||
bij een volgende poging: subnetten die al geconfigureerd waren werden uit de
|
||||
suggesties gefilterd. Dat pakt verkeerd uit — je kunt prima een tweede netwerk op
|
||||
hetzelfde subnet willen met een andere range, en zonder dat blok lijkt het
|
||||
formulier kapot.
|
||||
|
||||
- Gedetecteerde netwerken blijven staan en tonen "al toegevoegd" in plaats van
|
||||
te verdwijnen.
|
||||
- Levert de detectie niets op zonder dat er een fout is, dan staat er nu uitleg
|
||||
in plaats van een leeg blok.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.43-beta — Van-tot omrekenen naar een CIDR-blok
|
||||
|
||||
"Ik wil van 10.0.20.200 tot .254" is een volstrekt redelijke wens, maar bestaat
|
||||
niet als CIDR-notatie: dat zijn 55 adressen, en Docker accepteert alleen
|
||||
uitgelijnde blokken van 2, 4, 8, 16 … adressen.
|
||||
|
||||
Onder het IP-range-veld zit nu een **van-tot-hulp**. Vul de eerste en laatste
|
||||
gewenste adressen in en Server Up rekent uit welke blokken in de buurt komen:
|
||||
|
||||
* **dekt alles** — het kleinste blok dat je hele wens omvat (pakt er onderaan
|
||||
wat bij)
|
||||
* **past binnen** — het grootste blok dat volledig binnen je wens valt
|
||||
|
||||
Bij `.200` t/m `.254` levert dat `10.0.20.192/26` op: 62 adressen, `.193` t/m
|
||||
`.254`. Klikken vult het veld in.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.42-beta — Netwerk toevoegen: twee blokkades weg
|
||||
|
||||
Een netwerk aanmaken lukte niet, met wisselend gedrag: soms een foutmelding dat
|
||||
de IP-range buiten het subnet lag terwijl dat aantoonbaar niet zo was, soms geen
|
||||
melding maar toch geen resultaat. Het bleken twee losse oorzaken.
|
||||
|
||||
## De foutmelding die niet klopte
|
||||
|
||||
De beoordeling gaat af bij elke toetsaanslag. Tijdens het intypen van `/28` ga
|
||||
je langs `/2`, en `10.0.20.240/2` normaliseert naar `0.0.0.0/2` — inderdaad
|
||||
buiten je subnet. Kwam dat antwoord ná het antwoord voor de volledige waarde
|
||||
binnen, dan bleef die foutmelding staan en bleef de knop uitgeschakeld.
|
||||
|
||||
Er zit nu een volgnummer op: alleen het antwoord bij de laatste vraag telt. En
|
||||
de knop wordt niet meer uitgeschakeld op de clientstatus — bij het opslaan
|
||||
beslist de server, zodat een verouderde beoordeling je nooit kan blokkeren.
|
||||
|
||||
## De range die Docker weigerde
|
||||
|
||||
`10.0.20.200/28` heeft hostbits gezet. Python leest dat soepel als
|
||||
`10.0.20.192/28`, maar Docker is streng en antwoordt *"has host bits set"*. Wij
|
||||
valideerden soepel en stuurden vervolgens de ruwe tekst door, dus de interface
|
||||
keurde iets goed dat bij het aanmaken alsnog strandde.
|
||||
|
||||
Subnet en IP-range worden nu omgezet naar hun canonieke vorm voordat ze naar
|
||||
Docker gaan én voordat ze worden opgeslagen, met een waarschuwing die laat zien
|
||||
wat er van je invoer gemaakt is. `.200/28` is trouwens een logische invoer — je
|
||||
bedoelt "vanaf .200" — maar een /28 begint nu eenmaal op een veelvoud van 16.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.41-beta — Netwerk toevoegen liep vast tijdens het typen
|
||||
|
||||
Een netwerk toevoegen gaf een JSON-parsefout in de browser.
|
||||
|
||||
Oorzaak: de live beoordeling die bij elke toetsaanslag afgaat, bouwde een lijst
|
||||
van alle bruikbare adressen in het bereik. Tijdens het intypen van
|
||||
`192.168.1.0/24` is de tussenstand `192.168.1.0/2` een volkomen geldig
|
||||
netwerk — met 1.073.741.824 adressen. Het verzoek liep daarop vast en de browser
|
||||
kreeg geen JSON meer terug.
|
||||
|
||||
- `review()` rekent eerste adres, laatste adres en aantal nu uit in plaats van
|
||||
ze op te sommen. Antwoord binnen 0,05 seconde bij elk prefix.
|
||||
- `suggest_range()` had hetzelfde probleem: die somde alle /28-blokken op, wat
|
||||
bij een `/8` ruim een miljoen blokken zijn. Rekent nu van achteren naar voren.
|
||||
- Waarschuwing bij een bereik van meer dan 4096 adressen, want dat is vrijwel
|
||||
altijd een typefout in het prefix.
|
||||
- Ook `.env` van de deploy-map werd bij elke deploy gewist door `rsync --delete`,
|
||||
omdat het bestand in `.gitignore` staat en dus niet in de checkout zit. Daardoor
|
||||
raakte je `BIND` telkens kwijt. `--exclude='.env'` toegevoegd.
|
||||
- Nieuw `.env.example` met alle instellingen bij elkaar en uitleg per sleutel.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.40-beta — Netwerken instellen zonder uitzoekwerk
|
||||
|
||||
## 🔍 Automatische detectie
|
||||
|
||||
Bij **Instellingen → Netwerken → Netwerk** toont Server Up nu bovenaan het
|
||||
netwerk dat je server zelf gebruikt: interface, subnet, gateway en een
|
||||
voorgestelde vrije IP-range. Eén klik vult het hele formulier.
|
||||
|
||||
De detectie start heel kort een container die de netwerknamespace van de host
|
||||
deelt en leest daar de routetabel. Dat is nodig omdat Server Up in een eigen
|
||||
namespace zit: de vorige versie las `/sys/class/net` binnen de container en
|
||||
toonde daardoor de bridge-interface van de container zelf in plaats van de
|
||||
netwerkkaart van de host — een lijstje dat er goed uitzag maar niet klopte.
|
||||
|
||||
Lukt detecteren niet (geen docker-socket, ouder image), dan staat er een nette
|
||||
melding en vul je het als vanouds handmatig in.
|
||||
|
||||
## 💡 Live meedenken bij het invullen
|
||||
|
||||
Terwijl je typt controleert Server Up de combinatie en toont wat het oplevert:
|
||||
*"14 adressen beschikbaar: 192.168.1.241 tot en met 192.168.1.254"*. Klopt er
|
||||
iets niet, dan staat er in gewone taal bij waarom — een range buiten het subnet,
|
||||
een gateway die je beter buiten het bereik kunt houden, of een range zo klein
|
||||
dat er maar een paar stacks in passen.
|
||||
|
||||
Een knop stelt een vrij blok voor op basis van het subnet, met de gateway
|
||||
ontweken.
|
||||
|
||||
## 📖 Uitleg waar je hem nodig hebt
|
||||
|
||||
In het formulier zit een uitklapbaar blok dat uitlegt hoe subnet, gateway,
|
||||
IP-range en host-interface zich tot elkaar verhouden, met een concreet voorbeeld.
|
||||
`docs/netwerken.md` heeft dezelfde uitleg met een schema van de adresverdeling,
|
||||
een tabel met veelgebruikte ranges, en één punt dat er echt uit moet springen:
|
||||
**het instellen van de IP-range in Server Up doet niets aan je router** — je moet
|
||||
daar zelf het DHCP-bereik verkleinen, anders blijven dubbele adressen mogelijk.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.30-beta — Rollen, app-store-filter en twee planningsfouten
|
||||
|
||||
## 👥 Rollen per gebruiker
|
||||
|
||||
Tot nu toe had elk account volledige toegang. Nu drie rollen:
|
||||
|
||||
| Rol | Mag |
|
||||
|---|---|
|
||||
| **Beheerder** | alles |
|
||||
| **Operator** | stacks, containers en backups beheren — niet de instellingen, gebruikers, repo's, netwerken of modules |
|
||||
| **Alleen lezen** | alleen bekijken |
|
||||
|
||||
- Afgedwongen in de `before_request`-guard, niet alleen in de interface.
|
||||
- Je eigen wachtwoord wijzigen mag iedereen, ongeacht rol.
|
||||
- De laatste beheerder kan niet gedegradeerd of verwijderd worden.
|
||||
- Wie via de reverse proxy binnenkomt zonder eigen account krijgt de rol uit
|
||||
`AUTH.proxy_role`; bestaat er wél een lokaal account met die naam, dan wint
|
||||
dat account.
|
||||
- Accounts van vóór deze versie hebben geen rol en gelden als beheerder.
|
||||
|
||||
## 🔒 Rechtenescalatie verholpen
|
||||
|
||||
Bij het wijzigen van een wachtwoord werd het hele gebruikersrecord vervangen,
|
||||
waardoor het `role`-veld wegviel. Omdat een ontbrekende rol als beheerder geldt
|
||||
(nodig voor bestaande accounts), kon **elke operator of viewer zichzelf tot
|
||||
beheerder promoveren door zijn eigen wachtwoord te wijzigen.** Gevonden bij het
|
||||
naspelen van de rollenflow; de rol blijft nu behouden en een test dekt het af.
|
||||
|
||||
## ⏰ Geplande backups draaiden nooit
|
||||
|
||||
De scheduler stempelde ook taken af die zichzelf hadden overgeslagen. De
|
||||
backup-taak bewaakt zelf of het het ingestelde uur is, dus die werd afgestempeld
|
||||
op het moment van de eerste tick — waarna het volgende moment 24 uur later op
|
||||
precies dat verkeerde tijdstip viel. Resultaat: de geplande backup kwam nooit
|
||||
aan de beurt.
|
||||
|
||||
Een taak stempelt nu alleen af als hij `True` teruggeeft. De backup-taak draait
|
||||
daardoor op een kort interval en bepaalt zelf wanneer het zover is, zodat een
|
||||
gewijzigde planning ook meteen werkt zonder herstart. Voor wekelijkse backups is
|
||||
`BACKUP_SCHEDULE_DAY` toegevoegd.
|
||||
|
||||
## 🔎 Zoeken en filteren in de app store
|
||||
|
||||
Zoekveld over naam, omschrijving en tags, plus klikbare tagfilters (de veertien
|
||||
meestgebruikte, op frequentie gesorteerd). Repo's zonder treffers vallen weg.
|
||||
|
||||
## 🔧 Overig
|
||||
|
||||
- Opstartcontrole op de meegeleverde front-end-bestanden. Mislukt het downloaden
|
||||
tijdens de image-build, dan laadde de interface zonder opmaak terwijl de
|
||||
server prima leek te draaien; nu staat er een duidelijke melding in het log.
|
||||
- 227 tests.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.20-beta — Vertalingen, SSO-scherm, complete backups en app-updates
|
||||
|
||||
## 🌍 Vertalingen en SSO
|
||||
|
||||
- De schermen uit v0.5.x (login, Beveiliging, Netwerken, Updates,
|
||||
containerpaneel) gebruikten harde Nederlandse teksten terwijl de rest van de
|
||||
interface via `t()` loopt. Op Engels gaf dat een mengelmoes. Nu volledig
|
||||
vertaald: 208 sleutels in `nl` en `en`.
|
||||
- `t()` ondersteunt plaatshouders: `t('port_taken', {port: 8080})`. Zo blijven
|
||||
zinnen heel in plaats van in losse stukjes geknipt.
|
||||
- Nieuw instelscherm voor **reverse-proxy-SSO** onder Instellingen →
|
||||
Beveiliging: modus lokaal/proxy/beide, identiteitsheader en de vertrouwde
|
||||
proxy-adressen. De backend bestond al maar was alleen met `curl` te bereiken.
|
||||
- Nieuwe test bewaakt dat `nl` en `en` dezelfde sleutels houden, dat de
|
||||
plaatshouders in beide talen gelijk zijn, en dat de interface geen sleutels
|
||||
gebruikt die nergens gedefinieerd staan.
|
||||
|
||||
## 💾 Backups compleet
|
||||
|
||||
Backup was één `tar`-commando waarvan de returncode genegeerd werd — een
|
||||
mislukte backup gold als succes, en terugzetten kon alleen met de hand.
|
||||
|
||||
- **Terugzetten** met één klik: stack stoppen, huidige map opzij, uitpakken,
|
||||
starten. Mislukt het uitpakken, dan komt de oude situatie terug.
|
||||
- **Bewaarbeleid**: aantal per stack en/of maximale leeftijd. De nieuwste
|
||||
backup van een stack blijft altijd staan.
|
||||
- **Geplande backups**, dagelijks of wekelijks, via een eigen planner in de
|
||||
applicatie (geen cron). Een gemiste ronde loopt bij de eerstvolgende
|
||||
gelegenheid alsnog.
|
||||
- **Automatisch een backup vóór het bijwerken of verwijderen** van een stack.
|
||||
Mislukt die, dan gaat de actie door — anders kun je een kapotte stack niet
|
||||
meer opruimen.
|
||||
- Uitpakken gebeurt met `tarfile` en `filter="data"`: absolute paden en
|
||||
`..`-ingangen worden geweigerd. Met een kaal `tar xzf` kon een geprepareerd
|
||||
archief buiten de stackmap schrijven.
|
||||
- Backups binnen dezelfde seconde overschreven elkaar; namen krijgen nu een
|
||||
teller.
|
||||
- `docs/backups.md` legt uit wat er wél en niet in zit — de compose- en
|
||||
`.env`-bestanden, **niet** de Docker-volumes met de eigenlijke appdata.
|
||||
|
||||
## 📦 Updates per app
|
||||
|
||||
- Server Up controleert nu ook of er nieuwere images zijn voor de
|
||||
geïnstalleerde stacks, met een badge op de stackkaart en een knop om te
|
||||
controleren. Bijwerken doet de bestaande update-knop.
|
||||
- De vergelijking loopt via de Registry API v2 (`Docker-Content-Digest`), niet
|
||||
via `docker manifest inspect`: dat laatste geeft per platform een aparte
|
||||
digest terug terwijl `RepoDigests` de digest van de manifest-list bevat, wat
|
||||
bij elk multi-arch image permanent "update beschikbaar" zou opleveren.
|
||||
- Drie statussen per service — `update`, `current` en `unknown`. Een lokaal
|
||||
gebouwd image, een nog niet gepulld image of een onbereikbare registry levert
|
||||
`unknown` op en dus géén badge, zodat er nooit ten onrechte een update wordt
|
||||
gemeld.
|
||||
- Dagelijkse achtergrondcheck via dezelfde planner; resultaten 6 uur gecached.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.10-beta — Update-systeem met kanalen en één-klik bijwerken
|
||||
|
||||
## 🔄 Kanalen
|
||||
|
||||
Server Up kent nu twee update-kanalen in plaats van een vinkje "pre-releases
|
||||
meenemen":
|
||||
|
||||
- **stable** — alleen echte releases (`v0.5.10`)
|
||||
- **beta** — ook pre-releases (`v0.5.10-beta1`), die `release.yml` automatisch
|
||||
als zodanig markeert bij een tag met een streepje
|
||||
|
||||
Een release telt hoger dan zijn eigen beta (`0.5.10-beta1` < `0.5.10`), dus wie
|
||||
op beta zit krijgt de definitieve versie alsnog aangeboden. De oude instelling
|
||||
`UPDATE_INCLUDE_PRERELEASE` migreert automatisch naar het beta-kanaal.
|
||||
|
||||
## ⬇️ Bijwerken vanuit de interface
|
||||
|
||||
Nieuw: **Nu bijwerken** haalt het image uit je Forgejo container-registry en
|
||||
vervangt de eigen container.
|
||||
|
||||
- Omdat een container zichzelf niet kan hercreëren, doet Server Up alleen het
|
||||
voorwerk (image ophalen, `SU_TAG` wegschrijven) en laat het de hercreatie over
|
||||
aan een korte helper-container die op het nieuwe image draait — dat bevat de
|
||||
docker- en compose-CLI al.
|
||||
- De deploy-map wordt uitgelezen uit de compose-labels van de eigen container,
|
||||
niet geraden. Ontbreken die labels, draait de container niet vanaf een
|
||||
registry-image, of is de docker-socket er niet, dan meldt de interface
|
||||
precies waaróm bijwerken niet kan in plaats van iets te proberen.
|
||||
- De vorige tag wordt onthouden, met een **terugrolknop** in de instellingen.
|
||||
- Voortgang van de `docker pull` loopt via het bestaande job-logvenster; daarna
|
||||
pollt de browser `/healthz` tot de nieuwe versie leeft.
|
||||
|
||||
## 🔧 Overig
|
||||
|
||||
- Update-check wordt een uur gecached; **Controleren** forceert een verse check.
|
||||
Eerder deed elke paginalading een netwerkverzoek.
|
||||
- Laatst-gecontroleerd-tijdstip zichtbaar in de interface.
|
||||
- Registry-inloggegevens instelbaar voor een privé registry. Het token wordt net
|
||||
als de git-tokens nooit teruggegeven door de API (alleen een `has_`-vlag) en
|
||||
leeg laten betekent "ongewijzigd".
|
||||
- `docker-compose.yml` gebruikt `${SU_IMAGE:-server-up}:${SU_TAG:-latest}`, zodat
|
||||
image en tag los instelbaar zijn. Zonder `SU_IMAGE` blijft alles werken zoals
|
||||
voorheen (lokaal bouwen).
|
||||
- `deploy-prod.yml` bouwt én pusht het image in dezelfde job wanneer `SU_IMAGE`
|
||||
ingesteld is. Bewust niet als aparte workflow: bij één runner zou de deploy
|
||||
wachten op een build die zelf nog in de wachtrij staat.
|
||||
- `build.yml` is nu alleen handmatig, voor het herbouwen van een specifieke tag.
|
||||
- `docs/updates.md` toegevoegd: hoe het werkt, de complete Forgejo-instelling
|
||||
(registry, tokens, variables, secrets, runners), de release-procedure voor
|
||||
zowel stable als beta, terugrollen en een probleemoplostabel.
|
||||
|
||||
---
|
||||
|
||||
# v0.5.00-beta — Authenticatie, beveiliging en eigen IP-adressen
|
||||
|
||||
> **Let op bij het bijwerken.** Server Up heeft nu een login. Open na het
|
||||
> bijwerken meteen de webinterface en maak een beheerdersaccount aan — zolang
|
||||
> dat niet gebeurd is, kan iedereen die de pagina bereikt het account claimen.
|
||||
> De poort wordt voortaan standaard op `127.0.0.1` gebonden; zet `BIND=0.0.0.0`
|
||||
> in je `.env` als je er van buiten de server bij moet (liefst achter een
|
||||
> reverse proxy met TLS — zie `docs/beveiliging.md`).
|
||||
|
||||
## 🔐 Authenticatie
|
||||
|
||||
Tot nu toe was elke `/api/*`-route open. Omdat Server Up de docker-socket als
|
||||
root gebruikt, betekende dat: wie de poort kon bereiken, had root op de host.
|
||||
|
||||
- Lokale accounts met scrypt-gehashte wachtwoorden, sessiecookie
|
||||
(`HttpOnly`, `SameSite=Strict`) en lockout na vijf mislukte pogingen.
|
||||
- Optionele SSO via een reverse-proxy-header (Authelia/Authentik/Cloudflare
|
||||
Access). De header wordt alleen vertrouwd vanaf een geconfigureerd proxy-IP.
|
||||
- Loginscherm en eerste-account-setup in de interface; gebruikersbeheer en
|
||||
wachtwoord wijzigen onder Instellingen → Beveiliging.
|
||||
|
||||
## 🛡️ Beveiligingsfixes
|
||||
|
||||
- **CSRF**: elke mutatie vereist een `X-CSRF-Token`-header. Routes die de
|
||||
toestand wijzigen accepteren geen `GET` meer — `/api/docker/restart` was
|
||||
eerder met een `<img>`-tag vanaf een willekeurige website te triggeren.
|
||||
- **Path traversal**: `/api/store/install` controleerde de instantienaam niet;
|
||||
`"instance": "../../…"` schreef buiten de library. Alle stack-, instantie- en
|
||||
repo-namen lopen nu door één `safe_name()`-validatie.
|
||||
- **Tokenlek**: git-tokens werden teruggegeven door `/api/repos` en
|
||||
`/api/settings`. Die zijn vervangen door een `has_token`-vlag; opslaan met een
|
||||
leeg veld wist het bestaande token niet meer.
|
||||
- **Git-URL's**: alleen `http(s)://`, `ssh://` en `git@host:pad`. Git's
|
||||
`ext::`-transport voert een shell-commando uit en wordt nu geweigerd.
|
||||
- **Templates** renderen in een Jinja2-sandbox (server-side template injection).
|
||||
- **SSH**: host-keys worden geverifieerd (`accept-new` + `/data/known_hosts`);
|
||||
eerder stond `StrictHostKeyChecking=no`, waarmee elke MITM onzichtbaar was.
|
||||
- **Modules**: repo's worden niet meer automatisch bij elke start gepulld
|
||||
(`AUTO_SYNC_ON_BOOT`, standaard uit) en kunnen per repo op een commit worden
|
||||
vastgezet.
|
||||
- Productie-WSGI-server (waitress) i.p.v. de Flask-ontwikkelserver, limiet op
|
||||
request-grootte, `ProxyFix`, en CSP/`X-Frame-Options`/`nosniff`/
|
||||
`Referrer-Policy`-headers.
|
||||
- Tailwind, Alpine en htmx worden meegeleverd in plaats van vanaf een CDN
|
||||
geladen; Google Fonts is eruit. De interface werkt nu ook offline.
|
||||
- `config.json` en de sleutel staan op 0600.
|
||||
|
||||
## 🌐 Stacks met een eigen IP-adres
|
||||
|
||||
Nieuw: geef een stack een eigen adres in je LAN in plaats van poorten op de host
|
||||
(macvlan/ipvlan). Geen poortconflicten meer, apps op hun eigen standaardpoort, en
|
||||
je kunt per app firewallen.
|
||||
|
||||
- Netwerkbeheer onder Instellingen → Netwerken (driver, host-interface, subnet,
|
||||
gateway, optionele IP-range).
|
||||
- Bij het installeren kies je "Poorten op de host" of een netwerk; Server Up
|
||||
stelt het eerstvolgende vrije adres voor en houdt toegekende adressen vast.
|
||||
- Het gerenderde compose-bestand wordt automatisch omgezet: poortmappings eruit,
|
||||
netwerk met `ipv4_address` erin. De templates in `apps/` blijven ongewijzigd.
|
||||
- Uitleg en valkuilen (waaronder de shim-interface die de host nodig heeft om
|
||||
zijn eigen macvlan-containers te bereiken) staan in `docs/netwerken.md`.
|
||||
|
||||
## 🧩 Beheer per container
|
||||
|
||||
De stackkaart klapt uit naar de losse containers: per container starten, stoppen,
|
||||
herstarten, logs bekijken en live CPU-/geheugengebruik.
|
||||
|
||||
## 📦 Veiliger installeren
|
||||
|
||||
- Poortvelden krijgen een vrij poortnummer voorgesteld — `next_free_port()`
|
||||
bestond al maar werd nergens gebruikt. Bezette poorten worden gemeld.
|
||||
- Velden voor tokens en wachtwoorden krijgen een genereerknop.
|
||||
- Compose wordt gevalideerd (`docker compose config`) vóór het wegschrijven, dus
|
||||
een typefout in de editor maakt een draaiende stack niet meer onstartbaar.
|
||||
|
||||
## 🔧 Overig
|
||||
|
||||
- Testsuite met pytest (112 tests), ook als stap in beide deploy-workflows.
|
||||
- Audit-log gebruikt één gedeelde SQLite-verbinding — elke job lekte eerder een
|
||||
file descriptor. Joblogs worden afgekapt op 2000 regels.
|
||||
- Het `VERSION`-bestand is de enige bron voor het versienummer.
|
||||
- Lichte `/healthz` voor de healthcheck in plaats van `docker info`.
|
||||
- `fix-config.sh` verwijderd: bevatte een hardgecodeerd intern IP en
|
||||
overschreef de configuratie van de gebruiker.
|
||||
|
||||
---
|
||||
|
||||
# v0.4.60 — Tweecijferig patch-nummer
|
||||
|
||||
## Versiebeleid vanaf v0.4.60
|
||||
|
|
|
|||
23
Dockerfile
23
Dockerfile
|
|
@ -37,19 +37,38 @@ COPY --from=build /inst /usr/local
|
|||
WORKDIR /app
|
||||
COPY server-up/ ./
|
||||
COPY modules/ ./modules-bundled/
|
||||
COPY VERSION ./VERSION
|
||||
RUN mkdir -p static/fonts \
|
||||
&& curl -fsSL "https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css" -o static/fonts/mdi.min.css \
|
||||
&& curl -fsSL "https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/fonts/materialdesignicons-webfont.woff2" -o static/fonts/materialdesignicons-webfont.woff2 \
|
||||
&& sed -i "s|https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/fonts/||g" static/fonts/mdi.min.css
|
||||
|
||||
# Front-end libraries meeleveren in plaats van vanaf een CDN laden. Zo kan de
|
||||
# Content-Security-Policy op 'self' blijven, is er geen supply-chain-risico van
|
||||
# unpkg/jsdelivr op runtime, en werkt de UI ook zonder internetverbinding.
|
||||
RUN mkdir -p static/vendor \
|
||||
&& curl -fsSL "https://cdn.tailwindcss.com/3.4.16?plugins=forms,typography" \
|
||||
-o static/vendor/tailwind.js \
|
||||
&& curl -fsSL "https://cdn.jsdelivr.net/npm/alpinejs@3.14.1/dist/cdn.min.js" \
|
||||
-o static/vendor/alpine.min.js \
|
||||
&& curl -fsSL "https://cdn.jsdelivr.net/npm/htmx.org@2.0.3/dist/htmx.min.js" \
|
||||
-o static/vendor/htmx.min.js \
|
||||
&& for f in static/vendor/tailwind.js static/vendor/alpine.min.js static/vendor/htmx.min.js; do \
|
||||
test -s "$f" || { echo "LEEG: $f"; exit 1; }; \
|
||||
done
|
||||
|
||||
# Directories + git safe.directory (fix dubious ownership)
|
||||
RUN mkdir -p /data/stacks /data/appdata /data/backups /data/git modules /root \
|
||||
&& printf '[safe]\n\tdirectory = *\n' > /root/.gitconfig
|
||||
|
||||
# GIT_SSH_COMMAND: StrictHostKeyChecking=accept-new vertrouwt een host bij de
|
||||
# eerste verbinding en bewaart de sleutel in /data/known_hosts. Wijzigt die
|
||||
# sleutel later, dan faalt de verbinding — met `no` was elke MITM onzichtbaar.
|
||||
ENV PYTHONUNBUFFERED=1 PORT=5000 HOME=/root \
|
||||
SU_VERSION=${SU_VERSION} \
|
||||
SU_CONFIG=/data/config.json SU_AUDIT=/data/audit.db SU_GIT_CACHE=/data/git \
|
||||
GIT_SSH_COMMAND="ssh -F /dev/null -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
||||
SU_SECRET=/data/secret.key \
|
||||
GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/data/known_hosts"
|
||||
EXPOSE 5000
|
||||
HEALTHCHECK --interval=30s --timeout=8s --start-period=15s CMD curl -fs http://localhost:5000/api/docker/info || exit 1
|
||||
HEALTHCHECK --interval=30s --timeout=8s --start-period=15s CMD curl -fs http://localhost:5000/healthz || exit 1
|
||||
CMD ["python","app.py"]
|
||||
|
|
|
|||
137
README.md
Normal file
137
README.md
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
# Server Up
|
||||
|
||||
Zelfgehoste beheerinterface voor Docker: apps installeren uit een catalogus,
|
||||
stacks starten en stoppen, backups maken en terugzetten, en containers een eigen
|
||||
IP-adres in je netwerk geven.
|
||||
|
||||
> ⚠️ **Toegang tot Server Up staat gelijk aan root op de host.** De applicatie
|
||||
> beheert de Docker-daemon, en wie containers kan starten kan willekeurige mappen
|
||||
> van de host mounten. Behandel de interface navenant: maak direct een account
|
||||
> aan, zet hem niet zonder reverse proxy met TLS op internet, en lees
|
||||
> [docs/beveiliging.md](docs/beveiliging.md).
|
||||
|
||||
---
|
||||
|
||||
## Wat het doet
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **App-catalogus** | 96 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. |
|
||||
| **Backups** | Handmatig, gepland, en automatisch vóór een update of verwijdering. Met terugzetten en een bewaarbeleid. |
|
||||
| **Updates** | Voor Server Up zelf (stable of beta) en voor de images van je geïnstalleerde stacks. |
|
||||
| **Toegang** | Lokale accounts met rollen (beheerder, operator, alleen lezen), of SSO via een reverse proxy. |
|
||||
|
||||
## Wat je nodig hebt
|
||||
|
||||
- Een Linux-server met Docker en de compose-plugin
|
||||
- Toegang tot `/var/run/docker.sock`
|
||||
- Ongeveer 300 MB schijfruimte voor de applicatie zelf
|
||||
|
||||
## Installeren
|
||||
|
||||
```bash
|
||||
curl -fsSL https://git.ramonbesselink.nl/bes-r/server-up/raw/branch/main/install.sh | sh
|
||||
```
|
||||
|
||||
Dat controleert je systeem, installeert Docker als het ontbreekt, zet Server Up
|
||||
in `/opt/server-up` en start het op `http://localhost:5000`.
|
||||
|
||||
Liever eerst lezen wat je uitvoert — verstandig, want het script gebruikt
|
||||
root-rechten:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://git.ramonbesselink.nl/bes-r/server-up/raw/branch/main/install.sh -o install.sh
|
||||
less install.sh
|
||||
sh install.sh --dry-run # toont wat het zou doen, zonder iets te wijzigen
|
||||
sh install.sh
|
||||
```
|
||||
|
||||
Handmatig kan ook:
|
||||
|
||||
```bash
|
||||
git clone https://git.ramonbesselink.nl/bes-r/server-up.git /opt/server-up
|
||||
cd /opt/server-up
|
||||
cp .env.example .env
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Alle opties staan in [docs/installeren.md](docs/installeren.md):
|
||||
`--dir`, `--port`, `--bind`, `--branch`, `--token`, `--update`, `--uninstall`.
|
||||
|
||||
Open daarna de interface en **maak meteen een beheerdersaccount aan.**
|
||||
Zolang dat niet gebeurd is, kan iedereen die de pagina bereikt het account
|
||||
claimen — de container waarschuwt daar bij het opstarten ook voor.
|
||||
|
||||
### Instellingen
|
||||
|
||||
Alles staat met uitleg in [`.env.example`](.env.example). De twee die je
|
||||
waarschijnlijk meteen nodig hebt:
|
||||
|
||||
```bash
|
||||
BIND=127.0.0.1 # 0.0.0.0 om er van buiten de server bij te kunnen
|
||||
PORT=5000
|
||||
```
|
||||
|
||||
De poort bindt standaard op `127.0.0.1`. Zet hem pas open als er een reverse
|
||||
proxy met TLS voor staat.
|
||||
|
||||
## Documentatie
|
||||
|
||||
| Document | Waarover |
|
||||
|---|---|
|
||||
| [docs/installeren.md](docs/installeren.md) | Het installatiescript, opties, bijwerken en verwijderen |
|
||||
| [docs/beveiliging.md](docs/beveiliging.md) | Accounts, rollen, SSO, reverse proxy, wat wel en niet is afgedekt |
|
||||
| [docs/apps-maken.md](docs/apps-maken.md) | Eigen apps toevoegen: het volledige templateformaat |
|
||||
| [docs/netwerken.md](docs/netwerken.md) | Stacks een eigen IP geven met macvlan of ipvlan |
|
||||
| [docs/backups.md](docs/backups.md) | Wat er wél en niet in een backup zit, terugzetten, bewaarbeleid |
|
||||
| [docs/updates.md](docs/updates.md) | Update-kanalen en de Forgejo-registry inrichten |
|
||||
| [docs/synchroniseren.md](docs/synchroniseren.md) | Code van je apparaat naar de server via Forgejo |
|
||||
| [docs/forgejo-actions-setup.md](docs/forgejo-actions-setup.md) | Runners instellen |
|
||||
|
||||
## Eigen apps toevoegen
|
||||
|
||||
Wijs Server Up naar je eigen git-repo met app-sjablonen (Instellingen → App
|
||||
Store → Repository), of voeg een map toe onder `apps/`:
|
||||
|
||||
```
|
||||
apps/mijn-app/
|
||||
├── template.json metadata en de vragen bij het installeren
|
||||
└── files/
|
||||
└── compose.yaml het compose-bestand met << variabelen >>
|
||||
```
|
||||
|
||||
Het volledige formaat staat in [docs/apps-maken.md](docs/apps-maken.md).
|
||||
|
||||
## Bijwerken en verwijderen
|
||||
|
||||
```bash
|
||||
sh /opt/server-up/install.sh --update # nieuwste versie ophalen en herstarten
|
||||
sh /opt/server-up/install.sh --uninstall # stoppen; je gegevens blijven staan
|
||||
```
|
||||
|
||||
Draait Server Up vanaf een registry-image, dan kan bijwerken ook met een knop in
|
||||
de interface — zie [docs/updates.md](docs/updates.md).
|
||||
|
||||
## Ontwikkelen
|
||||
|
||||
```bash
|
||||
python3 -m venv venv && venv/bin/pip install -r server-up/requirements.txt pytest
|
||||
venv/bin/python -m pytest tests -q # de volledige suite
|
||||
cd server-up && SU_DEV=1 python app.py # lokaal draaien op poort 5000
|
||||
```
|
||||
|
||||
De testsuite draait ook over alle app-sjablonen: elke app moet renderen naar
|
||||
geldige compose-YAML, met gedeclareerde volumes en zonder onvervangen
|
||||
variabelen. Voeg je een app toe, dan wordt die automatisch meegenomen.
|
||||
|
||||
De deploy-workflows draaien de tests in een container (`python:3.12-slim`), dus
|
||||
op de runner is verder niets nodig dan Docker.
|
||||
|
||||
## Licentie en bijdragen
|
||||
|
||||
Zie `CHANGELOG.md` voor de geschiedenis. Werk op de `dev`-branch en bump
|
||||
`VERSION` bij elke wijziging; een test bewaakt dat er een changelog-sectie bij
|
||||
hoort.
|
||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.4.60
|
||||
0.7.30-beta
|
||||
|
|
|
|||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "Actual Budget",
|
||||
"description": "Lokaal persoonlijk financieel beheer en budgettering zonder cloudafhankelijkheid.",
|
||||
"tags": ["financiën", "budget", "persoonlijk", "privacy"],
|
||||
"icon": {"provider": "selfhst", "id": "actual-budget"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"financiën",
|
||||
"budget",
|
||||
"persoonlijk",
|
||||
"privacy"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "actual-budget"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"financien"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,9 +3,23 @@
|
|||
"metadata": {
|
||||
"name": "AdGuard Home",
|
||||
"description": "DNS-level advertentie- en trackerblokkering voor het hele netwerk",
|
||||
"tags": ["dns", "adblock", "netwerk", "privacy"],
|
||||
"icon": {"provider": "selfhst", "id": "adguard-home"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"dns",
|
||||
"adblock",
|
||||
"netwerk",
|
||||
"privacy"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "adguard-home"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"netwerk",
|
||||
"beveiliging"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,19 +1,13 @@
|
|||
# ARR-stack — kies per onderdeel of je het wilt.
|
||||
#
|
||||
# Aandachtspunten:
|
||||
# * Zet de download- en mediamap op hetzelfde bestandssysteem, anders kopieert
|
||||
# elke voltooide download in plaats van te verplaatsen (traag, dubbele opslag).
|
||||
# * Draai je met Gluetun, dan zitten de downloadclients in het netwerk van die
|
||||
# container en bereik je hun webinterface via de Gluetun-poorten.
|
||||
services:
|
||||
<< service_name >>-radarr:
|
||||
image: lscr.io/linuxserver/radarr:latest
|
||||
container_name: << service_name >>-radarr
|
||||
environment:
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/radarr:/config
|
||||
- << media_dir >>/films:/movies
|
||||
- << downloads_dir >>:/downloads
|
||||
ports:
|
||||
- "<< port_radarr >>:7878"
|
||||
restart: unless-stopped
|
||||
|
||||
<%- if enable_sonarr %>
|
||||
<< service_name >>-sonarr:
|
||||
image: lscr.io/linuxserver/sonarr:latest
|
||||
container_name: << service_name >>-sonarr
|
||||
|
|
@ -28,7 +22,26 @@ services:
|
|||
ports:
|
||||
- "<< port_sonarr >>:8989"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_radarr %>
|
||||
<< service_name >>-radarr:
|
||||
image: lscr.io/linuxserver/radarr:latest
|
||||
container_name: << service_name >>-radarr
|
||||
environment:
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/radarr:/config
|
||||
- << media_dir >>/films:/movies
|
||||
- << downloads_dir >>:/downloads
|
||||
ports:
|
||||
- "<< port_radarr >>:7878"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_lidarr %>
|
||||
<< service_name >>-lidarr:
|
||||
image: lscr.io/linuxserver/lidarr:latest
|
||||
container_name: << service_name >>-lidarr
|
||||
|
|
@ -43,7 +56,9 @@ services:
|
|||
ports:
|
||||
- "<< port_lidarr >>:8686"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_readarr %>
|
||||
<< service_name >>-readarr:
|
||||
image: lscr.io/linuxserver/readarr:develop
|
||||
container_name: << service_name >>-readarr
|
||||
|
|
@ -58,7 +73,26 @@ services:
|
|||
ports:
|
||||
- "<< port_readarr >>:8787"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_whisparr %>
|
||||
<< service_name >>-whisparr:
|
||||
image: ghcr.io/hotio/whisparr:latest
|
||||
container_name: << service_name >>-whisparr
|
||||
environment:
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/whisparr:/config
|
||||
- << media_dir >>/volwassen:/adult
|
||||
- << downloads_dir >>:/downloads
|
||||
ports:
|
||||
- "<< port_whisparr >>:6969"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_prowlarr %>
|
||||
<< service_name >>-prowlarr:
|
||||
image: lscr.io/linuxserver/prowlarr:latest
|
||||
container_name: << service_name >>-prowlarr
|
||||
|
|
@ -71,7 +105,24 @@ services:
|
|||
ports:
|
||||
- "<< port_prowlarr >>:9696"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_jackett %>
|
||||
<< service_name >>-jackett:
|
||||
image: lscr.io/linuxserver/jackett:latest
|
||||
container_name: << service_name >>-jackett
|
||||
environment:
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/jackett:/config
|
||||
ports:
|
||||
- "<< port_jackett >>:9117"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_bazarr %>
|
||||
<< service_name >>-bazarr:
|
||||
image: lscr.io/linuxserver/bazarr:latest
|
||||
container_name: << service_name >>-bazarr
|
||||
|
|
@ -86,14 +137,226 @@ services:
|
|||
ports:
|
||||
- "<< port_bazarr >>:6767"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_flaresolverr %>
|
||||
<< service_name >>-flaresolverr:
|
||||
image: ghcr.io/flaresolverr/flaresolverr:latest
|
||||
container_name: << service_name >>-flaresolverr
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- LOG_LEVEL=info
|
||||
ports:
|
||||
- "<< port_flaresolverr >>:8191"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_gluetun %>
|
||||
<< service_name >>-gluetun:
|
||||
image: qmcgaw/gluetun:latest
|
||||
container_name: << service_name >>-gluetun
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- VPN_SERVICE_PROVIDER=<< vpn_provider >>
|
||||
- VPN_TYPE=<< vpn_type >>
|
||||
- WIREGUARD_PRIVATE_KEY=<< wireguard_private_key >>
|
||||
- WIREGUARD_ADDRESSES=<< wireguard_addresses >>
|
||||
- OPENVPN_USER=<< openvpn_user >>
|
||||
- OPENVPN_PASSWORD=<< openvpn_password >>
|
||||
ports:
|
||||
# De downloadclients delen dit netwerk, dus hun poorten staan hier.
|
||||
<%- if enable_qbittorrent %>
|
||||
- "<< port_qbittorrent >>:8090"
|
||||
- "<< port_qbittorrent_tcp >>:6881"
|
||||
- "<< port_qbittorrent_tcp >>:6881/udp"
|
||||
<%- endif %>
|
||||
<%- if enable_sabnzbd %>
|
||||
- "<< port_sabnzbd >>:8080"
|
||||
<%- endif %>
|
||||
<%- if enable_nzbget %>
|
||||
- "<< port_nzbget >>:6789"
|
||||
<%- endif %>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/gluetun:/gluetun
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_qbittorrent %>
|
||||
<< service_name >>-qbittorrent:
|
||||
image: lscr.io/linuxserver/qbittorrent:latest
|
||||
container_name: << service_name >>-qbittorrent
|
||||
environment:
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- TZ=<< timezone >>
|
||||
- WEBUI_PORT=8090
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/qbittorrent:/config
|
||||
- << downloads_dir >>:/downloads
|
||||
<%- if enable_gluetun %>
|
||||
network_mode: "service:<< service_name >>-gluetun"
|
||||
depends_on:
|
||||
- << service_name >>-gluetun
|
||||
<%- endif %>
|
||||
<%- if not enable_gluetun %>
|
||||
ports:
|
||||
- "<< port_qbittorrent >>:8090"
|
||||
- "<< port_qbittorrent_tcp >>:6881"
|
||||
- "<< port_qbittorrent_tcp >>:6881/udp"
|
||||
<%- endif %>
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_sabnzbd %>
|
||||
<< service_name >>-sabnzbd:
|
||||
image: lscr.io/linuxserver/sabnzbd:latest
|
||||
container_name: << service_name >>-sabnzbd
|
||||
environment:
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/sabnzbd:/config
|
||||
- << downloads_dir >>:/downloads
|
||||
<%- if enable_gluetun %>
|
||||
network_mode: "service:<< service_name >>-gluetun"
|
||||
depends_on:
|
||||
- << service_name >>-gluetun
|
||||
<%- endif %>
|
||||
<%- if not enable_gluetun %>
|
||||
ports:
|
||||
- "<< port_sabnzbd >>:8080"
|
||||
<%- endif %>
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_nzbget %>
|
||||
<< service_name >>-nzbget:
|
||||
image: lscr.io/linuxserver/nzbget:latest
|
||||
container_name: << service_name >>-nzbget
|
||||
environment:
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/nzbget:/config
|
||||
- << downloads_dir >>:/downloads
|
||||
<%- if enable_gluetun %>
|
||||
network_mode: "service:<< service_name >>-gluetun"
|
||||
depends_on:
|
||||
- << service_name >>-gluetun
|
||||
<%- endif %>
|
||||
<%- if not enable_gluetun %>
|
||||
ports:
|
||||
- "<< port_nzbget >>:6789"
|
||||
<%- endif %>
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_jellyseerr %>
|
||||
<< service_name >>-jellyseerr:
|
||||
image: fallenbagel/jellyseerr:latest
|
||||
container_name: << service_name >>-jellyseerr
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- LOG_LEVEL=info
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/jellyseerr:/app/config
|
||||
ports:
|
||||
- "<< port_jellyseerr >>:5055"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_recyclarr %>
|
||||
<< service_name >>-recyclarr:
|
||||
image: ghcr.io/recyclarr/recyclarr:latest
|
||||
container_name: << service_name >>-recyclarr
|
||||
user: << puid >>:<< pgid >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/recyclarr:/config
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_unpackerr %>
|
||||
<< service_name >>-unpackerr:
|
||||
image: ghcr.io/unpackerr/unpackerr:latest
|
||||
container_name: << service_name >>-unpackerr
|
||||
user: << puid >>:<< pgid >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- UN_SONARR_0_URL=http://<< service_name >>-sonarr:8989
|
||||
- UN_RADARR_0_URL=http://<< service_name >>-radarr:7878
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/unpackerr:/config
|
||||
- << downloads_dir >>:/downloads
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_tdarr %>
|
||||
<< service_name >>-tdarr:
|
||||
image: ghcr.io/haveagitgat/tdarr:latest
|
||||
container_name: << service_name >>-tdarr
|
||||
environment:
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- TZ=<< timezone >>
|
||||
- serverIP=0.0.0.0
|
||||
- serverPort=8266
|
||||
- webUIPort=8265
|
||||
- internalNode=true
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/tdarr/server:/app/server
|
||||
- << data_dir >>/<< service_name >>/tdarr/configs:/app/configs
|
||||
- << media_dir >>:/media
|
||||
- << downloads_dir >>/tdarr-cache:/temp
|
||||
ports:
|
||||
- "<< port_tdarr >>:8265"
|
||||
- "<< port_tdarr_server >>:8266"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_autobrr %>
|
||||
<< service_name >>-autobrr:
|
||||
image: ghcr.io/autobrr/autobrr:latest
|
||||
container_name: << service_name >>-autobrr
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/autobrr:/config
|
||||
ports:
|
||||
- "<< port_autobrr >>:7474"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_maintainerr %>
|
||||
<< service_name >>-maintainerr:
|
||||
image: ghcr.io/jorenn92/maintainerr:latest
|
||||
container_name: << service_name >>-maintainerr
|
||||
user: << puid >>:<< pgid >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/maintainerr:/opt/data
|
||||
ports:
|
||||
- "<< port_maintainerr >>:6246"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
||||
<%- if enable_huntarr %>
|
||||
<< service_name >>-huntarr:
|
||||
image: ghcr.io/plexguide/huntarr:latest
|
||||
container_name: << service_name >>-huntarr
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/huntarr:/config
|
||||
ports:
|
||||
- "<< port_huntarr >>:9705"
|
||||
restart: unless-stopped
|
||||
<%- endif %>
|
||||
|
|
|
|||
|
|
@ -2,10 +2,25 @@
|
|||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "ARR-stack",
|
||||
"description": "Complete media-automatiseringsstack: Radarr (films), Sonarr (series), Lidarr (muziek), Readarr (boeken), Prowlarr (indexers), Bazarr (ondertitels) en Jellyseerr (verzoeken).",
|
||||
"tags": ["media", "automatisering", "radarr", "sonarr", "prowlarr", "bazarr", "jellyseerr"],
|
||||
"icon": {"provider": "selfhst", "id": "radarr"},
|
||||
"version": {"name": "latest"}
|
||||
"description": "Media-automatisering met een schakelaar per onderdeel: Sonarr, Radarr, Lidarr, Readarr, Whisparr, Prowlarr, Jackett, Bazarr, FlareSolverr, qBittorrent, SABnzbd, NZBGet, Gluetun (VPN), Jellyseerr, Recyclarr, Unpackerr, Tdarr, Autobrr, Maintainerr en Huntarr.",
|
||||
"tags": [
|
||||
"media",
|
||||
"automatisering",
|
||||
"films",
|
||||
"series",
|
||||
"downloaden"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "sonarr"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media",
|
||||
"downloaden"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -14,34 +29,34 @@
|
|||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam (prefix)",
|
||||
"title": "Naam van de stack",
|
||||
"default": "arr",
|
||||
"required": true,
|
||||
"description": "Prefix voor alle containers in de stack, bijv. 'arr' geeft arr-radarr, arr-sonarr, etc."
|
||||
"description": "Wordt het voorvoegsel van elke container, bv. arr-sonarr"
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Config directory",
|
||||
"title": "Configuratiemap",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor configuratiebestanden van alle ARR-apps"
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "media_dir",
|
||||
"type": "str",
|
||||
"title": "Media directory",
|
||||
"title": "Mediamap",
|
||||
"default": "/mnt/media",
|
||||
"required": true,
|
||||
"description": "Map voor films, series en muziek. Moet ook zichtbaar zijn voor de download-client."
|
||||
"description": "Hier komen films/, series/, muziek/ en boeken/ onder te staan"
|
||||
},
|
||||
{
|
||||
"name": "downloads_dir",
|
||||
"type": "str",
|
||||
"title": "Downloads directory",
|
||||
"title": "Downloadmap",
|
||||
"default": "/mnt/downloads",
|
||||
"required": true,
|
||||
"description": "Map waar de download-client bestanden neerzet (qBittorrent of SABnzbd). Moet overeenkomen met het pad in de download-client."
|
||||
"description": "Zet deze op hetzelfde bestandssysteem als de mediamap, anders kopieert elke download in plaats van te verplaatsen",
|
||||
"help": "Zet deze map op hetzelfde bestandssysteem als je mediamap. Staan ze op verschillende schijven of volumes, dan kopieert elke voltooide download in plaats van te verplaatsen: traag, en je hebt alles tijdelijk dubbel."
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
|
|
@ -49,84 +64,366 @@
|
|||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Gebruiker",
|
||||
"items": [
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "PUID",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "User ID van de systeemgebruiker (id -u)"
|
||||
"description": "`id -u` op je host; bepaalt de eigenaar van bestanden",
|
||||
"help": "Het gebruikersnummer waaronder de containers draaien. Klopt dit niet met de eigenaar van je mediamap, dan kunnen de apps er niet in schrijven. Vind het met `id -u` op je server."
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "PGID",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Group ID van de systeemgebruiker (id -g)"
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Poorten",
|
||||
"title": "Sonarr — series",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_sonarr",
|
||||
"type": "int",
|
||||
"title": "Poort",
|
||||
"default": 8989,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_sonarr",
|
||||
"toggle_default": true,
|
||||
"description": "Zoekt, downloadt en hernoemt series"
|
||||
},
|
||||
{
|
||||
"title": "Radarr — films",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_radarr",
|
||||
"type": "int",
|
||||
"title": "Radarr poort",
|
||||
"title": "Poort",
|
||||
"default": 7878,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_radarr",
|
||||
"toggle_default": true,
|
||||
"description": "Zoekt, downloadt en hernoemt films"
|
||||
},
|
||||
{
|
||||
"name": "port_sonarr",
|
||||
"type": "int",
|
||||
"title": "Sonarr poort",
|
||||
"default": 8989,
|
||||
"required": true
|
||||
},
|
||||
"title": "Lidarr — muziek",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_lidarr",
|
||||
"type": "int",
|
||||
"title": "Lidarr poort",
|
||||
"title": "Poort",
|
||||
"default": 8686,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_lidarr",
|
||||
"toggle_default": false
|
||||
},
|
||||
{
|
||||
"title": "Readarr — boeken",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_readarr",
|
||||
"type": "int",
|
||||
"title": "Readarr poort",
|
||||
"title": "Poort",
|
||||
"default": 8787,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_readarr",
|
||||
"toggle_default": false,
|
||||
"description": "Let op: de ontwikkeling van Readarr is stilgelegd; het draait nog wel"
|
||||
},
|
||||
{
|
||||
"title": "Whisparr — volwassenen",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_whisparr",
|
||||
"type": "int",
|
||||
"title": "Poort",
|
||||
"default": 6969,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_whisparr",
|
||||
"toggle_default": false
|
||||
},
|
||||
{
|
||||
"title": "Prowlarr — indexerbeheer",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_prowlarr",
|
||||
"type": "int",
|
||||
"title": "Prowlarr poort",
|
||||
"title": "Poort",
|
||||
"default": 9696,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_prowlarr",
|
||||
"toggle_default": true,
|
||||
"description": "Beheert je indexers centraal en duwt ze naar de andere *arr-apps"
|
||||
},
|
||||
{
|
||||
"title": "Jackett — indexerproxy",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_jackett",
|
||||
"type": "int",
|
||||
"title": "Poort",
|
||||
"default": 9117,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_jackett",
|
||||
"toggle_default": false,
|
||||
"description": "Ouder alternatief voor Prowlarr; meestal heb je er maar één nodig"
|
||||
},
|
||||
{
|
||||
"title": "FlareSolverr — Cloudflare omzeilen",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_flaresolverr",
|
||||
"type": "int",
|
||||
"title": "Poort",
|
||||
"default": 8191,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_flaresolverr",
|
||||
"toggle_default": false,
|
||||
"description": "Nodig voor indexers die achter een Cloudflare-controle zitten"
|
||||
},
|
||||
{
|
||||
"title": "Bazarr — ondertitels",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_bazarr",
|
||||
"type": "int",
|
||||
"title": "Bazarr poort",
|
||||
"title": "Poort",
|
||||
"default": 6767,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_bazarr",
|
||||
"toggle_default": true
|
||||
},
|
||||
{
|
||||
"title": "qBittorrent — torrents",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_qbittorrent",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8097,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port_qbittorrent_tcp",
|
||||
"type": "int",
|
||||
"title": "Inkomende poort",
|
||||
"default": 6881,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_qbittorrent",
|
||||
"toggle_default": true,
|
||||
"description": "Torrentclient met webinterface"
|
||||
},
|
||||
{
|
||||
"title": "SABnzbd — usenet",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_sabnzbd",
|
||||
"type": "int",
|
||||
"title": "Poort",
|
||||
"default": 8098,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_sabnzbd",
|
||||
"toggle_default": false
|
||||
},
|
||||
{
|
||||
"title": "NZBGet — usenet (lichter)",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_nzbget",
|
||||
"type": "int",
|
||||
"title": "Poort",
|
||||
"default": 6789,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_nzbget",
|
||||
"toggle_default": false,
|
||||
"description": "Zuiniger alternatief voor SABnzbd"
|
||||
},
|
||||
{
|
||||
"title": "Gluetun — VPN voor de downloadclient",
|
||||
"items": [
|
||||
{
|
||||
"name": "vpn_provider",
|
||||
"type": "str",
|
||||
"title": "VPN-aanbieder",
|
||||
"default": "mullvad",
|
||||
"required": true,
|
||||
"description": "Bijvoorbeeld mullvad, nordvpn, protonvpn of surfshark"
|
||||
},
|
||||
{
|
||||
"name": "vpn_type",
|
||||
"type": "enum",
|
||||
"title": "Protocol",
|
||||
"default": "wireguard",
|
||||
"required": true,
|
||||
"config": {
|
||||
"options": [
|
||||
"wireguard",
|
||||
"openvpn"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wireguard_private_key",
|
||||
"type": "str",
|
||||
"title": "WireGuard privésleutel",
|
||||
"default": "",
|
||||
"required": false,
|
||||
"config": {
|
||||
"placeholder": "alleen bij wireguard"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wireguard_addresses",
|
||||
"type": "str",
|
||||
"title": "WireGuard adressen",
|
||||
"default": "",
|
||||
"required": false,
|
||||
"config": {
|
||||
"placeholder": "10.64.0.2/32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "openvpn_user",
|
||||
"type": "str",
|
||||
"title": "OpenVPN gebruiker",
|
||||
"default": "",
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"name": "openvpn_password",
|
||||
"type": "str",
|
||||
"title": "OpenVPN wachtwoord",
|
||||
"default": "",
|
||||
"required": false
|
||||
}
|
||||
],
|
||||
"toggle": "enable_gluetun",
|
||||
"toggle_default": false,
|
||||
"description": "Leidt al je downloadverkeer door een VPN. De downloadclients delen dan het netwerk van deze container, dus hun poorten komen hier te liggen."
|
||||
},
|
||||
{
|
||||
"title": "Jellyseerr — verzoeken",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_jellyseerr",
|
||||
"type": "int",
|
||||
"title": "Jellyseerr poort",
|
||||
"title": "Poort",
|
||||
"default": 5055,
|
||||
"required": true,
|
||||
"description": "Webinterface voor gebruikers om films en series aan te vragen"
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"toggle": "enable_jellyseerr",
|
||||
"toggle_default": true,
|
||||
"description": "Laat huisgenoten films en series aanvragen"
|
||||
},
|
||||
{
|
||||
"title": "Recyclarr — TRaSH-instellingen",
|
||||
"items": [],
|
||||
"toggle": "enable_recyclarr",
|
||||
"toggle_default": false,
|
||||
"description": "Synchroniseert kwaliteitsprofielen uit de TRaSH-gidsen naar Sonarr en Radarr"
|
||||
},
|
||||
{
|
||||
"title": "Unpackerr — archieven uitpakken",
|
||||
"items": [],
|
||||
"toggle": "enable_unpackerr",
|
||||
"toggle_default": false,
|
||||
"description": "Pakt gedownloade rar-archieven automatisch uit"
|
||||
},
|
||||
{
|
||||
"title": "Tdarr — hercoderen",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_tdarr",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8265,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port_tdarr_server",
|
||||
"type": "int",
|
||||
"title": "Serverpoort",
|
||||
"default": 8266,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_tdarr",
|
||||
"toggle_default": false,
|
||||
"description": "Zet je bibliotheek om naar een zuiniger formaat"
|
||||
},
|
||||
{
|
||||
"title": "Autobrr — automatisch grijpen",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_autobrr",
|
||||
"type": "int",
|
||||
"title": "Poort",
|
||||
"default": 7474,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_autobrr",
|
||||
"toggle_default": false,
|
||||
"description": "Reageert direct op aankondigingen in plaats van periodiek te zoeken"
|
||||
},
|
||||
{
|
||||
"title": "Maintainerr — opruimen",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_maintainerr",
|
||||
"type": "int",
|
||||
"title": "Poort",
|
||||
"default": 6246,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_maintainerr",
|
||||
"toggle_default": false,
|
||||
"description": "Ruimt media op volgens regels die je zelf instelt"
|
||||
},
|
||||
{
|
||||
"title": "Huntarr — gaten opvullen",
|
||||
"items": [
|
||||
{
|
||||
"name": "port_huntarr",
|
||||
"type": "int",
|
||||
"title": "Poort",
|
||||
"default": 9705,
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"toggle": "enable_huntarr",
|
||||
"toggle_default": false,
|
||||
"description": "Zoekt gericht naar ontbrekende en te verbeteren afleveringen"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
13
apps/audiobookshelf/files/compose.yaml
Normal file
13
apps/audiobookshelf/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/advplyr/audiobookshelf:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << media_dir >>:/audiobooks
|
||||
- << data_dir >>/<< service_name >>/config:/config
|
||||
- << data_dir >>/<< service_name >>/metadata:/metadata
|
||||
restart: unless-stopped
|
||||
64
apps/audiobookshelf/template.json
Normal file
64
apps/audiobookshelf/template.json
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Audiobookshelf",
|
||||
"description": "Server voor luisterboeken en podcasts, met apps voor iOS en Android die je voortgang bijhouden.",
|
||||
"tags": [
|
||||
"media",
|
||||
"luisterboeken",
|
||||
"podcast"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "audiobookshelf"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "audiobookshelf",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 13378,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "media_dir",
|
||||
"type": "str",
|
||||
"title": "Map met luisterboeken",
|
||||
"default": "/opt/serverup/media/audiobooks",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
15
apps/authelia/files/compose.yaml
Normal file
15
apps/authelia/files/compose.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: authelia/authelia:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:9091"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- AUTHELIA_JWT_SECRET=<< jwt_secret >>
|
||||
- AUTHELIA_SESSION_SECRET=<< session_secret >>
|
||||
- AUTHELIA_STORAGE_ENCRYPTION_KEY=<< storage_key >>
|
||||
volumes:
|
||||
# Zet hier configuration.yml en users_database.yml neer voor de eerste start.
|
||||
- << data_dir >>/<< service_name >>/config:/config
|
||||
restart: unless-stopped
|
||||
93
apps/authelia/template.json
Normal file
93
apps/authelia/template.json
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Authelia",
|
||||
"description": "Inlogportaal met tweestapsverificatie voor al je diensten achter een reverse proxy. Werkt samen met de SSO-instelling van Server Up.",
|
||||
"tags": [
|
||||
"beveiliging",
|
||||
"sso",
|
||||
"authenticatie"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "authelia"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"beveiliging"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "authelia",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 9091,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "jwt_secret",
|
||||
"type": "str",
|
||||
"title": "JWT-sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Gebruik de dobbelsteenknop voor een willekeurige waarde",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
},
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "session_secret",
|
||||
"type": "str",
|
||||
"title": "Sessiesleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Gebruik de dobbelsteenknop voor een willekeurige waarde",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
},
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "storage_key",
|
||||
"type": "str",
|
||||
"title": "Opslagversleuteling",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Gebruik de dobbelsteenknop voor een willekeurige waarde",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
},
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
16
apps/baby-buddy/files/compose.yaml
Normal file
16
apps/baby-buddy/files/compose.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/babybuddy/babybuddy:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8000"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- SECRET_KEY=<< secret_key >>
|
||||
- ALLOWED_HOSTS=<< allowed_hosts >>
|
||||
- CSRF_TRUSTED_ORIGINS=http://<< allowed_hosts >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/app/data
|
||||
restart: unless-stopped
|
||||
94
apps/baby-buddy/template.json
Normal file
94
apps/baby-buddy/template.json
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Baby Buddy",
|
||||
"description": "Houdt voedingen, slaap, luiers en groei van je kind bij. Handig om het overzicht te bewaren in de eerste maanden.",
|
||||
"tags": [
|
||||
"gezin",
|
||||
"gezondheid",
|
||||
"logboek"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "baby-buddy"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"gezin"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "baby-buddy",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8000,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "secret_key",
|
||||
"type": "str",
|
||||
"title": "Geheime sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Willekeurige waarde voor sessieversleuteling; gebruik de dobbelsteenknop",
|
||||
"config": {
|
||||
"placeholder": "willekeurige-lange-string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "allowed_hosts",
|
||||
"type": "str",
|
||||
"title": "Toegestane hostnamen",
|
||||
"default": "*",
|
||||
"required": true,
|
||||
"description": "Bijvoorbeeld babybuddy.thuis.nl; * staat alles toe",
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
18
apps/bambuddy/files/compose.yaml
Normal file
18
apps/bambuddy/files/compose.yaml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/maziggy/bambuddy:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8000"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- PORT=8000
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/data:/app/data
|
||||
- << data_dir >>/<< service_name >>/logs:/app/logs
|
||||
cap_add:
|
||||
- NET_BIND_SERVICE
|
||||
stop_grace_period: 30s
|
||||
restart: unless-stopped
|
||||
74
apps/bambuddy/template.json
Normal file
74
apps/bambuddy/template.json
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Bambuddy",
|
||||
"description": "Zelfgehost bedieningspaneel voor Bambu Lab-printers, van één A1 tot een hele printerfarm. Zonder cloud.",
|
||||
"tags": [
|
||||
"3d-printen",
|
||||
"bambu-lab",
|
||||
"printerbeheer"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "bambuddy"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"3d-printen"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "bambuddy",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8011,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
12
apps/baserow/files/compose.yaml
Normal file
12
apps/baserow/files/compose.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: baserow/baserow:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- BASEROW_PUBLIC_URL=<< public_url >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>:/baserow/data
|
||||
restart: unless-stopped
|
||||
66
apps/baserow/template.json
Normal file
66
apps/baserow/template.json
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Baserow",
|
||||
"description": "Databases opbouwen zonder te programmeren, met formulieren en weergaven.",
|
||||
"tags": [
|
||||
"database",
|
||||
"no-code",
|
||||
"formulieren"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "baserow"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"ontwikkeling",
|
||||
"productiviteit"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "baserow",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8099,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "public_url",
|
||||
"type": "str",
|
||||
"title": "Publieke URL",
|
||||
"default": "http://localhost:8098",
|
||||
"required": true,
|
||||
"description": "Zonder dit kloppen links en uploads niet"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
23
apps/beszel/files/compose.yaml
Normal file
23
apps/beszel/files/compose.yaml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: henrygd/beszel:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8090"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/data:/beszel_data
|
||||
restart: unless-stopped
|
||||
|
||||
<< service_name >>-agent:
|
||||
image: henrygd/beszel-agent:latest
|
||||
container_name: << service_name >>-agent
|
||||
network_mode: host
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PORT=<< agent_port >>
|
||||
- KEY=<< agent_key >>
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
restart: unless-stopped
|
||||
73
apps/beszel/template.json
Normal file
73
apps/beszel/template.json
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Beszel",
|
||||
"description": "Lichte servermonitoring met grafieken en alarmen, zonder een hele Prometheus-opstelling.",
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"systeem",
|
||||
"lichtgewicht"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "beszel"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"monitoring"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "beszel",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8100,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "agent_port",
|
||||
"type": "int",
|
||||
"title": "Agent-poort",
|
||||
"default": 45876,
|
||||
"required": true,
|
||||
"description": "De agent meet deze host; extra servers wijs je later aan"
|
||||
},
|
||||
{
|
||||
"name": "agent_key",
|
||||
"type": "str",
|
||||
"title": "Publieke sleutel agent",
|
||||
"default": "",
|
||||
"required": false,
|
||||
"description": "Laat leeg bij de eerste installatie; je vindt hem in de webinterface"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
36
apps/bookstack/files/compose.yaml
Normal file
36
apps/bookstack/files/compose.yaml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: lscr.io/linuxserver/bookstack:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- APP_URL=<< app_url >>
|
||||
- DB_HOST=<< service_name >>-db
|
||||
- DB_PORT=3306
|
||||
- DB_USERNAME=bookstack
|
||||
- DB_PASSWORD=<< db_password >>
|
||||
- DB_DATABASE=bookstack
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/config
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
|
||||
<< service_name >>-db:
|
||||
image: lscr.io/linuxserver/mariadb:latest
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
- MYSQL_ROOT_PASSWORD=<< db_password >>
|
||||
- MYSQL_DATABASE=bookstack
|
||||
- MYSQL_USER=bookstack
|
||||
- MYSQL_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/db:/config
|
||||
restart: unless-stopped
|
||||
94
apps/bookstack/template.json
Normal file
94
apps/bookstack/template.json
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "BookStack",
|
||||
"description": "Wiki voor documentatie, geordend in boeken, hoofdstukken en pagina's. Prettig voor handleidingen thuis.",
|
||||
"tags": [
|
||||
"documentatie",
|
||||
"wiki",
|
||||
"kennis"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "bookstack"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"documenten"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "bookstack",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 6875,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Database wachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Gebruik de dobbelsteenknop voor een willekeurige waarde",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
},
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "app_url",
|
||||
"type": "str",
|
||||
"title": "Basis-URL",
|
||||
"default": "http://localhost:6875",
|
||||
"required": true,
|
||||
"description": "Het adres waarop je BookStack benadert; links kloppen anders niet"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
20
apps/caddy/files/compose.yaml
Normal file
20
apps/caddy/files/compose.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: caddy:2
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
- "<< https_port >>:443"
|
||||
- "<< https_port >>:443/udp"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
# Zet hier je Caddyfile neer; Caddy regelt de certificaten daarna zelf.
|
||||
- << data_dir >>/<< service_name >>/Caddyfile:/etc/caddy/Caddyfile
|
||||
- << service_name >>_data:/data
|
||||
- << service_name >>_config:/config
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
<< service_name >>_data:
|
||||
<< service_name >>_config:
|
||||
66
apps/caddy/template.json
Normal file
66
apps/caddy/template.json
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Caddy",
|
||||
"description": "Reverse proxy die HTTPS-certificaten volledig zelf regelt. Eenvoudiger in te stellen dan Traefik of Nginx.",
|
||||
"tags": [
|
||||
"proxy",
|
||||
"netwerk",
|
||||
"https"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "caddy"
|
||||
},
|
||||
"version": {
|
||||
"name": "2"
|
||||
},
|
||||
"categories": [
|
||||
"netwerk",
|
||||
"beheer"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "caddy",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "HTTP poort",
|
||||
"default": 80,
|
||||
"required": true,
|
||||
"help": "Caddy vraagt zelf certificaten aan bij Let's Encrypt en heeft daarvoor poort 80 nodig, ook als je alles via HTTPS aanbiedt."
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "https_port",
|
||||
"type": "int",
|
||||
"title": "HTTPS poort",
|
||||
"default": 443,
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
14
apps/calibre-web/files/compose.yaml
Normal file
14
apps/calibre-web/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: lscr.io/linuxserver/calibre-web:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8083"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/config
|
||||
- << books_dir >>:/books
|
||||
restart: unless-stopped
|
||||
83
apps/calibre-web/template.json
Normal file
83
apps/calibre-web/template.json
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Calibre-Web",
|
||||
"description": "Webinterface voor je Calibre-bibliotheek: bladeren, lezen en naar je e-reader sturen.",
|
||||
"tags": [
|
||||
"media",
|
||||
"boeken",
|
||||
"ebooks"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "calibre-web"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media",
|
||||
"documenten"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "calibre-web",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8083,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "books_dir",
|
||||
"type": "str",
|
||||
"title": "Calibre-bibliotheek",
|
||||
"default": "/opt/serverup/media/books",
|
||||
"required": true,
|
||||
"description": "Map met je bestaande metadata.db van Calibre"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "Changedetection.io",
|
||||
"description": "Monitor websites op wijzigingen en ontvang meldingen zodra er iets verandert.",
|
||||
"tags": ["monitoring", "websites", "alerting", "automatisering"],
|
||||
"icon": {"provider": "selfhst", "id": "changedetection-io"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"websites",
|
||||
"alerting",
|
||||
"automatisering"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "changedetection-io"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"monitoring"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -44,7 +57,9 @@
|
|||
"default": "",
|
||||
"required": false,
|
||||
"description": "Optioneel wachtwoord om de webinterface te beveiligen. Laat leeg voor geen beveiliging.",
|
||||
"config": {"placeholder": "sterk-wachtwoord"}
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
9
apps/cyberchef/files/compose.yaml
Normal file
9
apps/cyberchef/files/compose.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: mpepping/cyberchef:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8000"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
restart: unless-stopped
|
||||
51
apps/cyberchef/template.json
Normal file
51
apps/cyberchef/template.json
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "CyberChef",
|
||||
"description": "Zwitsers zakmes voor coderen, decoderen, hashen en data omzetten. Draait volledig lokaal.",
|
||||
"tags": [
|
||||
"hulpmiddel",
|
||||
"encoding",
|
||||
"ontwikkelaar"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "cyberchef"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"ontwikkeling",
|
||||
"beveiliging"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "cyberchef",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8106,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,23 @@
|
|||
"metadata": {
|
||||
"name": "Dozzle",
|
||||
"description": "Realtime Docker container log viewer in je browser. Geen data opgeslagen, lichtgewicht.",
|
||||
"tags": ["docker", "logs", "monitoring", "beheer"],
|
||||
"icon": {"provider": "selfhst", "id": "dozzle"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"docker",
|
||||
"logs",
|
||||
"monitoring",
|
||||
"beheer"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "dozzle"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"monitoring",
|
||||
"beheer"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
|
|||
15
apps/duplicati/files/compose.yaml
Normal file
15
apps/duplicati/files/compose.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: lscr.io/linuxserver/duplicati:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8200"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/config
|
||||
- << source_dir >>:/source:ro
|
||||
- << backup_dir >>:/backups
|
||||
restart: unless-stopped
|
||||
88
apps/duplicati/template.json
Normal file
88
apps/duplicati/template.json
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Duplicati",
|
||||
"description": "Versleutelde back-ups naar een NAS, externe schijf of cloudopslag, met een planner.",
|
||||
"tags": [
|
||||
"backup",
|
||||
"opslag",
|
||||
"beheer"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "duplicati"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"opslag"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "duplicati",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8200,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "source_dir",
|
||||
"type": "str",
|
||||
"title": "Map om te back-uppen",
|
||||
"default": "/opt/serverup",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "backup_dir",
|
||||
"type": "str",
|
||||
"title": "Bestemming",
|
||||
"default": "/opt/serverup/backups",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
12
apps/esphome/files/compose.yaml
Normal file
12
apps/esphome/files/compose.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/esphome/esphome:stable
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:6052"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/config
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
restart: unless-stopped
|
||||
58
apps/esphome/template.json
Normal file
58
apps/esphome/template.json
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "ESPHome",
|
||||
"description": "Bouw en beheer firmware voor ESP32/ESP8266-sensoren via een webinterface. Levert kant-en-klare Home Assistant-integratie.",
|
||||
"tags": [
|
||||
"domotica",
|
||||
"esp32",
|
||||
"diy"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "esphome"
|
||||
},
|
||||
"version": {
|
||||
"name": "stable"
|
||||
},
|
||||
"categories": [
|
||||
"domotica",
|
||||
"ontwikkeling"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "esphome",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 6052,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
9
apps/excalidraw/files/compose.yaml
Normal file
9
apps/excalidraw/files/compose.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: excalidraw/excalidraw:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
restart: unless-stopped
|
||||
50
apps/excalidraw/template.json
Normal file
50
apps/excalidraw/template.json
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Excalidraw",
|
||||
"description": "Schetsen en diagrammen tekenen in een handgetekende stijl. Draait volledig in de browser.",
|
||||
"tags": [
|
||||
"tekenen",
|
||||
"diagram",
|
||||
"samenwerken"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "excalidraw"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"productiviteit"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "excalidraw",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8101,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "File Browser",
|
||||
"description": "Webgebaseerde bestandsbeheerder voor je server: uploaden, downloaden, delen en bewerken.",
|
||||
"tags": ["bestanden", "beheer", "cloud", "opslag"],
|
||||
"icon": {"provider": "selfhst", "id": "filebrowser"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"bestanden",
|
||||
"beheer",
|
||||
"cloud",
|
||||
"opslag"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "filebrowser"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"opslag"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
|
|||
34
apps/firefly-iii/files/compose.yaml
Normal file
34
apps/firefly-iii/files/compose.yaml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: fireflyiii/core:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8080"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- APP_KEY=<< app_key >>
|
||||
- DB_CONNECTION=pgsql
|
||||
- DB_HOST=<< service_name >>-db
|
||||
- DB_PORT=5432
|
||||
- DB_DATABASE=firefly
|
||||
- DB_USERNAME=firefly
|
||||
- DB_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/upload:/var/www/html/storage/upload
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=firefly
|
||||
- POSTGRES_USER=firefly
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << service_name >>_pgdata:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
<< service_name >>_pgdata:
|
||||
81
apps/firefly-iii/template.json
Normal file
81
apps/firefly-iii/template.json
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Firefly III",
|
||||
"description": "Huishoudboekje met budgetten, rekeningen en rapportages. Kan bankafschriften importeren.",
|
||||
"tags": [
|
||||
"financien",
|
||||
"huishouden",
|
||||
"budget"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "firefly-iii"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"financien"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "firefly-iii",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8093,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Database wachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Gebruik de dobbelsteenknop voor een willekeurige waarde",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
},
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "app_key",
|
||||
"type": "str",
|
||||
"title": "App-sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Exact 32 tekens; gebruik de dobbelsteenknop en kort zo nodig in",
|
||||
"config": {
|
||||
"placeholder": "32-tekens-lange-sleutel"
|
||||
},
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
11
apps/focalboard/files/compose.yaml
Normal file
11
apps/focalboard/files/compose.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: mattermost/focalboard:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8000"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>:/opt/focalboard/data
|
||||
restart: unless-stopped
|
||||
57
apps/focalboard/template.json
Normal file
57
apps/focalboard/template.json
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Focalboard",
|
||||
"description": "Taken en projecten bijhouden in borden, tabellen en kalenders.",
|
||||
"tags": [
|
||||
"productiviteit",
|
||||
"taken",
|
||||
"projecten"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "focalboard"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"productiviteit"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "focalboard",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8102,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,24 @@
|
|||
"metadata": {
|
||||
"name": "Forgejo MCP Server",
|
||||
"description": "MCP-server voor Forgejo en Gitea. Laat AI-assistenten zoals Claude je repositories, issues, pull requests en releases beheren via natuurlijke taal.",
|
||||
"tags": ["mcp", "ai", "forgejo", "gitea", "claude"],
|
||||
"icon": {"provider": "selfhst", "id": "forgejo"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"mcp",
|
||||
"ai",
|
||||
"forgejo",
|
||||
"gitea",
|
||||
"claude"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "forgejo"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"ontwikkeling",
|
||||
"ai"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -38,7 +53,9 @@
|
|||
"default": "https://jouw-forgejo-url",
|
||||
"required": true,
|
||||
"description": "Volledige URL van je Forgejo- of Gitea-instantie",
|
||||
"config": {"placeholder": "https://git.example.com"}
|
||||
"config": {
|
||||
"placeholder": "https://git.example.com"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "forgejo_token",
|
||||
|
|
@ -47,7 +64,9 @@
|
|||
"default": "",
|
||||
"required": true,
|
||||
"description": "Maak een token aan via Forgejo → Instellingen → Toepassingen → Access Tokens. Geef minimaal 'repository' en 'issue' schrijfrechten.",
|
||||
"config": {"placeholder": "jouw-api-token"}
|
||||
"config": {
|
||||
"placeholder": "jouw-api-token"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "Forgejo",
|
||||
"description": "Lichtgewicht zelfgehoste Git-server. Actief onderhouden community-fork van Gitea.",
|
||||
"tags": ["git", "code", "versiebeheer", "ontwikkeling"],
|
||||
"icon": {"provider": "selfhst", "id": "forgejo"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"git",
|
||||
"code",
|
||||
"versiebeheer",
|
||||
"ontwikkeling"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "forgejo"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"ontwikkeling"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
|
|||
13
apps/freshrss/files/compose.yaml
Normal file
13
apps/freshrss/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: freshrss/freshrss:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- CRON_MIN=*/20
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/data:/var/www/FreshRSS/data
|
||||
- << data_dir >>/<< service_name >>/extensions:/var/www/FreshRSS/extensions
|
||||
restart: unless-stopped
|
||||
72
apps/freshrss/template.json
Normal file
72
apps/freshrss/template.json
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "FreshRSS",
|
||||
"description": "RSS-lezer die je nieuws en blogs op één plek verzamelt, zonder algoritme.",
|
||||
"tags": [
|
||||
"nieuws",
|
||||
"rss",
|
||||
"lezen"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "freshrss"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"documenten"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "freshrss",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8082,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host"
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
20
apps/frigate/files/compose.yaml
Normal file
20
apps/frigate/files/compose.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/blakeblackshear/frigate:stable
|
||||
container_name: << service_name >>
|
||||
shm_size: "<< shm_size >>"
|
||||
ports:
|
||||
- "<< port >>:8971"
|
||||
- "<< rtsp_port >>:8554"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/config
|
||||
- << data_dir >>/<< service_name >>/media:/media/frigate
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
# Opnamebuffer in geheugen; voorkomt slijtage van je SSD
|
||||
- type: tmpfs
|
||||
target: /tmp/cache
|
||||
tmpfs:
|
||||
size: 1000000000
|
||||
restart: unless-stopped
|
||||
76
apps/frigate/template.json
Normal file
76
apps/frigate/template.json
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Frigate NVR",
|
||||
"description": "Camerabewaking met objectherkenning die lokaal draait. Werkt samen met Home Assistant en MQTT.",
|
||||
"tags": [
|
||||
"camera",
|
||||
"nvr",
|
||||
"domotica"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "frigate"
|
||||
},
|
||||
"version": {
|
||||
"name": "stable"
|
||||
},
|
||||
"categories": [
|
||||
"domotica",
|
||||
"media"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "frigate",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8971,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "rtsp_port",
|
||||
"type": "int",
|
||||
"title": "RTSP poort",
|
||||
"default": 8554,
|
||||
"required": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "shm_size",
|
||||
"type": "str",
|
||||
"title": "Gedeeld geheugen",
|
||||
"default": "128mb",
|
||||
"required": true,
|
||||
"description": "Verhoog dit bij meer dan twee camera's (ongeveer 64mb per camera)",
|
||||
"advanced": true,
|
||||
"help": "Frigate houdt camerabeelden in gedeeld geheugen. Reken op ongeveer 64 MB per camera bovenop de standaard; te weinig leidt tot vastlopers zonder duidelijke foutmelding."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "Ghost",
|
||||
"description": "Professioneel blogplatform en CMS met abonnementen, nieuwsbrieven en moderne editor.",
|
||||
"tags": ["blog", "cms", "publiceren", "nieuwsbrief"],
|
||||
"icon": {"provider": "selfhst", "id": "ghost"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"blog",
|
||||
"cms",
|
||||
"publiceren",
|
||||
"nieuwsbrief"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "ghost"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"documenten"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -44,7 +57,9 @@
|
|||
"default": "http://localhost",
|
||||
"required": true,
|
||||
"description": "Volledige URL van je Ghost-site, inclusief protocol",
|
||||
"config": {"placeholder": "https://mijn-blog.nl"}
|
||||
"config": {
|
||||
"placeholder": "https://mijn-blog.nl"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -57,7 +72,9 @@
|
|||
"title": "Database wachtwoord",
|
||||
"default": "ghost_db_pass",
|
||||
"required": true,
|
||||
"config": {"placeholder": "sterk-wachtwoord"}
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "Gotify",
|
||||
"description": "Eenvoudige push-notificatieserver voor je eigen apparaten, scripts en apps.",
|
||||
"tags": ["notificaties", "push", "messaging", "alerts"],
|
||||
"icon": {"provider": "selfhst", "id": "gotify"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"notificaties",
|
||||
"push",
|
||||
"messaging",
|
||||
"alerts"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "gotify"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"communicatie"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -44,7 +57,9 @@
|
|||
"default": "admin",
|
||||
"required": true,
|
||||
"description": "Wijzig dit na de eerste aanmelding",
|
||||
"config": {"placeholder": "sterk-wachtwoord"}
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "Grafana",
|
||||
"description": "Visualiseer metrics, logs en traces in aanpasbare dashboards.",
|
||||
"tags": ["monitoring", "dashboards", "metrics", "visualisatie"],
|
||||
"icon": {"provider": "selfhst", "id": "grafana"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"dashboards",
|
||||
"metrics",
|
||||
"visualisatie"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "grafana"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"monitoring"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -51,7 +64,9 @@
|
|||
"default": "admin",
|
||||
"required": true,
|
||||
"description": "Wijzig dit na de eerste aanmelding",
|
||||
"config": {"placeholder": "sterk-wachtwoord"}
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
13
apps/grocy/files/compose.yaml
Normal file
13
apps/grocy/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: lscr.io/linuxserver/grocy:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/config
|
||||
restart: unless-stopped
|
||||
74
apps/grocy/template.json
Normal file
74
apps/grocy/template.json
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Grocy",
|
||||
"description": "Voorraadbeheer voor je huishouden: boodschappen, houdbaarheidsdata, klusjes en recepten.",
|
||||
"tags": [
|
||||
"huishouden",
|
||||
"voorraad",
|
||||
"gezin"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "grocy"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"gezin"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "grocy",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 9283,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
31
apps/hedgedoc/files/compose.yaml
Normal file
31
apps/hedgedoc/files/compose.yaml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: quay.io/hedgedoc/hedgedoc:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- CMD_DB_URL=postgres://hedgedoc:<< db_password >>@<< service_name >>-db:5432/hedgedoc
|
||||
- CMD_DOMAIN=<< app_url >>
|
||||
- CMD_URL_ADDPORT=false
|
||||
- CMD_ALLOW_ANONYMOUS=false
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/uploads:/hedgedoc/public/uploads
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_USER=hedgedoc
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
- POSTGRES_DB=hedgedoc
|
||||
volumes:
|
||||
- << service_name >>_pgdata:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
<< service_name >>_pgdata:
|
||||
77
apps/hedgedoc/template.json
Normal file
77
apps/hedgedoc/template.json
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "HedgeDoc",
|
||||
"description": "Samen documenten schrijven in Markdown, realtime in de browser.",
|
||||
"tags": [
|
||||
"notities",
|
||||
"samenwerken",
|
||||
"markdown"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "hedgedoc"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"documenten",
|
||||
"productiviteit"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "hedgedoc",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 3011,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Database wachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Gebruik de dobbelsteenknop voor een willekeurige waarde",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
},
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "app_url",
|
||||
"type": "str",
|
||||
"title": "Basis-URL",
|
||||
"default": "http://localhost:3010",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,21 @@
|
|||
"metadata": {
|
||||
"name": "Home Assistant",
|
||||
"description": "Open-source domotica platform voor het automatiseren van je slimme huis.",
|
||||
"tags": ["domotica", "smart-home", "automatisering"],
|
||||
"icon": {"provider": "selfhst", "id": "home-assistant"},
|
||||
"version": {"name": "stable"}
|
||||
"tags": [
|
||||
"domotica",
|
||||
"smart-home",
|
||||
"automatisering"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "home-assistant"
|
||||
},
|
||||
"version": {
|
||||
"name": "stable"
|
||||
},
|
||||
"categories": [
|
||||
"domotica"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,9 +3,24 @@
|
|||
"metadata": {
|
||||
"name": "Home Assistant MCP Server",
|
||||
"description": "MCP-server voor Home Assistant. Laat AI-assistenten zoals Claude je slimme apparaten bedienen, automations beheren en statussen opvragen via natuurlijke taal.",
|
||||
"tags": ["mcp", "ai", "home-assistant", "smarthome", "claude"],
|
||||
"icon": {"provider": "selfhst", "id": "home-assistant"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"mcp",
|
||||
"ai",
|
||||
"home-assistant",
|
||||
"smarthome",
|
||||
"claude"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "home-assistant"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"domotica",
|
||||
"ai"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -45,7 +60,9 @@
|
|||
"default": "http://homeassistant:8123",
|
||||
"required": true,
|
||||
"description": "URL van je Home Assistant instantie",
|
||||
"config": {"placeholder": "http://192.168.1.x:8123"}
|
||||
"config": {
|
||||
"placeholder": "http://192.168.1.x:8123"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "hass_token",
|
||||
|
|
@ -54,7 +71,9 @@
|
|||
"default": "",
|
||||
"required": true,
|
||||
"description": "Maak een token aan via Home Assistant → Profiel → Lange termijn toegangstokens (onderaan de pagina)",
|
||||
"config": {"placeholder": "eyJ..."}
|
||||
"config": {
|
||||
"placeholder": "eyJ..."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
13
apps/homebridge/files/compose.yaml
Normal file
13
apps/homebridge/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: homebridge/homebridge:latest
|
||||
container_name: << service_name >>
|
||||
# HomeKit gebruikt mDNS voor het vinden van apparaten; dat werkt alleen
|
||||
# betrouwbaar met het netwerk van de host, of met een eigen IP-adres.
|
||||
network_mode: host
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- HOMEBRIDGE_CONFIG_UI_PORT=<< port >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>:/homebridge
|
||||
restart: unless-stopped
|
||||
57
apps/homebridge/template.json
Normal file
57
apps/homebridge/template.json
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Homebridge",
|
||||
"description": "Maakt apparaten die geen HomeKit ondersteunen alsnog zichtbaar in de Woning-app van Apple.",
|
||||
"tags": [
|
||||
"domotica",
|
||||
"homekit",
|
||||
"apple"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "homebridge"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"domotica"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "homebridge",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8581,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
14
apps/homepage/files/compose.yaml
Normal file
14
apps/homepage/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/gethomepage/homepage:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- HOMEPAGE_ALLOWED_HOSTS=<< allowed_hosts >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/app/config
|
||||
# Alleen-lezen socket voor de Docker-widget die containers toont
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
restart: unless-stopped
|
||||
65
apps/homepage/template.json
Normal file
65
apps/homepage/template.json
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Homepage",
|
||||
"description": "Startpagina met tegels voor al je diensten, inclusief live status en systeemgegevens.",
|
||||
"tags": [
|
||||
"dashboard",
|
||||
"startpagina",
|
||||
"overzicht"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "homepage"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"beheer"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "homepage",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 3002,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "allowed_hosts",
|
||||
"type": "str",
|
||||
"title": "Toegestane hostnamen",
|
||||
"default": "localhost:3001",
|
||||
"required": true,
|
||||
"description": "Komma-gescheiden; anders weigert Homepage het verzoek"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "Immich",
|
||||
"description": "Zelfgehoste foto- en videobeheer met automatische back-up. Google Photos alternatief.",
|
||||
"tags": ["fotos", "media", "backup"],
|
||||
"icon": {"provider": "selfhst", "id": "immich"},
|
||||
"version": {"name": "release"}
|
||||
"tags": [
|
||||
"fotos",
|
||||
"media",
|
||||
"backup"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "immich"
|
||||
},
|
||||
"version": {
|
||||
"name": "release"
|
||||
},
|
||||
"categories": [
|
||||
"fotos",
|
||||
"opslag"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -31,7 +44,8 @@
|
|||
"title": "Upload directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor foto-uploads en database"
|
||||
"description": "Basismap voor foto-uploads en database",
|
||||
"help": "Hier komen je originele foto's en video's te staan. Reken op net zoveel ruimte als je telefoon en camera bij elkaar produceren, plus wat marge voor de miniaturen."
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
|
|
@ -52,7 +66,10 @@
|
|||
"default": "immich_db_pass",
|
||||
"required": true,
|
||||
"description": "Wachtwoord voor de interne PostgreSQL database",
|
||||
"config": {"placeholder": "sterk-wachtwoord"}
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
},
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
17
apps/influxdb/files/compose.yaml
Normal file
17
apps/influxdb/files/compose.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: influxdb:2
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8086"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- DOCKER_INFLUXDB_INIT_MODE=setup
|
||||
- DOCKER_INFLUXDB_INIT_USERNAME=<< admin_user >>
|
||||
- DOCKER_INFLUXDB_INIT_PASSWORD=<< admin_password >>
|
||||
- DOCKER_INFLUXDB_INIT_ORG=<< org >>
|
||||
- DOCKER_INFLUXDB_INIT_BUCKET=<< bucket >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/data:/var/lib/influxdb2
|
||||
- << data_dir >>/<< service_name >>/config:/etc/influxdb2
|
||||
restart: unless-stopped
|
||||
92
apps/influxdb/template.json
Normal file
92
apps/influxdb/template.json
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "InfluxDB",
|
||||
"description": "Tijdreeksdatabase voor meetwaarden van sensoren, servers en Home Assistant.",
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"database",
|
||||
"metrics"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "influxdb"
|
||||
},
|
||||
"version": {
|
||||
"name": "2"
|
||||
},
|
||||
"categories": [
|
||||
"monitoring",
|
||||
"ontwikkeling"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "influxdb",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8089,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "org",
|
||||
"type": "str",
|
||||
"title": "Organisatie",
|
||||
"default": "thuis",
|
||||
"required": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "bucket",
|
||||
"type": "str",
|
||||
"title": "Bucket",
|
||||
"default": "metingen",
|
||||
"required": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "admin_user",
|
||||
"type": "str",
|
||||
"title": "Beheerder",
|
||||
"default": "admin",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "admin_password",
|
||||
"type": "str",
|
||||
"title": "Beheerderswachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Minimaal 8 tekens",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "IT-Tools",
|
||||
"description": "Verzameling handige online tools voor developers: encoding, hashing, formattering, converters en meer.",
|
||||
"tags": ["tools", "developer", "utilities", "encoding"],
|
||||
"icon": {"provider": "selfhst", "id": "it-tools"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"tools",
|
||||
"developer",
|
||||
"utilities",
|
||||
"encoding"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "it-tools"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"ontwikkeling"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "Jellyfin",
|
||||
"description": "Gratis en open-source mediaserver voor films, series en muziek. Geen abonnement.",
|
||||
"tags": ["media", "streaming", "films", "muziek"],
|
||||
"icon": {"provider": "selfhst", "id": "jellyfin"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"media",
|
||||
"streaming",
|
||||
"films",
|
||||
"muziek"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "jellyfin"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
|
|||
12
apps/jellyseerr/files/compose.yaml
Normal file
12
apps/jellyseerr/files/compose.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: fallenbagel/jellyseerr:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:5055"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- LOG_LEVEL=info
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/app/config
|
||||
restart: unless-stopped
|
||||
57
apps/jellyseerr/template.json
Normal file
57
apps/jellyseerr/template.json
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Jellyseerr",
|
||||
"description": "Verzoeken voor films en series, gekoppeld aan Jellyfin of Plex en de *arr-stack.",
|
||||
"tags": [
|
||||
"media",
|
||||
"verzoeken",
|
||||
"films"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "jellyseerr"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "jellyseerr",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 5055,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
43
apps/karakeep/files/compose.yaml
Normal file
43
apps/karakeep/files/compose.yaml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/karakeep-app/karakeep:release
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- NEXTAUTH_SECRET=<< secret >>
|
||||
- MEILI_ADDR=http://<< service_name >>-meilisearch:7700
|
||||
- BROWSER_WEB_URL=http://<< service_name >>-chrome:9222
|
||||
- DATA_DIR=/data
|
||||
- OPENAI_API_KEY=<< openai_key >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/data:/data
|
||||
depends_on:
|
||||
- << service_name >>-meilisearch
|
||||
- << service_name >>-chrome
|
||||
restart: unless-stopped
|
||||
|
||||
<< service_name >>-chrome:
|
||||
image: gcr.io/zenika-hub/alpine-chrome:124
|
||||
container_name: << service_name >>-chrome
|
||||
command:
|
||||
- --no-sandbox
|
||||
- --disable-gpu
|
||||
- --disable-dev-shm-usage
|
||||
- --remote-debugging-address=0.0.0.0
|
||||
- --remote-debugging-port=9222
|
||||
- --hide-scrollbars
|
||||
restart: unless-stopped
|
||||
|
||||
<< service_name >>-meilisearch:
|
||||
image: getmeili/meilisearch:v1.41.0
|
||||
container_name: << service_name >>-meilisearch
|
||||
environment:
|
||||
- MEILI_NO_ANALYTICS=true
|
||||
volumes:
|
||||
- << service_name >>_meili:/meili_data
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
<< service_name >>_meili:
|
||||
78
apps/karakeep/template.json
Normal file
78
apps/karakeep/template.json
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Karakeep",
|
||||
"description": "Bewaart bladwijzers, artikelen en notities met volledige tekstzoekfunctie. Voorheen Hoarder.",
|
||||
"tags": [
|
||||
"bladwijzers",
|
||||
"archief",
|
||||
"lezen"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "karakeep"
|
||||
},
|
||||
"version": {
|
||||
"name": "release"
|
||||
},
|
||||
"categories": [
|
||||
"documenten"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "karakeep",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 3012,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "secret",
|
||||
"type": "str",
|
||||
"title": "Geheime sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Willekeurige waarde voor sessies",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
},
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "openai_key",
|
||||
"type": "str",
|
||||
"title": "OpenAI-sleutel (optioneel)",
|
||||
"default": "",
|
||||
"required": false,
|
||||
"description": "Alleen nodig als je automatisch labels wilt laten toekennen",
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
14
apps/kavita/files/compose.yaml
Normal file
14
apps/kavita/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: lscr.io/linuxserver/kavita:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:5000"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PUID=<< puid >>
|
||||
- PGID=<< pgid >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/config
|
||||
- << library_dir >>:/library
|
||||
restart: unless-stopped
|
||||
82
apps/kavita/template.json
Normal file
82
apps/kavita/template.json
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Kavita",
|
||||
"description": "Leesserver voor strips, manga en e-books, met leesvoortgang per gebruiker.",
|
||||
"tags": [
|
||||
"media",
|
||||
"boeken",
|
||||
"strips"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "kavita"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media",
|
||||
"documenten"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "kavita",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 5001,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "library_dir",
|
||||
"type": "str",
|
||||
"title": "Bibliotheekmap",
|
||||
"default": "/opt/serverup/media/books",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
32
apps/keycloak/files/compose.yaml
Normal file
32
apps/keycloak/files/compose.yaml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: quay.io/keycloak/keycloak:latest
|
||||
container_name: << service_name >>
|
||||
command: start-dev
|
||||
ports:
|
||||
- "<< port >>:8080"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- KC_BOOTSTRAP_ADMIN_USERNAME=<< admin_user >>
|
||||
- KC_BOOTSTRAP_ADMIN_PASSWORD=<< admin_password >>
|
||||
- KC_DB=postgres
|
||||
- KC_DB_URL=jdbc:postgresql://<< service_name >>-db:5432/keycloak
|
||||
- KC_DB_USERNAME=keycloak
|
||||
- KC_DB_PASSWORD=<< db_password >>
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=keycloak
|
||||
- POSTGRES_USER=keycloak
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << service_name >>_pgdata:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
<< service_name >>_pgdata:
|
||||
87
apps/keycloak/template.json
Normal file
87
apps/keycloak/template.json
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Keycloak",
|
||||
"description": "Volwaardige identiteitsserver met OIDC en SAML, gebruikersbeheer en federatie.",
|
||||
"tags": [
|
||||
"beveiliging",
|
||||
"sso",
|
||||
"oidc"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "keycloak"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"beveiliging"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "keycloak",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8103,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "admin_user",
|
||||
"type": "str",
|
||||
"title": "Beheerder",
|
||||
"default": "admin",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "admin_password",
|
||||
"type": "str",
|
||||
"title": "Beheerderswachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Gebruik de dobbelsteenknop voor een willekeurige waarde",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Database wachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Gebruik de dobbelsteenknop voor een willekeurige waarde",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
},
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
32
apps/kimai/files/compose.yaml
Normal file
32
apps/kimai/files/compose.yaml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: kimai/kimai2:apache
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8001"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- DATABASE_URL=mysql://kimai:<< db_password >>@<< service_name >>-db/kimai?charset=utf8mb4&serverVersion=8.0.0
|
||||
- ADMINMAIL=<< admin_email >>
|
||||
- ADMINPASS=<< admin_password >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/data:/opt/kimai/var/data
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
|
||||
<< service_name >>-db:
|
||||
image: mysql:8
|
||||
container_name: << service_name >>-db
|
||||
command: --default-storage-engine innodb
|
||||
environment:
|
||||
- MYSQL_DATABASE=kimai
|
||||
- MYSQL_USER=kimai
|
||||
- MYSQL_PASSWORD=<< db_password >>
|
||||
- MYSQL_ROOT_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << service_name >>_dbdata:/var/lib/mysql
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
<< service_name >>_dbdata:
|
||||
88
apps/kimai/template.json
Normal file
88
apps/kimai/template.json
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Kimai",
|
||||
"description": "Urenregistratie voor projecten en klanten, met rapportages en facturen.",
|
||||
"tags": [
|
||||
"productiviteit",
|
||||
"uren",
|
||||
"administratie"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "kimai"
|
||||
},
|
||||
"version": {
|
||||
"name": "apache"
|
||||
},
|
||||
"categories": [
|
||||
"productiviteit",
|
||||
"financien"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "kimai",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8104,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Database wachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Gebruik de dobbelsteenknop voor een willekeurige waarde",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
},
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "admin_email",
|
||||
"type": "str",
|
||||
"title": "Beheerder e-mail",
|
||||
"default": "admin@example.com",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "admin_password",
|
||||
"type": "str",
|
||||
"title": "Beheerderswachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Minimaal 8 tekens",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
13
apps/komga/files/compose.yaml
Normal file
13
apps/komga/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: gotson/komga:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:25600"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
user: "<< puid >>:<< pgid >>"
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/config
|
||||
- << library_dir >>:/data
|
||||
restart: unless-stopped
|
||||
81
apps/komga/template.json
Normal file
81
apps/komga/template.json
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Komga",
|
||||
"description": "Server voor strips en manga met leesvoortgang en een ingebouwde lezer.",
|
||||
"tags": [
|
||||
"media",
|
||||
"strips",
|
||||
"manga"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "komga"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "komga",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 25600,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "library_dir",
|
||||
"type": "str",
|
||||
"title": "Stripboekenmap",
|
||||
"default": "/opt/serverup/media/comics",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
21
apps/kopia/files/compose.yaml
Normal file
21
apps/kopia/files/compose.yaml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: kopia/kopia:latest
|
||||
container_name: << service_name >>
|
||||
command:
|
||||
- server
|
||||
- start
|
||||
- --insecure
|
||||
- --address=0.0.0.0:51515
|
||||
- --server-username=<< ui_user >>
|
||||
- --server-password=<< ui_password >>
|
||||
ports:
|
||||
- "<< port >>:51515"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/app/config
|
||||
- << data_dir >>/<< service_name >>/cache:/app/cache
|
||||
- << source_dir >>:/data:ro
|
||||
- << repo_dir >>:/repository
|
||||
restart: unless-stopped
|
||||
89
apps/kopia/template.json
Normal file
89
apps/kopia/template.json
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Kopia",
|
||||
"description": "Versleutelde back-ups met deduplicatie naar schijf, NAS of cloudopslag.",
|
||||
"tags": [
|
||||
"backup",
|
||||
"opslag",
|
||||
"versleuteling"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "kopia"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"opslag"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "kopia",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 51515,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "source_dir",
|
||||
"type": "str",
|
||||
"title": "Map om te back-uppen",
|
||||
"default": "/opt/serverup",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "repo_dir",
|
||||
"type": "str",
|
||||
"title": "Repository",
|
||||
"default": "/opt/serverup/backups/kopia",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "ui_user",
|
||||
"type": "str",
|
||||
"title": "Gebruikersnaam",
|
||||
"default": "kopia",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "ui_password",
|
||||
"type": "str",
|
||||
"title": "Wachtwoord webinterface",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"description": "Gebruik de dobbelsteenknop voor een willekeurige waarde",
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
14
apps/languagetool/files/compose.yaml
Normal file
14
apps/languagetool/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: erikvl87/languagetool:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8010"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- Java_Xms=512m
|
||||
- Java_Xmx=2g
|
||||
<%- if ngrams %>
|
||||
- langtool_languageModel=/ngrams
|
||||
<%- endif %>
|
||||
restart: unless-stopped
|
||||
59
apps/languagetool/template.json
Normal file
59
apps/languagetool/template.json
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "LanguageTool",
|
||||
"description": "Spelling- en grammaticacontrole voor tientallen talen, zonder je tekst naar een clouddienst te sturen.",
|
||||
"tags": [
|
||||
"taal",
|
||||
"schrijven",
|
||||
"privacy"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "languagetool"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"productiviteit",
|
||||
"documenten"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "languagetool",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8107,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "ngrams",
|
||||
"type": "bool",
|
||||
"title": "N-gram data gebruiken",
|
||||
"default": false,
|
||||
"description": "Betere suggesties, maar vraagt enkele gigabytes aan schijfruimte",
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,21 @@
|
|||
"metadata": {
|
||||
"name": "Linkding",
|
||||
"description": "Eenvoudige zelfgehoste bladwijzerbeheerder met tags, zoekfunctie en browserextensie.",
|
||||
"tags": ["bladwijzers", "links", "productiviteit"],
|
||||
"icon": {"provider": "selfhst", "id": "linkding"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"bladwijzers",
|
||||
"links",
|
||||
"productiviteit"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "linkding"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"documenten"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -50,7 +62,9 @@
|
|||
"title": "Admin wachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"config": {"placeholder": "sterk-wachtwoord"}
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "Mealie",
|
||||
"description": "Receptenbeheer met maaltijdplanning, boodschappenlijsten en automatisch importeren van recepten.",
|
||||
"tags": ["recepten", "koken", "maaltijdplanning", "voedsel"],
|
||||
"icon": {"provider": "selfhst", "id": "mealie"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"recepten",
|
||||
"koken",
|
||||
"maaltijdplanning",
|
||||
"voedsel"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "mealie"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"gezin"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
|
|||
11
apps/memos/files/compose.yaml
Normal file
11
apps/memos/files/compose.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: neosmemo/memos:stable
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:5230"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>:/var/opt/memos
|
||||
restart: unless-stopped
|
||||
58
apps/memos/template.json
Normal file
58
apps/memos/template.json
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Memos",
|
||||
"description": "Snel gedachten en notities vastleggen in een tijdlijn. Als een privé-microblog.",
|
||||
"tags": [
|
||||
"notities",
|
||||
"schrijven",
|
||||
"persoonlijk"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "memos"
|
||||
},
|
||||
"version": {
|
||||
"name": "stable"
|
||||
},
|
||||
"categories": [
|
||||
"documenten",
|
||||
"productiviteit"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "memos",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 5230,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
12
apps/metabase/files/compose.yaml
Normal file
12
apps/metabase/files/compose.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: metabase/metabase:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- MB_DB_FILE=/metabase-data/metabase.db
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>:/metabase-data
|
||||
restart: unless-stopped
|
||||
58
apps/metabase/template.json
Normal file
58
apps/metabase/template.json
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Metabase",
|
||||
"description": "Vragen stellen aan je databases en de antwoorden als grafiek of dashboard tonen.",
|
||||
"tags": [
|
||||
"dashboard",
|
||||
"database",
|
||||
"rapportage"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "metabase"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"monitoring",
|
||||
"ontwikkeling"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "metabase",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 3013,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
13
apps/metube/files/compose.yaml
Normal file
13
apps/metube/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/alexta69/metube:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:8081"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- UID=<< puid >>
|
||||
- GID=<< pgid >>
|
||||
volumes:
|
||||
- << downloads_dir >>:/downloads
|
||||
restart: unless-stopped
|
||||
82
apps/metube/template.json
Normal file
82
apps/metube/template.json
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "MeTube",
|
||||
"description": "Video's van YouTube en honderden andere sites downloaden via een webformulier.",
|
||||
"tags": [
|
||||
"media",
|
||||
"downloaden",
|
||||
"video"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "metube"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media",
|
||||
"downloaden"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "metube",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 8105,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "Bepaalt de eigenaar van de bestanden; `id -u` op je host",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "downloads_dir",
|
||||
"type": "str",
|
||||
"title": "Downloadmap",
|
||||
"default": "/opt/serverup/media/downloads",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "Miniflux",
|
||||
"description": "Minimalistische en snelle RSS-lezer, zelfgehost met een opgeruimde interface.",
|
||||
"tags": ["rss", "nieuws", "lezer", "feeds"],
|
||||
"icon": {"provider": "selfhst", "id": "miniflux"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"rss",
|
||||
"nieuws",
|
||||
"lezer",
|
||||
"feeds"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "miniflux"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"documenten"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -50,7 +63,9 @@
|
|||
"title": "Admin wachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"config": {"placeholder": "sterk-wachtwoord"}
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -63,7 +78,9 @@
|
|||
"title": "Database wachtwoord",
|
||||
"default": "miniflux_db_pass",
|
||||
"required": true,
|
||||
"config": {"placeholder": "sterk-wachtwoord"}
|
||||
"config": {
|
||||
"placeholder": "sterk-wachtwoord"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
14
apps/mosquitto/files/compose.yaml
Normal file
14
apps/mosquitto/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: eclipse-mosquitto:2
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:1883"
|
||||
- "<< websocket_port >>:9001"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << data_dir >>/<< service_name >>/config:/mosquitto/config
|
||||
- << data_dir >>/<< service_name >>/data:/mosquitto/data
|
||||
- << data_dir >>/<< service_name >>/log:/mosquitto/log
|
||||
restart: unless-stopped
|
||||
65
apps/mosquitto/template.json
Normal file
65
apps/mosquitto/template.json
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Mosquitto MQTT",
|
||||
"description": "Lichtgewicht MQTT-broker. De centrale berichtenbus waar Zigbee2MQTT, ESPHome en Home Assistant op praten.",
|
||||
"tags": [
|
||||
"domotica",
|
||||
"mqtt",
|
||||
"infrastructuur"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "eclipse-mosquitto"
|
||||
},
|
||||
"version": {
|
||||
"name": "2"
|
||||
},
|
||||
"categories": [
|
||||
"domotica",
|
||||
"netwerk"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "mosquitto",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "MQTT poort",
|
||||
"default": 1883,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "websocket_port",
|
||||
"type": "int",
|
||||
"title": "WebSocket poort",
|
||||
"default": 9001,
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -3,9 +3,22 @@
|
|||
"metadata": {
|
||||
"name": "n8n",
|
||||
"description": "No-code/low-code workflow automatisering. Zapier-alternatief met 400+ integraties.",
|
||||
"tags": ["automatisering", "workflow", "integratie"],
|
||||
"icon": {"provider": "selfhst", "id": "n8n"},
|
||||
"version": {"name": "latest"}
|
||||
"tags": [
|
||||
"automatisering",
|
||||
"workflow",
|
||||
"integratie"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "n8n"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"productiviteit",
|
||||
"ontwikkeling"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
|
|
@ -51,7 +64,9 @@
|
|||
"default": "localhost",
|
||||
"required": false,
|
||||
"description": "Hostname of IP van je server voor webhook-URLs. Gebruik je domeinnaam als je een reverse proxy hebt.",
|
||||
"config": {"placeholder": "mijn-server.nl"}
|
||||
"config": {
|
||||
"placeholder": "mijn-server.nl"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
14
apps/navidrome/files/compose.yaml
Normal file
14
apps/navidrome/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: deluan/navidrome:latest
|
||||
container_name: << service_name >>
|
||||
ports:
|
||||
- "<< port >>:4533"
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- ND_SCANSCHEDULE=<< scan_schedule >>
|
||||
- ND_LOGLEVEL=info
|
||||
volumes:
|
||||
- << music_dir >>:/music:ro
|
||||
- << data_dir >>/<< service_name >>/data:/data
|
||||
restart: unless-stopped
|
||||
72
apps/navidrome/template.json
Normal file
72
apps/navidrome/template.json
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Navidrome",
|
||||
"description": "Muziekstreaming vanaf je eigen collectie. Werkt met alle Subsonic-apps.",
|
||||
"tags": [
|
||||
"media",
|
||||
"muziek",
|
||||
"streaming"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "navidrome"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "navidrome",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Web poort",
|
||||
"default": 4533,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "data_dir",
|
||||
"type": "str",
|
||||
"title": "Data directory",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "music_dir",
|
||||
"type": "str",
|
||||
"title": "Muziekmap",
|
||||
"default": "/opt/serverup/media/music",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "scan_schedule",
|
||||
"type": "str",
|
||||
"title": "Scaninterval",
|
||||
"default": "@every 1h",
|
||||
"required": true,
|
||||
"description": "Hoe vaak de collectie opnieuw wordt ingelezen"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue