157 lines
4.3 KiB
Bash
Executable File
157 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# sync-nextcloud-ecosystem-conf.sh
|
|
#
|
|
# Pull/push a fixed set of server files under /data to a local git-tracked tree,
|
|
# preserving folder structure but stripping the leading "/data".
|
|
#
|
|
# Requires: rsync, ssh
|
|
#
|
|
# Examples:
|
|
# ./sync-nextcloud-ecosystem-conf.sh pull
|
|
# ./sync-nextcloud-ecosystem-conf.sh push --dry-run
|
|
# ./sync-nextcloud-ecosystem-conf.sh pull --host henrov@nextcloud.data-pro.nu --port 22
|
|
#
|
|
# Notes:
|
|
# - Uses remote sudo via: --rsync-path="sudo rsync"
|
|
# - Allocates a TTY for sudo prompting with ssh -tt
|
|
# - Transfers ONLY the listed files (push and pull)
|
|
|
|
DEFAULT_HOST="henrov@nextcloud.data-pro.nu"
|
|
DEFAULT_PORT="22"
|
|
DEFAULT_REMOTE_BASE="/data"
|
|
DEFAULT_LOCAL_ROOT="$HOME/Repos/nextcloud_ecosystem/conf"
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage:
|
|
sync-nextcloud-ecosystem-conf.sh <pull|push> [--host USER@HOST] [--port N] [--local-root PATH] [--dry-run]
|
|
|
|
Options:
|
|
--host USER@HOST SSH target (default: henrov@nextcloud.data-pro.nu)
|
|
--port N SSH port (default: 22)
|
|
--local-root PATH Local destination root (default: ~/Repos/nextcloud_ecosystem/conf)
|
|
--dry-run Show what would change without writing (rsync -n + itemize)
|
|
-h, --help Show this help
|
|
|
|
Behavior:
|
|
pull: server:/data/<paths> -> local-root/<paths>
|
|
push: local-root/<paths> -> server:/data/<paths>
|
|
|
|
Always overwrites destination files (as rsync updates them). Preserves timestamps.
|
|
|
|
USAGE
|
|
}
|
|
|
|
MODE="${1:-}"
|
|
shift || true
|
|
|
|
HOST="$DEFAULT_HOST"
|
|
PORT="$DEFAULT_PORT"
|
|
REMOTE_BASE="$DEFAULT_REMOTE_BASE"
|
|
LOCAL_ROOT="$DEFAULT_LOCAL_ROOT"
|
|
DRY_RUN=0
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--host) HOST="${2:?missing value for --host}"; shift 2 ;;
|
|
--port) PORT="${2:?missing value for --port}"; shift 2 ;;
|
|
--local-root) LOCAL_ROOT="${2:?missing value for --local-root}"; shift 2 ;;
|
|
--dry-run) DRY_RUN=1; shift ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) echo "Unknown argument: $1" >&2; usage; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
if [[ "$MODE" != "pull" && "$MODE" != "push" ]]; then
|
|
echo "Error: first argument must be 'pull' or 'push'." >&2
|
|
usage
|
|
exit 2
|
|
fi
|
|
|
|
mkdir -p "$LOCAL_ROOT"
|
|
|
|
# File list is RELATIVE to /data, so /data is effectively "stripped" on local.
|
|
# Only these files are transferred in either direction.
|
|
read -r -d '' FILES_FROM <<'EOF' || true
|
|
caddy/Caddyfile
|
|
nextcloud/config/config.php
|
|
nextcloud/php/conf.d/opcache.ini
|
|
signaling/config/server.conf
|
|
janus/janus.transport.http.jcfg
|
|
janus/janus.transport.websockets.jcfg
|
|
gitlab/config/gitlab.rb
|
|
EOF
|
|
|
|
tmp_files_from="$(mktemp)"
|
|
cleanup() { rm -f "$tmp_files_from"; }
|
|
trap cleanup EXIT
|
|
printf "%s\n" "$FILES_FROM" > "$tmp_files_from"
|
|
|
|
# rsync options:
|
|
# -a : archive (recursive, preserve perms, etc.)
|
|
# -t : preserve times (also included in -a, but explicit for clarity)
|
|
# -v : verbose
|
|
# --itemize-changes: useful output, especially with --dry-run
|
|
# --files-from: copy only specified files
|
|
# --relative not needed because paths are already relative to REMOTE_BASE/LOCAL_ROOT
|
|
#
|
|
# Excludes (mostly relevant if you ever extend this to directories):
|
|
# *~ , *.swp / *.sw? , *.tmp
|
|
RSYNC_OPTS=(
|
|
-avt
|
|
--itemize-changes
|
|
--files-from="$tmp_files_from"
|
|
--exclude='*~'
|
|
--exclude='*.swp'
|
|
--exclude='*.sw?'
|
|
--exclude='*.tmp'
|
|
)
|
|
|
|
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
RSYNC_OPTS+=(
|
|
--dry-run
|
|
)
|
|
fi
|
|
|
|
# Use ssh with a TTY so sudo can prompt on the remote end if needed.
|
|
SSH_CMD=(ssh -T -p "$PORT")
|
|
|
|
# Remote sudo for rsync (read/write privileged files)
|
|
|
|
# Preflight: ensure sudo won't prompt during rsync
|
|
if ! ssh -p "$PORT" "$HOST" 'sudo -n true' >/dev/null 2>&1; then
|
|
echo "[warn] Remote sudo needs authentication. Running 'sudo -v' interactively once..."
|
|
ssh -t -p "$PORT" "$HOST" 'sudo -v'
|
|
fi
|
|
|
|
REMOTE_RSYNC_PATH='sudo -n rsync'
|
|
|
|
REMOTE_SRC="${HOST}:${REMOTE_BASE}/"
|
|
REMOTE_DST="${HOST}:${REMOTE_BASE}/"
|
|
|
|
LOCAL_SRC="${LOCAL_ROOT}/"
|
|
LOCAL_DST="${LOCAL_ROOT}/"
|
|
|
|
echo "[info] mode=$MODE host=$HOST port=$PORT"
|
|
echo "[info] remote_base=$REMOTE_BASE"
|
|
echo "[info] local_root=$LOCAL_ROOT"
|
|
[[ "$DRY_RUN" -eq 1 ]] && echo "[info] dry-run enabled"
|
|
|
|
if [[ "$MODE" == "pull" ]]; then
|
|
# server -> local
|
|
rsync "${RSYNC_OPTS[@]}" \
|
|
-e "${SSH_CMD[*]}" \
|
|
--rsync-path="$REMOTE_RSYNC_PATH" \
|
|
"$REMOTE_SRC" "$LOCAL_DST"
|
|
else
|
|
# local -> server
|
|
rsync "${RSYNC_OPTS[@]}" \
|
|
-e "${SSH_CMD[*]}" \
|
|
--rsync-path="$REMOTE_RSYNC_PATH" \
|
|
"$LOCAL_SRC" "$REMOTE_DST"
|
|
fi
|
|
|
|
echo "[ok] done"
|