Installatiescript met opslagkeuze, standaard /srv/server-up (v0.2.04 beta)
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled

Nieuw: scripts/install.sh — installeert de stack in zeven zichtbare stappen
met drie vragen, standaard in /srv/server-up (aan te passen met
ROOSTERWIJS_DIR). Het script:
- controleert git, docker, de compose-plugin en of de daemon bereikbaar is;
- maakt de doelmap aan, of legt uit welk commando daarvoor nodig is als de
  rechten ontbreken (roept zelf geen sudo aan);
- kloont of werkt de checkout bij;
- laat kiezen waar de gegevens komen (zie hieronder);
- genereert .env met een willekeurige DJANGO_SECRET_KEY en een sterk
  databasewachtwoord, en zet hostnaam, CSRF-origin en DJANGO_SECURE op basis
  van twee vragen; een bestaande .env wordt nooit zomaar overschreven;
- bouwt en start de containers;
- meldt of er een account is en biedt aan er een aan te maken.

Opslagkeuze bij de installatie:
- docker-compose.yml gebruikt nu ${DATA_DB}, ${DATA_MEDIA} en ${DATA_STATIC}.
  Een naam = Docker-volume, een pad = gewone map naast de code.
- De standaardwaarden zijn de bestaande named volumes, dus installaties die
  al draaien veranderen niet en er gaan geen gegevens verloren.
- Kies je voor mappen, dan komt alles onder /srv/server-up/data/.

Verder:
- .gitignore: /data/ uitgesloten. Zonder dat zou de gegevensmap als lokale
  wijziging gelden en zou deploy.sh weigeren te draaien.
- deploy.sh maakt de gegevensmappen aan als de opslagkeuze paden gebruikt,
  zodat Docker ze niet als root aanmaakt.
- DEPLOY.md en README: installatie via het script, de opslagkeuze in een
  tabel, en de dump/restore-stappen die nodig zijn bij het omzetten van
  volumes naar mappen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FAQ4Np13v8fwbTtKHKnwDz
This commit is contained in:
Ramon 2026-08-19 15:17:08 +02:00
parent 500cf6c558
commit f795e85333
10 changed files with 374 additions and 34 deletions

View file

@ -27,6 +27,16 @@ DJANGO_CSRF_TRUSTED_ORIGINS=https://rooster.example.nl
# in dit project geeft die header door. # in dit project geeft die header door.
DJANGO_SECURE=1 DJANGO_SECURE=1
# --- Opslag ---------------------------------------------------------------
# Waar de gegevens staan. Een NAAM = Docker beheert het volume; een PAD =
# gewone map naast de code (direct benaderbaar, makkelijk te back-uppen).
# scripts/install.sh vult dit in op basis van je keuze.
# Docker-volumes: DATA_DB=pgdata DATA_MEDIA=media_volume DATA_STATIC=static_volume
# Gewone mappen: DATA_DB=./data/postgres DATA_MEDIA=./data/media DATA_STATIC=./data/static
DATA_DB=pgdata
DATA_MEDIA=media_volume
DATA_STATIC=static_volume
# --- PostgreSQL ----------------------------------------------------------- # --- PostgreSQL -----------------------------------------------------------
POSTGRES_DB=rooster POSTGRES_DB=rooster
POSTGRES_USER=rooster POSTGRES_USER=rooster

6
.gitignore vendored
View file

@ -68,3 +68,9 @@ logs/
.DS_Store .DS_Store
Thumbs.db Thumbs.db
desktop.ini desktop.ini
# Gegevens bij de 'gewone mappen'-opslagkeuze (database, media, statics).
# Deze map hoort nooit in git en moet buiten 'git status' blijven, anders
# weigert scripts/deploy.sh te draaien wegens 'lokale wijzigingen'.
/data/
.env.backup-*

View file

