SSD Nodes Learn 🎉 VPS from $5.50/mo
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-13

Claude for sysadmins: server work wey e fit do

See six server jobs Claude fit help with, from failed systemd logs to nginx and Compose review, plus the private keys and credentials wey you no suppose paste.

Claude for sysadmins: advice first, execution second

Claude for sysadmins dey work best as reviewer. You fit paste log excerpt, config file, command wey you no recognise, or error string, and you go get explanation wey you fit check before you change anything for the box. Wrong answer no go cost you anything until you run am, so keeping the model for advice side of that line na the whole safety model.

Six jobs dey come up every week for rented Linux VPS (virtual private server). Each one below get prompt pattern wey dey work, command wey prove the answer, and failure mode wey you suppose expect. None of dem need the model to get access to your server.

The order matter for production box: read the explanation, run the check by yourself, then decide. Autonomy dey okay for scratch VM. For the box wey dey serve your customers, review win, because the model no fit see the state wey e dey guess about.

Wetin you must never paste

Everything wey dey inside the prompt go comot from your server. Four categories dey remain for the box:

  • Private keys: ~/.ssh/id_ed25519, /etc/ssh/ssh_host_*_key, and any TLS (transport layer security) key under /etc/letsencrypt/live/.
  • Credential files: .env, ~/.aws/credentials, /root/.docker/config.json, and database passwords for any file or any log line.
  • Account data: /etc/shadow and /etc/gshadow. No sysadmin question need password hash to answer am.
  • Anything wey belong to your users: email addresses, order rows, request logs wey carry session cookies or PII (personally identifiable information).

Public keys safe to paste. Private keys no safe, and the two files fit look alike at first glance, so read the first line before you copy: file wey first line get BEGIN OPENSSH PRIVATE KEY inside must never enter prompt. How to keep your SSH key material straight worth ten minutes by itself.

Redact before you paste, instead make you trust yourself to notice one token inside 200 lines:

sudo journalctl -u myapp -n 200 --no-pager | sed -E 's/(token|secret|password|api[_-]?key)[=:][^[:space:]]+/\1=REDACTED/gI'

One Docker trap dey. docker compose config dey interpolate your .env values into the output wey e prints, so that output na secret even though the file for disk no be secret. Use docker compose config -q instead; e validates and prints nothing. For the wider policy about wetin agent fit see, how to keep secrets away from AI agents explain the environment side.

Job 1: why this service fail?

Start with the two commands wey get the answer:

systemctl status myapp.service --no-pager
sudo journalctl -u myapp.service -b -n 100 --no-pager -o short-iso

Paste both, together with the context wey model no fit guess: the distribution and version, wetin you change last, whether e ever work before, and how long e don spoil. Ask for the mechanism first.

Ubuntu 24.04. myapp.service dey work fine until I edit the unit one hour ago. Na here be systemctl status and the last 100 journal lines. Which line be the first real error, and wetin e mean? No fix yet.

"No fix yet" dey do important work for that prompt. Logs dey hide the first failure under the retries wey e cause, so if you ask model for fix, e go explain the last line wey e see. The line wey matter usually dey about twenty lines above the noise.

The benefit na a line like Main PID: 1841 (code=exited, status=203/EXEC). Exit status 203/EXEC mean say kernel no fit execute the file wey ExecStart name: either the path no exist, or the file exist but e no get execute permission. A #! line wey name interpreter wey no dey installed go produce the same status. You fit test all of this with ls -l and head -1.

Failure mode: invented cause. If you paste too little, model go fill the gap with something general, like "the port dey already in use". The cure na to ask one question back: "which line for wetin I give you support that?" If nobody fit point to the cause inside the text, na guess.

Job 2: draft systemd unit or cron entry

Give am the facts wey unit file need: the exact command, the user wey e go run as, the working directory, whether e must wait for network, and wetin suppose happen when e exits non-zero. Then verify wetin come back before you enable anything.

sudo systemd-analyze verify /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl start myapp.service
systemctl status myapp.service --no-pager

systemd-analyze verify dey parse the file the same way systemd dey do am, so e dey catch things wey human eye fit overlook. If directive get spelling mistake, e go print /etc/systemd/system/myapp.service:7: Unknown key name 'Enviroment' in section 'Service', ignoring.. If binary no dey, e go print Command /usr/local/bin/myapp is not executable: No such file or directory. Both no go show during daemon-reload, na why unit fit load cleanly and still fail immediately e run.

