#!/usr/bin/env bash set -euo pipefail usage() { cat <<'EOF' >&2 Usage: ladill-hosting-admin self-check ladill-hosting-admin mkdir ladill-hosting-admin chown ladill-hosting-admin chmod ladill-hosting-admin write-file ladill-hosting-admin symlink ladill-hosting-admin nginx-test ladill-hosting-admin reload-nginx ladill-hosting-admin certbot-webroot ladill-hosting-admin certbot-renew ladill-hosting-admin run-cmd ladill-hosting-admin read-file EOF exit 64 } require_abs_path() { local path="${1:-}" if [[ -z "$path" || "${path#/}" == "$path" ]]; then echo "Expected an absolute path, got: $path" >&2 exit 64 fi } ensure_domain() { local value="${1:-}" if [[ ! "$value" =~ ^[A-Za-z0-9.-]+$ ]]; then echo "Invalid domain: $value" >&2 exit 64 fi } ensure_owner_group() { local value="${1:-}" if [[ ! "$value" =~ ^[A-Za-z_][A-Za-z0-9_-]*:[A-Za-z_][A-Za-z0-9_-]*$ ]]; then echo "Invalid owner:group value: $value" >&2 exit 64 fi } ensure_mode() { local value="${1:-}" if [[ ! "$value" =~ ^[0-7]{3,4}$ && ! "$value" =~ ^[ugoa,+-=rwxX]+$ ]]; then echo "Invalid chmod mode: $value" >&2 exit 64 fi } command="${1:-}" case "$command" in self-check) exit 0 ;; mkdir) [[ $# -eq 2 ]] || usage require_abs_path "$2" exec mkdir -p "$2" ;; chown) [[ $# -eq 3 ]] || usage ensure_owner_group "$2" require_abs_path "$3" exec chown -R "$2" "$3" ;; chmod) [[ $# -eq 3 ]] || usage ensure_mode "$2" require_abs_path "$3" exec chmod "$2" "$3" ;; write-file) [[ $# -eq 3 ]] || usage require_abs_path "$2" tmpfile="$(mktemp)" trap 'rm -f "$tmpfile"' EXIT printf '%s' "$3" | base64 --decode > "$tmpfile" install -m 0644 "$tmpfile" "$2" rm -f "$tmpfile" trap - EXIT ;; symlink) [[ $# -eq 3 ]] || usage require_abs_path "$2" require_abs_path "$3" exec ln -sfn "$2" "$3" ;; nginx-test) exec nginx -t ;; reload-nginx) exec systemctl reload nginx ;; certbot-webroot) [[ $# -eq 4 ]] || usage ensure_domain "$3" require_abs_path "$4" exec certbot certonly --webroot --non-interactive --agree-tos --no-eff-email -m "$2" -w "$4" -d "$3" -d "www.$3" ;; certbot-renew) exec certbot renew --quiet --no-random-sleep-on-renew ;; run-cmd) [[ $# -ge 2 ]] || usage shift exec bash -c "$*" ;; read-file) [[ $# -eq 2 ]] || usage require_abs_path "$2" exec cat "$2" ;; *) usage ;; esac