v0.8.10-beta - Vervangers voor big tech, en sleutels in het juiste formaat
All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 2m31s
All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 2m31s
- Sjablonen kunnen nu secret_format ("hex" of "laravel") en secret_bytes
opgeven. De generator maakte altijd url-veilige base64, en dat is precies wat
Laravel, Homarr en LibreChat weigeren
- Daarmee kwamen twee fouten uit v0.8.00 aan het licht: Homarr en LibreChat
kregen sleutels die hun containers niet accepteren. Rechtgezet
- Snipe-IT en Invoice Ninja alsnog toegevoegd; die vielen vorige ronde af omdat
hun APP_KEY niet te genereren was
- 19 vervangers voor big tech erbij, van 197 naar 218 apps:
Baikal en Radicale (Google Agenda/Contacten), LibreTranslate (Translate),
CryptPad, Collabora en ONLYOFFICE (Google Docs), Formbricks (Forms),
Jitsi Meet (Meet/Zoom), PeerTube, Invidious en Tube Archivist (YouTube),
Owncast (Twitch), Mastodon (X), Pixelfed (Instagram), Lemmy (Reddit),
Cal.com (Calendly), Rallly (Doodle), DocuSeal (DocuSign), Penpot (Figma)
- Communicatie van 12 naar 16 apps, productiviteit van 21 naar 31
- Nieuwe JS-test voor de sleutelformaten; alle 242 images in de catalogus
opnieuw tegen hun registry gecontroleerd
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q9eqpADJSRs49SoGGr4NAy
This commit is contained in:
parent
7d178a68b0
commit
c9b73d8b69
55 changed files with 2738 additions and 9 deletions
43
CHANGELOG.md
43
CHANGELOG.md
|
|
@ -1,3 +1,46 @@
|
|||
# v0.8.10-beta — Vervangers voor big tech, en sleutels in het juiste formaat
|
||||
|
||||
**Een sleutel is niet zomaar een willekeurige string.** De generator maakte
|
||||
altijd url-veilige base64, en dat is precies wat Laravel, Homarr en LibreChat
|
||||
níét accepteren. Laravel wil `base64:` ervoor met standaard-base64; Homarr wil 64
|
||||
hexadecimale tekens; LibreChat wil er twee, van 64 en 32. Een waarde in het
|
||||
verkeerde formaat levert een container op die niet start, met een foutmelding die
|
||||
nergens naar de sleutel wijst. Sjablonen kunnen nu `secret_format` (`hex` of
|
||||
`laravel`) en `secret_bytes` opgeven.
|
||||
|
||||
Daarmee vielen twee fouten uit de vorige versie op: **Homarr** en **LibreChat**
|
||||
kregen sleutels die ze hadden geweigerd. Rechtgezet. En **Snipe-IT** en **Invoice
|
||||
Ninja**, die vorige ronde afvielen omdat hun APP_KEY niet te genereren was, staan
|
||||
er nu wel in.
|
||||
|
||||
**Negentien vervangers voor big tech.** De catalogus gaat van 197 naar 218 apps:
|
||||
|
||||
| In plaats van | Nu |
|
||||
|---|---|
|
||||
| Google Agenda en Contacten | Baïkal, Radicale |
|
||||
| Google Translate | LibreTranslate |
|
||||
| Google Docs | CryptPad, Collabora Online, ONLYOFFICE |
|
||||
| Google Forms | Formbricks |
|
||||
| Google Meet en Zoom | Jitsi Meet |
|
||||
| YouTube | PeerTube, Invidious, Tube Archivist |
|
||||
| Twitch | Owncast |
|
||||
| X (Twitter) | Mastodon |
|
||||
| Instagram | Pixelfed |
|
||||
| Reddit | Lemmy |
|
||||
| Calendly | Cal.com |
|
||||
| Doodle | Rallly |
|
||||
| DocuSign | DocuSeal |
|
||||
| Figma | Penpot |
|
||||
|
||||
Communicatie gaat daarmee van 12 naar 16 apps en productiviteit van 21 naar 31 —
|
||||
de twee hoeken waar zelfhosten het meest oplevert en de catalogus het dunst was.
|
||||
|
||||
**Wat er niet in ging.** Bij een paar apps staat een waarschuwing in de
|
||||
omschrijving in plaats van dat ik doe alsof het vanzelf gaat: Mastodon en PeerTube
|
||||
leggen hun domein vast zodra andere servers je kennen, CryptPad heeft echt twee
|
||||
verschillende domeinen nodig om zijn sandbox te laten werken, en LibreTranslate
|
||||
haalt bij de eerste start zijn taalmodellen op.
|
||||
|
||||
# v0.8.00-beta — 55 apps erbij, en drie kapotte images gevonden
|
||||
|
||||
**De catalogus stond scheef.** Na het ARR-werk telde media 42 apps en downloaden
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ IP-adres in je netwerk geven.
|
|||
|
||||
| | |
|
||||
|---|---|
|
||||
| **App-catalogus** | 197 kant-en-klare apps, ingedeeld in categorieën met kleur. Zoeken, filteren en installeren met een formulier in plaats van YAML. |
|
||||
| **App-catalogus** | 218 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. |
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.8.00-beta
|
||||
0.8.10-beta
|
||||
|
|
|
|||
|
|
@ -1086,6 +1086,8 @@
|
|||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"secret_format": "hex",
|
||||
"secret_bytes": 32,
|
||||
"description": "64 tekens; versleutelt de opgeslagen API-sleutels van je apps"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
12
apps/baikal/files/compose.yaml
Normal file
12
apps/baikal/files/compose.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: ckulka/baikal:nginx
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/var/www/baikal/config
|
||||
- << appdata_dir >>/<< service_name >>-specific:/var/www/baikal/Specific
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
restart: unless-stopped
|
||||
61
apps/baikal/template.json
Normal file
61
apps/baikal/template.json
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Baïkal",
|
||||
"description": "Je agenda en contacten op je eigen server, via CalDAV en CardDAV. iPhone, Android en Thunderbird praten er zo mee. Vervangt Google Agenda en Google Contacten.",
|
||||
"tags": [
|
||||
"agenda",
|
||||
"contacten",
|
||||
"caldav",
|
||||
"carddav"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "baikal"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"gezin",
|
||||
"productiviteit"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "baikal",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8180,
|
||||
"required": true,
|
||||
"description": "Standaard 80; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
26
apps/cal-com/files/compose.yaml
Normal file
26
apps/cal-com/files/compose.yaml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: calcom/cal.com:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- DATABASE_URL=postgresql://calcom:<< db_password >>@<< service_name >>-db:5432/calcom
|
||||
- NEXTAUTH_SECRET=<< nextauth_secret >>
|
||||
- CALENDSO_ENCRYPTION_KEY=<< encryption_key >>
|
||||
- NEXT_PUBLIC_WEBAPP_URL=<< app_url >>
|
||||
- NEXTAUTH_URL=<< app_url >>/api/auth
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=calcom
|
||||
- POSTGRES_USER=calcom
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
107
apps/cal-com/template.json
Normal file
107
apps/cal-com/template.json
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Cal.com",
|
||||
"description": "Laat anderen een afspraak in je agenda prikken, zonder heen-en-weer mailen over wanneer het uitkomt. Vervangt Calendly.",
|
||||
"tags": [
|
||||
"agenda",
|
||||
"afspraken",
|
||||
"planning"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "cal-com"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"productiviteit",
|
||||
"zakelijk"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "calcom",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8194,
|
||||
"required": true,
|
||||
"description": "Standaard 3000; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "app_url",
|
||||
"type": "str",
|
||||
"title": "Publiek adres",
|
||||
"default": "http://localhost:8194",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "nextauth_secret",
|
||||
"type": "str",
|
||||
"title": "Sleutel voor de inlogsessies",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
},
|
||||
{
|
||||
"name": "encryption_key",
|
||||
"type": "str",
|
||||
"title": "Sleutel voor gekoppelde agenda's",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"secret_format": "hex",
|
||||
"secret_bytes": 16
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
15
apps/collabora/files/compose.yaml
Normal file
15
apps/collabora/files/compose.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: collabora/code:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- aliasgroup1=<< nextcloud_url >>
|
||||
- extra_params=--o:ssl.enable=false --o:ssl.termination=true
|
||||
- username=<< admin_user >>
|
||||
- password=<< admin_password >>
|
||||
ports:
|
||||
- "<< port >>:9980"
|
||||
cap_add:
|
||||
- MKNOD
|
||||
restart: unless-stopped
|
||||
91
apps/collabora/template.json
Normal file
91
apps/collabora/template.json
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Collabora Online",
|
||||
"description": "Documenten, spreadsheets en presentaties bewerken in je browser, samen met anderen. Koppelt aan Nextcloud. Vervangt Google Docs en Microsoft Office.",
|
||||
"tags": [
|
||||
"documenten",
|
||||
"kantoor",
|
||||
"samenwerken"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "collabora"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"documenten",
|
||||
"productiviteit"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "collabora",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8201,
|
||||
"required": true,
|
||||
"description": "Standaard 9980; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "nextcloud_url",
|
||||
"type": "str",
|
||||
"title": "Adres van Nextcloud",
|
||||
"default": "https://cloud.example.com",
|
||||
"required": true,
|
||||
"connect": {
|
||||
"app": "nextcloud-aio",
|
||||
"scheme": "https",
|
||||
"port": 443
|
||||
},
|
||||
"help": "Collabora accepteert alleen verzoeken van dit adres. Klopt het niet, dan blijft de bewerker leeg."
|
||||
},
|
||||
{
|
||||
"name": "admin_user",
|
||||
"type": "str",
|
||||
"title": "Beheerdersnaam",
|
||||
"default": "admin",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "admin_password",
|
||||
"type": "str",
|
||||
"title": "Beheerderswachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"eigen_invoer": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
15
apps/cryptpad/files/compose.yaml
Normal file
15
apps/cryptpad/files/compose.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: cryptpad/cryptpad:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- CPAD_MAIN_DOMAIN=<< hoofddomein >>
|
||||
- CPAD_SANDBOX_DOMAIN=<< sandbox_domein >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/cryptpad/data
|
||||
- << appdata_dir >>/<< service_name >>-blob:/cryptpad/blob
|
||||
- << appdata_dir >>/<< service_name >>-block:/cryptpad/block
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
restart: unless-stopped
|
||||
82
apps/cryptpad/template.json
Normal file
82
apps/cryptpad/template.json
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "CryptPad",
|
||||
"description": "Documenten, spreadsheets en presentaties die in je browser versleuteld worden. De server ziet alleen onleesbare blokken. Vervangt Google Docs.",
|
||||
"tags": [
|
||||
"documenten",
|
||||
"samenwerken",
|
||||
"privacy",
|
||||
"versleuteling"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "cryptpad"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"documenten",
|
||||
"productiviteit"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "cryptpad",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8190,
|
||||
"required": true,
|
||||
"description": "Standaard 3000; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "hoofddomein",
|
||||
"type": "str",
|
||||
"title": "Hoofddomein",
|
||||
"default": "https://pad.example.com",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "sandbox_domein",
|
||||
"type": "str",
|
||||
"title": "Sandbox-domein",
|
||||
"default": "https://pad-sandbox.example.com",
|
||||
"required": true,
|
||||
"description": "Moet een ánder domein zijn dan het hoofddomein",
|
||||
"help": "CryptPad zet de documentbewerker in een aparte oorsprong, zodat een lek in de bewerker niet bij je sleutels kan. Twee keer hetzelfde domein invullen haalt die scheiding weg."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
26
apps/docuseal/files/compose.yaml
Normal file
26
apps/docuseal/files/compose.yaml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: docuseal/docuseal:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- DATABASE_URL=postgresql://docuseal:<< db_password >>@<< service_name >>-db:5432/docuseal
|
||||
- SECRET_KEY_BASE=<< secret_key_base >>
|
||||
- FORCE_SSL=false
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/data
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=docuseal
|
||||
- POSTGRES_USER=docuseal
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
84
apps/docuseal/template.json
Normal file
84
apps/docuseal/template.json
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "DocuSeal",
|
||||
"description": "Documenten laten ondertekenen met een digitale handtekening, inclusief invulvelden en een controlespoor. Vervangt DocuSign.",
|
||||
"tags": [
|
||||
"documenten",
|
||||
"handtekening",
|
||||
"formulieren"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "docuseal"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"documenten",
|
||||
"zakelijk"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "docuseal",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8196,
|
||||
"required": true,
|
||||
"description": "Standaard 3000; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "secret_key_base",
|
||||
"type": "str",
|
||||
"title": "Rails-sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
26
apps/formbricks/files/compose.yaml
Normal file
26
apps/formbricks/files/compose.yaml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: formbricks/formbricks:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- DATABASE_URL=postgresql://formbricks:<< db_password >>@<< service_name >>-db:5432/formbricks
|
||||
- NEXTAUTH_SECRET=<< nextauth_secret >>
|
||||
- ENCRYPTION_KEY=<< encryption_key >>
|
||||
- WEBAPP_URL=<< app_url >>
|
||||
- NEXTAUTH_URL=<< app_url >>
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=formbricks
|
||||
- POSTGRES_USER=formbricks
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
107
apps/formbricks/template.json
Normal file
107
apps/formbricks/template.json
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Formbricks",
|
||||
"description": "Enquêtes en formulieren maken en de antwoorden zelf houden, met logica per vraag. Vervangt Google Forms.",
|
||||
"tags": [
|
||||
"formulieren",
|
||||
"enquetes",
|
||||
"onderzoek"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "formbricks"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"productiviteit",
|
||||
"zakelijk"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "formbricks",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8197,
|
||||
"required": true,
|
||||
"description": "Standaard 3000; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "app_url",
|
||||
"type": "str",
|
||||
"title": "Publiek adres",
|
||||
"default": "http://localhost:8197",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "nextauth_secret",
|
||||
"type": "str",
|
||||
"title": "Sleutel voor de inlogsessies",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
},
|
||||
{
|
||||
"name": "encryption_key",
|
||||
"type": "str",
|
||||
"title": "Sleutel voor de antwoorden",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"secret_format": "hex",
|
||||
"secret_bytes": 32
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -64,6 +64,8 @@
|
|||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"secret_format": "hex",
|
||||
"secret_bytes": 32,
|
||||
"description": "64 tekens; versleutelt de opgeslagen API-sleutels van je apps"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
23
apps/invidious/files/compose.yaml
Normal file
23
apps/invidious/files/compose.yaml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: quay.io/invidious/invidious:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- ./config.yml:/invidious/config/config.yml:ro
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=invidious
|
||||
- POSTGRES_USER=invidious
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
8
apps/invidious/files/config.yml
Normal file
8
apps/invidious/files/config.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
db:
|
||||
dbname: invidious
|
||||
user: invidious
|
||||
password: << db_password >>
|
||||
host: << service_name >>-db
|
||||
port: 5432
|
||||
check_tables: true
|
||||
hmac_key: << hmac_key >>
|
||||
83
apps/invidious/template.json
Normal file
83
apps/invidious/template.json
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Invidious",
|
||||
"description": "Kijkt YouTube zonder reclame, zonder account en zonder dat Google meekijkt. Abonnementen blijven op je eigen server. Vervangt YouTube.",
|
||||
"tags": [
|
||||
"video",
|
||||
"youtube",
|
||||
"privacy"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "invidious"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "invidious",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8186,
|
||||
"required": true,
|
||||
"description": "Standaard 3000; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "hmac_key",
|
||||
"type": "str",
|
||||
"title": "HMAC-sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
36
apps/invoiceninja/files/compose.yaml
Normal file
36
apps/invoiceninja/files/compose.yaml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: invoiceninja/invoiceninja:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- APP_KEY=<< app_key >>
|
||||
- APP_URL=<< app_url >>
|
||||
- APP_ENV=production
|
||||
- APP_DEBUG=false
|
||||
- DB_HOST=<< service_name >>-db
|
||||
- DB_PORT=3306
|
||||
- DB_DATABASE=ninja
|
||||
- DB_USERNAME=ninja
|
||||
- DB_PASSWORD=<< db_password >>
|
||||
- IN_USER_EMAIL=<< admin_email >>
|
||||
- IN_PASSWORD=<< admin_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/var/www/app/public
|
||||
- << appdata_dir >>/<< service_name >>-storage:/var/www/app/storage
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: mariadb:11
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- MARIADB_DATABASE=ninja
|
||||
- MARIADB_USER=ninja
|
||||
- MARIADB_PASSWORD=<< db_password >>
|
||||
- MARIADB_ROOT_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/mysql
|
||||
restart: unless-stopped
|
||||
115
apps/invoiceninja/template.json
Normal file
115
apps/invoiceninja/template.json
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Invoice Ninja",
|
||||
"description": "Facturen, offertes en urenregistratie voor zzp'ers en kleine bedrijven, met online betalen en herinneringen.",
|
||||
"tags": [
|
||||
"facturen",
|
||||
"boekhouding",
|
||||
"zzp"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "invoiceninja"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"zakelijk",
|
||||
"financien"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "invoiceninja",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8179,
|
||||
"required": true,
|
||||
"description": "Standaard 80; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "app_url",
|
||||
"type": "str",
|
||||
"title": "Publiek adres",
|
||||
"default": "http://localhost:8179",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "admin_email",
|
||||
"type": "str",
|
||||
"title": "E-mailadres beheerder",
|
||||
"default": "admin@example.com",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "app_key",
|
||||
"type": "str",
|
||||
"title": "Applicatiesleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"secret_format": "laravel",
|
||||
"secret_bytes": 32,
|
||||
"description": "Laravel-formaat; wordt automatisch in de juiste vorm gemaakt"
|
||||
},
|
||||
{
|
||||
"name": "admin_password",
|
||||
"type": "str",
|
||||
"title": "Beheerderswachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"eigen_invoer": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
69
apps/jitsi/files/compose.yaml
Normal file
69
apps/jitsi/files/compose.yaml
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: jitsi/web:stable
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- ENABLE_AUTH=0
|
||||
- ENABLE_GUESTS=1
|
||||
- PUBLIC_URL=<< public_url >>
|
||||
- XMPP_SERVER=<< service_name >>-prosody
|
||||
- XMPP_DOMAIN=meet.jitsi
|
||||
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
|
||||
- XMPP_MUC_DOMAIN=muc.meet.jitsi
|
||||
- XMPP_BOSH_URL_BASE=http://<< service_name >>-prosody:5280
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/config
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
depends_on:
|
||||
- << service_name >>-prosody
|
||||
restart: unless-stopped
|
||||
<< service_name >>-prosody:
|
||||
image: jitsi/prosody:stable
|
||||
container_name: << service_name >>-prosody
|
||||
environment:
|
||||
- XMPP_DOMAIN=meet.jitsi
|
||||
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
|
||||
- XMPP_MUC_DOMAIN=muc.meet.jitsi
|
||||
- XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
|
||||
- JICOFO_AUTH_USER=focus
|
||||
- JICOFO_AUTH_PASSWORD=<< jicofo_password >>
|
||||
- JVB_AUTH_USER=jvb
|
||||
- JVB_AUTH_PASSWORD=<< jvb_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-prosody:/config
|
||||
restart: unless-stopped
|
||||
<< service_name >>-jicofo:
|
||||
image: jitsi/jicofo:stable
|
||||
container_name: << service_name >>-jicofo
|
||||
environment:
|
||||
- XMPP_SERVER=<< service_name >>-prosody
|
||||
- XMPP_DOMAIN=meet.jitsi
|
||||
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
|
||||
- XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
|
||||
- JICOFO_AUTH_USER=focus
|
||||
- JICOFO_AUTH_PASSWORD=<< jicofo_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-jicofo:/config
|
||||
depends_on:
|
||||
- << service_name >>-prosody
|
||||
restart: unless-stopped
|
||||
<< service_name >>-jvb:
|
||||
image: jitsi/jvb:stable
|
||||
container_name: << service_name >>-jvb
|
||||
environment:
|
||||
- XMPP_SERVER=<< service_name >>-prosody
|
||||
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
|
||||
- XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
|
||||
- JVB_AUTH_USER=jvb
|
||||
- JVB_AUTH_PASSWORD=<< jvb_password >>
|
||||
- JVB_PORT=<< port_media >>
|
||||
- PUBLIC_URL=<< public_url >>
|
||||
ports:
|
||||
- "<< port_media >>:<< port_media >>/udp"
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-jvb:/config
|
||||
depends_on:
|
||||
- << service_name >>-prosody
|
||||
restart: unless-stopped
|
||||
102
apps/jitsi/template.json
Normal file
102
apps/jitsi/template.json
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Jitsi Meet",
|
||||
"description": "Videovergaderen in de browser, zonder account en zonder installatie. Deel een link en je zit erin. Vervangt Google Meet en Zoom.",
|
||||
"tags": [
|
||||
"video",
|
||||
"vergaderen",
|
||||
"communicatie"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "jitsi"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"communicatie"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "jitsi",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8193,
|
||||
"required": true,
|
||||
"description": "Standaard 80; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "port_media",
|
||||
"type": "int",
|
||||
"title": "Mediapoort (UDP)",
|
||||
"default": 10000,
|
||||
"required": true,
|
||||
"description": "Hier loopt het beeld en geluid; zet deze open in je router"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "public_url",
|
||||
"type": "str",
|
||||
"title": "Publiek adres",
|
||||
"default": "https://meet.example.com",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "jicofo_password",
|
||||
"type": "str",
|
||||
"title": "Wachtwoord voor de conferentiebeheerder",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
},
|
||||
{
|
||||
"name": "jvb_password",
|
||||
"type": "str",
|
||||
"title": "Wachtwoord voor de mediabrug",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
43
apps/lemmy/files/compose.yaml
Normal file
43
apps/lemmy/files/compose.yaml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: dessalines/lemmy:0.19.11
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- RUST_LOG=warn
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/config
|
||||
- ./lemmy.hjson:/config/config.hjson:ro
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
<< service_name >>-ui:
|
||||
image: dessalines/lemmy-ui:0.19.11
|
||||
container_name: << service_name >>-ui
|
||||
environment:
|
||||
- LEMMY_UI_LEMMY_INTERNAL_HOST=<< service_name >>:8536
|
||||
- LEMMY_UI_LEMMY_EXTERNAL_HOST=<< domein >>
|
||||
- LEMMY_UI_HTTPS=true
|
||||
ports:
|
||||
- "<< port_ui >>:1234"
|
||||
depends_on:
|
||||
- << service_name >>
|
||||
restart: unless-stopped
|
||||
<< service_name >>-pictrs:
|
||||
image: asonix/pictrs:0.5
|
||||
container_name: << service_name >>-pictrs
|
||||
environment:
|
||||
- PICTRS__SERVER__API_KEY=<< pictrs_key >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-pictrs:/mnt
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=lemmy
|
||||
- POSTGRES_USER=lemmy
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
16
apps/lemmy/files/lemmy.hjson
Normal file
16
apps/lemmy/files/lemmy.hjson
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
hostname: "<< domein >>"
|
||||
bind: "0.0.0.0"
|
||||
port: 8536
|
||||
database: {
|
||||
host: "<< service_name >>-db"
|
||||
user: "lemmy"
|
||||
password: "<< db_password >>"
|
||||
database: "lemmy"
|
||||
port: 5432
|
||||
}
|
||||
pictrs: {
|
||||
url: "http://<< service_name >>-pictrs:8080/"
|
||||
api_key: "<< pictrs_key >>"
|
||||
}
|
||||
}
|
||||
95
apps/lemmy/template.json
Normal file
95
apps/lemmy/template.json
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Lemmy",
|
||||
"description": "Forum in gemeenschappen, opgebouwd uit servers die elkaar volgen. Berichten stemmen omhoog of omlaag. Vervangt Reddit.",
|
||||
"tags": [
|
||||
"forum",
|
||||
"sociaal",
|
||||
"federatie"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "lemmy"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"communicatie"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "lemmy",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port_ui",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8189,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "domein",
|
||||
"type": "str",
|
||||
"title": "Publiek domein",
|
||||
"default": "forum.example.com",
|
||||
"required": true,
|
||||
"description": "Ligt vast zodra andere servers je kennen"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "pictrs_key",
|
||||
"type": "str",
|
||||
"title": "Sleutel voor de afbeeldingsdienst",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -75,7 +75,9 @@
|
|||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
"generate": "auto",
|
||||
"secret_format": "hex",
|
||||
"secret_bytes": 32
|
||||
},
|
||||
{
|
||||
"name": "creds_iv",
|
||||
|
|
@ -84,7 +86,9 @@
|
|||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
"generate": "auto",
|
||||
"secret_format": "hex",
|
||||
"secret_bytes": 16
|
||||
},
|
||||
{
|
||||
"name": "jwt_secret",
|
||||
|
|
|
|||
13
apps/libretranslate/files/compose.yaml
Normal file
13
apps/libretranslate/files/compose.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: libretranslate/libretranslate:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- LT_LOAD_ONLY=<< talen >>
|
||||
- LT_DISABLE_WEB_UI=false
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/home/libretranslate/.local/share/argos-translate
|
||||
ports:
|
||||
- "<< port >>:5000"
|
||||
restart: unless-stopped
|
||||
73
apps/libretranslate/template.json
Normal file
73
apps/libretranslate/template.json
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "LibreTranslate",
|
||||
"description": "Vertaalt tekst met modellen die op je eigen server draaien. Je zinnen verlaten je netwerk niet. Vervangt Google Translate. Let op: Bij de eerste start worden de taalmodellen gedownload; dat duurt even.",
|
||||
"tags": [
|
||||
"vertalen",
|
||||
"taal",
|
||||
"privacy"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "libretranslate"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"productiviteit",
|
||||
"ai"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "libretranslate",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8183,
|
||||
"required": true,
|
||||
"description": "Standaard 5000; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "talen",
|
||||
"type": "str",
|
||||
"title": "Talen",
|
||||
"default": "en,nl,de,fr",
|
||||
"required": true,
|
||||
"description": "Komma-gescheiden; minder talen betekent een veel kleinere download"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
46
apps/mastodon/files/compose.yaml
Normal file
46
apps/mastodon/files/compose.yaml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: ghcr.io/mastodon/mastodon:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- LOCAL_DOMAIN=<< domein >>
|
||||
- RAILS_ENV=production
|
||||
- DB_HOST=<< service_name >>-db
|
||||
- DB_USER=mastodon
|
||||
- DB_NAME=mastodon
|
||||
- DB_PASS=<< db_password >>
|
||||
- DB_PORT=5432
|
||||
- REDIS_HOST=<< service_name >>-redis
|
||||
- REDIS_PORT=6379
|
||||
- SECRET_KEY_BASE=<< secret_key_base >>
|
||||
- OTP_SECRET=<< otp_secret >>
|
||||
- ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=<< ar_primary_key >>
|
||||
- ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=<< ar_deterministic_key >>
|
||||
- ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=<< ar_salt >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/mastodon/public/system
|
||||
command: bash -c "rails db:migrate && rails s -p 3000"
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
- << service_name >>-redis
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=mastodon
|
||||
- POSTGRES_USER=mastodon
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
<< service_name >>-redis:
|
||||
image: valkey/valkey:8-alpine
|
||||
container_name: << service_name >>-redis
|
||||
command: valkey-server --save 60 1
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-redis:/data
|
||||
restart: unless-stopped
|
||||
132
apps/mastodon/template.json
Normal file
132
apps/mastodon/template.json
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Mastodon",
|
||||
"description": "Sociaal netwerk dat met duizenden andere servers samenwerkt. Jij bepaalt de regels op je eigen server. Vervangt X (Twitter). Let op: Maak na de eerste start een beheerder aan met `docker exec -it <container> bin/tootctl accounts create ... --role Owner`.",
|
||||
"tags": [
|
||||
"sociaal",
|
||||
"federatie",
|
||||
"microblog"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "mastodon"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"communicatie"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "mastodon",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8187,
|
||||
"required": true,
|
||||
"description": "Standaard 3000; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "domein",
|
||||
"type": "str",
|
||||
"title": "Publiek domein",
|
||||
"default": "social.example.com",
|
||||
"required": true,
|
||||
"description": "Zit in het adres van elke gebruiker en ligt daarna vast"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "secret_key_base",
|
||||
"type": "str",
|
||||
"title": "Rails-sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
},
|
||||
{
|
||||
"name": "otp_secret",
|
||||
"type": "str",
|
||||
"title": "Sleutel voor tweefactorcodes",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
},
|
||||
{
|
||||
"name": "ar_primary_key",
|
||||
"type": "str",
|
||||
"title": "Sleutel voor versleutelde velden",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
},
|
||||
{
|
||||
"name": "ar_deterministic_key",
|
||||
"type": "str",
|
||||
"title": "Sleutel voor doorzoekbare velden",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
},
|
||||
{
|
||||
"name": "ar_salt",
|
||||
"type": "str",
|
||||
"title": "Salt voor de sleutelafleiding",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
14
apps/onlyoffice/files/compose.yaml
Normal file
14
apps/onlyoffice/files/compose.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: onlyoffice/documentserver:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- JWT_ENABLED=true
|
||||
- JWT_SECRET=<< jwt_secret >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/var/www/onlyoffice/Data
|
||||
- << appdata_dir >>/<< service_name >>-log:/var/log/onlyoffice
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
restart: unless-stopped
|
||||
75
apps/onlyoffice/template.json
Normal file
75
apps/onlyoffice/template.json
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "ONLYOFFICE",
|
||||
"description": "Kantoorsuite in je browser die goed overweg kan met docx, xlsx en pptx. Koppelt aan Nextcloud en Seafile. Vervangt Google Docs en Microsoft Office.",
|
||||
"tags": [
|
||||
"documenten",
|
||||
"kantoor",
|
||||
"samenwerken"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "onlyoffice"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"documenten",
|
||||
"productiviteit"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "onlyoffice",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8192,
|
||||
"required": true,
|
||||
"description": "Standaard 80; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "jwt_secret",
|
||||
"type": "str",
|
||||
"title": "JWT-sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Dezelfde waarde vul je in bij Nextcloud of Seafile"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
12
apps/owncast/files/compose.yaml
Normal file
12
apps/owncast/files/compose.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: owncast/owncast:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/app/data
|
||||
ports:
|
||||
- "<< port >>:8080"
|
||||
- "<< port_rtmp >>:1935"
|
||||
restart: unless-stopped
|
||||
67
apps/owncast/template.json
Normal file
67
apps/owncast/template.json
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Owncast",
|
||||
"description": "Je eigen livestream met chat, zonder platform ertussen. Zendt uit vanuit OBS via RTMP. Vervangt Twitch.",
|
||||
"tags": [
|
||||
"streaming",
|
||||
"video",
|
||||
"live"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "owncast"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "owncast",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8184,
|
||||
"required": true,
|
||||
"description": "Standaard 8080; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "port_rtmp",
|
||||
"type": "int",
|
||||
"title": "RTMP-poort",
|
||||
"default": 1935,
|
||||
"required": true,
|
||||
"description": "Hier zendt OBS naartoe"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
41
apps/peertube/files/compose.yaml
Normal file
41
apps/peertube/files/compose.yaml
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: chocobozzz/peertube:production-bookworm
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PEERTUBE_WEBSERVER_HOSTNAME=<< hostname >>
|
||||
- PEERTUBE_WEBSERVER_PORT=443
|
||||
- PEERTUBE_WEBSERVER_HTTPS=true
|
||||
- PEERTUBE_DB_HOSTNAME=<< service_name >>-db
|
||||
- PEERTUBE_DB_USERNAME=peertube
|
||||
- PEERTUBE_DB_PASSWORD=<< db_password >>
|
||||
- PEERTUBE_REDIS_HOSTNAME=<< service_name >>-redis
|
||||
- PEERTUBE_SECRET=<< peertube_secret >>
|
||||
- PEERTUBE_ADMIN_EMAIL=<< admin_email >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/data
|
||||
- << appdata_dir >>/<< service_name >>-config:/config
|
||||
ports:
|
||||
- "<< port >>:9000"
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
- << service_name >>-redis
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=peertube
|
||||
- POSTGRES_USER=peertube
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
<< service_name >>-redis:
|
||||
image: valkey/valkey:8-alpine
|
||||
container_name: << service_name >>-redis
|
||||
command: valkey-server --save 60 1
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-redis:/data
|
||||
restart: unless-stopped
|
||||
103
apps/peertube/template.json
Normal file
103
apps/peertube/template.json
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "PeerTube",
|
||||
"description": "Videoplatform dat met andere PeerTube-servers samenwerkt en kijkers de video onderling laat doorgeven. Vervangt YouTube.",
|
||||
"tags": [
|
||||
"video",
|
||||
"streaming",
|
||||
"federatie"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "peertube"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "peertube",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8185,
|
||||
"required": true,
|
||||
"description": "Standaard 9000; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "hostname",
|
||||
"type": "str",
|
||||
"title": "Publiek domein",
|
||||
"default": "video.example.com",
|
||||
"required": true,
|
||||
"description": "Ligt vast zodra je server bekend is bij andere servers"
|
||||
},
|
||||
{
|
||||
"name": "admin_email",
|
||||
"type": "str",
|
||||
"title": "E-mailadres beheerder",
|
||||
"default": "admin@example.com",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "peertube_secret",
|
||||
"type": "str",
|
||||
"title": "Geheime sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
56
apps/penpot/files/compose.yaml
Normal file
56
apps/penpot/files/compose.yaml
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: penpotapp/frontend:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- PENPOT_FLAGS=enable-registration enable-login-with-password
|
||||
- PENPOT_BACKEND_URI=http://<< service_name >>-backend:6060
|
||||
- PENPOT_EXPORTER_URI=http://<< service_name >>-exporter:6061
|
||||
ports:
|
||||
- "<< port >>:8080"
|
||||
depends_on:
|
||||
- << service_name >>-backend
|
||||
restart: unless-stopped
|
||||
<< service_name >>-backend:
|
||||
image: penpotapp/backend:latest
|
||||
container_name: << service_name >>-backend
|
||||
environment:
|
||||
- PENPOT_FLAGS=enable-registration enable-login-with-password
|
||||
- PENPOT_PUBLIC_URI=<< app_url >>
|
||||
- PENPOT_SECRET_KEY=<< secret_key >>
|
||||
- PENPOT_DATABASE_URI=postgresql://<< service_name >>-db/penpot
|
||||
- PENPOT_DATABASE_USERNAME=penpot
|
||||
- PENPOT_DATABASE_PASSWORD=<< db_password >>
|
||||
- PENPOT_REDIS_URI=redis://<< service_name >>-redis/0
|
||||
- PENPOT_ASSETS_STORAGE_BACKEND=assets-fs
|
||||
- PENPOT_STORAGE_ASSETS_FS_DIRECTORY=/opt/data/assets
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-assets:/opt/data
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
- << service_name >>-redis
|
||||
restart: unless-stopped
|
||||
<< service_name >>-exporter:
|
||||
image: penpotapp/exporter:latest
|
||||
container_name: << service_name >>-exporter
|
||||
environment:
|
||||
- PENPOT_PUBLIC_URI=http://<< service_name >>:8080
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=penpot
|
||||
- POSTGRES_USER=penpot
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
<< service_name >>-redis:
|
||||
image: valkey/valkey:8-alpine
|
||||
container_name: << service_name >>-redis
|
||||
command: valkey-server --save 60 1
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-redis:/data
|
||||
restart: unless-stopped
|
||||
96
apps/penpot/template.json
Normal file
96
apps/penpot/template.json
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Penpot",
|
||||
"description": "Ontwerpen en prototypes maken in je browser, met open bestandsformaten in plaats van een gesloten dienst. Vervangt Figma.",
|
||||
"tags": [
|
||||
"ontwerp",
|
||||
"prototypes",
|
||||
"samenwerken"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "penpot"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"productiviteit",
|
||||
"ontwikkeling"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "penpot",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8198,
|
||||
"required": true,
|
||||
"description": "Standaard 8080; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "app_url",
|
||||
"type": "str",
|
||||
"title": "Publiek adres",
|
||||
"default": "http://localhost:8198",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "secret_key",
|
||||
"type": "str",
|
||||
"title": "Geheime sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
35
apps/pixelfed/files/compose.yaml
Normal file
35
apps/pixelfed/files/compose.yaml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: zknt/pixelfed:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- APP_KEY=<< app_key >>
|
||||
- APP_URL=<< app_url >>
|
||||
- APP_DOMAIN=<< domein >>
|
||||
- ADMIN_DOMAIN=<< domein >>
|
||||
- SESSION_DOMAIN=<< domein >>
|
||||
- DB_CONNECTION=mysql
|
||||
- DB_HOST=<< service_name >>-db
|
||||
- DB_PORT=3306
|
||||
- DB_DATABASE=pixelfed
|
||||
- DB_USERNAME=pixelfed
|
||||
- DB_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/var/www/storage
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: mariadb:11
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- MARIADB_DATABASE=pixelfed
|
||||
- MARIADB_USER=pixelfed
|
||||
- MARIADB_PASSWORD=<< db_password >>
|
||||
- MARIADB_ROOT_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/mysql
|
||||
restart: unless-stopped
|
||||
106
apps/pixelfed/template.json
Normal file
106
apps/pixelfed/template.json
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Pixelfed",
|
||||
"description": "Foto's delen op een netwerk dat met Mastodon en de rest van de fediverse praat. Vervangt Instagram.",
|
||||
"tags": [
|
||||
"fotos",
|
||||
"sociaal",
|
||||
"federatie"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "pixelfed"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"fotos",
|
||||
"communicatie"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "pixelfed",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8188,
|
||||
"required": true,
|
||||
"description": "Standaard 80; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "domein",
|
||||
"type": "str",
|
||||
"title": "Publiek domein",
|
||||
"default": "foto.example.com",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "app_url",
|
||||
"type": "str",
|
||||
"title": "Publiek adres",
|
||||
"default": "https://foto.example.com",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "app_key",
|
||||
"type": "str",
|
||||
"title": "Applicatiesleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"secret_format": "laravel",
|
||||
"secret_bytes": 32,
|
||||
"description": "Laravel-formaat; wordt automatisch in de juiste vorm gemaakt"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
12
apps/radicale/files/compose.yaml
Normal file
12
apps/radicale/files/compose.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: tomsquest/docker-radicale:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/config
|
||||
- << appdata_dir >>/<< service_name >>-data:/data
|
||||
ports:
|
||||
- "<< port >>:5232"
|
||||
restart: unless-stopped
|
||||
61
apps/radicale/template.json
Normal file
61
apps/radicale/template.json
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Radicale",
|
||||
"description": "Kleine, rustige CalDAV- en CardDAV-server. Bestanden op schijf, geen database, weinig onderhoud. Vervangt Google Agenda en Google Contacten.",
|
||||
"tags": [
|
||||
"agenda",
|
||||
"contacten",
|
||||
"caldav",
|
||||
"carddav"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "radicale"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"gezin",
|
||||
"productiviteit"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "radicale",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8182,
|
||||
"required": true,
|
||||
"description": "Standaard 5232; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
25
apps/rallly/files/compose.yaml
Normal file
25
apps/rallly/files/compose.yaml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: lukevella/rallly:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- TZ=<< timezone >>
|
||||
- DATABASE_URL=postgresql://rallly:<< db_password >>@<< service_name >>-db:5432/rallly
|
||||
- SECRET_PASSWORD=<< secret_password >>
|
||||
- NEXT_PUBLIC_BASE_URL=<< app_url >>
|
||||
- NOREPLY_EMAIL=<< afzender >>
|
||||
ports:
|
||||
- "<< port >>:3000"
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- POSTGRES_DB=rallly
|
||||
- POSTGRES_USER=rallly
|
||||
- POSTGRES_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
104
apps/rallly/template.json
Normal file
104
apps/rallly/template.json
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Rallly",
|
||||
"description": "Prikt een datum met een groep: iedereen vinkt aan wanneer het kan, jij ziet meteen wat wint. Vervangt Doodle.",
|
||||
"tags": [
|
||||
"planning",
|
||||
"agenda",
|
||||
"groep"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "rallly"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"productiviteit",
|
||||
"gezin"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "rallly",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8195,
|
||||
"required": true,
|
||||
"description": "Standaard 3000; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "app_url",
|
||||
"type": "str",
|
||||
"title": "Publiek adres",
|
||||
"default": "http://localhost:8195",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "afzender",
|
||||
"type": "str",
|
||||
"title": "Afzenderadres",
|
||||
"default": "noreply@example.com",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "secret_password",
|
||||
"type": "str",
|
||||
"title": "Geheime sleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Minimaal 32 tekens"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
35
apps/snipe-it/files/compose.yaml
Normal file
35
apps/snipe-it/files/compose.yaml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: snipe/snipe-it:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- APP_KEY=<< app_key >>
|
||||
- APP_URL=<< app_url >>
|
||||
- APP_TIMEZONE=<< timezone >>
|
||||
- MYSQL_DATABASE=snipeit
|
||||
- MYSQL_USER=snipeit
|
||||
- MYSQL_PASSWORD=<< db_password >>
|
||||
- DB_CONNECTION=mysql
|
||||
- DB_HOST=<< service_name >>-db
|
||||
- DB_PORT=3306
|
||||
- DB_DATABASE=snipeit
|
||||
- DB_USERNAME=snipeit
|
||||
- DB_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/var/lib/snipeit
|
||||
ports:
|
||||
- "<< port >>:80"
|
||||
depends_on:
|
||||
- << service_name >>-db
|
||||
restart: unless-stopped
|
||||
<< service_name >>-db:
|
||||
image: mariadb:11
|
||||
container_name: << service_name >>-db
|
||||
environment:
|
||||
- MARIADB_DATABASE=snipeit
|
||||
- MARIADB_USER=snipeit
|
||||
- MARIADB_PASSWORD=<< db_password >>
|
||||
- MARIADB_ROOT_PASSWORD=<< db_password >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-db:/var/lib/mysql
|
||||
restart: unless-stopped
|
||||
98
apps/snipe-it/template.json
Normal file
98
apps/snipe-it/template.json
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Snipe-IT",
|
||||
"description": "Houdt bij welke apparaten je hebt, wie ze in gebruik heeft en wanneer de garantie afloopt. Met barcodes en een uitleenregistratie.",
|
||||
"tags": [
|
||||
"assetbeheer",
|
||||
"inventaris",
|
||||
"hardware"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "snipe-it"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"zakelijk"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "snipeit",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8178,
|
||||
"required": true,
|
||||
"description": "Standaard 80; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "app_url",
|
||||
"type": "str",
|
||||
"title": "Publiek adres",
|
||||
"default": "http://localhost:8178",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "app_key",
|
||||
"type": "str",
|
||||
"title": "Applicatiesleutel",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"secret_format": "laravel",
|
||||
"secret_bytes": 32,
|
||||
"description": "Laravel-formaat; wordt automatisch in de juiste vorm gemaakt"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
41
apps/tubearchivist/files/compose.yaml
Normal file
41
apps/tubearchivist/files/compose.yaml
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
services:
|
||||
<< service_name >>:
|
||||
image: bbilly1/tubearchivist:latest
|
||||
container_name: << service_name >>
|
||||
environment:
|
||||
- ES_URL=http://<< service_name >>-es:9200
|
||||
- REDIS_CON=redis://<< service_name >>-redis:6379
|
||||
- HOST_UID=<< puid >>
|
||||
- HOST_GID=<< pgid >>
|
||||
- TA_HOST=<< app_url >>
|
||||
- TA_USERNAME=<< admin_user >>
|
||||
- TA_PASSWORD=<< admin_password >>
|
||||
- ELASTIC_PASSWORD=<< db_password >>
|
||||
- TZ=<< timezone >>
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>:/cache
|
||||
- << data_root >>:/data
|
||||
ports:
|
||||
- "<< port >>:8000"
|
||||
depends_on:
|
||||
- << service_name >>-es
|
||||
- << service_name >>-redis
|
||||
restart: unless-stopped
|
||||
<< service_name >>-es:
|
||||
image: bbilly1/tubearchivist-es:latest
|
||||
container_name: << service_name >>-es
|
||||
environment:
|
||||
- ELASTIC_PASSWORD=<< db_password >>
|
||||
- discovery.type=single-node
|
||||
- xpack.security.enabled=true
|
||||
- path.repo=/usr/share/elasticsearch/data/snapshot
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-es:/usr/share/elasticsearch/data
|
||||
restart: unless-stopped
|
||||
<< service_name >>-redis:
|
||||
image: valkey/valkey:8-alpine
|
||||
container_name: << service_name >>-redis
|
||||
command: valkey-server --save 60 1
|
||||
volumes:
|
||||
- << appdata_dir >>/<< service_name >>-redis:/data
|
||||
restart: unless-stopped
|
||||
132
apps/tubearchivist/template.json
Normal file
132
apps/tubearchivist/template.json
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
{
|
||||
"kind": "compose",
|
||||
"metadata": {
|
||||
"name": "Tube Archivist",
|
||||
"description": "Bewaart YouTube-kanalen en afspeellijsten op je eigen schijf, met eigen zoekfunctie en kijkgeschiedenis. Vervangt YouTube-abonnementen.",
|
||||
"tags": [
|
||||
"video",
|
||||
"youtube",
|
||||
"archief"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "selfhst",
|
||||
"id": "tubearchivist"
|
||||
},
|
||||
"version": {
|
||||
"name": "latest"
|
||||
},
|
||||
"categories": [
|
||||
"media",
|
||||
"downloaden"
|
||||
]
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Algemeen",
|
||||
"items": [
|
||||
{
|
||||
"name": "service_name",
|
||||
"type": "str",
|
||||
"title": "Servicenaam",
|
||||
"default": "tubearchivist",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "port",
|
||||
"type": "int",
|
||||
"title": "Webinterface",
|
||||
"default": 8199,
|
||||
"required": true,
|
||||
"description": "Standaard 8000; hier verplaatst omdat die poort al bezet is"
|
||||
},
|
||||
{
|
||||
"name": "appdata_dir",
|
||||
"type": "str",
|
||||
"title": "Appdata-map",
|
||||
"default": "/opt/serverup/appdata",
|
||||
"required": true,
|
||||
"description": "Basismap voor de gegevens van deze app"
|
||||
},
|
||||
{
|
||||
"name": "data_root",
|
||||
"type": "str",
|
||||
"title": "Gedeelde datamap",
|
||||
"default": "/mnt/data",
|
||||
"required": true,
|
||||
"description": "Eén map met je media, gekoppeld als /data",
|
||||
"help": "Media en downloads horen onder één map te staan, die als /data in elke container komt. Alleen dan kan een voltooide download met een hardlink naar je bibliotheek: geen kopie, geen dubbele opslag. Eronder: media/films, media/series, torrents/ en usenet/."
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"type": "str",
|
||||
"title": "Tijdzone",
|
||||
"default": "Europe/Amsterdam",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Gebruiker",
|
||||
"items": [
|
||||
{
|
||||
"name": "puid",
|
||||
"type": "int",
|
||||
"title": "Gebruikers-ID (PUID)",
|
||||
"default": 1000,
|
||||
"required": true,
|
||||
"description": "`id -u` op je server"
|
||||
},
|
||||
{
|
||||
"name": "pgid",
|
||||
"type": "int",
|
||||
"title": "Groeps-ID (PGID)",
|
||||
"default": 1000,
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Instellingen",
|
||||
"items": [
|
||||
{
|
||||
"name": "app_url",
|
||||
"type": "str",
|
||||
"title": "Publiek adres",
|
||||
"default": "http://localhost:8199",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "admin_user",
|
||||
"type": "str",
|
||||
"title": "Beheerdersnaam",
|
||||
"default": "admin",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Toegang",
|
||||
"items": [
|
||||
{
|
||||
"name": "db_password",
|
||||
"type": "str",
|
||||
"title": "Databasewachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"generate": "auto",
|
||||
"description": "Wordt automatisch ingevuld en in .env bewaard"
|
||||
},
|
||||
{
|
||||
"name": "admin_password",
|
||||
"type": "str",
|
||||
"title": "Beheerderswachtwoord",
|
||||
"default": "",
|
||||
"required": true,
|
||||
"secret": true,
|
||||
"eigen_invoer": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -373,6 +373,24 @@ containernamen zonder. Het wachtwoord is een veld met `"secret": true` en
|
|||
belandt in plaats van in het compose-bestand. Vergeet `depends_on` niet, anders
|
||||
start de app vóór zijn database en valt hij om op de eerste verbinding.
|
||||
|
||||
**Sleutels in een bepaald formaat.** `"generate": "auto"` maakt url-veilige
|
||||
base64 van 24 bytes — 32 tekens. Wil de app iets anders, zeg dat er dan bij:
|
||||
|
||||
| `secret_format` | Levert | Voor |
|
||||
|---|---|---|
|
||||
| *(weglaten)* | url-veilige base64, 32 tekens | het meeste |
|
||||
| `hex` | hexadecimaal, `secret_bytes` × 2 tekens | Homarr, LibreChat |
|
||||
| `laravel` | `base64:` + standaard-base64 | Snipe-IT, Invoice Ninja, Pixelfed |
|
||||
|
||||
```json
|
||||
{"name": "app_key", "type": "str", "title": "Applicatiesleutel",
|
||||
"default": "", "required": true, "secret": true, "generate": "auto",
|
||||
"secret_format": "laravel", "secret_bytes": 32}
|
||||
```
|
||||
|
||||
Dit is geen kosmetiek: een sleutel in het verkeerde formaat levert een container
|
||||
op die niet start, met een foutmelding die nergens naar de sleutel wijst.
|
||||
|
||||
**Een geheim dat je nergens vandaan kunt genereren** — het client-secret van een
|
||||
OIDC-toepassing, een wachtwoord dat de gebruiker zelf kiest — markeer je met
|
||||
`"eigen_invoer": true`. Anders klaagt de testsuite terecht dat er een verplicht
|
||||
|
|
|
|||
|
|
@ -152,6 +152,12 @@ def fields(d: Path) -> list[dict]:
|
|||
# willekeurigs. "auto" = ook meteen invullen, True = alleen een
|
||||
# knop (voor wachtwoorden waarmee je zelf inlogt).
|
||||
"generate": item.get("generate") or "",
|
||||
# In welke vorm de gegenereerde waarde moet komen. Laravel wil
|
||||
# `base64:` ervoor, Homarr en LibreChat willen hexadecimaal van
|
||||
# een vaste lengte. Zonder dit kreeg je een geldige willekeurige
|
||||
# string die de app niet accepteert.
|
||||
"secret_format": item.get("secret_format") or "",
|
||||
"secret_bytes": item.get("secret_bytes") or 0,
|
||||
# Een geheim dat de gebruiker ergens anders vandaan haalt: het
|
||||
# client-secret van een OIDC-toepassing, een wachtwoord dat hij
|
||||
# zelf kiest. Daar valt niets voor te genereren, en het is geen
|
||||
|
|
|
|||
|
|
@ -1738,7 +1738,7 @@ tailwind.config = {
|
|||
<span class="mdi" :class="revealed[f.name] ? 'mdi-eye-off-outline' : 'mdi-eye-outline'"></span>
|
||||
</button>
|
||||
<button type="button" class="btn-sm shrink-0" x-show="f.generate" :title="t('generate_value')"
|
||||
@click="install.values[f.name] = randomSecret(); revealed[f.name] = true"><span class="mdi mdi-dice-5-outline"></span></button>
|
||||
@click="install.values[f.name] = veldSecret(f); revealed[f.name] = true"><span class="mdi mdi-dice-5-outline"></span></button>
|
||||
</div>
|
||||
</template>
|
||||
<p x-show="f.port_taken" class="text-[11px] text-wr mt-1"
|
||||
|
|
@ -2838,11 +2838,22 @@ function app() {
|
|||
|
||||
// Cryptografisch willekeurige waarde voor admin-tokens en wachtwoorden.
|
||||
// Lokaal gegenereerd, dus het geheim gaat niet heen en weer over het net.
|
||||
randomSecret(bytes = 24) {
|
||||
// Niet elke sleutel mag er hetzelfde uitzien. Laravel wil `base64:` met
|
||||
// standaard-base64 ervoor, Homarr en LibreChat willen hexadecimaal van een
|
||||
// vaste lengte. Een waarde in het verkeerde formaat levert een container op
|
||||
// die niet start — met een foutmelding die nergens naar een sleutel wijst.
|
||||
randomSecret(bytes = 24, formaat = 'base64url') {
|
||||
const buf = new Uint8Array(bytes);
|
||||
crypto.getRandomValues(buf);
|
||||
return btoa(String.fromCharCode(...buf))
|
||||
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
||||
if (formaat === 'hex')
|
||||
return Array.from(buf, b => b.toString(16).padStart(2, '0')).join('');
|
||||
const b64 = btoa(String.fromCharCode(...buf));
|
||||
if (formaat === 'laravel') return 'base64:' + b64;
|
||||
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
||||
},
|
||||
// De sleutel zoals dít veld hem wil hebben.
|
||||
veldSecret(f) {
|
||||
return this.randomSecret(f.secret_bytes || 24, f.secret_format || 'base64url');
|
||||
},
|
||||
|
||||
// ── Containers op deze host ──────────────────────────────────────────────
|
||||
|
|
@ -2975,7 +2986,7 @@ function app() {
|
|||
for (const f of (d.fields || [])) {
|
||||
// 'auto': waarden die je nooit hoeft te kennen. Een inlogwachtwoord
|
||||
// krijgt alleen een knop, want dat moet je zelf noteren.
|
||||
if (f.generate === 'auto' && !init[f.name]) init[f.name] = this.randomSecret();
|
||||
if (f.generate === 'auto' && !init[f.name]) init[f.name] = this.veldSecret(f);
|
||||
}
|
||||
this.install.values = init;
|
||||
this.install.preview_files = d.preview_files || {};
|
||||
|
|
|
|||
|
|
@ -92,6 +92,27 @@ check('één groep: geen kop', c.stepGroups('basis')[0].showHeader === false);
|
|||
c.install.fields.push(veld('c','basis',{group:'Tweede'}));
|
||||
check('twee groepen: wel koppen', c.stepGroups('basis').every(g => g.showHeader));
|
||||
|
||||
// ── Sleutelformaten ─────────────────────────────────────────────────────────
|
||||
// Een willekeurige string is niet genoeg: Laravel wil `base64:` ervoor, Homarr
|
||||
// en LibreChat willen hexadecimaal van een vaste lengte. In het verkeerde
|
||||
// formaat start de container niet, met een foutmelding die nergens naar de
|
||||
// sleutel wijst.
|
||||
const standaard = c.veldSecret({});
|
||||
check('standaard is url-veilig', /^[A-Za-z0-9_-]+$/.test(standaard));
|
||||
check('standaard is 32 tekens', standaard.length === 32);
|
||||
|
||||
const hex = c.veldSecret({secret_format: 'hex', secret_bytes: 32});
|
||||
check('hex is 64 tekens', hex.length === 64);
|
||||
check('hex bevat alleen hexcijfers', /^[0-9a-f]{64}$/.test(hex));
|
||||
check('hex van 16 bytes is 32 tekens',
|
||||
c.veldSecret({secret_format: 'hex', secret_bytes: 16}).length === 32);
|
||||
|
||||
const lar = c.veldSecret({secret_format: 'laravel', secret_bytes: 32});
|
||||
check('laravel begint met base64:', lar.startsWith('base64:'));
|
||||
check('laravel is standaard-base64 van 32 bytes',
|
||||
Buffer.from(lar.slice(7), 'base64').length === 32);
|
||||
check('twee sleutels zijn niet gelijk', c.veldSecret({}) !== c.veldSecret({}));
|
||||
|
||||
// ── Stap Onderdelen ─────────────────────────────────────────────────────────
|
||||
// Een stack als de ARR-stack heeft vijftig schakelbare onderdelen. Die horen in
|
||||
// één eigen stap, gegroepeerd per kopje — en nergens anders nóg een keer.
|
||||
|
|
|
|||
|
|
@ -535,6 +535,9 @@ def _speciaal(app):
|
|||
{"name": "homarr_encryption_key", "type": "str",
|
||||
"title": "Versleutelingssleutel", "default": "", "required": True,
|
||||
"secret": True, "generate": "auto",
|
||||
# Homarr accepteert alleen 64 hexadecimale tekens; een gewone
|
||||
# willekeurige string weigert hij bij het opstarten.
|
||||
"secret_format": "hex", "secret_bytes": 32,
|
||||
"description": "64 tekens; versleutelt de opgeslagen API-sleutels van je apps"},
|
||||
]}]
|
||||
app["env_speciaal"] = ["SECRET_ENCRYPTION_KEY=<< homarr_encryption_key >>"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue