Repository navigation
Agent Root Access
Agent root access (server page, admin/owner, passkey step-up) restarts the agent as root so the [Web-Terminal](Web terminal.md) can open shells as other OS users. Spec: docs/operations.md.
- The control plane sends
AgentRootCommand{enabled:true}to the agent. - The agent runs
sudo -n /usr/libexec/croncompose/agent-privctl elevate. -
agent-privctlchecks the agent really iscroncompose-agent.service, writes the drop-in/etc/systemd/system/croncompose-agent.service.d/root.conf(User=root), runsdaemon-reload, checks the unit now resolvesUser=root, then restarts the unit. - The agent reconnects and its Hello reports
euid_root=true. The badge turns On (root).
Turning the switch off runs agent-privctl demote, which removes root.conf and restarts the unit as the original user.
Requirements: Linux with systemd, the agent running as the croncompose-agent.service unit (not pm2, nohup or a shell), the helper installed at /usr/libexec/croncompose/agent-privctl, and the sudoers grant from the installer.
This means the agent never came back as root and reported no error. Run these on the server.
systemctl show -p User,MainPID,FragmentPath,DropInPaths croncompose-agent
pgrep -af 'agent run|croncompose-agent'-
MainPID=0, or thepgrepPID differs fromMainPID→ the agent was started by pm2 / nohup / a shell. Restarting the unit does nothing for it. See Move the agent under systemd. -
User=is notrootalthoughroot.confexists → another drop-in inDropInPathssetsUser=after it. Remove that line and runsudo systemctl daemon-reload.
Confirm with the running PID's cgroup; it must end in croncompose-agent.service:
cat /proc/<pid>/cgroupls -l /etc/systemd/system/croncompose-agent.service.d/
cat /etc/systemd/system/croncompose-agent.service.d/root.confroot.conf missing on a .deb/.apk install from before this fix: the packaged unit has ProtectSystem=full, which makes /etc read-only for the agent and its sudo children. Fix:
sudo mkdir -p /etc/systemd/system/croncompose-agent.service.d
sudo systemctl edit croncompose-agent
# add:
# [Service]
# ReadWritePaths=-/etc/systemd/system/croncompose-agent.service.d
sudo systemctl restart croncompose-agentls -l /usr/libexec/croncompose/agent-privctl # root:root, 0755
sudo cat /etc/sudoers.d/croncompose-agent
sudo -u <agent-user> sudo -n -l | grep agent-privctlIf the helper is missing, build and install it from the checkout:
cd agent && go build -o bin/agent-privctl ./cmd/agent-privctl
sudo install -d -m 0755 /usr/libexec/croncompose
sudo install -m 0755 -o root -g root bin/agent-privctl /usr/libexec/croncompose/agent-privctlIf the grant is missing, re-run the installer's sudoers step:
sudo ./install/lib/agent_sudoers.sh <agent-user>Never grant NOPASSWD: ALL.
journalctl -u croncompose-agent -n 100 --no-pagerThe default ./install/install.sh stack runs everything under pm2, where root access is not supported (agent-privctl fails with systemd required to run agent as root under pm2). To switch the stack to systemd units:
pm2 delete croncompose-agent # stop the pm2 copy so two agents don't share one identity
sudo ./install/systemd-setup.sh # writes croncompose-*.service, installs helper + sudoers
echo systemd | sudo tee "$CC_RUNTIME_DIR/agent/.run/agent-supervisor"Then toggle Agent root access again.
Use this when you want root access and cannot get agent-privctl working. Leave the switch on in the UI (the timeout does not turn it off); the badge turns On (root) once the agent reconnects as root.
DATA_DIR is /var/lib/croncompose for package / install-agent.sh installs, or $CC_RUNTIME_DIR/agent for the full stack. <agent-user> is the normal service user (croncompose, or the user who ran the installer).
sudo mkdir -p /etc/systemd/system/croncompose-agent.service.d
sudo tee /etc/systemd/system/croncompose-agent.service.d/root.conf >/dev/null <<'EOF'
[Service]
User=root
ProtectHome=false
UnsetEnvironment=AGENT_VERSION
ProtectSystem=false
EOF
# Markers the helper uses to demote back to the right user later.
sudo mkdir -p "$DATA_DIR/.run"
echo <agent-user> | sudo tee "$DATA_DIR/.run/agent-service-user"
echo systemd | sudo tee "$DATA_DIR/.run/agent-supervisor"
sudo systemctl daemon-reload
sudo systemctl restart croncompose-agent
systemctl show -p User croncompose-agent # User=root
ps -o user= -p "$(systemctl show -p MainPID --value croncompose-agent)" # rootTurn the switch off in the UI, then on the host:
sudo rm -f /etc/systemd/system/croncompose-agent.service.d/root.conf
sudo systemctl daemon-reload
sudo systemctl restart croncompose-agent
systemctl show -p User croncompose-agent # back to the service user