diff --git a/services/mattermost.sh b/services/mattermost.sh index 390d496..486fe97 100644 --- a/services/mattermost.sh +++ b/services/mattermost.sh @@ -592,6 +592,126 @@ MD log_warning "WebRTC (voice/video calls) requires HTTPS. Configure Caddy and update SITE_URL." fi + # ── Migration helper (new/fresh installs only — not "update" reruns, + # where an existing instance is already in real use and importing over + # it would be destructive) ──────────────────────────────────────────── + if [ "$MODE" != "update" ]; then + echo "" + local MIGRATING="" + prompt_yn "Migrating from an existing Mattermost instance (e.g. PikaPods)? (y/n):" "n" MIGRATING + if [[ "$MIGRATING" =~ ^[Yy]$ ]]; then + cat > "$DIR/migrate-from-pikapods.sh" << 'MIGRATE_HEAD' +#!/bin/bash +################################################################################ +# migrate-from-pikapods.sh — generated by ubuntu-post-install +# +# Imports a Mattermost database dump + file storage exported from another +# instance (e.g. PikaPods) into THIS freshly-created instance, replacing its +# empty database and populating its file storage. +# +# PikaPods export procedure (Pod Settings): enable SFTP + Database access, +# STOP the pod first (flushes anything still in memory to disk), SFTP the +# pod's files down, then use the Adminer link PikaPods gives you to export +# the database as a plain SQL dump. See docs.pikapods.com/manage/backup. +# +# This script assumes a PLAIN-TEXT SQL dump (what Adminer produces by +# default). If you have a custom-format pg_dump instead, use `pg_restore` +# in place of the `psql < dump` step below. +# +# IMPORTANT: point the files argument at the SUBDIRECTORY that holds +# Mattermost's own file storage inside whatever you downloaded via SFTP +# (commonly named `data`), not the whole SFTP root — PikaPods' exact +# layout wasn't verified against a live pod, so confirm this yourself +# before running. +# +# Usage: +# ./migrate-from-pikapods.sh +################################################################################ + +MIGRATE_HEAD + + cat >> "$DIR/migrate-from-pikapods.sh" << MIGRATE_VARS +PROJECT_DIR="$DIR" +MM_CONTAINER="$MM_CONTAINER" +DB_CONTAINER="$DB_CONTAINER" +DB_NAME="mattermost" +DB_USER="mattermost" +MIGRATE_VARS + + cat >> "$DIR/migrate-from-pikapods.sh" << 'MIGRATE_BODY' +set -uo pipefail +cd "$PROJECT_DIR" || exit 1 + +SQL_DUMP="${1:-}" +FILES_DIR="${2:-}" + +if [ -z "$SQL_DUMP" ] || [ -z "$FILES_DIR" ]; then + echo "Usage: $0 " + exit 1 +fi +[ -f "$SQL_DUMP" ] || { echo "SQL dump not found: $SQL_DUMP"; exit 1; } +[ -d "$FILES_DIR" ] || { echo "Files directory not found: $FILES_DIR"; exit 1; } +[ -f "docker-compose.yml" ] || { echo "Run this from $PROJECT_DIR (docker-compose.yml not found here)."; exit 1; } + +echo "" +echo "┌─────────────────────────────────────────────────────────────────┐" +echo "│ MATTERMOST MIGRATION — THIS REPLACES THE CURRENT DATABASE │" +echo "└─────────────────────────────────────────────────────────────────┘" +echo "" +echo " Target instance: $PROJECT_DIR" +echo " SQL dump: $SQL_DUMP" +echo " Files: $FILES_DIR (copied into ./data)" +echo "" +read -r -p " Type YES to proceed: " CONFIRM +[ "$CONFIRM" = "YES" ] || { echo "Aborted — no changes made."; exit 0; } + +echo "" +echo "Stopping $MM_CONTAINER (keeping $DB_CONTAINER running)..." +docker compose stop mattermost + +echo "Waiting for $DB_CONTAINER to accept connections..." +tries=0 +until docker exec "$DB_CONTAINER" pg_isready -U "$DB_USER" >/dev/null 2>&1 || [ "$tries" -ge 30 ]; do + sleep 1; tries=$((tries + 1)) +done + +echo "Dropping and recreating '$DB_NAME' (owned by the existing '$DB_USER' role — .env credentials are untouched)..." +if ! docker exec "$DB_CONTAINER" psql -U "$DB_USER" -d postgres -c "DROP DATABASE IF EXISTS $DB_NAME;" \ + || ! docker exec "$DB_CONTAINER" psql -U "$DB_USER" -d postgres -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;"; then + echo "Failed to reset the database — check: docker compose logs db" + exit 1 +fi + +echo "Importing $SQL_DUMP..." +if ! docker exec -i "$DB_CONTAINER" psql -U "$DB_USER" -d "$DB_NAME" < "$SQL_DUMP" > /tmp/mm-migrate-import.log 2>&1; then + echo "Import reported errors — check /tmp/mm-migrate-import.log before continuing." + echo "(Some warnings, e.g. about extensions already existing, are expected and harmless." + echo " Look for actual failures — missing tables, permission errors — before deciding.)" +fi + +echo "Copying files into ./data..." +mkdir -p ./data +rsync -a "$FILES_DIR"/ ./data/ 2>/dev/null || cp -a "$FILES_DIR"/. ./data/ + +echo "Starting Mattermost..." +docker compose up -d + +echo "" +echo "Done. Verify before treating this as live:" +echo " - Open the site and confirm you can log in as an existing (migrated) user" +echo " - Spot-check a channel with history and a message that has an attached file" +echo " - Check System Console → users/teams counts look right" +echo "" +echo "Import log: /tmp/mm-migrate-import.log" +MIGRATE_BODY + + chmod +x "$DIR/migrate-from-pikapods.sh" + chown "$ACTUAL_USER:$ACTUAL_USER" "$DIR/migrate-from-pikapods.sh" + log_success "Migration helper written: $DIR/migrate-from-pikapods.sh" + log_info "Run it once you have both a SQL dump and the files directory from PikaPods." + fi + fi + local START="" prompt_yn "Start Mattermost now? (y/n):" "y" START if [ "$START" = "y" ] || [ "$START" = "Y" ]; then