From f795e85333918142e88bf331078711a7df9cb118 Mon Sep 17 00:00:00 2001
From: Ramon
Date: Wed, 19 Aug 2026 15:17:08 +0200
Subject: [PATCH] Installatiescript met opslagkeuze, standaard /srv/server-up
(v0.2.04 beta)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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
Claude-Session: https://claude.ai/code/session_01FAQ4Np13v8fwbTtKHKnwDz
---
.env.example | 10 ++
.gitignore | 6 +
DEPLOY.md | 83 ++++++++----
README.md | 17 +++
docker-compose.yml | 22 ++--
frontend/package-lock.json | 4 +-
frontend/package.json | 2 +-
frontend/src/modern.css | 2 +-
scripts/deploy.sh | 10 ++
scripts/install.sh | 252 +++++++++++++++++++++++++++++++++++++
10 files changed, 374 insertions(+), 34 deletions(-)
create mode 100755 scripts/install.sh
diff --git a/.env.example b/.env.example
index 261f3fd..a4d00a3 100644
--- a/.env.example
+++ b/.env.example
@@ -27,6 +27,16 @@ DJANGO_CSRF_TRUSTED_ORIGINS=https://rooster.example.nl
# in dit project geeft die header door.
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 -----------------------------------------------------------
POSTGRES_DB=rooster
POSTGRES_USER=rooster
diff --git a/.gitignore b/.gitignore
index 184a620..ac38de3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,3 +68,9 @@ logs/
.DS_Store
Thumbs.db
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-*
diff --git a/DEPLOY.md b/DEPLOY.md
index bfacd37..9940e76 100644
--- a/DEPLOY.md
+++ b/DEPLOY.md
@@ -78,30 +78,67 @@ Je hoeft op de server **niets** te installeren behalve Docker zelf (met de
## Eenmalig: server klaarzetten
-1. Zorg dat Docker + Compose op de test-server staan:
- ```bash
- docker --version
- docker compose version
- ```
-2. Haal de code op:
- ```bash
- git clone /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://` achter TLS (of `http://:8080` zonder TLS)
- - `POSTGRES_PASSWORD` — een sterk wachtwoord
+Het installatiescript doet alles hieronder in zeven stappen en stelt drie
+vragen. Standaard komt alles in **`/srv/server-up`**.
- `.env` staat in `.gitignore` en komt dus **niet** in git — dat hoort zo.
+```bash
+git clone /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 /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://` achter TLS (of `http://: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
diff --git a/README.md b/README.md
index 38ffae1..84d3193 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,23 @@ geboortedatum vast.
Een nieuwe module toevoegen = nieuwe app maken, één regel in
`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 /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)
> Voor een test- of productieserver gelden **andere** stappen: zie `DEPLOY.md`.
diff --git a/docker-compose.yml b/docker-compose.yml
index 377614a..2e738e7 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -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
# backend - Django via gunicorn
# nginx - serveert de frontend en proxyt /api + /admin naar de backend
@@ -13,7 +21,7 @@ services:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- - pgdata:/var/lib/postgresql/data
+ - ${DATA_DB:-pgdata}:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
@@ -47,9 +55,9 @@ services:
FRONTEND_BASE_URL: ${FRONTEND_BASE_URL:-}
volumes:
# Verzamelde statics delen met nginx.
- - static_volume:/app/staticfiles
- # Geüploade media (pictogrammen) delen met nginx.
- - media_volume:/app/media
+ - ${DATA_STATIC:-static_volume}:/app/staticfiles
+ # Geüploade media (pictogrammen, logo) delen met nginx.
+ - ${DATA_MEDIA:-media_volume}:/app/media
nginx:
build: ./frontend
@@ -61,8 +69,8 @@ services:
- "8080:80"
volumes:
# Lees de door Django verzamelde statics (alleen-lezen).
- - static_volume:/static:ro
- - media_volume:/media:ro
+ - ${DATA_STATIC:-static_volume}:/static:ro
+ - ${DATA_MEDIA:-media_volume}:/media:ro
volumes:
pgdata:
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 663a237..b7976d3 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "roosterwijs-frontend",
- "version": "0.2.3-beta",
+ "version": "0.2.4-beta",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "roosterwijs-frontend",
- "version": "0.2.3-beta",
+ "version": "0.2.4-beta",
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
diff --git a/frontend/package.json b/frontend/package.json
index 51abb99..11479d5 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,7 +1,7 @@
{
"name": "roosterwijs-frontend",
"private": true,
- "version": "0.2.3-beta",
+ "version": "0.2.4-beta",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/frontend/src/modern.css b/frontend/src/modern.css
index 48ff542..eedd161 100644
--- a/frontend/src/modern.css
+++ b/frontend/src/modern.css
@@ -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::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}
-.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-wide{padding:24px 28px 42px}
h1{font-size:clamp(24px,2.4vw,30px);line-height:1.2;letter-spacing:-.025em;font-weight:750}
diff --git a/scripts/deploy.sh b/scripts/deploy.sh
index cbb3a95..f1be707 100755
--- a/scripts/deploy.sh
+++ b/scripts/deploy.sh
@@ -66,6 +66,16 @@ else
fi
# --- 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
# --- Controleren ----------------------------------------------------------
diff --git a/scripts/install.sh b/scripts/install.sh
new file mode 100755
index 0000000..d4e4176
--- /dev/null
+++ b/scripts/install.sh
@@ -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/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/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 <
+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/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"