Two drafting mistakes dey show again and again. The first one na After=network.target, wey only mean say network stack don configure, no be say address don dey available. Service wey bind to specific IP then fit fail for boot with bind: Cannot assign requested address, and the fix na Wants=network-online.target together with After=network-online.target. The second one na Type=simple for program wey daemonises: systemd dey treat the first process as the service, the parent exits immediately, and the unit dey marked dead while the real process continues to run without management.

For schedule, check am instead of just reading am:

systemd-analyze calendar 'Mon *-*-* 04:00:00'

That one go print the normalised form and the next time the expression go run, so e go settle any argument about wetin e mean. If you dey choose between timer and crontab, systemd services and timers for VPS explain the trade-off.

Cron get one trap wey no model go warn you about unless you ask. Cron dey run jobs with minimal environment, so PATH na roughly /usr/bin:/bin and e no dey read your shell profile. Job wey work when you paste am for your terminal fit fail under cron with /bin/sh: 1: docker: not found, because that binary dey inside /usr/local/bin. Use absolute paths for crontabs.

Job 3: check nginx or Compose file before you put am live

This job dey give the best result. Paste the file, talk wetin e suppose do, then ask make e explain line by line wetin e actually dey do.

This vhost suppose serve example.com through HTTPS and proxy /api go local service for port 8080. Read am back to me and name anything wey no match this description.

Then run the tool wey sabi the grammar:

sudo nginx -t
docker compose config -q

nginx -t dey print nginx: configuration file /etc/nginx/nginx.conf test is successful, or e go name the file and line, like nginx: [emerg] unknown directive "proxy_pas" in /etc/nginx/conf.d/app.conf:12. docker compose config -q no dey print anything when the file parse correctly. E go print direct error like yaml: line 7: did not find expected key when your indentation get problem.

Neither tool dey check intention. Config wey pass nginx -t fit still proxy to wrong port, or listen on 0.0.0.0 when you mean 127.0.0.1. Na this gap model fit help with, and na here e fit fail too: if you ask am to fix one directive, e often return the whole file rewritten and quietly remove two of your directives. Ask for only the lines wey change and the reason for each one, then edit am by hand.

Confirm wetin you actually expose:

sudo ss -tulpn

Without sudo, you go see the listening sockets but you no go see the processes wey own dem. If that output surprise you, short explanation of ports and how Linux binds dem na the shorter read.

Job 4: explain unfamiliar command before you run am

Paste the command and ask four questions about am: wetin each flag dey do, wetin e dey write, wetin e dey delete, and wetin go happen if I run am twice. The last question dey catch more damage pass the others.

Take find /var/log -name '*.gz' -mtime +7 -delete. Correct answer go tell you say -mtime +7 dey count complete 24 hour periods and discard the remaining fraction. So e match files wey don old at least eight days, no be seven. E go also tell you say find dey evaluate expression from left to right. So if you move -delete put before -name, e go delete everything under the starting path. That second point dey inside the find man page as warning, and e don cost people their /var/log.

Or take rsync -a --delete /srv/app/ /backup/app/. The trailing slash for the source mean "the contents of this directory". If you remove am, you get /backup/app/app/. If you add --delete, anything for the destination wey no dey for the source go delete. That one correct for a mirror, but e fit cause disaster if the source path wrong.

Verify am with the tool, no be with the model:

rsync -a --delete --dry-run /srv/app/ /backup/app/ | head -20
find /var/log -name '*.gz' -mtime +7

Run the find without -delete and you go get list instead of loss.

Failure mode: flag hallucination. The model reliable for tools wey get thirty years of documentation, but e weak for vendor CLIs (command line interfaces) and recent subcommands. For those ones, e fit produce flag wey look correct but no dey exist. --help go settle the matter within one second. Quoting na the other weak point. So when command dey wrap a $(...) expression, read how command substitution dey expand before command run instead of trusting the explanation.

Job 5: turn shell history go runbook

You just spend two hours make something work. That knowledge dey your scrollback, and next month e go don disappear.

history 200 > /tmp/session.txt

Read that file and delete every line wey get password, token, or customer identifier before you send am anywhere. Shell history na one of the most reliable places to find secret for Linux box, because everybody dey type one inline at least once. Set HISTCONTROL=ignorespace inside your ~/.bashrc, and command wey you type with leading space no go write enter history at all.

