feat: ground-up .bashrc rewrite — sudo→mdo alias, ZFS safety (Sam & Hermes)
- shell-system.sh (runs last, step 6): rewrite .profile with agent launcher, full .bashrc with sudo() shell function that fire-and-forget snapshots zroot@cli-<ts> before mdo -u root. PATH, prompt, history, aliases (ll/la/lt). Agent fallback for non-login shells via ~/.ssh-agent-env. - shell-ssh.sh (step 4): strip to ~/.ssh/config only. Agent/profile/tmux seeding moved to shell-system.sh so it is not overwritten. - AGENTS.md: document sudo→mdo decision with rationale table (ISO size, audit surface, single privilege path, ZFS rollback safety).
This commit is contained in:
parent
f07144664e
commit
f1dd03da0a
3 changed files with 78 additions and 57 deletions
22
AGENTS.md
22
AGENTS.md
|
|
@ -101,11 +101,31 @@ inspection as final proof that SDDM/XFCE works.
|
|||
**Privilege model:** distinguish build-host administration from live-USB runtime.
|
||||
|
||||
- On the FreeBSD 15 build host, operator-facing commands may use `sudo`.
|
||||
- Inside the live USB, `sudo` is intentionally absent.
|
||||
- Inside the live USB, `sudo` is intentionally absent (deleted via `pkg delete -f sudo`).
|
||||
- Live privileged actions use FreeBSD `mac_do` via `mdo -u root <command>`.
|
||||
- `~/.bashrc` aliases `sudo` → `mdo -u root` for muscle-memory compatibility.
|
||||
The shell function wraps `mdo` with a fire-and-forget ZFS snapshot
|
||||
(`zroot@cli-<timestamp>`) before each privileged invocation, so rollback
|
||||
is always available without confirmation prompts or warning popups.
|
||||
- Agent runtime code must not shell out to `sudo` for privileged host changes.
|
||||
- Privileged Clawdie-AI host operations go through the hostd RPC layer.
|
||||
|
||||
**Why `sudo` as alias, not as pkg:**
|
||||
|
||||
| Approach | Install sudo pkg | Alias to mdo |
|
||||
|----------|-----------------|--------------|
|
||||
| Extra package | Yes (sudo + deps) | No |
|
||||
| Two privilege paths | `sudo` AND `mdo` coexist | Single path (`mdo`) |
|
||||
| Audit surface | Two tools to audit | One kernel-enforced MAC |
|
||||
| ZFS safety net | Requires sudoers hooks | Built into bash function |
|
||||
| Agent confusion | Agents try both paths | Agents use `sudo`, get `mdo` |
|
||||
| ISO size | Larger | Zero bytes |
|
||||
|
||||
The alias approach keeps the ISO lean, eliminates dual-privilege-path
|
||||
confusion, and bakes ZFS rollback safety directly into the operator shell.
|
||||
`mac_do` is FreeBSD base system — no package dependency, kernel-enforced,
|
||||
auditable via MAC framework.
|
||||
|
||||
---
|
||||
|
||||
## Installer Temp Files
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ clawdie_shell_ssh_setup() {
|
|||
# 1. Configure SSH keys (if provided)
|
||||
# 2. Set system passwords (if provided or auto-generate)
|
||||
# 3. Configure SSH auth methods (key-only or key+password)
|
||||
# 4. Seed SSH agent persistence (~/.ssh/config + ~/.tmux.conf)
|
||||
# 4. Seed SSH client defaults (~/.ssh/config)
|
||||
|
||||
log_msg "[ssh] Starting SSH and password setup"
|
||||
|
||||
|
|
@ -43,8 +43,8 @@ clawdie_shell_ssh_setup() {
|
|||
if [ -n "${SSH_PUBLIC_KEY:-}" ]; then
|
||||
clawdie_shell_ssh_install_pubkey
|
||||
clawdie_shell_ssh_disable_password_auth
|
||||
clawdie_shell_ssh_seed_agent_config
|
||||
log_msg "[ssh] SSH public key installed, password auth disabled, agent config seeded"
|
||||
clawdie_shell_ssh_seed_client_config
|
||||
log_msg "[ssh] SSH public key installed, password auth disabled, client config seeded"
|
||||
else
|
||||
clawdie_shell_ssh_enable_password_auth
|
||||
log_msg "[ssh] No SSH key provided, password auth enabled (less secure)"
|
||||
|
|
@ -105,45 +105,18 @@ clawdie_shell_ssh_install_pubkey() {
|
|||
}
|
||||
|
||||
# ============================================================================
|
||||
# SSH AGENT PERSISTENCE (seed ~/.profile, ~/.ssh/config, ~/.tmux.conf)
|
||||
# SSH CLIENT CONFIGURATION (seed ~/.ssh/config)
|
||||
# ============================================================================
|
||||
|
||||
clawdie_shell_ssh_seed_agent_config() {
|
||||
# Seed SSH agent launcher, auto-load, and terminal preferences.
|
||||
# FreeBSD: no systemd — use ~/.profile to start the agent on login.
|
||||
# tmux's default update-environment already includes SSH_AUTH_SOCK;
|
||||
# do NOT override it (would drop DISPLAY, XAUTHORITY, etc.).
|
||||
clawdie_shell_ssh_seed_client_config() {
|
||||
# Seed SSH client defaults for the clawdie user.
|
||||
# .profile / .bashrc / .tmux.conf are handled by shell-system.sh
|
||||
# (which runs after this module).
|
||||
# Run after clawdie_shell_ssh_install_pubkey (requires user to exist).
|
||||
|
||||
local profile="/home/clawdie/.profile"
|
||||
local ssh_config="/home/clawdie/.ssh/config"
|
||||
local tmux_conf="/home/clawdie/.tmux.conf"
|
||||
|
||||
# --- Tier 1: ~/.profile — start agent on every login (FreeBSD, no systemd) ---
|
||||
if [ ! -f "$profile" ]; then
|
||||
cat > "$profile" <<'PROFEOF'
|
||||
# Start SSH agent if not already running
|
||||
if [ -z "$SSH_AUTH_SOCK" ]; then
|
||||
eval $(ssh-agent -s) > /dev/null 2>&1
|
||||
fi
|
||||
PROFEOF
|
||||
chmod 644 "$profile"
|
||||
chown clawdie:clawdie "$profile" 2>/dev/null || true
|
||||
log_msg "[ssh] Seeded ~/.profile with SSH agent launcher"
|
||||
else
|
||||
if ! grep -q 'ssh-agent -s' "$profile" 2>/dev/null; then
|
||||
cat >> "$profile" <<'PROFEOF'
|
||||
|
||||
# Start SSH agent if not already running
|
||||
if [ -z "$SSH_AUTH_SOCK" ]; then
|
||||
eval $(ssh-agent -s) > /dev/null 2>&1
|
||||
fi
|
||||
PROFEOF
|
||||
log_msg "[ssh] Appended SSH agent launcher to existing ~/.profile"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Tier 2: ~/.ssh/config — auto-load key on first use ---
|
||||
# --- ~/.ssh/config: auto-load key on first use, no agent forwarding ---
|
||||
if [ ! -f "$ssh_config" ]; then
|
||||
cat > "$ssh_config" <<'SSHEOF'
|
||||
Host *
|
||||
|
|
@ -160,20 +133,6 @@ SSHEOF
|
|||
fi
|
||||
fi
|
||||
|
||||
# --- Tier 3: ~/.tmux.conf — UI preferences only (agent socket is default) ---
|
||||
# tmux update-environment already includes SSH_AUTH_SOCK + DISPLAY.
|
||||
# Seed mouse + indexing; do NOT override update-environment.
|
||||
if [ ! -f "$tmux_conf" ]; then
|
||||
cat > "$tmux_conf" <<'TMUXEOF'
|
||||
set -g base-index 1
|
||||
setw -g pane-base-index 1
|
||||
set -g mouse on
|
||||
TMUXEOF
|
||||
chmod 644 "$tmux_conf"
|
||||
chown clawdie:clawdie "$tmux_conf" 2>/dev/null || true
|
||||
log_msg "[ssh] Seeded ~/.tmux.conf (base-index 1, mouse on)"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -354,6 +354,12 @@ EOF
|
|||
cat > /home/clawdie/.profile <<'EOF'
|
||||
# Clawdie operator POSIX shell profile.
|
||||
[ -r /etc/profile.d/clawdie.sh ] && . /etc/profile.d/clawdie.sh
|
||||
|
||||
# Start SSH agent on login (FreeBSD: no systemd, no X11 agent launcher).
|
||||
# Non-login shells (tmux windows) use ~/.bashrc fallback instead.
|
||||
if [ -z "$SSH_AUTH_SOCK" ]; then
|
||||
eval $(ssh-agent -s) > /dev/null 2>&1
|
||||
fi
|
||||
EOF
|
||||
cat > /home/clawdie/.bash_profile <<'EOF'
|
||||
# Clawdie operator bash login profile.
|
||||
|
|
@ -365,14 +371,50 @@ EOF
|
|||
}
|
||||
[ -r "${HOME}/.bashrc" ] && . "${HOME}/.bashrc"
|
||||
EOF
|
||||
cat > /home/clawdie/.bashrc <<'EOF'
|
||||
# Clawdie operator interactive bash profile.
|
||||
cat > /home/clawdie/.bashrc <<'BASHRC'
|
||||
# Clawdie operator interactive bash shell.
|
||||
# Non-interactive shells stop here.
|
||||
case $- in *i*) ;; *) return ;; esac
|
||||
|
||||
# ── PATH (FreeBSD: /usr/local first) ──────────────────────────
|
||||
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
[ -r /etc/profile.d/clawdie.sh ] && . /etc/profile.d/clawdie.sh
|
||||
if [ -n "${PS1:-}" ]; then
|
||||
export HISTFILE="${HISTFILE:-/tmp/clawdie/bash_history}"
|
||||
mkdir -p /tmp/clawdie 2>/dev/null || true
|
||||
|
||||
# ── Privilege escalation ──────────────────────────────────────
|
||||
# Clawdie ISO: no sudo pkg. Use FreeBSD mac_do instead.
|
||||
# mac_do rules (gid=0>uid=0) allow wheel→root transitions.
|
||||
# ZFS auto-snapshot provides safety net — no confirmation prompts.
|
||||
sudo() {
|
||||
local pool
|
||||
pool=$(zpool list -H -o name 2>/dev/null | head -1)
|
||||
if [ -n "$pool" ]; then
|
||||
(zfs snapshot "${pool}@cli-$(date +%s)" 2>/dev/null &)
|
||||
fi
|
||||
mdo -u root "$@"
|
||||
}
|
||||
|
||||
# ── SSH agent (fallback for non-login shells) ─────────────────
|
||||
# .profile starts the agent for login shells; tmux windows
|
||||
# (non-login) inherit via SSH_AUTH_SOCK if the parent had one,
|
||||
# but if not, try a stored env file from a prior login.
|
||||
if [ -z "$SSH_AUTH_SOCK" ] && [ -f ~/.ssh-agent-env ]; then
|
||||
. ~/.ssh-agent-env 2>/dev/null || true
|
||||
fi
|
||||
EOF
|
||||
|
||||
# ── Prompt ────────────────────────────────────────────────────
|
||||
PS1='\h:\w\$ '
|
||||
|
||||
# ── History ───────────────────────────────────────────────────
|
||||
export HISTFILE="${HISTFILE:-/tmp/clawdie/bash_history}"
|
||||
export HISTSIZE=5000
|
||||
export HISTFILESIZE=10000
|
||||
mkdir -p /tmp/clawdie 2>/dev/null || true
|
||||
|
||||
# ── Aliases ───────────────────────────────────────────────────
|
||||
alias ll='ls -lah'
|
||||
alias la='ls -A'
|
||||
alias lt='ls -laht'
|
||||
BASHRC
|
||||
cat > /home/clawdie/.zprofile <<'EOF'
|
||||
# Clawdie operator zsh login profile.
|
||||
[ -r /etc/profile ] && . /etc/profile
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue