#!/usr/bin/env bash set -euo pipefail usage() { cat >&2 <<'USAGE' usage: klops.sh run-remote [args...] klops.sh wg klops.sh homepage klops.sh quadlets klops.sh pkg-site klops.sh site klops.sh site-index klops.sh ci [luci-quadlet] klops.sh gc klops.sh caddyfile USAGE exit 2 } repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" brand_svg="${repo_root}/assets/bugabinga.min.svg" nugu_css="${repo_root}/assets/nugu.css" cmd="${1:-}" [ -n "${cmd}" ] || usage shift run_with_ssh_cooldown() { local status=0 "$@" || status=$? sleep 2 return "${status}" } ssh_run() { run_with_ssh_cooldown ssh "$@"; } scp_run() { run_with_ssh_cooldown scp "$@"; } rsync_run() { run_with_ssh_cooldown rsync "$@"; } run_remote() { [ "$#" -ge 4 ] || usage local host="$1" port="$2" user="$3" script="$4" shift 4 ssh_run -p "${port}" "${user}@${host}" 'bash -s' -- "$@" <"${script}" } validate_luci_quadlet() ( local source_dir="$1" luci_quadlet="$2" rendered rendered="$(mktemp -d)" trap 'rm -rf "${rendered}"' EXIT cp -a "${source_dir}/." "${rendered}/" cp "${luci_quadlet}" "${rendered}/luci.container" QUADLET_UNIT_DIRS="${rendered}" /usr/lib/systemd/system-generators/podman-system-generator --user --dryrun ) case "${cmd}" in run-remote) run_remote "$@" ;; wg) [ "$#" -eq 3 ] || usage host="$1" port="$2" wg_conf="$3" scp_run -P "${port}" "${wg_conf}" "root@${host}:/root/wg0.conf" run_remote "${host}" "${port}" root "${repo_root}/scripts/remote/apply-wg.sh" ;; homepage) [ "$#" -eq 5 ] || usage host="$1" port="$2" user="$3" homepage_dir="$4" icon_file="$5" ssh_user="${user}@${host}" ssh_run -p "${port}" "${ssh_user}" 'mkdir -p /data/Databases/homepage/config /data/Databases/homepage/icons' rsync_run -az --no-owner --no-group -e "ssh -p ${port}" "${homepage_dir}/" "${ssh_user}:/data/Databases/homepage/config/" scp_run -P "${port}" "${nugu_css}" "${ssh_user}:/data/Databases/homepage/config/nugu.css" scp_run -P "${port}" "${icon_file}" "${ssh_user}:/data/Databases/homepage/icons/$(basename "${icon_file}")" ssh_run -p "${port}" "${ssh_user}" 'chmod 600 /data/Databases/homepage/config/homepage.env && systemctl --user try-restart homepage.service || true' ;; quadlets) [ "$#" -eq 16 ] || usage host="$1" port="$2" user="$3" quadlets_dir="$4" luigit_dir="$5" ddns_quadlet="$6" soft_serve_quadlet="$7" soft_serve_env="$8" zot_config="$9" zot_htpasswd="${10}" hallucygenie_env="${11}" hallucygenie_basic_auth="${12}" toad_basic_auth="${13}" paperless_env="${14}" quest_log_env="${15}" remote_restart_script="${16}" ssh_user="${user}@${host}" ssh_run -p "${port}" "${ssh_user}" 'mkdir -p ~/.config/containers/systemd/ ~/.config/systemd/user/ /data/Databases/soft-serve /data/Databases/zot /data/Databases/zot/storage /data/Databases/hallucygenie/data /data/Databases/quest-log/data /data/Databases/caddy/etc /data/Databases/jellyfin/config/config /data/vcs/public/repos /data/vcs/luigit-source /data/vcs/luigit-manifest /data/vcs/luigit-derived /data/pkg/arch /data/pkg/releases /data/pkg/www /data/sites /data/sites/registry-overrides/assets /data/sites/dawarich-overrides/assets && rm -f /data/Databases/vaultwarden/templates/scss/user.vaultwarden.scss.hbs' ssh_run -p "${port}" "root@${host}" 'mkdir -p /data/Databases/paperless/media/logo' scp_run -P "${port}" "${repo_root}/assets/jellyfin-branding.xml" "root@${host}:/data/Databases/jellyfin/config/config/branding.xml" scp_run -P "${port}" "${brand_svg}" "root@${host}:/data/Databases/paperless/media/logo/bugabinga-logo.svg" scp_run -P "${port}" "${repo_root}/assets/registry/index-BAkATJzA.css" "${ssh_user}:/data/sites/registry-overrides/assets/index-BAkATJzA.css" scp_run -P "${port}" "${repo_root}/assets/dawarich/application-b5a7662b4bd877f1de1fe5769d2b98adfa15a8095b784d392ae1154df6f3b865.js" "${ssh_user}:/data/sites/dawarich-overrides/assets/application-b5a7662b4bd877f1de1fe5769d2b98adfa15a8095b784d392ae1154df6f3b865.js" ssh_run -p "${port}" "root@${host}" "chown ${user}:${user} /data/Databases/jellyfin/config/config/branding.xml && chmod 0644 /data/Databases/jellyfin/config/config/branding.xml && chown --reference=/data/Databases/paperless/media /data/Databases/paperless/media/logo /data/Databases/paperless/media/logo/bugabinga-logo.svg && chmod 0755 /data/Databases/paperless/media/logo && chmod 0644 /data/Databases/paperless/media/logo/bugabinga-logo.svg && rm -f /data/Databases/paperless/media/overrides.css" rsync_run -az --delete --no-owner --no-group -e "ssh -p ${port}" "${quadlets_dir}/" "${ssh_user}:~/.config/containers/systemd/" ssh_run -p "${port}" "${ssh_user}" 'cp ~/.config/containers/systemd/*.timer ~/.config/systemd/user/ 2>/dev/null || true' rsync_run -az --delete --exclude target --no-owner --no-group -e "ssh -p ${port}" "${luigit_dir}/" "${ssh_user}:/data/vcs/luigit-source/" scp_run -P "${port}" "${nugu_css}" "${ssh_user}:/data/vcs/luigit-source/src/nugu.css" scp_run -P "${port}" "${ddns_quadlet}" "${ssh_user}:~/.config/containers/systemd/ddns.container" scp_run -P "${port}" "${soft_serve_quadlet}" "${ssh_user}:~/.config/containers/systemd/soft-serve.container" scp_run -P "${port}" "${soft_serve_env}" "${ssh_user}:/data/Databases/soft-serve/soft-serve.env" scp_run -P "${port}" "${zot_config}" "${ssh_user}:/data/Databases/zot/config.json" scp_run -P "${port}" "${zot_htpasswd}" "${ssh_user}:/data/Databases/zot/htpasswd" scp_run -P "${port}" "${hallucygenie_env}" "${ssh_user}:/data/Databases/hallucygenie/hallucygenie.env" scp_run -P "${port}" "${hallucygenie_basic_auth}" "${ssh_user}:/data/Databases/caddy/etc/genie-basicauth.caddy" scp_run -P "${port}" "${toad_basic_auth}" "${ssh_user}:/data/Databases/caddy/etc/toad-basicauth.caddy" scp_run -P "${port}" "${paperless_env}" "${ssh_user}:/data/Databases/paperless/paperless.env" scp_run -P "${port}" "${quest_log_env}" "${ssh_user}:/data/Databases/quest-log/quest-log.env" ssh_run -p "${port}" "${ssh_user}" 'podman build -t localhost/bugabinga-luigit:1 /data/vcs/luigit-source' ssh_run -p "${port}" "${ssh_user}" 'bash -s' <"${remote_restart_script}" ;; pkg-site) [ "$#" -eq 4 ] || usage host="$1" port="$2" user="$3" site_dir="$4" ssh_user="${user}@${host}" ssh_run -p "${port}" "${ssh_user}" 'mkdir -p /data/pkg/www' rsync_run -az --delete --no-owner --no-group -e "ssh -p ${port}" "${site_dir}/" "${ssh_user}:/data/pkg/www/" scp_run -P "${port}" "${brand_svg}" "${ssh_user}:/data/pkg/www/bugabinga.min.svg" scp_run -P "${port}" "${nugu_css}" "${ssh_user}:/data/pkg/www/nugu.css" ;; site) [ "$#" -eq 5 ] || usage host="$1" port="$2" user="$3" site_dir="$4" site_name="$5" ssh_user="${user}@${host}" ssh_run -p "${port}" "${ssh_user}" "mkdir -p /data/sites/${site_name}" rsync_run -az --delete --no-owner --no-group -e "ssh -p ${port}" "${site_dir}/" "${ssh_user}:/data/sites/${site_name}/" scp_run -P "${port}" "${brand_svg}" "${ssh_user}:/data/sites/${site_name}/bugabinga.min.svg" scp_run -P "${port}" "${nugu_css}" "${ssh_user}:/data/sites/${site_name}/nugu.css" ;; site-index) [ "$#" -eq 4 ] || usage host="$1" port="$2" user="$3" site_dir="$4" ssh_user="${user}@${host}" ssh_run -p "${port}" "${ssh_user}" 'mkdir -p /data/sites' rsync_run -az --no-owner --no-group --no-perms --omit-dir-times -e "ssh -p ${port}" "${site_dir}/" "${ssh_user}:/data/sites/" scp_run -P "${port}" "${nugu_css}" "${ssh_user}:/data/sites/nugu.css" ;; ci) [ "$#" -eq 4 ] || [ "$#" -eq 5 ] || usage host="$1" port="$2" publish_user="$3" ci_quadlets_dir="$4" luci_quadlet="${5:-}" if [ -n "${luci_quadlet}" ]; then validate_luci_quadlet "${ci_quadlets_dir}" "${luci_quadlet}" fi run_remote "${host}" "${port}" root "${repo_root}/scripts/remote/setup-ci-user.sh" "${publish_user}" scp_run -P "${port}" "${nugu_css}" "root@${host}:/data/ci/nugu.css" rsync_run -az --no-owner --no-group -e "ssh -p ${port}" "${ci_quadlets_dir}/" "root@${host}:/home/ci/.config/containers/systemd/" if [ -n "${luci_quadlet}" ]; then remote_luci=/home/ci/.config/containers/systemd/luci.container remote_stage="${remote_luci}.new.$$" scp_run -P "${port}" "${luci_quadlet}" "root@${host}:${remote_stage}" ssh_run -p "${port}" "root@${host}" "chown ci:ci '${remote_stage}' && chmod 0644 '${remote_stage}' && mv -f '${remote_stage}' '${remote_luci}'" fi run_remote "${host}" "${port}" root "${repo_root}/scripts/remote/start-luci.sh" ;; gc) [ "$#" -eq 5 ] || usage host="$1" port="$2" service_user="$3" ci_user="$4" toad_user="$5" scp_run -P "${port}" "${repo_root}/scripts/remote/check-maintenance.sh" "root@${host}:/usr/local/sbin/bugabinga-check-maintenance" ssh_run -p "${port}" "root@${host}" 'chmod 0755 /usr/local/sbin/bugabinga-check-maintenance' run_remote "${host}" "${port}" root "${repo_root}/scripts/remote/setup-garbage-collection.sh" "${service_user}" "${ci_user}" "${toad_user}" ;; caddyfile) [ "$#" -eq 4 ] || usage host="$1" port="$2" user="$3" caddyfile="$4" ssh_user="${user}@${host}" scp_run -P "${port}" "${caddyfile}" "${ssh_user}:/data/Databases/caddy/etc/Caddyfile" ssh_run -p "${port}" "${ssh_user}" 'systemctl --user restart caddy.service' ;; *) usage ;; esac