Changeset bb42dfb in Klonkt


Ignore:
Timestamp:
06/23/2026 05:35:46 PM (3 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
834bcc3
Parents:
bbbfa3c
Message:

docs: install.sh + .env.example to English (public repo)

Translate all comments + user-facing messages to English; logic unchanged.

Co-Authored-By: Claude <noreply@…>

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • .env.example

    rbbbfa3c rbb42dfb  
    55MEDIA_PATH=./storage/media
    66
    7 # Canonieke publieke URL van deze site (scheme + host, geen pad/slash). Gebruikt
    8 # voor links in e-mails (wachtwoord-reset) i.p.v. request-headers — voorkomt
    9 # host-header-spoofing. Niet gezet? Dan valt het terug op de request-host (dev).
     7# Canonical public URL of this site (scheme + host, no path/slash). Used for
     8# links in emails (password reset) instead of request headers — prevents
     9# host-header spoofing. Not set? Then it falls back to the request host (dev).
    1010PUBLIC_BASE_URL=https://example.com
    1111
    12 # ── Beheerder ───────────────────────────────────────────────────────
    13 # De beheerder logt in met gebruikersnaam + wachtwoord. Bij de eerste keer
    14 # opstarten maak je via /auth/register je beheerdersaccount aan; daarna is
    15 # registratie gesloten. Wachtwoord vergeten? -> "Wachtwoord vergeten" (mail,
    16 # zie SMTP hieronder) of altijd: `npm run reset-admin` op de server.
     12# ── Administrator ───────────────────────────────────────────────────
     13# The admin logs in with username + password. On first start you create your
     14# admin account via /auth/register; after that, registration is closed.
     15# Forgot your password? -> "Forgot password" (email, see SMTP below) or always:
     16# `npm run reset-admin` on the server.
    1717
    18 # ── Google login voor LUISTERAARS (optioneel) ───────────────────────
    19 # Wil je dat luisteraars met Google kunnen inloggen om te reageren? Maak dan
    20 # een EIGEN Google OAuth-client aan (Google Cloud Console -> Credentials ->
    21 # OAuth client ID -> "Web application") en vul hieronder in. Eigen client =
    22 # eigen Google Cloud project; deze site hangt nergens centraal aan vast.
    23 # Niet ingesteld? Dan is er simpelweg geen Google-knop. Google-login geeft
    24 # NOOIT beheerrechten (alleen reageren).
    25 # GOOGLE_REDIRECT_URI = <jouw domein>/auth/google/callback (exact in de client zetten)
     18# ── Google login for LISTENERS (optional) ───────────────────────────
     19# Want listeners to sign in with Google to comment? Create your OWN Google OAuth
     20# client (Google Cloud Console -> Credentials -> OAuth client ID -> "Web
     21# application") and fill it in below. Your own client = your own Google Cloud
     22# project; this site isn't centrally tied to anything. Not set? Then there's
     23# simply no Google button. Google login NEVER grants admin rights (commenting only).
     24# GOOGLE_REDIRECT_URI = <your domain>/auth/google/callback (set it exactly in the client)
    2625GOOGLE_CLIENT_ID=
    2726GOOGLE_CLIENT_SECRET=
    2827GOOGLE_REDIRECT_URI=https://example.com/auth/google/callback
    2928
    30 # ── E-mail (optioneel) — voor "wachtwoord vergeten" reset-links ─────
    31 # Niet ingesteld? Dan werkt reset alleen via `npm run reset-admin` op de server.
     29# ── Email (optional) — for "forgot password" reset links ────────────
     30# Not set? Then reset only works via `npm run reset-admin` on the server.
    3231SMTP_HOST=
    3332SMTP_PORT=587
     
    3635SMTP_FROM=
    3736
    38 # ── Lite-modus (optioneel) ─────────────────────────────────────────
    39 # Zet op "off" om de hele audio-feature uit te schakelen (geen eigen muziek-
    40 # hosting/speler, geen ffmpeg nodig). Klonkt draait dan als lichte blog/foto/
    41 # EPK-site, ook op een omgeving zonder ffmpeg. Hub en Cirkels blijven werken.
    42 # Externe embeds (YouTube/SoundCloud/Spotify) blijven ook werken.
     37# ── Lite mode (optional) ────────────────────────────────────────────
     38# Set to "off" to disable the whole audio feature (no built-in music hosting/
     39# player, no ffmpeg needed). Klonkt then runs as a lightweight blog/photo/EPK
     40# site, even on an environment without ffmpeg. Hub and Circles keep working.
     41# External embeds (YouTube/SoundCloud/Spotify) keep working too.
    4342KLONKT_AUDIO=on
  • scripts/install.sh

    rbbbfa3c rbb42dfb  
    11#!/usr/bin/env bash
    22#
    3 # Klonkt — installer voor een Debian/Ubuntu VPS.
    4 # Installeert Node 20, Caddy (automatische HTTPS) en Klonkt als systemd-service.
    5 #
    6 # Veilig op een server die AL iets draait: upgradet je systeem-Node niet,
    7 # kiest automatisch een vrije poort, en slaat Caddy over als er al een
    8 # webserver/reverse-proxy op poort 80/443 luistert (dan krijg je instructies
    9 # om Klonkt achter je eigen proxy te zetten).
    10 #
    11 # Gebruik (als root), niet-interactief:
     3# Klonkt — installer for a Debian/Ubuntu VPS.
     4# Installs Node 20, Caddy (automatic HTTPS) and Klonkt as a systemd service.
     5#
     6# Safe on a server that ALREADY runs things: it won't upgrade your system Node,
     7# auto-picks a free port, and skips Caddy if a webserver/reverse-proxy is already
     8# listening on port 80/443 (you then get instructions to put Klonkt behind your
     9# own proxy).
     10#
     11# Usage (as root), non-interactive:
    1212#   curl -fsSL https://raw.githubusercontent.com/roboburr/klonkt/main/scripts/install.sh \
    13 #     | sudo bash -s -- --domain klonkt.voorbeeld.nl
    14 # Of interactief vanaf een gedownload bestand:
     13#     | sudo bash -s -- --domain klonkt.example.com
     14# Or interactively from a downloaded file:
    1515#   sudo bash install.sh
    1616#
    17 # Opnieuw draaien op dezelfde server = bijwerken (git pull + herstart).
    18 # Volledig geïsoleerd alternatief: Docker (zie docker-compose.yml in de repo).
     17# Re-running on the same server = update (git pull + restart).
     18# Fully isolated alternative: Docker (see docker-compose.yml in the repo).
    1919#
    2020set -euo pipefail
    2121
    22 # ── Instellingen (override via env-variabele of vlag) ──────────────────────
    23 KLONKT_REPO="${KLONKT_REPO:-https://github.com/roboburr/klonkt.git}"  # TODO: echte GitHub-URL
     22# ── Settings (override via env var or flag) ────────────────────────────────
     23KLONKT_REPO="${KLONKT_REPO:-https://github.com/roboburr/klonkt.git}"
    2424KLONKT_BRANCH="${KLONKT_BRANCH:-main}"
    2525KLONKT_DIR="${KLONKT_DIR:-/opt/klonkt}"
     
    2929KLONKT_LANG="${KLONKT_DEFAULT_LANG:-}"
    3030NODE_MAJOR="${NODE_MAJOR:-20}"
    31 NO_CADDY="${KLONKT_NO_CADDY:-}"     # zet op 1 om Caddy NOOIT te installeren (eigen proxy)
    32 NODE_FORCE="${NODE_FORCE:-}"        # zet op 1 om systeem-Node tóch te (her)installeren
     31NO_CADDY="${KLONKT_NO_CADDY:-}"     # set to 1 to NEVER install Caddy (own proxy)
     32NODE_FORCE="${NODE_FORCE:-}"        # set to 1 to (re)install system Node anyway
    3333PORT_EXPLICIT=0
    3434
     
    4444    --force-node) NODE_FORCE=1; shift;;
    4545    -h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0;;
    46     *) echo "Onbekende optie: $1" >&2; exit 1;;
     46    *) echo "Unknown option: $1" >&2; exit 1;;
    4747  esac
    4848done
     
    5555port_busy() { ss -ltnH 2>/dev/null | awk '{print $4}' | grep -qE "[:.]${1}$"; }
    5656
    57 [ "$(id -u)" = 0 ] || die "Draai dit als root (sudo bash install.sh)."
    58 command -v apt-get >/dev/null || die "Alleen Debian/Ubuntu (apt). Gebruik op andere systemen de Docker-route."
     57[ "$(id -u)" = 0 ] || die "Run this as root (sudo bash install.sh)."
     58command -v apt-get >/dev/null || die "Debian/Ubuntu only (apt). On other systems use the Docker route."
    5959
    6060if [ -z "$KLONKT_DOMAIN" ]; then
    61   read -rp "Domein voor Klonkt (bv. klonkt.voorbeeld.nl): " KLONKT_DOMAIN </dev/tty || true
    62 fi
    63 [ -n "$KLONKT_DOMAIN" ] || die "Geen domein opgegeven (--domain of KLONKT_DOMAIN)."
     61  read -rp "Domain for Klonkt (e.g. klonkt.example.com): " KLONKT_DOMAIN </dev/tty || true
     62fi
     63[ -n "$KLONKT_DOMAIN" ] || die "No domain given (--domain or KLONKT_DOMAIN)."
    6464case "$KLONKT_REPO" in
    65   *OWNER/*) die "Zet eerst de echte repo-URL: --repo https://github.com/<jij>/klonkt.git (of KLONKT_REPO=...).";;
     65  *OWNER/*) die "Set the real repo URL first: --repo https://github.com/<you>/klonkt.git (or KLONKT_REPO=...).";;
    6666esac
    6767
    6868export DEBIAN_FRONTEND=noninteractive
    6969
    70 # ── Preflight: kijk wat er al draait, pas je aan i.p.v. clobberen ──────────
    71 log "Preflight (wat draait er al?)…"
     70# ── Preflight: see what's already running, adapt instead of clobbering ──────
     71log "Preflight (what's already running?)…"
    7272apt-get update -y >/dev/null
    7373apt-get install -y iproute2 >/dev/null 2>&1 || true
    7474
    75 # Poort: bezet? Bij --port → fout. Anders automatisch een vrije kiezen.
     75# Port: busy? With --port → error. Otherwise auto-pick a free one.
    7676if port_busy "$KLONKT_PORT"; then
    7777  if [ "$PORT_EXPLICIT" = 1 ]; then
    78     die "Poort ${KLONKT_PORT} is al in gebruik. Kies een vrije poort met --port."
     78    die "Port ${KLONKT_PORT} is already in use. Pick a free port with --port."
    7979  fi
    8080  picked=""
     
    8282    port_busy "$p" || { picked="$p"; break; }
    8383  done
    84   [ -n "$picked" ] || die "Geen vrije poort gevonden rond ${KLONKT_PORT}. Geef er een met --port."
    85   warn "poort ${KLONKT_PORT} bezet → Klonkt gebruikt ${picked}"
     84  [ -n "$picked" ] || die "No free port found near ${KLONKT_PORT}. Provide one with --port."
     85  warn "port ${KLONKT_PORT} busy → Klonkt uses ${picked}"
    8686  KLONKT_PORT="$picked"
    8787else
    88   ok "poort ${KLONKT_PORT} vrij"
    89 fi
    90 
    91 # Webserver op 80/443 die niet Caddy is? → Caddy overslaan, eigen-proxy-modus.
     88  ok "port ${KLONKT_PORT} free"
     89fi
     90
     91# Webserver on 80/443 that isn't Caddy? → skip Caddy, own-proxy mode.
    9292FOREIGN_PROXY=0
    9393if [ -z "$NO_CADDY" ] && command -v ss >/dev/null 2>&1; then
    9494  if ss -ltnpH 2>/dev/null | grep -E '[:.](80|443) ' | grep -viq 'caddy'; then
    9595    NO_CADDY=1; FOREIGN_PROXY=1
    96     warn "er luistert al iets op poort 80/443 (geen Caddy) → ik installeer Caddy NIET en geef je proxy-instructies"
    97   fi
    98 fi
    99 
    100 # ── Node: bestaande versie respecteren, niet stilletjes upgraden ──────────
     96    warn "something is already listening on port 80/443 (not Caddy) → NOT installing Caddy; you'll get proxy instructions"
     97  fi
     98fi
     99
     100# ── Node: respect an existing version, don't silently upgrade ──────────────
    101101log "Node ${NODE_MAJOR}.x…"
    102102if command -v node >/dev/null 2>&1 && [ -z "$NODE_FORCE" ]; then
    103103  CUR="$(node -v | sed 's/v//;s/\..*//')"
    104104  if [ "$CUR" -lt "$NODE_MAJOR" ]; then
    105     die "Er staat al Node $(node -v) op deze server; Klonkt heeft ≥${NODE_MAJOR} nodig.
    106    Ik upgrade je systeem-Node NIET automatisch — dat kan andere apps breken.
    107    Opties: (a) gebruik de Docker-route (eigen Node, raakt niets aan), of
    108            (b) upgrade Node zelf, of (c) forceer met NODE_FORCE=1 (eigen risico)."
    109   fi
    110   ok "bestaande node $(node -v) wordt gebruikt"
     105    die "Node $(node -v) is already installed on this server; Klonkt needs ≥${NODE_MAJOR}.
     106   I will NOT auto-upgrade your system Node — that could break other apps.
     107   Options: (a) use the Docker route (own Node, touches nothing), or
     108            (b) upgrade Node yourself, or (c) force with NODE_FORCE=1 (at your own risk)."
     109  fi
     110  ok "using existing node $(node -v)"
    111111else
    112112  curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash -
    113113  apt-get install -y nodejs
    114   ok "node $(node -v) geïnstalleerd"
    115 fi
    116 
    117 log "Overige pakketten…"
     114  ok "node $(node -v) installed"
     115fi
     116
     117log "Other packages…"
    118118apt-get install -y curl ca-certificates git gnupg openssl build-essential python3
    119 apt-get install -y webp >/dev/null 2>&1 || true   # cwebp = afbeelding→WebP (optioneel)
    120 ok "basis-pakketten"
     119apt-get install -y webp >/dev/null 2>&1 || true   # cwebp = image→WebP (optional)
     120ok "base packages"
    121121
    122122if [ -z "$NO_CADDY" ]; then
     
    128128    apt-get install -y caddy
    129129  fi
    130   ok "caddy aanwezig"
    131 fi
    132 
    133 log "Service-gebruiker '${KLONKT_USER}'…"
     130  ok "caddy present"
     131fi
     132
     133log "Service user '${KLONKT_USER}'…"
    134134id -u "$KLONKT_USER" >/dev/null 2>&1 || useradd --system --home-dir "$KLONKT_DIR" --shell /usr/sbin/nologin "$KLONKT_USER"
    135 ok "gebruiker"
    136 
    137 log "Klonkt-broncode ophalen…"
     135ok "user"
     136
     137log "Fetching Klonkt source…"
    138138if [ -d "$KLONKT_DIR/.git" ]; then
    139139  git -C "$KLONKT_DIR" remote set-url origin "$KLONKT_REPO"
     
    141141  git -C "$KLONKT_DIR" reset --hard "origin/$KLONKT_BRANCH"
    142142else
    143   [ -e "$KLONKT_DIR" ] && [ -n "$(ls -A "$KLONKT_DIR" 2>/dev/null)" ] && die "$KLONKT_DIR bestaat al en is geen git-checkout. Kies --dir, of ruim 'm op."
     143  [ -e "$KLONKT_DIR" ] && [ -n "$(ls -A "$KLONKT_DIR" 2>/dev/null)" ] && die "$KLONKT_DIR already exists and is not a git checkout. Pick --dir, or clean it up."
    144144  mkdir -p "$KLONKT_DIR"
    145145  git clone --depth 1 --branch "$KLONKT_BRANCH" "$KLONKT_REPO" "$KLONKT_DIR"
     
    149149ok "code in $KLONKT_DIR"
    150150
    151 log "Dependencies installeren (npm ci)…"
     151log "Installing dependencies (npm ci)…"
    152152as_klonkt bash -c "cd '$KLONKT_DIR' && npm ci --omit=dev"
    153153ok "node_modules"
     
    168168  } > "$ENV"
    169169  chown "$KLONKT_USER:$KLONKT_USER" "$ENV"; chmod 600 "$ENV"
    170   ok "nieuwe .env (willekeurige SESSION_SECRET)"
    171 else
    172   # poort in bestaande .env synchroniseren met de gekozen poort
     170  ok "new .env (random SESSION_SECRET)"
     171else
     172  # sync the port in an existing .env with the chosen port
    173173  if grep -q '^PORT=' "$ENV"; then sed -i "s/^PORT=.*/PORT=${KLONKT_PORT}/" "$ENV"; fi
    174   ok "bestaande .env behouden (poort gesynchroniseerd)"
    175 fi
    176 
    177 log "systemd-service…"
     174  ok "kept existing .env (port synced)"
     175fi
     176
     177log "systemd service…"
    178178NODE_BIN="$(command -v node)"
    179179cat > /etc/systemd/system/klonkt.service <<EOF
     
    200200systemctl daemon-reload
    201201systemctl enable --now klonkt
    202 ok "klonkt.service draait op 127.0.0.1:${KLONKT_PORT}"
     202ok "klonkt.service running on 127.0.0.1:${KLONKT_PORT}"
    203203
    204204if [ -z "$NO_CADDY" ]; then
    205   log "Caddy-config voor ${KLONKT_DOMAIN}…"
     205  log "Caddy config for ${KLONKT_DOMAIN}…"
    206206  CADDY=/etc/caddy/Caddyfile
    207207  SITE_BLOCK="${KLONKT_DOMAIN} {
     
    216216    printf '\n%s\n' "$SITE_BLOCK" >> "$CADDY"
    217217  fi
    218   caddy validate --config "$CADDY" --adapter caddyfile >/dev/null 2>&1 || die "Caddy-config ongeldig — controleer $CADDY"
     218  caddy validate --config "$CADDY" --adapter caddyfile >/dev/null 2>&1 || die "Caddy config invalid — check $CADDY"
    219219  systemctl reload caddy 2>/dev/null || systemctl restart caddy
    220   ok "caddy serveert ${KLONKT_DOMAIN}"
    221 fi
    222 
    223 log "Update-commando 'klonkt-update'…"
     220  ok "caddy serving ${KLONKT_DOMAIN}"
     221fi
     222
     223log "Update command 'klonkt-update'…"
    224224cat > /usr/local/bin/klonkt-update <<EOF
    225225#!/usr/bin/env bash
     
    234234fi
    235235systemctl restart klonkt
    236 echo "Klonkt bijgewerkt (\$A) + herstart."
     236echo "Klonkt updated (\$A) + restarted."
    237237EOF
    238238chmod +x /usr/local/bin/klonkt-update
     
    241241echo
    242242echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    243 echo "  Klonkt draait! 🎉"
     243echo "  Klonkt is running! 🎉"
    244244echo
    245245if [ -n "$NO_CADDY" ]; then
    246   echo "  Klonkt luistert op:  http://127.0.0.1:${KLONKT_PORT}"
     246  echo "  Klonkt listens on:  http://127.0.0.1:${KLONKT_PORT}"
    247247  if [ "$FOREIGN_PROXY" = 1 ]; then
    248     echo "  Er draait al een webserver op 80/443 — zet Klonkt erachter."
    249   fi
    250   echo "  Voorbeeld nginx:"
     248    echo "  A webserver is already running on 80/443 — put Klonkt behind it."
     249  fi
     250  echo "  Example nginx:"
    251251  echo "      location / { proxy_pass http://127.0.0.1:${KLONKT_PORT}; proxy_set_header Host \$host;"
    252252  echo "                   proxy_set_header X-Forwarded-Proto \$scheme; }"
    253   echo "  Voorbeeld Caddy:"
     253  echo "  Example Caddy:"
    254254  echo "      ${KLONKT_DOMAIN} { reverse_proxy 127.0.0.1:${KLONKT_PORT} }"
    255255else
    256   echo "  • Open je site:   https://${KLONKT_DOMAIN}"
    257 fi
    258 echo "  • Eerste keer:    ga naar /auth/register en maak je beheerdersaccount aan."
    259 echo
    260 echo "  Beheer:  systemctl status klonkt · journalctl -u klonkt -f · klonkt-update"
    261 echo "  Wachtwoord kwijt: cd ${KLONKT_DIR} && runuser -u ${KLONKT_USER} -- env HOME=${KLONKT_DIR} npm run reset-admin"
    262 echo
    263 echo "  DNS: zorg dat A + AAAA van ${KLONKT_DOMAIN} naar deze server wijzen."
     256  echo "  • Open your site:  https://${KLONKT_DOMAIN}"
     257fi
     258echo "  • First run:       go to /auth/register and create your admin account."
     259echo
     260echo "  Manage:  systemctl status klonkt · journalctl -u klonkt -f · klonkt-update"
     261echo "  Lost password: cd ${KLONKT_DIR} && runuser -u ${KLONKT_USER} -- env HOME=${KLONKT_DIR} npm run reset-admin"
     262echo
     263echo "  DNS: make sure A + AAAA of ${KLONKT_DOMAIN} point to this server."
    264264echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
Note: See TracChangeset for help on using the changeset viewer.