The prompt wey go produce usable runbook dey ask for checks, no be steps only:

This na shell session wey take fresh Debian 13 box reach working Postgres install. Write am as numbered runbook. Use one command for each step. After every step, give the command wey go prove say e work and describe how healthy output suppose look. Mark any step wey depend on my specific host.

Failure mode: clean story. Your session get one step wey you get wrong two times before you fix am, and na that step model dey smooth away, because transcript dey read cleaner without am. Compare the runbook with your history and put the correction back. E also dey invent verification commands wey sound correct, so run every check wey e write before you save the file. If the runbook cover first boot, read am against the first ten minutes for new VPS so you no write down worse version of problem wey you don already solve.

Job 6: turn error message into fix

Paste the exact string, the command wey produce am, and the one thing wey you change before e appear. Ask for the likely causes in rank order, plus one command wey fit distinguish each cause. This one force the answer to be something wey you fit test.

nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use). Rank the likely causes and give me one command per cause that confirms or rules it out.

For this error, the mechanism no ambiguous: another process already dey hold port 80, and sudo ss -tulpn | grep ':80 ' name am. Many times, na second nginx master wey remain after failed reload, or Apache wey package dependency pull in and start by itself.

Failure mode: fix wey only hide the cause. chmod 777, --privileged, disabling SELinux, and running the service as root all fit make the error disappear. Reject any fix wey increase permissions until the model explain why the narrow permission fail. Na that explanation be the real answer. Workaround only make the error quiet.

Wetin e dey get wrong, every time

  • E no fit see your box. Every answer dey depend on wetin you paste, and e no go tell you say the excerpt too short.
  • E dey mix up versions. Package names and default flags dey change between distributions and releases, and the model dey average across all of dem.
  • E dey fluent even when e wrong. A mechanism wey e invent go read exactly like correct one. Na why every cause above come with command wey dey test am.
  • E dey lose the matter for long sessions. Facts from the beginning of two-hour conversation no dey shape the answers for the end.

That last one na practical problem more than model problem, and how to manage context for long Claude Code session na the practical fix: shorter sessions, one task each.

Putting the agent for the server itself

Everything wey dey above na copy and paste, so the model never touch your machine. Once e dey run for the box, dey read files and execute commands, the risk don change: wrong command fit now take down your service. Give am im own unprivileged user instead of root, keep am away from the production box while you dey learn how e dey behave, and take snapshot first. How to run Claude Code safely for a VPS explain the sandboxing and permission model. How to drive Claude Code inside tmux solve the other side, because dropped SSH (secure shell) session go kill foreground agent halfway through the work. Build the account the same way you go build any service account, as least privilege users for a VPS explain.

FAQ

Claude fit read my server logs directly?

No be by itself. Chat interface only fit see the text wey you paste inside am. Claude Code, wey you run for server as command line tool, fit read files and run commands with the permissions of the user wey start am, and this na bigger trust decision. For normal support question, to paste redacted 100 line excerpt dey faster and safer pass to give agent shell access.

Wetin I suppose never paste from server?

Private keys, .env files and other credential stores, /etc/shadow, and any data wey belong to your users. Redact tokens from log excerpts before dem reach the prompt. One case wey no too obvious: output of docker compose config get your .env values interpolated inside am, so use docker compose config -q, wey validate the file and print nothing.

E safe to let Claude run commands for production VPS?

Treat am like new admin wey no get context: e fit read, but writing need review. For production, ask for the explanation and run the command by yourself. If you really want agent to execute commands, give am dedicated unprivileged account without blanket sudo, and start for staging box where mistake go cost you rebuild instead of outage.

Why Claude dey suggest flag wey no exist?

Because e dey predict plausible text, and plausible flag fit look the same as real one. E dey happen mostly with vendor CLIs and newer subcommands, where documentation wey model get no complete or don change since. --help and man na the final authority, and any command wey delete or overwrite deserve dry run first.

How I fit check systemd unit before I enable am?

Run sudo systemd-analyze verify /etc/systemd/system/myapp.service. E parse the file with systemd own parser, report unknown directives with their line numbers, and flag an ExecStart binary wey missing or no executable. Then run daemon-reload, start, and read systemctl status before you enable am, because unit wey load cleanly fit still fail for the first run.