Skip to content

Using AI CLIs Like Claude Code for Linux Server Maintenance

Agentic CLIs can investigate and fix servers, which is why they need guardrails: read-only first, a dedicated user, tight allowlists, dry-run plans and audit logs.

●By 12 min read

Pasting command output into a chat window is slow but safe: a human sits between the model and the shell. Agentic CLIs such as Claude Code and aider remove that human. They read files, run commands, look at the results, and decide what to run next β€” which is exactly what makes them good at chasing a disk-full alert through five layers of logs.

It is also what makes them dangerous on a server. A model that is wrong with a shell is a different class of problem from a model that is wrong in a chat. The fix is not to avoid these tools but to give them the same treatment you would give a new contractor: limited access, a clear brief, and a record of everything they did.

Start Read-Only, Every Time

Most maintenance work is diagnosis, and diagnosis needs no write access. Begin every session in a mode where the agent can look but not touch. In Claude Code that is plan mode; in print mode you can also restrict the tool list outright:

# Interactive session that can read and propose, but not edit or execute changes

$ claude --permission-mode plan

# One-shot investigation with only read-style tools allowed

$ claude -p "Why is /var nearly full? Find the largest growth and explain it." \

--allowedTools "Read" "Grep" "Glob" "Bash(df:*)" "Bash(du:*)" "Bash(journalctl:*)"

# aider equivalent: load files as read-only context, never auto-commit

$ aider --read /etc/nginx/nginx.conf --no-auto-commits --dry-run

Diagnosis first, always β€” ask for an explanation and a proposed plan before any change. A model that has to justify its theory in writing is much less likely to start "fixing" the wrong thing.

Read-only is not harmless β€” a read-only agent can still read /etc/shadow, private keys and .env files and send them to an API. Access control and secret hygiene still apply β€” see below.

Prefer evidence over memory β€” tell it to cite the command output behind every conclusion. This is the same discipline as in our AI log analysis guide: no claim without a line of evidence.

Never Run It as Root: A Dedicated User With Narrow sudo

The agent runs with whatever privileges its process has. Running it as root, or as your own account with unrestricted sudo, means every mistake executes with full authority. Create a separate account and grant only the commands the task actually needs:

# A dedicated account for agent sessions

$ sudo useradd -m -s /bin/bash aiops

# /etc/sudoers.d/aiops β€” edit with: sudo visudo -f /etc/sudoers.d/aiops

Cmnd_Alias AI_READ = /usr/bin/systemctl status *, /usr/bin/journalctl --no-pager *, \

/usr/bin/ss -tlnp, /usr/bin/df -h

Cmnd_Alias AI_SVC = /usr/bin/systemctl restart myapp.service

aiops ALL=(root) NOPASSWD: AI_READ, AI_SVC

Defaults:aiops log_output, iolog_dir=/var/log/sudo-io/%{user}

# Validate the file and confirm what the account can do

$ sudo visudo -cf /etc/sudoers.d/aiops

$ sudo -l -U aiops

Watch for shell escapes β€” many common binaries can spawn a shell: less, vim, find -exec, and journalctl or systemctl when they open a pager. Force --no-pager and check every allowed binary against GTFOBins before granting it.

Wildcards match more than you think β€” in sudoers, * matches any arguments, including spaces and extra flags. Pin full command lines for anything that writes, like the single systemctl restart above.

No editors, no interpreters β€” never allow bash, python3, tee, cp or an editor via sudo. Any of them turns a narrow grant into full root.

File permissions do the rest β€” the account should be unable to read secrets in the first place. Check modes and ownership with the permissions calculator rather than trusting that it cannot.

Allowlists and Deny Rules in the Agent Itself

OS permissions are the hard boundary; the agent's own permission rules are a second layer that stops it even trying. Claude Code reads them from a settings file in the project directory or ~/.claude/settings.json:

{

"permissions": {

"allow": [

"Bash(systemctl status:*)",

"Bash(journalctl --no-pager:*)",

"Bash(df:*)",

"Bash(du:*)",

"Bash(ss -tlnp)"

],

"deny": [

"Bash(rm:*)",

"Bash(curl:*)",

"Bash(wget:*)",

"Read(//etc/shadow)",

"Read(~/.ssh/**)",

"Read(./.env)"

]

}

}

Deny network egress tools β€” blocking curl and wget removes the easy path for exfiltration and for "let me just download this script".

Read rules do not cover Bash β€” a Read deny rule stops the file tool, not cat or grep in a shell command. That is why the OS-level permissions above are the real control and these rules are defense in depth.

Prefix matching is coarse β€” Bash(git:*) allows git push --force too. Allow specific subcommands, and assume anything you can chain with && or ; deserves scrutiny.

