#!/bin/bash # deploy-nextcloud-credentials.sh — деплой кредов Nextcloud в CT 101 # Секреты из Vaultwarden (объект NEXTCLOUD). Атомарная запись .env, обновление config.php через occ. # # Использование: # /root/scripts/deploy-nextcloud-credentials.sh # /root/scripts/deploy-nextcloud-credentials.sh --dry-run # # Ротация: сменил пароль/ключи в Vaultwarden → запустил скрипт → docker compose up -d --force-recreate # # Требования: bw, jq, /root/.bw-master (chmod 600) set -e CT_ID=101 NEXTCLOUD_PATH="/opt/nextcloud" CONFIG_PATH="/mnt/nextcloud-data/html/config/config.php" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BW_MASTER_FILE="${BW_MASTER_PASSWORD_FILE:-/root/.bw-master}" DRY_RUN=false for arg in "$@"; do case "$arg" in --dry-run) DRY_RUN=true ;; esac done export PATH="/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PATH}" log() { echo "[$(date -Iseconds)] $*"; } err() { echo "[$(date -Iseconds)] ERROR: $*" >&2; } ensure_bw_unlocked() { local status status=$(bw status 2>/dev/null | jq -r '.status' 2>/dev/null || echo "unknown") if [ "$status" = "unlocked" ]; then log "bw already unlocked, reusing session" return 0 fi if [ ! -f "$BW_MASTER_FILE" ]; then err "Missing $BW_MASTER_FILE" exit 1 fi export BW_SESSION=$(bw unlock --passwordfile "$BW_MASTER_FILE" --raw 2>/dev/null) || { err "bw unlock failed" exit 1 } log "bw unlocked" } get_secrets() { local item item=$(bw get item "NEXTCLOUD" 2>/dev/null) POSTGRES_PASSWORD=$(bw get password "NEXTCLOUD" 2>/dev/null) NEXTCLOUD_TRUSTED_DOMAINS=$(echo "$item" | jq -r '.fields[] | select(.name=="NEXTCLOUD_TRUSTED_DOMAINS") | .value // empty') DBPASSWORD=$(echo "$item" | jq -r '.fields[] | select(.name=="dbpassword") | .value // empty') SECRET=$(echo "$item" | jq -r '.fields[] | select(.name=="secret") | .value // empty') PASSWORDSALT=$(echo "$item" | jq -r '.fields[] | select(.name=="passwordsalt") | .value // empty') INSTANCEID=$(echo "$item" | jq -r '.fields[] | select(.name=="instanceid") | .value // empty') if [ -z "$POSTGRES_PASSWORD" ]; then err "NEXTCLOUD: missing password (POSTGRES_PASSWORD)" exit 1 fi NEXTCLOUD_TRUSTED_DOMAINS="${NEXTCLOUD_TRUSTED_DOMAINS:-cloud.katykhin.ru 192.168.1.101}" } gen_env() { local tmp tmp=$(mktemp) cat > "$tmp" << EOF POSTGRES_PASSWORD=${POSTGRES_PASSWORD} NEXTCLOUD_TRUSTED_DOMAINS=${NEXTCLOUD_TRUSTED_DOMAINS} EOF echo "$tmp" } push_env_atomic() { local tmp="$1" < "$tmp" pct exec "$CT_ID" -- bash -c "cat > ${NEXTCLOUD_PATH}/.env.tmp && chmod 600 ${NEXTCLOUD_PATH}/.env.tmp && mv ${NEXTCLOUD_PATH}/.env.tmp ${NEXTCLOUD_PATH}/.env" log ".env written (atomic), chmod 600" } push_compose() { local compose_src="${SCRIPT_DIR}/nextcloud/docker-compose.yml" if [ -f "$compose_src" ]; then pct push "$CT_ID" "$compose_src" "${NEXTCLOUD_PATH}/docker-compose.yml" log "docker-compose.yml pushed" fi } update_config_occ() { [ -n "$DBPASSWORD" ] && pct exec "$CT_ID" -- docker exec nextcloud-nextcloud-1 php /var/www/html/occ config:system:set dbpassword --value="$DBPASSWORD" 2>/dev/null || true [ -n "$SECRET" ] && pct exec "$CT_ID" -- docker exec nextcloud-nextcloud-1 php /var/www/html/occ config:system:set secret --value="$SECRET" 2>/dev/null || true [ -n "$PASSWORDSALT" ] && pct exec "$CT_ID" -- docker exec nextcloud-nextcloud-1 php /var/www/html/occ config:system:set passwordsalt --value="$PASSWORDSALT" 2>/dev/null || true [ -n "$INSTANCEID" ] && pct exec "$CT_ID" -- docker exec nextcloud-nextcloud-1 php /var/www/html/occ config:system:set instanceid --value="$INSTANCEID" 2>/dev/null || true log "config.php updated via occ" } run_compose() { pct exec "$CT_ID" -- bash -c "cd ${NEXTCLOUD_PATH} && docker compose up -d --force-recreate" log "Nextcloud started" } main() { log "deploy-nextcloud-credentials start (dry_run=$DRY_RUN)" ensure_bw_unlocked get_secrets if [ "$DRY_RUN" = true ]; then log "DRY-RUN: would push .env, compose, update config, run compose" log " POSTGRES_PASSWORD=***" exit 0 fi tmp=$(gen_env) trap "rm -f $tmp" EXIT push_env_atomic "$tmp" push_compose run_compose update_config_occ log "done" } main