Archived
feat(raspberrypi): add Raspberry Pi configuration section
Secret Scan / Scan for secrets and sensitive config (push) Failing after 5s
Secret Scan / Scan for secrets and sensitive config (push) Failing after 5s
Documents and scripts to reproduce the IPA integration on the Pi (raspberrypi.tail13f623.ts.net, Debian 12 bookworm): - setup-ipa-sudo.sh: writes /etc/sudoers.d/ipa-admins granting %admins NOPASSWD:ALL (same IPA admins group as pbs/pdm/pve1) - setup-docker-ipa-gid.sh: pins local docker group GID to 50010 via groupmod --non-unique so IPA docker-access group membership alone grants docker socket access (mirrors NixOS lib.mkForce approach) - README.md + CLAUDE.md: quick-start, current status, guardrails Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
# Shared helpers for raspberrypi scripts. Sourced, not executed directly:
|
||||
# SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# source "${SCRIPT_DIR}/lib/common.sh"
|
||||
|
||||
require_root() {
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "Must run as root." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# backup_file <path>
|
||||
# Copies an existing file to <path>.bak.<epoch>. No-op if it doesn't exist.
|
||||
backup_file() {
|
||||
local path="$1"
|
||||
if [ -f "$path" ]; then
|
||||
cp "$path" "${path}.bak.$(date +%s)"
|
||||
echo "Backed up ${path}"
|
||||
fi
|
||||
}
|
||||
|
||||
# write_if_changed <path> <content>
|
||||
# Writes content to path only if it differs from what's already there,
|
||||
# backing up the previous version first. Prints what happened.
|
||||
write_if_changed() {
|
||||
local path="$1" content="$2"
|
||||
if [ -f "$path" ] && [ "$(cat "$path")" = "$content" ]; then
|
||||
echo "Already up to date: $path"
|
||||
return 0
|
||||
fi
|
||||
backup_file "$path"
|
||||
printf '%s\n' "$content" > "$path"
|
||||
echo "Wrote $path"
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
# Pin the local 'docker' group GID to match the IPA 'docker-access' group
|
||||
# (GID 50010) so that IPA group membership alone grants docker socket access.
|
||||
#
|
||||
# On Debian, GID 50010 is already present via SSSD (the IPA group), so
|
||||
# groupmod requires --non-unique to allow the local docker group to share
|
||||
# it. The docker.socket + docker.service pair must be fully stopped before
|
||||
# removing the stale socket so systemd recreates it with the new GID.
|
||||
#
|
||||
# Idempotent — exits 0 without touching anything if the GID is already 50010.
|
||||
#
|
||||
# Run as root after setup-ipa-sudo.sh has been applied and docker is running.
|
||||
#
|
||||
# Usage: sudo ./setup-docker-ipa-gid.sh
|
||||
set -euo pipefail
|
||||
|
||||
DOCKER_ACCESS_GID=50010
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=lib/common.sh
|
||||
source "${SCRIPT_DIR}/lib/common.sh"
|
||||
require_root
|
||||
|
||||
if ! command -v docker &>/dev/null; then
|
||||
echo "ERROR: docker not found -- install Docker before running this script." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
current_gid=$(getent group docker | cut -d: -f3)
|
||||
if [ "$current_gid" = "$DOCKER_ACCESS_GID" ]; then
|
||||
echo "docker group is already GID ${DOCKER_ACCESS_GID} -- nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Changing docker group GID: ${current_gid} -> ${DOCKER_ACCESS_GID}"
|
||||
|
||||
# SSSD exposes GID 50010 via the IPA docker-access group, so groupmod sees
|
||||
# it as already in use. --non-unique lets the local docker group share it.
|
||||
groupmod --non-unique -g "${DOCKER_ACCESS_GID}" docker
|
||||
|
||||
echo "Restarting docker to recreate socket with new GID..."
|
||||
systemctl stop docker.service docker.socket
|
||||
rm -f /var/run/docker.sock
|
||||
systemctl start docker.socket docker.service
|
||||
|
||||
actual_gid=$(stat -c '%g' /var/run/docker.sock)
|
||||
if [ "$actual_gid" != "$DOCKER_ACCESS_GID" ]; then
|
||||
echo "ERROR: socket GID is ${actual_gid}, expected ${DOCKER_ACCESS_GID}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Done. Docker socket is now GID ${DOCKER_ACCESS_GID} (docker / docker-access)."
|
||||
echo "IPA members of the 'docker-access' group can now run docker without explicit local group membership."
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
# Grant the IPA 'admins' group passwordless sudo on this Raspberry Pi.
|
||||
#
|
||||
# Writes /etc/sudoers.d/ipa-admins with NOPASSWD: ALL for the admins group.
|
||||
# Idempotent — safe to re-run.
|
||||
#
|
||||
# Run as root (or via the local 'raspi' user's NOPASSWD sudo) after
|
||||
# ipa-client-install has been completed and SSSD is active.
|
||||
#
|
||||
# Usage: sudo ./setup-ipa-sudo.sh
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=lib/common.sh
|
||||
source "${SCRIPT_DIR}/lib/common.sh"
|
||||
require_root
|
||||
|
||||
if [ ! -f /etc/ipa/default.conf ]; then
|
||||
echo "ERROR: /etc/ipa/default.conf not found -- is this host enrolled in FreeIPA?" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
write_if_changed /etc/sudoers.d/ipa-admins '%admins ALL=(ALL) NOPASSWD:ALL'
|
||||
chmod 0440 /etc/sudoers.d/ipa-admins
|
||||
|
||||
visudo -c >/dev/null
|
||||
echo "Sudoers file valid. IPA admins group has NOPASSWD sudo on this host."
|
||||
Reference in New Issue
Block a user