@ -78,30 +78,67 @@ Je hoeft op de server **niets** te installeren behalve Docker zelf (met de
## Eenmalig: server klaarzetten ## Eenmalig: server klaarzetten
1. Zorg dat Docker + Compose op de test-server staan: Het installatiescript doet alles hieronder in zeven stappen en stelt drie
```bash vragen. Standaard komt alles in **`/srv/server-up`**.
docker --version
docker compose version
```
2. Haal de code op:
```bash
git clone <jouw-forgejo-url>/roosterwijs.git
cd roosterwijs
```
3. Maak het `.env`-bestand aan vanuit het voorbeeld en vul echte waarden in:
```bash
cp .env.example .env
nano .env
```
Belangrijk om aan te passen:
- `DJANGO_SECRET_KEY` — genereer met
`python3 -c "import secrets; print(secrets.token_urlsafe(50))"`
- `DJANGO_ALLOWED_HOSTS` — de hostnaam/IP van de test-server
- `DJANGO_CSRF_TRUSTED_ORIGINS` — exact de origin die de browser gebruikt,
dus `https://<host>` achter TLS (of `http://<host>:8080` zonder TLS)
- `POSTGRES_PASSWORD` — een sterk wachtwoord
`.env` staat in `.gitignore` en komt dus **niet** in git — dat hoort zo. ```bash
git clone <jouw-forgejo-url>/roosterwijs.git /tmp/roosterwijs-install
/tmp/roosterwijs-install/scripts/install.sh
```
Heb je nog geen schrijfrechten op `/srv`, dan zegt het script welk commando je
eenmalig als beheerder moet draaien. Een andere map kan met:
```bash
ROOSTERWIJS_DIR=/pad/naar/map ./scripts/install.sh
```
Het script controleert Docker, haalt de code op, vraagt waar de gegevens moeten
staan, genereert `.env` met een willekeurige `DJANGO_SECRET_KEY` en een sterk
databasewachtwoord, bouwt de containers en biedt aan een beheerder aan te maken.
### De opslagkeuze
Bij stap 4 kies je waar database, media en statics terechtkomen:
| Keuze | Waar | Wanneer |
|-------|------|---------|
| **1. Docker-volumes** | door Docker beheerd (`docker volume ls`) | standaard; afgeschermd, maar alleen bereikbaar via docker-commando's |
| **2. Gewone mappen** | `/srv/server-up/data/` | alles zichtbaar naast de code, makkelijk te back-uppen en in te zien |
De keuze staat als `DATA_DB`, `DATA_MEDIA` en `DATA_STATIC` in `.env` en is
later te wijzigen. **Let op:** omzetten verplaatst geen gegevens. Wissel je van
volumes naar mappen, maak dan eerst een dump en zet die daarna terug:
```bash
docker compose exec db pg_dump -U rooster rooster > ~/rooster.sql # vóór het omzetten
# ... DATA_* aanpassen in .env, dan:
docker compose down && docker compose up -d db
cat ~/rooster.sql | docker compose exec -T db psql -U rooster rooster
docker compose up -d
```
Zonder die stap start de app met een **lege** database — de oude gegevens staan
dan nog wel in het oude volume, maar worden niet meer gebruikt.
### Handmatig, zonder script
```bash
git clone <jouw-forgejo-url>/roosterwijs.git /srv/server-up
cd /srv/server-up
cp .env.example .env
nano .env
```
Belangrijk om aan te passen:
- `DJANGO_SECRET_KEY` — genereer met `openssl rand -base64 48`
- `DJANGO_ALLOWED_HOSTS` — de hostnaam/IP van de server
- `DJANGO_CSRF_TRUSTED_ORIGINS` — exact de origin die de browser gebruikt,
dus `https://<host>` achter TLS (of `http://<host>:8080` zonder TLS)
- `POSTGRES_PASSWORD` — een sterk wachtwoord
- `DATA_DB` / `DATA_MEDIA` / `DATA_STATIC` — zie de tabel hierboven
`.env` staat in `.gitignore` en komt dus **niet** in git — dat hoort zo.
## Starten ## Starten

View file

@ -79,6 +79,23 @@ geboortedatum vast.
Een nieuwe module toevoegen = nieuwe app maken, één regel in Een nieuwe module toevoegen = nieuwe app maken, één regel in
`MODULE_APPS` (in `backend/config/settings.py`), klaar. `MODULE_APPS` (in `backend/config/settings.py`), klaar.
## Installeren op een server
Eén commando, zeven stappen, drie vragen. Alles komt standaard in
`/srv/server-up`:
```bash
git clone <jouw-forgejo-url>/roosterwijs.git /tmp/roosterwijs-install
/tmp/roosterwijs-install/scripts/install.sh
```
Het script controleert Docker, haalt de code op, laat je kiezen of de gegevens
in **Docker-volumes** of in **gewone mappen** (`/srv/server-up/data/`) komen,
genereert `.env` met willekeurige geheimen, bouwt de containers en maakt een
beheerder aan. Bijwerken doe je daarna met `./scripts/deploy.sh`.
Details, de opslagkeuze en het draaien achter TLS staan in `DEPLOY.md`.
## Starten (lokaal ontwikkelen) ## Starten (lokaal ontwikkelen)
> Voor een test- of productieserver gelden **andere** stappen: zie `DEPLOY.md`. > Voor een test- of productieserver gelden **andere** stappen: zie `DEPLOY.md`.

View file

@ -1,4 +1,12 @@
# Stack voor de test-server (en later productie): # Stack voor de test-server (en later productie).
#
# Waar de gegevens staan, bepaal je in .env (scripts/install.sh vraagt ernaar):
# DATA_DB / DATA_MEDIA / DATA_STATIC
# - een naam (bv. pgdata) -> Docker beheert het volume
# - een pad (bv. ./data/postgres) -> gewone map, direct benaderbaar
# Laat je ze leeg, dan gelden de named volumes hieronder — precies zoals
# bestaande installaties nu al draaien.
#
# db - PostgreSQL # db - PostgreSQL
# backend - Django via gunicorn # backend - Django via gunicorn
# nginx - serveert de frontend en proxyt /api + /admin naar de backend # nginx - serveert de frontend en proxyt /api + /admin naar de backend
@ -13,7 +21,7 @@ services:
POSTGRES_USER: ${POSTGRES_USER} POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes: volumes:
- pgdata:/var/lib/postgresql/data - ${DATA_DB:-pgdata}:/var/lib/postgresql/data
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s interval: 5s
@ -47,9 +55,9 @@ services:
FRONTEND_BASE_URL: ${FRONTEND_BASE_URL:-} FRONTEND_BASE_URL: ${FRONTEND_BASE_URL:-}
volumes: volumes:
# Verzamelde statics delen met nginx. # Verzamelde statics delen met nginx.
- static_volume:/app/staticfiles - ${DATA_STATIC:-static_volume}:/app/staticfiles
# Geüploade media (pictogrammen) delen met nginx. # Geüploade media (pictogrammen, logo) delen met nginx.
- media_volume:/app/media - ${DATA_MEDIA:-media_volume}:/app/media
nginx: nginx:
build: ./frontend build: ./frontend
@ -61,8 +69,8 @@ services:
- "8080:80" - "8080:80"
volumes: volumes:
# Lees de door Django verzamelde statics (alleen-lezen). # Lees de door Django verzamelde statics (alleen-lezen).
- static_volume:/static:ro - ${DATA_STATIC:-static_volume}:/static:ro
- media_volume:/media:ro - ${DATA_MEDIA:-media_volume}:/media:ro
volumes: volumes:
pgdata: pgdata:

View file

@ -1,12 +1,12 @@
{ {
"name": "roosterwijs-frontend", "name": "roosterwijs-frontend",
"version": "0.2.3-beta", "version": "0.2.4-beta",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "roosterwijs-frontend", "name": "roosterwijs-frontend",
"version": "0.2.3-beta", "version": "0.2.4-beta",
"dependencies": { "dependencies": {
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1" "react-dom": "^18.3.1"

View file

@ -1,7 +1,7 @@
{ {
"name": "roosterwijs-frontend", "name": "roosterwijs-frontend",
"private": true, "private": true,
"version": "0.2.3-beta", "version": "0.2.4-beta",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View file

@ -35,7 +35,7 @@ button,a,input,select{transition:border-color .15s,background-color .15s,color .
.cog-btn{width:100%;min-height:38px;justify-content:flex-start;font-size:15px;padding:0} .cog-btn{width:100%;min-height:38px;justify-content:flex-start;font-size:15px;padding:0}
.cog-btn::after{content:"Beheer en instellingen";margin-left:8px;font-size:13px} .cog-btn::after{content:"Beheer en instellingen";margin-left:8px;font-size:13px}
.cog-dropdown{position:static;min-width:0;margin:4px 0 0;box-shadow:none} .cog-dropdown{position:static;min-width:0;margin:4px 0 0;box-shadow:none}
.topbar::after{content:"v0.2.03 beta";order:4;margin:10px 8px 0;color:#98a2b3;font-size:10px} .topbar::after{content:"v0.2.04 beta";order:4;margin:10px 8px 0;color:#98a2b3;font-size:10px}
.content{margin-left:var(--sidebar);width:calc(100% - var(--sidebar));max-width:1680px;padding:32px 38px 48px} .content{margin-left:var(--sidebar);width:calc(100% - var(--sidebar));max-width:1680px;padding:32px 38px 48px}
.content-wide{padding:24px 28px 42px} .content-wide{padding:24px 28px 42px}
h1{font-size:clamp(24px,2.4vw,30px);line-height:1.2;letter-spacing:-.025em;font-weight:750} h1{font-size:clamp(24px,2.4vw,30px);line-height:1.2;letter-spacing:-.025em;font-weight:750}

View file

@ -66,6 +66,16 @@ else
fi fi
# --- Bouwen en starten ---------------------------------------------------- # --- Bouwen en starten ----------------------------------------------------
# Bij de 'gewone mappen'-opslagkeuze moeten die mappen bestaan; Docker zou ze
# anders als root aanmaken.
# shellcheck disable=SC1091
set -a; . ./.env; set +a
for pad in "${DATA_DB:-}" "${DATA_MEDIA:-}" "${DATA_STATIC:-}"; do
case "$pad" in
./*|/*) mkdir -p "$pad" ;;
esac
done
docker compose up -d --build docker compose up -d --build
# --- Controleren ---------------------------------------------------------- # --- Controleren ----------------------------------------------------------

252
scripts/install.sh Executable file
View file

@ -0,0 +1,252 @@
#!/usr/bin/env bash
#
# Roosterwijs installeren op een server.
#
# Gebruik: ./scripts/install.sh
# ROOSTERWIJS_DIR=/pad/naar/map ./scripts/install.sh
#
# Het script doorloopt zeven stappen, stelt onderweg drie vragen en raakt
# nooit iets aan zonder dat te melden. Afbreken kan altijd met Ctrl-C.
set -euo pipefail
DOELMAP="${ROOSTERWIJS_DIR:-/srv/server-up}"
# ---------------------------------------------------------------- vormgeving
# Kleuren alleen als we naar een terminal schrijven (en NO_COLOR niet gezet is),
# zodat de uitvoer in een logbestand leesbaar blijft.
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
VET=$'\033[1m'; DOF=$'\033[2m'; STOP=$'\033[0m'
GROEN=$'\033[32m'; GEEL=$'\033[33m'; ROOD=$'\033[31m'; BLAUW=$'\033[36m'
else
VET=''; DOF=''; STOP=''; GROEN=''; GEEL=''; ROOD=''; BLAUW=''
fi
LIJN=$(printf '─%.0s' $(seq 1 62))
STAP_NR=0
STAP_TOTAAL=7
kop() {
printf '\n%s%s%s\n' "$BLAUW" "$LIJN" "$STOP"
printf ' %sROOSTERWIJS%s %s· installatie%s\n' "$VET" "$STOP" "$DOF" "$STOP"
printf '%s%s%s\n' "$BLAUW" "$LIJN" "$STOP"
}
stap() { STAP_NR=$((STAP_NR + 1)); printf '\n %s[%d/%d]%s %s%s%s\n' "$BLAUW" "$STAP_NR" "$STAP_TOTAAL" "$STOP" "$VET" "$1" "$STOP"; }
ok() { printf ' %s✓%s %s\n' "$GROEN" "$STOP" "$1"; }
info() { printf ' %s·%s %s\n' "$DOF" "$STOP" "$1"; }
let_op(){ printf ' %s!%s %s\n' "$GEEL" "$STOP" "$1"; }
fout() { printf '\n %s✗ %s%s\n\n' "$ROOD" "$1" "$STOP" >&2; exit 1; }
# vraag "Tekst" "standaardwaarde" -> antwoord in $ANTWOORD
vraag() {
local tekst="$1" standaard="${2:-}" invoer
if [ -n "$standaard" ]; then
printf ' %s%s%s %s[%s]%s: ' "$VET" "$tekst" "$STOP" "$DOF" "$standaard" "$STOP"
else
printf ' %s%s%s: ' "$VET" "$tekst" "$STOP"
fi
read -r invoer </dev/tty 2>/dev/null || invoer=""
ANTWOORD="${invoer:-$standaard}"
}
# jaNee "Vraag" "j|n" -> 0 = ja, 1 = nee
jaNee() {
local tekst="$1" standaard="${2:-j}" invoer
local hint="j/N"; [ "$standaard" = "j" ] && hint="J/n"
printf ' %s%s%s %s(%s)%s: ' "$VET" "$tekst" "$STOP" "$DOF" "$hint" "$STOP"
read -r invoer </dev/tty 2>/dev/null || invoer=""
invoer="${invoer:-$standaard}"
case "$invoer" in [jJyY]*) return 0 ;; *) return 1 ;; esac
}
# Wachtwoord/sleutel genereren zonder Python op de server te vereisen.
genereer_geheim() {
if command -v openssl >/dev/null 2>&1; then
openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | cut -c1-50
else
LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 50
fi
}
kop
# ------------------------------------------------------------- 1. vereisten
stap "Vereisten controleren"
command -v git >/dev/null 2>&1 || fout "git ontbreekt. Installeer git en probeer opnieuw."
ok "git $(git --version | awk '{print $3}')"
command -v docker >/dev/null 2>&1 || fout "docker ontbreekt. Zie https://docs.docker.com/engine/install/"
ok "docker $(docker --version | awk '{print $3}' | tr -d ,)"
docker compose version >/dev/null 2>&1 || fout "'docker compose' werkt niet. Installeer de compose-plugin."
ok "docker compose $(docker compose version --short 2>/dev/null || echo aanwezig)"
docker info >/dev/null 2>&1 || fout "Kan niet met de Docker-daemon praten. Draait Docker, en zit je in de groep 'docker'?"
ok "Docker-daemon bereikbaar"
# --------------------------------------------------------------- 2. doelmap
stap "Doelmap $DOELMAP"
if [ ! -d "$DOELMAP" ]; then
if mkdir -p "$DOELMAP" 2>/dev/null; then
ok "aangemaakt"
else
printf '\n'
let_op "Geen rechten om $DOELMAP aan te maken."
info "Draai eenmalig, als beheerder:"
printf '\n %ssudo mkdir -p %s && sudo chown "$USER":"$USER" %s%s\n\n' "$VET" "$DOELMAP" "$DOELMAP" "$STOP"
fout "Start daarna dit script opnieuw."
fi
else
[ -w "$DOELMAP" ] || fout "$DOELMAP bestaat, maar je hebt er geen schrijfrechten."
ok "bestaat en is beschrijfbaar"
fi
# ------------------------------------------------------------------ 3. code
stap "Code ophalen"
if [ -d "$DOELMAP/.git" ]; then
ok "checkout gevonden"
if jaNee "Bijwerken naar de laatste versie?" j; then
git -C "$DOELMAP" fetch origin --quiet
tak="$(git -C "$DOELMAP" rev-parse --abbrev-ref HEAD)"
git -C "$DOELMAP" reset --hard "origin/$tak" --quiet
ok "bijgewerkt naar $(git -C "$DOELMAP" rev-parse --short HEAD) op $tak"
else
info "overgeslagen; huidige versie blijft staan"
fi
elif [ -n "$(ls -A "$DOELMAP" 2>/dev/null)" ]; then
fout "$DOELMAP is niet leeg en bevat geen git-checkout. Maak de map leeg of kies een andere met ROOSTERWIJS_DIR=..."
else
herkomst=""
if git -C "$(dirname "$0")/.." rev-parse --git-dir >/dev/null 2>&1; then
herkomst="$(git -C "$(dirname "$0")/.." remote get-url origin 2>/dev/null || true)"
fi
vraag "Git-URL van de repository" "$herkomst"
[ -n "$ANTWOORD" ] || fout "Zonder URL kan de code niet worden opgehaald."
git clone "$ANTWOORD" "$DOELMAP" --quiet || fout "Klonen mislukt. Klopt de URL en heb je toegang (SSH-sleutel)?"
ok "gekloond naar $DOELMAP"
fi
cd "$DOELMAP"
# --------------------------------------------------------------- 4. opslag
stap "Waar komen de gegevens te staan?"
printf '\n'
printf ' %s1)%s %sDocker-volumes%s %s(standaard)%s\n' "$VET" "$STOP" "$VET" "$STOP" "$DOF" "$STOP"
printf ' Docker beheert de opslag. Netjes afgeschermd, maar je\n'
printf ' komt er alleen bij via docker-commandos.\n\n'
printf ' %s2)%s %sGewone mappen%s onder %s/data\n' "$VET" "$STOP" "$VET" "$STOP" "$DOELMAP"
printf ' Database, media en statics staan als zichtbare mappen\n'
printf ' naast de code. Makkelijk back-uppen en inzien.\n\n'
vraag "Keuze (1 of 2)" "1"
case "$ANTWOORD" in
2)
OPSLAG="mappen"
DATA_DB="./data/postgres"; DATA_MEDIA="./data/media"; DATA_STATIC="./data/static"
mkdir -p data/postgres data/media data/static
ok "mappen aangemaakt onder $DOELMAP/data"
;;
*)
OPSLAG="volumes"
DATA_DB="pgdata"; DATA_MEDIA="media_volume"; DATA_STATIC="static_volume"
ok "Docker beheert de opslag (volumes pgdata, media_volume, static_volume)"
;;
esac
# ------------------------------------------------------------------ 5. .env
stap "Instellingen (.env)"
if [ -f .env ]; then
ok ".env bestaat al"
if jaNee "Laten staan en ongewijzigd gebruiken?" j; then
info "bestaande instellingen blijven gelden"
if ! grep -q '^DATA_DB=' .env; then
{ echo ""; echo "# Opslagkeuze (toegevoegd door install.sh)"
echo "DATA_DB=$DATA_DB"; echo "DATA_MEDIA=$DATA_MEDIA"; echo "DATA_STATIC=$DATA_STATIC"; } >> .env
ok "opslagkeuze toegevoegd aan .env"
fi
else
cp .env ".env.backup-$(date +%Y%m%d-%H%M%S)"
ok "oude .env bewaard als .env.backup-*"
rm -f .env
fi
fi
if [ ! -f .env ]; then
vraag "Hostnaam waarop de app bereikbaar is" "rooster.example.nl"
HOSTNAAM="$ANTWOORD"
if jaNee "Draait er TLS (https) voor deze server?" j; then
SCHEMA="https"; SECURE=1
else
SCHEMA="http"; SECURE=0
fi
BASIS_URL="$SCHEMA://$HOSTNAAM"
[ "$SCHEMA" = "http" ] && BASIS_URL="$BASIS_URL:8080"
cat > .env <<ENVEOF
# Aangemaakt door scripts/install.sh op $(date '+%Y-%m-%d %H:%M').
# Dit bestand bevat geheimen en staat in .gitignore.
# --- Django ---------------------------------------------------------------
DJANGO_SECRET_KEY=$(genereer_geheim)
DJANGO_DEBUG=0
DJANGO_ALLOWED_HOSTS=$HOSTNAAM,localhost,127.0.0.1
DJANGO_CSRF_TRUSTED_ORIGINS=$BASIS_URL
# 1 = veilige cookies, HSTS en https-redirect. Vereist dat de proxy
# X-Forwarded-Proto: https meestuurt (zie DEPLOY.md).
DJANGO_SECURE=$SECURE
# --- Opslag ---------------------------------------------------------------
# Een naam = Docker-volume, een pad = gewone map naast de code.
DATA_DB=$DATA_DB
DATA_MEDIA=$DATA_MEDIA
DATA_STATIC=$DATA_STATIC
# --- PostgreSQL -----------------------------------------------------------
POSTGRES_DB=rooster
POSTGRES_USER=rooster
POSTGRES_PASSWORD=$(genereer_geheim)
# --- E-mail (wachtwoordreset) --------------------------------------------
# Leeg = e-mail gaat naar de log van de backend-container.
EMAIL_HOST=
EMAIL_PORT=587
EMAIL_HOST_USER=
EMAIL_HOST_PASSWORD=
EMAIL_USE_TLS=1
DEFAULT_FROM_EMAIL=Roosterwijs <noreply@$HOSTNAAM>
FRONTEND_BASE_URL=$BASIS_URL
ENVEOF
chmod 600 .env
ok "aangemaakt met willekeurige sleutel en databasewachtwoord"
info "hostnaam: $HOSTNAAM · $( [ "$SECURE" = 1 ] && echo 'TLS aan' || echo 'TLS uit' )"
fi
# ------------------------------------------------------------ 6. bouwen
stap "Containers bouwen en starten"
info "dit duurt de eerste keer enkele minuten"
docker compose up -d --build || fout "Bouwen mislukt. Bekijk de uitvoer hierboven."
ok "db, backend en nginx draaien"
# --------------------------------------------------------- 7. beheerder
stap "Beheerder"
aantal="$(docker compose exec -T backend python manage.py shell -c \
'from django.contrib.auth import get_user_model; print(get_user_model().objects.count())' 2>/dev/null | tr -dc '0-9')"
aantal="${aantal:-0}"
if [ "$aantal" -gt 0 ]; then
ok "er zijn al $aantal account(s); geen nieuwe nodig"
else
let_op "Er is nog geen account. Zonder account kun je nergens inloggen."
if jaNee "Nu een beheerder aanmaken?" j; then
docker compose exec backend python manage.py createsuperuser </dev/tty 2>/dev/null || \
let_op "Aanmaken afgebroken; doe het later met het commando hieronder."
fi
fi
# ------------------------------------------------------------------ klaar
printf '\n%s%s%s\n' "$GROEN" "$LIJN" "$STOP"
printf ' %s✓ Installatie afgerond%s\n' "$GROEN$VET" "$STOP"
printf '%s%s%s\n\n' "$GROEN" "$LIJN" "$STOP"
printf ' %sMap%s %s\n' "$DOF" "$STOP" "$DOELMAP"
if [ "$OPSLAG" = "mappen" ]; then
printf ' %sGegevens%s %s/data (database, media, statics)\n' "$DOF" "$STOP" "$DOELMAP"
else
printf ' %sGegevens%s Docker-volumes (docker volume ls)\n' "$DOF" "$STOP"
fi
printf ' %sBijwerken%s ./scripts/deploy.sh\n' "$DOF" "$STOP"
printf ' %sLogs%s docker compose logs -f\n' "$DOF" "$STOP"
printf ' %sBeheerder%s docker compose exec backend python manage.py createsuperuser\n\n' "$DOF" "$STOP"