Changeset 2dd1dc4 in Klonkt
- Timestamp:
- 07/31/2026 12:48:10 PM (6 weeks ago)
- Branches:
- main
- Children:
- ccaa530
- Parents:
- e2c3d09
- Files:
-
- 4 added
- 2 edited
-
deploy/DEPLOY.md (modified) (1 diff)
-
deploy/MULTI-INSTANCE.md (added)
-
deploy/klonkt@.service (added)
-
scripts/install.sh (modified) (8 diffs)
-
scripts/klonkt-add-instance.sh (added)
-
scripts/klonkt-migrate-data.sh (added)
Legend:
- Unmodified
- Added
- Removed
-
deploy/DEPLOY.md
re2c3d09 r2dd1dc4 198 198 (`/sites/<slug>/`) and its own PWA scope, so installing the PWA from one 199 199 site won't navigate into another. 200 201 These sites live inside one Klonkt, sharing one database and one process. For 202 separate domains with separate databases, see the next section instead. 203 204 --- 205 206 ## 9b. Several independent Klonkts on one server 207 208 A different question from the one above: not several sites inside one Klonkt, 209 but several Klonkts side by side, each with its own domain, database and 210 uploads, all sharing a single copy of the code. 211 212 That layout keeps user data out of the checkout: 213 214 ``` 215 /opt/klonkt/ the code, shared by every instance 216 /var/lib/klonkt/<slug>/ one instance: .env, database, uploads 217 ``` 218 219 Adding a site is then a directory plus an `.env`, and `klonkt-update` moves all 220 of them to the new code in one step. Existing single site installs can be 221 converted with `scripts/klonkt-migrate-data.sh`. 222 223 See **[MULTI-INSTANCE.md](MULTI-INSTANCE.md)** for the layout, the migration, 224 the file ownership and the backup routine. 200 225 201 226 --- -
scripts/install.sh
re2c3d09 r2dd1dc4 28 28 KLONKT_BRANCH="${KLONKT_BRANCH:-stable}" 29 29 KLONKT_DIR="${KLONKT_DIR:-/opt/klonkt}" 30 # Where instance data lives, one directory per slug. The code in KLONKT_DIR is 31 # shared; everything an instance writes stays under here. 32 KLONKT_DATA_ROOT="${KLONKT_DATA_ROOT:-/var/lib/klonkt}" 33 # Short name for this instance: its directory under the data root and its 34 # systemd unit (klonkt@<slug>). Derived from the domain when left empty. 35 KLONKT_SLUG="${KLONKT_SLUG:-}" 30 36 KLONKT_USER="${KLONKT_USER:-klonkt}" 31 37 KLONKT_PORT="${KLONKT_PORT:-3000}" … … 164 170 git clone --depth 1 --branch "$KLONKT_BRANCH" "$KLONKT_REPO" "$KLONKT_DIR" 165 171 fi 166 mkdir -p "$KLONKT_DIR/storage/media" "$KLONKT_DIR/storage/audio"167 172 chown -R "$KLONKT_USER:$KLONKT_USER" "$KLONKT_DIR" 168 173 ok "code in $KLONKT_DIR" 174 175 # --- where this instance keeps its data ------------------------------------- 176 # New installs put data in /var/lib/klonkt/<slug> so the checkout stays free of 177 # user data and can be shared by more instances later. An install that already 178 # has its .env inside the checkout is left exactly as it is: re-running the 179 # installer must never move a live database. Convert those deliberately with 180 # scripts/klonkt-migrate-data.sh. 181 if [ -z "$KLONKT_SLUG" ]; then 182 KLONKT_SLUG="$(printf '%s' "${KLONKT_DOMAIN:-default}" | sed 's/^www\.//' | cut -d. -f1 \ 183 | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9._-')" 184 [ -n "$KLONKT_SLUG" ] || KLONKT_SLUG=default 185 fi 186 # A database in the checkout but no .env is too ambiguous to guess at: refuse, 187 # rather than start a fresh empty instance beside data nobody is reading. 188 if [ ! -f "$KLONKT_DIR/.env" ] && [ -f "$KLONKT_DIR/storage/database.sqlite" ]; then 189 die "found $KLONKT_DIR/storage/database.sqlite but no .env next to it. 190 Put the .env back and re-run, or move the old storage/ aside first." 191 fi 192 if [ -f "$KLONKT_DIR/.env" ]; then 193 LAYOUT=legacy 194 ENV="$KLONKT_DIR/.env" 195 DATA_DIR="$KLONKT_DIR/storage" 196 SERVICE="klonkt" 197 mkdir -p "$DATA_DIR/media" "$DATA_DIR/audio" 198 chown -R "$KLONKT_USER:$KLONKT_USER" "$DATA_DIR" 199 ok "existing layout kept (data inside $KLONKT_DIR; split it with scripts/klonkt-migrate-data.sh)" 200 else 201 LAYOUT=split 202 DATA_DIR="$KLONKT_DATA_ROOT/$KLONKT_SLUG" 203 ENV="$DATA_DIR/.env" 204 SERVICE="klonkt@${KLONKT_SLUG}" 205 mkdir -p "$DATA_DIR/media" "$DATA_DIR/audio" 206 chown -R "$KLONKT_USER:$KLONKT_USER" "$DATA_DIR" 207 chmod 750 "$DATA_DIR" 208 ok "data in $DATA_DIR (instance '$KLONKT_SLUG')" 209 fi 169 210 170 211 log "Installing dependencies (npm ci)…" … … 173 214 174 215 log ".env…" 175 ENV="$KLONKT_DIR/.env"176 216 if [ ! -f "$ENV" ]; then 177 217 SECRET="$(openssl rand -hex 32)" … … 183 223 echo "HOST=127.0.0.1" 184 224 echo "SESSION_SECRET=${SECRET}" 185 echo "DATABASE_PATH=./storage/database.sqlite" 186 echo "MEDIA_PATH=./storage/media" 187 echo "AUDIO_PATH=./storage/audio" 225 # Absolute, so the app does not depend on its working directory and the 226 # data can sit outside the checkout. Media subdirectories (avatars, 227 # post-images, ...) follow MEDIA_PATH by themselves. 228 echo "DATABASE_PATH=${DATA_DIR}/database.sqlite" 229 echo "MEDIA_PATH=${DATA_DIR}/media" 230 echo "AUDIO_PATH=${DATA_DIR}/audio" 188 231 echo "PUBLIC_BASE_URL=https://${KLONKT_DOMAIN}" 189 232 [ -n "$KLONKT_LANG" ] && echo "KLONKT_DEFAULT_LANG=${KLONKT_LANG}" … … 201 244 log "systemd service…" 202 245 NODE_BIN="$(command -v node)" 203 cat > /etc/systemd/system/klonkt.service <<EOF 246 if [ "$LAYOUT" = split ]; then 247 # One template, one service per instance. Adding a site later is a data 248 # directory plus an .env, with no second copy of the code. 249 sed -e "s#^User=klonkt\$#User=${KLONKT_USER}#" \ 250 -e "s#^Group=klonkt\$#Group=${KLONKT_USER}#" \ 251 -e "s#^WorkingDirectory=/opt/klonkt\$#WorkingDirectory=${KLONKT_DIR}#" \ 252 -e "s#^EnvironmentFile=/var/lib/klonkt/%i/.env\$#EnvironmentFile=${KLONKT_DATA_ROOT}/%i/.env#" \ 253 -e "s#^ReadWritePaths=/var/lib/klonkt/%i\$#ReadWritePaths=${KLONKT_DATA_ROOT}/%i#" \ 254 -e "s#^ExecStart=/usr/bin/node src/server.js\$#ExecStart=${NODE_BIN} src/server.js#" \ 255 "$KLONKT_DIR/deploy/klonkt@.service" > /etc/systemd/system/klonkt@.service 256 chmod 0644 /etc/systemd/system/klonkt@.service 257 systemctl daemon-reload 258 systemctl enable --now "klonkt@${KLONKT_SLUG}" 259 ok "klonkt@${KLONKT_SLUG} running on 127.0.0.1:${KLONKT_PORT}" 260 else 261 cat > /etc/systemd/system/klonkt.service <<EOF 204 262 [Unit] 205 263 Description=Klonkt … … 222 280 WantedBy=multi-user.target 223 281 EOF 224 systemctl daemon-reload 225 systemctl enable --now klonkt 226 ok "klonkt.service running on 127.0.0.1:${KLONKT_PORT}" 282 systemctl daemon-reload 283 systemctl enable --now klonkt 284 ok "klonkt.service running on 127.0.0.1:${KLONKT_PORT}" 285 fi 227 286 228 287 if [ -z "$NO_CADDY" ]; then … … 261 320 runuser -u ${KLONKT_USER} -- env HOME="\$D" bash -c "cd '\$D' && npm ci --omit=dev" 262 321 fi 263 systemctl restart klonkt 264 echo "Klonkt updated (\$A) + restarted." 322 # Restart every instance. Each directory under the data root with an .env is one 323 # instance sharing this checkout. An install that has not been split yet has no 324 # such directories and still runs the single klonkt.service. 325 N=0 326 for d in ${KLONKT_DATA_ROOT}/*/; do 327 [ -f "\$d/.env" ] || continue 328 s=\$(basename "\$d") 329 systemctl restart "klonkt@\$s" && N=\$((N+1)) 330 done 331 if [ "\$N" = 0 ]; then 332 systemctl restart klonkt 333 echo "Klonkt updated (\$A) + restarted." 334 else 335 echo "Klonkt updated (\$A) + restarted \$N instance(s)." 336 fi 265 337 EOF 266 338 chmod +x /usr/local/bin/klonkt-update … … 286 358 echo " • First run: go to /auth/register and create your admin account." 287 359 echo 288 echo " Manage: systemctl status klonkt · journalctl -u klonkt-f · klonkt-update"360 echo " Manage: systemctl status ${SERVICE} · journalctl -u ${SERVICE} -f · klonkt-update" 289 361 echo " Lost password: cd ${KLONKT_DIR} && runuser -u ${KLONKT_USER} -- env HOME=${KLONKT_DIR} npm run reset-admin" 362 if [ "$LAYOUT" = split ]; then 363 echo 364 echo " Code: ${KLONKT_DIR} shared, nothing of yours lives here" 365 echo " Data: ${DATA_DIR} database, uploads and .env — back up this one" 366 echo " Another site on this server, sharing the same code:" 367 echo " sudo bash ${KLONKT_DIR}/scripts/klonkt-add-instance.sh <slug> <domain>" 368 fi 290 369 echo 291 370 echo " DNS: make sure A + AAAA of ${KLONKT_DOMAIN} point to this server."
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)