From f7494a8c62cd4c934aa0519db7c65241778c3b4e Mon Sep 17 00:00:00 2001 From: root Date: Wed, 30 Sep 2026 10:15:20 +0300 Subject: [PATCH] Add Nextcloud CI/CD with PostgreSQL backup --- .gitea/workflows/nextcloud.yml | 34 + scripts/deploy-nextcloud.sh | 1214 +++++++++++++++++++++++++++ stacks/nextcloud/docker-compose.yml | 91 ++ 3 files changed, 1339 insertions(+) create mode 100644 .gitea/workflows/nextcloud.yml create mode 100755 scripts/deploy-nextcloud.sh create mode 100644 stacks/nextcloud/docker-compose.yml diff --git a/.gitea/workflows/nextcloud.yml b/.gitea/workflows/nextcloud.yml new file mode 100644 index 0000000..91594a7 --- /dev/null +++ b/.gitea/workflows/nextcloud.yml @@ -0,0 +1,34 @@ +name: Nextcloud CI/CD + +on: + push: + paths: + - "stacks/nextcloud/**" + - "scripts/deploy-nextcloud.sh" + - ".gitea/workflows/nextcloud.yml" + + workflow_dispatch: + +permissions: + contents: read + + +jobs: + + nextcloud: + + name: Deploy Nextcloud + + runs-on: docker-home-01 + + steps: + + - name: Checkout repository + uses: actions/checkout@v7 + with: + persist-credentials: false + + - name: Deploy Nextcloud + if: ${{ gitea.ref == 'refs/heads/main' }} + run: | + ./scripts/deploy-nextcloud.sh diff --git a/scripts/deploy-nextcloud.sh b/scripts/deploy-nextcloud.sh new file mode 100755 index 0000000..140579a --- /dev/null +++ b/scripts/deploy-nextcloud.sh @@ -0,0 +1,1214 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail + +umask 077 + + +# ============================================================ +# Configuration +# ============================================================ + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +SRC="${ROOT}/stacks/nextcloud" + +LIVE="/srv/nfs/infra/nextcloud" +ENV_FILE="${LIVE}/.env" + +BACKUP_ROOT="/srv/nfs/infra/.deploy-backups/nextcloud" +BACKUP_KEEP=3 + +STAMP="$(date '+%Y%m%d-%H%M%S')" + +BACKUP_DIR="${BACKUP_ROOT}/${STAMP}" +DB_BACKUP_DIR="${BACKUP_DIR}/database" + +DB_BACKUP_FILE="${DB_BACKUP_DIR}/nextcloud.dump" + + +# ============================================================ +# Helpers +# ============================================================ + +log() +{ + echo + echo "============================================================" + echo "$*" + echo "============================================================" +} + + +fail() +{ + echo + echo "ERROR: $*" >&2 + exit 1 +} + + +on_error() +{ + rc=$? + + trap - ERR + + echo + echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + echo " Nextcloud deployment FAILED" + echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + + if [[ -d "${BACKUP_DIR}" ]]; then + echo + echo "Pre-upgrade backup:" + echo " ${BACKUP_DIR}" + fi + + echo + echo "Automatic rollback is intentionally NOT performed." + echo "The Nextcloud database schema may already have been modified." + echo "Use the pre-upgrade PostgreSQL dump if a rollback is required." + + exit "${rc}" +} + + +cleanup_old_backups() +{ + echo + echo "--- Backup retention ---" + echo "Keeping last ${BACKUP_KEEP} pre-upgrade backups." + + mkdir -p "${BACKUP_ROOT}" + + mapfile -t BACKUPS < <( + find "${BACKUP_ROOT}" \ + -mindepth 1 \ + -maxdepth 1 \ + -type d \ + -printf '%f\n' | + grep -E '^[0-9]{8}-[0-9]{6}$' | + sort -r + ) + + + if (( ${#BACKUPS[@]} <= BACKUP_KEEP )); then + + echo "Current backup count: ${#BACKUPS[@]}" + echo "Nothing to delete." + + return 0 + + fi + + + for BACKUP_NAME in "${BACKUPS[@]:${BACKUP_KEEP}}" + do + + OLD_BACKUP="${BACKUP_ROOT}/${BACKUP_NAME}" + + echo + echo "Removing old backup:" + echo " ${OLD_BACKUP}" + + rm -rf -- "${OLD_BACKUP}" + + done +} + + +version_less_than() +{ + local A="$1" + local B="$2" + + [[ "${A}" == "${B}" ]] && return 1 + + [[ "$( + printf '%s\n%s\n' "${A}" "${B}" | + sort -V | + head -n1 + )" == "${A}" ]] +} + + +trap on_error ERR + + +# ============================================================ +# Required commands +# ============================================================ + +log "Pre-flight checks" + +for CMD in \ + docker \ + psql \ + pg_dump \ + pg_restore \ + sha256sum \ + sort \ + grep \ + find +do + + command -v "${CMD}" >/dev/null 2>&1 || \ + fail "Required command not found: ${CMD}" + +done + + +docker compose version >/dev/null 2>&1 || \ + fail "Docker Compose plugin is not available" + + +# ============================================================ +# Required files +# ============================================================ + +[[ -f "${SRC}/docker-compose.yml" ]] || \ + fail "${SRC}/docker-compose.yml not found" + +[[ -f "${LIVE}/docker-compose.yml" ]] || \ + fail "${LIVE}/docker-compose.yml not found" + +[[ -f "${ENV_FILE}" ]] || \ + fail "${ENV_FILE} not found" + + +# ============================================================ +# Backup directory access +# ============================================================ + +mkdir -p "${BACKUP_ROOT}" + +[[ -w "${BACKUP_ROOT}" ]] || \ + fail "${BACKUP_ROOT} is not writable" + + +# ============================================================ +# Load PostgreSQL settings +# +# .env must be shell-compatible. +# +# Example: +# +# POSTGRES_HOST=192.168.1.20 +# POSTGRES_DB=nextcloud +# POSTGRES_USER=nextcloud +# POSTGRES_PASSWORD='complex@password' +# ============================================================ + +set -a + +# shellcheck disable=SC1090 +source "${ENV_FILE}" + +set +a + + +: "${POSTGRES_HOST:?POSTGRES_HOST not defined}" +: "${POSTGRES_DB:?POSTGRES_DB not defined}" +: "${POSTGRES_USER:?POSTGRES_USER not defined}" +: "${POSTGRES_PASSWORD:?POSTGRES_PASSWORD not defined}" + + +export PGPASSWORD="${POSTGRES_PASSWORD}" +export PGCONNECT_TIMEOUT=10 + + +# ============================================================ +# Validate requested Compose +# ============================================================ + +log "Validate Docker Compose" + +docker compose \ + -f "${SRC}/docker-compose.yml" \ + config >/dev/null + +echo "Docker Compose configuration is valid." + + +# ============================================================ +# Detect requested Nextcloud image +# +# nextcloud and cron MUST use exactly the same image. +# ============================================================ + +log "Detect requested Nextcloud image" + +mapfile -t NEXTCLOUD_IMAGES < <( + docker compose \ + -f "${SRC}/docker-compose.yml" \ + config --images | + grep '^nextcloud:' | + sort -u +) + + +if [[ "${#NEXTCLOUD_IMAGES[@]}" -ne 1 ]]; then + + echo "Detected Nextcloud images:" + + if (( ${#NEXTCLOUD_IMAGES[@]} > 0 )); then + printf ' %s\n' "${NEXTCLOUD_IMAGES[@]}" + else + echo " none" + fi + + fail "Services nextcloud and cron must use exactly the same Nextcloud image" + +fi + + +NEW_IMAGE="${NEXTCLOUD_IMAGES[0]}" + +echo "Requested image:" +echo " ${NEW_IMAGE}" + + +# ============================================================ +# Current Nextcloud container +# ============================================================ + +docker inspect nextcloud >/dev/null 2>&1 || \ + fail "Current Nextcloud container does not exist" + + +CURRENT_RUNNING="$( + docker inspect \ + -f '{{.State.Running}}' \ + nextcloud +)" + + +[[ "${CURRENT_RUNNING}" == "true" ]] || \ + fail "Current Nextcloud container is not running" + + +OLD_IMAGE="$( + docker inspect \ + -f '{{.Config.Image}}' \ + nextcloud +)" + + +# ============================================================ +# Detect actual current Nextcloud version +# ============================================================ + +log "Detect current Nextcloud version" + +CURRENT_NC_VERSION="$( + docker exec \ + nextcloud \ + php -r ' + require "/var/www/html/version.php"; + echo implode(".", $OC_Version); + ' +)" + + +[[ -n "${CURRENT_NC_VERSION}" ]] || \ + fail "Could not determine current Nextcloud version" + + +echo "Current Docker image:" +echo " ${OLD_IMAGE}" + +echo "Current Nextcloud version:" +echo " ${CURRENT_NC_VERSION}" + + +# ============================================================ +# Pull target Nextcloud image +# +# This does not modify the running container. +# ============================================================ + +log "Pull target Nextcloud image" + +docker pull "${NEW_IMAGE}" + + +# ============================================================ +# Determine actual Nextcloud version in target image +# ============================================================ + +log "Detect target Nextcloud version" + +TARGET_NC_VERSION="$( + docker run \ + --rm \ + --entrypoint php \ + "${NEW_IMAGE}" \ + -r ' + require "/usr/src/nextcloud/version.php"; + echo implode(".", $OC_Version); + ' +)" + + +[[ -n "${TARGET_NC_VERSION}" ]] || \ + fail "Could not determine target Nextcloud version" + + +echo "Target Docker image:" +echo " ${NEW_IMAGE}" + +echo "Target Nextcloud version:" +echo " ${TARGET_NC_VERSION}" + + +# ============================================================ +# Version safety checks +# ============================================================ + +log "Validate version transition" + + +# ------------------------------------------------------------ +# Downgrade protection +# ------------------------------------------------------------ + +if version_less_than \ + "${TARGET_NC_VERSION}" \ + "${CURRENT_NC_VERSION}" +then + + fail \ + "Nextcloud downgrade is not allowed: ${CURRENT_NC_VERSION} -> ${TARGET_NC_VERSION}" + +fi + + +CURRENT_MAJOR="${CURRENT_NC_VERSION%%.*}" +TARGET_MAJOR="${TARGET_NC_VERSION%%.*}" + + +# ------------------------------------------------------------ +# Prevent skipping major versions +# ------------------------------------------------------------ + +if (( TARGET_MAJOR > CURRENT_MAJOR + 1 )) +then + + fail \ + "Skipping Nextcloud major versions is forbidden: ${CURRENT_MAJOR} -> ${TARGET_MAJOR}" + +fi + + +# ------------------------------------------------------------ +# Determine whether actual Nextcloud version changed +# ------------------------------------------------------------ + +VERSION_CHANGED=false + +if [[ "${CURRENT_NC_VERSION}" != "${TARGET_NC_VERSION}" ]] +then + VERSION_CHANGED=true +fi + + +echo "Current version: ${CURRENT_NC_VERSION}" +echo "Target version: ${TARGET_NC_VERSION}" +echo "Version changed: ${VERSION_CHANGED}" + + +# ============================================================ +# Check current Nextcloud status +# ============================================================ + +log "Check current Nextcloud status" + +CURRENT_STATUS="$( + docker exec \ + -u www-data \ + nextcloud \ + php occ status +)" + + +echo "${CURRENT_STATUS}" + + +echo "${CURRENT_STATUS}" | + grep -Eq 'needsDbUpgrade:[[:space:]]*false' || \ + fail "Current Nextcloud already requires a DB upgrade" + + +echo "${CURRENT_STATUS}" | + grep -Eq 'maintenance:[[:space:]]*false' || \ + fail "Current Nextcloud is already in maintenance mode" + + +docker exec \ + -u www-data \ + nextcloud \ + php occ status -e + + +# ============================================================ +# PRE-UPGRADE BACKUP +# +# Created ONLY if actual Nextcloud version changes. +# ============================================================ + +if [[ "${VERSION_CHANGED}" == "true" ]] +then + + log "Prepare Nextcloud pre-upgrade backup" + + + # -------------------------------------------------------- + # Create backup directories + # -------------------------------------------------------- + + mkdir -p "${DB_BACKUP_DIR}" + + + # -------------------------------------------------------- + # Save current Compose + # + # Do NOT use cp -a because this NFS does not support + # preserving all POSIX metadata. + # -------------------------------------------------------- + + echo + echo "--- Backup current docker-compose.yml ---" + + cp \ + "${LIVE}/docker-compose.yml" \ + "${BACKUP_DIR}/docker-compose.yml" + + + # -------------------------------------------------------- + # Save current Nextcloud status + # -------------------------------------------------------- + + printf '%s\n' "${CURRENT_STATUS}" \ + > "${BACKUP_DIR}/nextcloud-status-before.txt" + + + # -------------------------------------------------------- + # Save metadata + # -------------------------------------------------------- + + cat > "${BACKUP_DIR}/metadata.txt" < "${DB_BACKUP_DIR}/postgresql-version.txt" + + + SERVER_MAJOR="${SERVER_VERSION%%.*}" + + + PG_DUMP_VERSION="$( + pg_dump --version | + sed -E 's/.* ([0-9]+(\.[0-9]+)?).*/\1/' + )" + + + PG_DUMP_MAJOR="${PG_DUMP_VERSION%%.*}" + + + echo "PostgreSQL server:" + echo " ${SERVER_VERSION}" + + echo "pg_dump client:" + echo " ${PG_DUMP_VERSION}" + + + if (( PG_DUMP_MAJOR < SERVER_MAJOR )) + then + + fail \ + "pg_dump ${PG_DUMP_VERSION} is older than PostgreSQL server ${SERVER_VERSION}" + + fi + + + # ======================================================== + # Database size + # ======================================================== + + echo + echo "--- Database size ---" + + DB_SIZE="$( + psql \ + -h "${POSTGRES_HOST}" \ + -U "${POSTGRES_USER}" \ + -d "${POSTGRES_DB}" \ + -Atqc \ + 'SELECT pg_size_pretty(pg_database_size(current_database()));' + )" + + + echo "Database:" + echo " ${POSTGRES_DB}" + + echo "Size:" + echo " ${DB_SIZE}" + + + # ======================================================== + # PostgreSQL dump + # ======================================================== + + log "Create PostgreSQL backup" + + pg_dump \ + -h "${POSTGRES_HOST}" \ + -U "${POSTGRES_USER}" \ + -d "${POSTGRES_DB}" \ + --format=custom \ + --no-owner \ + --no-privileges \ + --file="${DB_BACKUP_FILE}" + + + [[ -s "${DB_BACKUP_FILE}" ]] || \ + fail "PostgreSQL dump does not exist or is empty" + + + # ======================================================== + # Validate PostgreSQL dump + # ======================================================== + + echo + echo "--- Validate PostgreSQL dump ---" + + pg_restore \ + --list \ + "${DB_BACKUP_FILE}" \ + > "${DB_BACKUP_DIR}/nextcloud.dump.list" + + + [[ -s "${DB_BACKUP_DIR}/nextcloud.dump.list" ]] || \ + fail "pg_restore could not validate PostgreSQL dump" + + + # ======================================================== + # SHA256 checksum + # ======================================================== + + echo + echo "--- Generate SHA256 ---" + + ( + cd "${DB_BACKUP_DIR}" + + sha256sum \ + nextcloud.dump \ + > nextcloud.dump.sha256 + ) + + + sha256sum \ + -c "${DB_BACKUP_DIR}/nextcloud.dump.sha256" + + + DB_BACKUP_SIZE="$( + du -h "${DB_BACKUP_FILE}" | + awk '{print $1}' + )" + + + echo + echo "PostgreSQL backup successful." + + echo + echo "Backup directory:" + echo " ${BACKUP_DIR}" + + echo + echo "Database dump:" + echo " ${DB_BACKUP_FILE}" + + echo + echo "Dump size:" + echo " ${DB_BACKUP_SIZE}" + + echo + echo "SHA256:" + cat "${DB_BACKUP_DIR}/nextcloud.dump.sha256" + + + # ======================================================== + # Backup retention + # + # The new backup has already been successfully validated, + # so it is now safe to remove older backups. + # ======================================================== + + cleanup_old_backups + +fi + + +# ============================================================ +# Deploy requested Compose +# +# Production is not touched until pre-upgrade backup succeeds. +# ============================================================ + +log "Deploy docker-compose.yml" + +cp \ + "${SRC}/docker-compose.yml" \ + "${LIVE}/docker-compose.yml" + + +cd "${LIVE}" + + +# ============================================================ +# Pull all Compose images +# ============================================================ + +log "Pull Docker images" + +docker compose pull + + +# ============================================================ +# NEXTCLOUD VERSION UPGRADE +# ============================================================ + +if [[ "${VERSION_CHANGED}" == "true" ]] +then + + log "Nextcloud upgrade ${CURRENT_NC_VERSION} -> ${TARGET_NC_VERSION}" + + + # ======================================================== + # Stop cron during application/DB upgrade + # ======================================================== + + echo + echo "--- Stop Nextcloud cron ---" + + docker compose stop cron || true + + + # ======================================================== + # Timestamp used for startup log analysis + # ======================================================== + + UPGRADE_STARTED="$( + date -u '+%Y-%m-%dT%H:%M:%SZ' + )" + + + # ======================================================== + # Recreate ONLY main Nextcloud container first + # + # Redis remains running. + # Cron remains stopped. + # ======================================================== + + echo + echo "--- Recreate Nextcloud container ---" + + docker compose \ + up -d \ + --no-deps \ + nextcloud + + + # ======================================================== + # Wait for official Nextcloud Docker entrypoint + # + # The official image may execute occ upgrade automatically. + # + # 180 * 5 sec = 15 minutes maximum. + # ======================================================== + + log "Wait for Nextcloud initialization" + + INITIALIZED=false + + for _ in $(seq 1 180) + do + + RUNNING="$( + docker inspect \ + -f '{{.State.Running}}' \ + nextcloud 2>/dev/null || + echo false + )" + + + if [[ "${RUNNING}" != "true" ]] + then + + echo + echo "--- Nextcloud container log ---" + + docker logs \ + --since "${UPGRADE_STARTED}" \ + nextcloud || true + + fail "Nextcloud container stopped during upgrade" + + fi + + + STARTUP_LOG="$( + docker logs \ + --since "${UPGRADE_STARTED}" \ + nextcloud 2>&1 || true + )" + + + # Explicit failure from Nextcloud upgrade. + if echo "${STARTUP_LOG}" | + grep -q 'Update failed' + then + + echo "${STARTUP_LOG}" + + fail "Nextcloud automatic upgrade failed" + + fi + + + # Standard completion marker of official image. + if echo "${STARTUP_LOG}" | + grep -q 'Initializing finished' + then + + INITIALIZED=true + break + + fi + + + sleep 5 + + done + + + if [[ "${INITIALIZED}" != "true" ]] + then + + echo + echo "--- Nextcloud container log ---" + + docker logs \ + --since "${UPGRADE_STARTED}" \ + nextcloud || true + + fail "Timeout waiting for Nextcloud initialization" + + fi + + + # ======================================================== + # Capture entrypoint upgrade result + # ======================================================== + + log "Nextcloud startup upgrade output" + + STARTUP_LOG="$( + docker logs \ + --since "${UPGRADE_STARTED}" \ + nextcloud 2>&1 + )" + + + echo "${STARTUP_LOG}" + + + STARTUP_UPDATE_SUCCESS=false + + + if echo "${STARTUP_LOG}" | + grep -q 'Update successful' + then + + STARTUP_UPDATE_SUCCESS=true + + fi + + + echo + echo "Startup log contains 'Update successful':" + echo " ${STARTUP_UPDATE_SUCCESS}" + + + # ======================================================== + # Explicit OCC upgrade + # + # If Docker entrypoint already performed the migration, + # occ upgrade can report that Nextcloud is already current. + # ======================================================== + + log "Run explicit occ upgrade" + + set +e + + OCC_UPGRADE_OUTPUT="$( + docker exec \ + -u www-data \ + nextcloud \ + php occ upgrade 2>&1 + )" + + OCC_UPGRADE_RC=$? + + set -e + + + echo "${OCC_UPGRADE_OUTPUT}" + + + if [[ "${OCC_UPGRADE_RC}" -ne 0 ]] + then + + fail \ + "Explicit occ upgrade returned exit code ${OCC_UPGRADE_RC}" + + fi + + + EXPLICIT_UPDATE_SUCCESS=false + EXPLICIT_ALREADY_CURRENT=false + + + if echo "${OCC_UPGRADE_OUTPUT}" | + grep -q 'Update successful' + then + + EXPLICIT_UPDATE_SUCCESS=true + + fi + + + if echo "${OCC_UPGRADE_OUTPUT}" | + grep -Eqi \ + 'already.*(latest|up.?to.?date)|(is|already).*up.?to.?date' + then + + EXPLICIT_ALREADY_CURRENT=true + + fi + + + echo + echo "Explicit occ upgrade contains 'Update successful':" + echo " ${EXPLICIT_UPDATE_SUCCESS}" + + echo "Explicit occ upgrade reports already current:" + echo " ${EXPLICIT_ALREADY_CURRENT}" + + + # ======================================================== + # Require confirmed update + # + # Either: + # Docker entrypoint -> Update successful + # + # or: + # explicit occ upgrade -> Update successful + # + # ======================================================== + + if [[ "${STARTUP_UPDATE_SUCCESS}" != "true" ]] && + [[ "${EXPLICIT_UPDATE_SUCCESS}" != "true" ]] + then + + if [[ "${EXPLICIT_ALREADY_CURRENT}" == "true" ]] + then + + echo + echo "occ reports that Nextcloud is already current," + echo "but 'Update successful' was not found in either" + echo "the startup log or explicit occ upgrade output." + + fi + + fail "Could not confirm 'Update successful'" + + fi + + + # ======================================================== + # Validate Nextcloud state after DB migration + # ======================================================== + + log "Validate Nextcloud status after upgrade" + + FINAL_STATUS="$( + docker exec \ + -u www-data \ + nextcloud \ + php occ status + )" + + + echo "${FINAL_STATUS}" + + + echo "${FINAL_STATUS}" | + grep -Eq 'needsDbUpgrade:[[:space:]]*false' || \ + fail "needsDbUpgrade is not false" + + + echo "${FINAL_STATUS}" | + grep -Eq 'maintenance:[[:space:]]*false' || \ + fail "maintenance is not false" + + + # -------------------------------------------------------- + # Nextcloud: + # + # 0 = normal + # 1 = maintenance + # 2 = DB upgrade required + # -------------------------------------------------------- + + docker exec \ + -u www-data \ + nextcloud \ + php occ status -e + + + echo + echo "Nextcloud database state validated successfully." + + + # ======================================================== + # Start cron using upgraded image + # ======================================================== + + log "Start Nextcloud cron" + + docker compose \ + up -d \ + --no-deps \ + cron + + + # ======================================================== + # Apply remaining Compose changes + # ======================================================== + + log "Apply remaining Compose changes" + + docker compose \ + up -d \ + --remove-orphans + + +# ============================================================ +# NO NEXTCLOUD VERSION CHANGE +# ============================================================ + +else + + log "No Nextcloud version change" + + echo "Current version:" + echo " ${CURRENT_NC_VERSION}" + + docker compose \ + up -d \ + --remove-orphans + +fi + + +# ============================================================ +# Final container checks +# ============================================================ + +log "Final container checks" + +for CONTAINER in \ + nextcloud \ + nextcloud-cron \ + nextcloud-redis +do + + RUNNING="$( + docker inspect \ + -f '{{.State.Running}}' \ + "${CONTAINER}" 2>/dev/null || + echo false + )" + + + if [[ "${RUNNING}" != "true" ]] + then + + fail "${CONTAINER} is not running" + + fi + + + echo "${CONTAINER}: running" + +done + + +# ============================================================ +# Final Nextcloud status +# ============================================================ + +log "Final OCC status" + +FINAL_STATUS="$( + docker exec \ + -u www-data \ + nextcloud \ + php occ status +)" + + +echo "${FINAL_STATUS}" + + +echo "${FINAL_STATUS}" | + grep -Eq 'needsDbUpgrade:[[:space:]]*false' || \ + fail "Final needsDbUpgrade is not false" + + +echo "${FINAL_STATUS}" | + grep -Eq 'maintenance:[[:space:]]*false' || \ + fail "Final maintenance is not false" + + +docker exec \ + -u www-data \ + nextcloud \ + php occ status -e + + +# ============================================================ +# Show actual running version +# ============================================================ + +RUNNING_NC_VERSION="$( + docker exec \ + nextcloud \ + php -r ' + require "/var/www/html/version.php"; + echo implode(".", $OC_Version); + ' +)" + + +RUNNING_IMAGE="$( + docker inspect \ + -f '{{.Config.Image}}' \ + nextcloud +)" + + +# ============================================================ +# Success +# ============================================================ + +log "Nextcloud deployment successful" + +echo "Previous Nextcloud version:" +echo " ${CURRENT_NC_VERSION}" + +echo +echo "Running Nextcloud version:" +echo " ${RUNNING_NC_VERSION}" + +echo +echo "Previous Docker image:" +echo " ${OLD_IMAGE}" + +echo +echo "Running Docker image:" +echo " ${RUNNING_IMAGE}" + + +if [[ "${VERSION_CHANGED}" == "true" ]] +then + + echo + echo "Pre-upgrade backup:" + echo " ${BACKUP_DIR}" + + echo + echo "PostgreSQL dump:" + echo " ${DB_BACKUP_FILE}" + + echo + echo "Backup retention:" + echo " last ${BACKUP_KEEP} backups" + +fi + + +# ============================================================ +# Remove credentials from process environment +# ============================================================ + +unset PGPASSWORD +unset POSTGRES_PASSWORD diff --git a/stacks/nextcloud/docker-compose.yml b/stacks/nextcloud/docker-compose.yml new file mode 100644 index 0000000..43e9d18 --- /dev/null +++ b/stacks/nextcloud/docker-compose.yml @@ -0,0 +1,91 @@ +services: + + nextcloud: + image: nextcloud:35.0.1 + container_name: nextcloud + restart: unless-stopped + + env_file: + - /srv/nfs/infra/nextcloud/.env + + environment: + OVERWRITEHOST: "nc.zk-tech.info" + OVERWRITEPROTOCOL: "https" + + TRUSTED_PROXIES: "127.0.0.1,172.19.0.0/16,172.19.0.15" + NEXTCLOUD_TRUSTED_DOMAINS: "nc.zk-tech.info" + + UPLOAD_MAX_FILESIZE: "16G" + POST_MAX_FILE_SIZE: "16G" + + PHP_MEMORY_LIMIT: "4G" + PHP_UPLOAD_LIMIT: "16G" + + REDIS_HOST: "redis" + + volumes: + - /srv/nfs/infra/nextcloud/config:/var/www/html/config + - /srv/nfs/infra/nextcloud/data:/var/www/html/data + - /srv/nfs/infra/nextcloud/apps:/var/www/html/custom_apps + - /srv/nfs/infra/nextcloud/themes:/var/www/html/themes + - /srv/nfs/infra/nextcloud/config/php/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro + + depends_on: + - redis + + networks: + - default + - interdock + + + cron: + image: nextcloud:35.0.1 + container_name: nextcloud-cron + restart: unless-stopped + + entrypoint: /cron.sh + + env_file: + - /srv/nfs/infra/nextcloud/.env + + environment: + REDIS_HOST: "redis" + + volumes: + - /srv/nfs/infra/nextcloud/config:/var/www/html/config + - /srv/nfs/infra/nextcloud/data:/var/www/html/data + - /srv/nfs/infra/nextcloud/apps:/var/www/html/custom_apps + - /srv/nfs/infra/nextcloud/themes:/var/www/html/themes + + depends_on: + - redis + + networks: + - default + + + redis: + image: redis:rc-32bit-buster + container_name: nextcloud-redis + restart: unless-stopped + + command: + - redis-server + - --appendonly + - "yes" + + volumes: + - redis-data:/data + + networks: + - default + + +volumes: + redis-data: + driver: local + + +networks: + interdock: + external: true