Adds bootstrap-host.sh (one-time, run as root on a fresh Proxmox host) and fix-lxc-apparmor.sh, the fixed-content script it installs. The sudoers rule it wires up only ever invokes that one root-owned script with a VMID argument - deliberately not a broader rule like `tee -a <conf>` or `sh -c '...'`, since those only restrict the command's own argv, not stdin/heredoc content, letting the caller write arbitrary lines to any 200-299 container's config instead of just this one fixed line. create-graylog-lxc.sh now tries `sudo -n fix-lxc-apparmor.sh` first and falls back to the existing manual instructions if that sudoers rule isn't present yet - fully backward compatible with hosts that haven't run bootstrap-host.sh. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
44 lines
1.9 KiB
Bash
44 lines
1.9 KiB
Bash
#!/bin/bash
|
|
# Run ONCE, as root, on a fresh Proxmox host - not part of the claude-deploy
|
|
# workflow, since claude-deploy is exactly the account this script is
|
|
# widening permissions FOR. Idempotent: safe to re-run.
|
|
#
|
|
# Installs fix-lxc-apparmor.sh (root-owned, not writable by claude-deploy)
|
|
# and a narrow sudoers rule that lets claude-deploy invoke it - and only
|
|
# it, only with a VMID argument in the 200-299 range - so create-graylog-lxc.sh
|
|
# can clear the "Docker-in-unprivileged-LXC AppArmor block" quirk (see
|
|
# README.md) without a human editing /etc/pve/lxc/*.conf by hand every time.
|
|
#
|
|
# Deliberately does NOT grant broader access (e.g. `tee -a` or `sh -c` on
|
|
# the conf file): those let the caller write arbitrary content to any
|
|
# 200-299 container's config, not just this one fixed line. See the
|
|
# "Automating the AppArmor fix" note in README.md for why.
|
|
set -euo pipefail
|
|
|
|
[ "$(id -u)" -eq 0 ] || { echo "Must run as root." >&2; exit 1; }
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
TARGET="/usr/local/sbin/fix-lxc-apparmor.sh"
|
|
SUDOERS_FILE="/etc/sudoers.d/claude-deploy-apparmor"
|
|
SUDOERS_LINE="claude-deploy ALL=(root) NOPASSWD: ${TARGET} 2[0-9][0-9]"
|
|
|
|
if [ -f "$TARGET" ] && cmp -s "$SCRIPT_DIR/fix-lxc-apparmor.sh" "$TARGET"; then
|
|
echo "⏭ $TARGET already up to date"
|
|
else
|
|
install -o root -g root -m 700 "$SCRIPT_DIR/fix-lxc-apparmor.sh" "$TARGET"
|
|
echo "✓ installed $TARGET (root-owned, 700)"
|
|
fi
|
|
|
|
if [ -f "$SUDOERS_FILE" ] && grep -qxF "$SUDOERS_LINE" "$SUDOERS_FILE"; then
|
|
echo "⏭ sudoers rule already present in $SUDOERS_FILE"
|
|
else
|
|
tmp="$(mktemp)"
|
|
echo "$SUDOERS_LINE" > "$tmp"
|
|
chmod 440 "$tmp"
|
|
visudo -c -f "$tmp" || { echo "generated sudoers snippet failed validation" >&2; rm -f "$tmp"; exit 1; }
|
|
mv "$tmp" "$SUDOERS_FILE"
|
|
chown root:root "$SUDOERS_FILE"
|
|
echo "✓ installed sudoers rule at $SUDOERS_FILE"
|
|
fi
|
|
|
|
echo "Done. claude-deploy can now run: sudo $TARGET <vmid>"
|