Avoid the bypass flag β€” --dangerously-skip-permissions removes every prompt. It belongs in a disposable container, never on a server you care about.

sponsored

Make It Write the Plan Before It Acts

When a change is needed, separate deciding from doing. Ask for a plan in a fixed format, review it, and only then allow execution β€” ideally by running the commands yourself:

$ claude -p "Disk on /var is 94% full. Investigate read-only, then output a plan.

For each proposed step give:

1. The exact command

2. What it changes and whether it is reversible

3. How to verify it worked

4. How to undo it

Mark anything that deletes data with DESTRUCTIVE. Do not execute any step.

If you are unsure a file is safe to remove, say so instead of guessing." \

--permission-mode plan > /tmp/plan.md

$ less /tmp/plan.md

The reversibility column is the point β€” it forces the model to think about rollback, and it shows you instantly which steps need a backup taken first.

Watch for confident deletion β€” models readily suggest removing "old logs" that a compliance policy requires you to keep, or rotating files a running process still holds open. lsof +L1 shows deleted-but-open files that will not free space.

Review it like a script β€” the plan is code. Apply the same checklist as in reviewing AI-generated shell scripts: quoting, globs, error handling, and anything that runs as root.

Apply changes yourself for anything risky β€” letting the agent investigate and you execute keeps a human at the one point that matters, at the cost of a few minutes.

Audit Trails: Know Exactly What It Ran

After a session you should be able to answer "what did the agent touch?" without relying on its summary. Use three independent records:

# 1. The agent's own transcript (Claude Code stores JSONL per session)

$ ls -t ~/.claude/projects/*/ | head

# aider keeps .aider.chat.history.md in the working directory

# 2. Every command executed by the account, via auditd

$ sudo auditctl -a always,exit -F arch=b64 -S execve -F uid=$(id -u aiops) -k aiops

$ sudo ausearch -k aiops -i --start today | grep -i proctitle

# 3. Full input/output of every sudo command (from log_output above)

$ sudo sudoreplay -l user aiops

$ sudo sudoreplay <session-id>

Do not trust the summary β€” an agent's closing message describes what it intended to do. The audit log records what actually executed, including retries and commands it did not mention.

Persist the audit rule β€” auditctl rules vanish on reboot. Put the rule in /etc/audit/rules.d/aiops.rules if you use agents regularly.

Transcripts contain secrets β€” anything the agent read is in the transcript file, in plain text. Treat those directories as sensitive and expire them.

Secrets, Data Residency, and When Not to Use One

Everything the agent reads is sent to the model provider unless the model runs locally. On a production server that can include customer data in logs, database credentials in config files, and tokens in environment variables. Start the session with a clean environment (env -i plus only what is needed), and if data cannot leave the host, use a local model β€” see running LLMs locally with Ollama or the air-gapped setup guide.

SituationAgentic CLI?Why
Diagnosing a slow or full serverYes, read-onlyFast evidence gathering; no writes needed
Drafting config or unit file changesYes, in a repoChanges land in git and get reviewed
Routine restart of a known serviceMaybeOnly via a pinned sudo rule; a script is often simpler
Active security incidentNoEvidence preservation and chain of custody come first
Database migrations, data deletionNoIrreversible; needs a human-owned, tested procedure
Hosts with regulated dataLocal model onlyLogs and configs would leave your boundary

For incidents specifically, keep the AI on the analysis side of the line, working from copies of evidence β€” the approach in our AI incident response guide.

Frequently Asked Questions

Is it safe to run Claude Code on a production server?

It can be, if you treat it as an untrusted operator: a dedicated non-root user, a narrow sudoers file, read-only or plan mode for investigation, deny rules for network and destructive commands, and auditd logging. Without those controls, every mistake it makes runs with your privileges.

Why not just run the agent as root to save time?

Because the model will eventually be wrong, and as root a wrong guess can delete data, break SSH access, or overwrite configs with nothing to stop it. A dedicated user with specific sudo grants limits the damage of a bad decision to the commands you chose to allow.

Do the agent's own permission rules replace Linux permissions?

No. They are a useful second layer, but they match command prefixes and tool types, and a Read deny rule does not stop a shell command like cat. The operating system's user, file permissions and sudoers are the boundary that actually holds.

How do I see exactly what an AI agent ran on my server?

Combine the agent's own session transcript with auditd execve logging filtered to the agent's user ID, and sudo I/O logging viewed with sudoreplay. The audit and sudo logs are independent of the agent, so they capture commands it ran but did not mention in its summary.

Can an agentic CLI leak secrets from my server?

Yes. Anything it reads, including config files, environment variables and log lines, is sent to the model provider and stored in the local transcript. Make secrets unreadable to the agent's account, start it with a clean environment, and use a local model for hosts whose data must not leave.

sponsored

Related Tools

See also