Claude gebruiken voor Linux systeembeheer
Ontdek zes dagelijkse taken voor Claude op uw server, van het analyseren van logbestanden tot het schrijven van systemd units. Leer wat u nooit in de prompt mag plakken.
Claude voor systeembeheerders: eerst advies, dan uitvoering
Claude voor systeembeheerders werkt het best als reviewer. U plakt een logfragment, een configuratiebestand, een commando dat u niet herkent of een foutmelding, en u krijgt een uitleg die u kunt controleren voordat u wijzigingen aanbrengt op de server. Een foutief antwoord kost u niets zolang u het niet uitvoert; het model aan de adviserende kant van die grens houden is het volledige veiligheidsmodel.
Elke week komen er zes taken voorbij op een gehuurde Linux VPS (virtual private server). Hieronder staat voor elk daarvan een promptpatroon dat werkt, het commando dat het antwoord verifieert en de foutmodus waar u rekening mee moet houden. Voor geen van deze taken hoeft het model toegang te hebben tot uw server. U kunt plakken vanuit een browsertabblad of vanuit een venster op uw eigen desktop, aangezien Claude native op Linux draait als zowel desktop-app als CLI.
De volgorde is van belang op een productieomgeving: lees de uitleg, voer zelf de controle uit en beslis dan. Autonomie is prima op een test-VM. Op de server die uw klanten bedient, wint beoordeling, omdat het model de status waarover het speculeert niet kan zien.
Wat u nooit mag plakken
Alles wat u in de prompt invoert, verlaat uw server. Vier categorieën moeten op de server blijven:
- Privésleutels:
~/.ssh/id_ed25519,/etc/ssh/ssh_host_*_keyen elke TLS (transport layer security) sleutel onder/etc/letsencrypt/live/. - Inloggegevens:
.env,~/.aws/credentials,/root/.docker/config.jsonen databasewachtwoorden in elk bestand of elke logregel. - Accountgegevens:
/etc/shadowen/etc/gshadow. Geen enkele vraag over systeembeheer vereist een wachtwoordhash om beantwoord te kunnen worden. - Alles wat toebehoort aan uw gebruikers: e-mailadressen, orderregels, verzoeklogs met sessiecookies of PII (persoonlijk identificeerbare informatie).
Publieke sleutels mogen veilig worden geplakt. Privésleutels mogen dat niet, en de twee bestandstypen lijken op het eerste gezicht op elkaar. Lees daarom de eerste regel voordat u kopieert: een bestand waarvan de eerste regel BEGIN OPENSSH PRIVATE KEY bevat, mag nooit in een prompt worden geplaatst. Het beheren van uw SSH-sleutelmateriaal is op zichzelf tien minuten tijd waard.
Redigeer gegevens voordat u ze plakt, in plaats van erop te vertrouwen dat u één token in 200 regels herkent:
sudo journalctl -u myapp -n 200 --no-pager | sed -E 's/(token|secret|password|api[_-]?key)[=:][^[:space:]]+/\1=REDACTED/gI'Eén valkuil is specifiek voor Docker. docker compose config interpoleert uw .env-waarden in de uitvoer die het toont, waardoor die uitvoer een geheim is, ook al was het bestand op de schijf dat niet. Gebruik docker compose config -q, dat valideert en niets afdrukt. Voor het bredere beleid over wat een agent mag zien, behandelt geheimen buiten AI-agents houden de kant van de omgeving.
Taak 1: waarom is deze service mislukt?
Begin met de twee commando's die het antwoord bevatten:
systemctl status myapp.service --no-pager
sudo journalctl -u myapp.service -b -n 100 --no-pager -o short-isoPlak beide, inclusief de context die het model niet kan raden: de distributie en versie, wat u als laatste heeft gewijzigd, of het ooit heeft gewerkt en hoe lang geleden het defect is opgetreden. Vraag eerst naar het mechanisme.
Ubuntu 24.04.myapp.servicewerkte prima totdat ik een uur geleden de unit bewerkte. Hier issystemctl statusen de laatste 100 regels uit het logboek. Welke regel is de eerste echte fout en wat betekent deze? Nog geen oplossing.
"Nog geen oplossing" is essentieel in deze prompt. Logs verbergen de eerste fout onder de herhaalde pogingen die het heeft veroorzaakt, dus een model dat om een oplossing wordt gevraagd, zal de laatste regel uitleggen die het zag. De relevante regel staat meestal twintig regels boven de ruis.
Het resultaat is een regel zoals Main PID: 1841 (code=exited, status=203/EXEC). Exit status 203/EXEC betekent dat de kernel het bestand genoemd in ExecStart niet kon uitvoeren: of het pad bestaat niet, of het bestand bestaat wel maar is niet uitvoerbaar. Een #! regel die een interpreter noemt die niet is geïnstalleerd, produceert dezelfde status. Dit alles is testbaar met ls -l en head -1.
Foutmodus: een verzonnen oorzaak. Plak te weinig informatie en het model vult het gat op met iets algemeens, zoals "de poort is al in gebruik". De remedie is één wedervraag: "welke regel in wat ik u heb gegeven ondersteunt dat?" Een oorzaak waar niemand in de tekst naar kan wijzen, is een gok.
Taak 2: een systemd-unit of een cron-entry opstellen
Verstrek de gegevens die een unit-bestand vereist: het exacte commando, de gebruiker waaronder het proces draait, de werkmap, of het moet wachten op het netwerk en wat er moet gebeuren bij een exit-code die niet nul is. Controleer vervolgens wat er wordt geretourneerd voordat u iets inschakelt.
sudo systemd-analyze verify /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl start myapp.service
systemctl status myapp.service --no-pagersystemd-analyze verify parseert het bestand op de manier waarop systemd dat doet, waardoor fouten worden opgemerkt die een menselijk oog over het hoofd ziet. Een verkeerd gespelde instructie resulteert in /etc/systemd/system/myapp.service:7: Unknown key name 'Enviroment' in section 'Service', ignoring.. Een ontbrekend binaire bestand resulteert in Command /usr/local/bin/myapp is not executable: No such file or directory. Beide blijven onopgemerkt tijdens daemon-reload, wat de reden is dat een unit foutloos kan laden en toch kan falen zodra deze wordt uitgevoerd.
Twee fouten bij het opstellen komen steeds weer voor. De eerste is After=network.target, wat alleen betekent dat de netwerkstack is geconfigureerd, niet dat er al een adres bestaat. Een service die bindt aan een specifiek IP-adres faalt dan bij het opstarten met bind: Cannot assign requested address; de oplossing is Wants=network-online.target in combinatie met After=network-online.target. De tweede is Type=simple voor een programma dat zichzelf als daemon uitvoert: systemd beschouwt het eerste proces als de service, het ouderproces sluit direct af en de unit wordt gemarkeerd als gestopt terwijl het werkelijke proces onbeheerd blijft draaien. Dit is de fout die een model u het snelst zal aanreiken, omdat het aan uw commando niet kan zien of het binaire bestand een fork maakt. Het is daarom de moeite waard om te weten wat elke Type=-waarde aan systemd belooft voordat u het concept accepteert.
Controleer voor een planning de invoer in plaats van deze alleen te lezen:
systemd-analyze calendar 'Mon *-*-* 04:00:00'Dit drukt de genormaliseerde vorm af en het volgende tijdstip waarop de expressie wordt uitgevoerd, wat elke discussie over de betekenis beëindigt. Als u twijfelt tussen een timer en een crontab, behandelt systemd-services en timers op een VPS de afwegingen.
Cron bevat een valkuil waarover geen enkel model u zal waarschuwen tenzij u erom vraagt. Cron voert taken uit met een minimale omgeving; PATH is ongeveer /usr/bin:/bin en uw shell-profiel wordt nooit ingelezen. Een taak die werkt wanneer u deze in uw terminal plakt, faalt onder cron met /bin/sh: 1: docker: not found, omdat dat binaire bestand zich in /usr/local/bin bevindt. Gebruik absolute paden in crontabs. Als de nadruk van een unit-bestand op het specificeren van de gebruiker, de omgeving en de afhankelijkheden aanvoelt als overbodige formaliteit vergeleken met een enkele crontab-regel, dan legt de problemen die systemd moest oplossen uit waar die uitgebreidheid vandaan komt.
Taak 3: controleer een Nginx- of Compose-bestand voordat het live gaat
Deze taak levert het meeste op. Plak het bestand, vermeld wat het hoort te doen en vraag om een regel-voor-regel uitleg van wat het daadwerkelijk uitvoert.
Deze vhost moetexample.comvia HTTPS serveren en/apidoorsturen naar een lokale service op poort 8080. Lees het voor mij terug en benoem alles wat niet overeenkomt met die beschrijving.
Voer daarna de tool uit die de grammatica kent:
sudo nginx -t
docker compose config -qnginx -t geeft nginx: configuration file /etc/nginx/nginx.conf test is successful weer, of het benoemt het bestand en de regel, zoals in nginx: [emerg] unknown directive "proxy_pas" in /etc/nginx/conf.d/app.conf:12. docker compose config -q geeft niets weer als het bestand correct geparseerd wordt, en iets kortaf zoals yaml: line 7: did not find expected key wanneer uw inspringing niet klopt.
Geen van beide tools controleert de intentie. Een configuratie die slaagt voor nginx -t kan nog steeds doorsturen naar de verkeerde poort, of luisteren op 0.0.0.0 terwijl u 127.0.0.1 bedoelde. Dat gat is waar het model zijn waarde bewijst, maar het is ook waar het faalt: als u vraagt om één directive te corrigeren, wordt vaak het hele bestand herschreven waarbij twee van uw directives stilletjes verdwijnen. Vraag om de gewijzigde regels en de reden voor elk, en pas het daarna handmatig aan.
Bevestig wat u daadwerkelijk heeft blootgesteld:
sudo ss -tulpnZonder sudo ziet u de luisterende sockets, maar niet de processen die ze bezitten. Als die output u verrast, is wat poorten zijn en hoe Linux ze bindt de kortere leesstof.
Taak 4: verklaar een onbekend commando voordat u het uitvoert
Plak het commando en stel vier vragen: wat doet elke vlag, wat schrijft het, wat verwijdert het en wat gebeurt er als ik het twee keer uitvoer? De laatste vraag voorkomt vaak meer schade dan de andere.
Neem find /var/log -name '*.gz' -mtime +7 -delete. Een goed antwoord vermeldt dat -mtime +7 volledige periodes van 24 uur telt en de restfractie negeert, waardoor het bestanden vindt die minimaal acht dagen oud zijn in plaats van zeven. Het vermeldt ook dat find de expressie van links naar rechts evalueert, dus het verplaatsen van -delete vóór -name verwijdert alles onder het startpad. Dat tweede punt staat als waarschuwing in de find man-pagina en heeft mensen al hun /var/log gekost.
Of neem rsync -a --delete /srv/app/ /backup/app/. De afsluitende slash bij de bron betekent "de inhoud van deze map". Laat deze weg en u krijgt /backup/app/app/. Voeg --delete toe en alles in de bestemming dat ontbreekt in de bron wordt verwijderd; dit is correct voor een mirror, maar rampzalig als het bronpad onjuist is.
Controleer met de tool, niet met het model:
rsync -a --delete --dry-run /srv/app/ /backup/app/ | head -20
find /var/log -name '*.gz' -mtime +7Voer de find uit zonder -delete en u krijgt een lijst in plaats van verlies.
Faalmodus: vlag-hallucinatie. Het model is betrouwbaar bij tools met dertig jaar aan documentatie en aanzienlijk zwakker bij vendor CLI's (command line interfaces) en recente subcommando's, waarbij het een vlag genereert die logisch klinkt maar niet bestaat. --help lost dit in één seconde op. Quoting is het andere zwakke punt; wanneer een commando een $(...)-expressie bevat, lees dan hoe command substitution uitbreidt voordat het commando wordt uitgevoerd in plaats van te vertrouwen op de uitleg.
Taak 5: zet uw shell-geschiedenis om in een draaiboek
U bent zojuist twee uur bezig geweest om iets werkend te krijgen. Die kennis zit nu in uw scrollback en is volgende maand verdwenen.
history 200 > /tmp/session.txtLees dat bestand en verwijder elke regel die een wachtwoord, token of klantidentificatie bevat voordat u het ergens anders opslaat. Shell-geschiedenis is een van de meest betrouwbare plekken om een geheim te vinden op een Linux-systeem, omdat iedereen wel eens een wachtwoord direct in de opdrachtregel typt. Stel HISTCONTROL=ignorespace in uw ~/.bashrc in; een commando dat begint met een spatie wordt dan helemaal niet naar de geschiedenis geschreven.
De prompt die een bruikbaar draaiboek oplevert, vraagt om controles, niet alleen om stappen:
Dit is een shell-sessie die een verse Debian 13-server heeft omgezet naar een werkende Postgres-installatie. Schrijf dit uit als een genummerd draaiboek. Eén commando per stap. Geef na elke stap het commando dat bewijst dat het werkte en beschrijf hoe gezonde output eruitziet. Markeer elke stap die afhankelijk was van mijn specifieke host.
Faalwijze: een te netjes verhaal. Uw sessie bevatte een stap die u twee keer fout deed voordat u deze herstelde, en dat is precies de stap die het model wegpoetst, omdat het transcript zonder die fouten leesbaarder is. Vergelijk het draaiboek met uw geschiedenis en voeg de correctie weer toe. Het model verzint ook aannemelijke verificatiecommando's, dus voer elke controle uit die het schrijft voordat u het bestand opslaat. Als het draaiboek een eerste opstart betreft, vergelijk het dan met de eerste tien minuten op een nieuwe VPS zodat u geen slechtere versie van een reeds opgelost probleem opschrijft.
Taak 6: een foutmelding omzetten in een oplossing
Plak de exacte tekenreeks, het commando dat deze genereerde en het ene ding dat u wijzigde voordat deze verscheen. Vraag om een rangschikking van oorzaken met een onderscheidend commando voor elk, wat het antwoord dwingt tot iets testbaars.
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use). Rangschik de waarschijnlijke oorzaken en geef mij één commando per oorzaak dat deze bevestigt of uitsluit.
Voor die fout is het mechanisme niet dubbelzinnig: een ander proces bezet al poort 80 en sudo ss -tulpn | grep ':80 ' benoemt dit. Vaak is het een tweede nginx-master die is achtergebleven na een mislukte herlaadactie, of Apache dat als afhankelijkheid is meegekomen en door het eigen pakket is gestart.
Faalmodus: een oplossing die werkt door de oorzaak te verbergen. chmod 777, --privileged, het uitschakelen van SELinux en het uitvoeren van de service als root laten de fout allemaal verdwijnen. Weiger elke oplossing die de rechten verruimt totdat het model heeft uitgelegd waarom de beperkte rechten faalden. Die uitleg is het eigenlijke antwoord. Een tijdelijke oplossing maakt de fout alleen maar stil.
Wat er steevast misgaat
- Het systeem kan uw server niet inzien. Elk antwoord is gebaseerd op wat u heeft geplakt; het zal niet aangeven dat het fragment te kort was.
- Het loopt achter op versies. Pakketnamen en standaard-flags veranderen tussen distributies en releases, en het model middelt over alle varianten heen.
- Het is overtuigend wanneer het onjuist is. Een gefantaseerd mechanisme leest precies als een correcte procedure; daarom is elke hierboven genoemde oorzaak voorzien van een commando om dit te verifiëren.
- Het verliest de draad tijdens lange sessies. Feiten van het begin van een gesprek van twee uur beïnvloeden de antwoorden aan het einde niet meer.
Dat laatste punt is eerder een werkmethodeprobleem dan een modelprobleem, en contextbeheer in een lange Claude Code-sessie is de praktische oplossing: kortere sessies, één taak per keer.
De agent op de server zelf plaatsen
Alles hierboven is kopiëren en plakken, waardoor het model nooit uw machine aanraakt. Zodra het op de server draait, bestanden leest en commando's uitvoert, verandert het risicoprofiel: een foutief commando kan nu een service kosten. Geef de agent een eigen gebruiker zonder privileges in plaats van root, houd deze weg van de productieserver terwijl u het gedrag leert kennen, en maak eerst een snapshot. Veilig draaien van Claude Code op een VPS behandelt de sandboxing en het permissiemodel. Claude Code aansturen binnen tmux lost het andere deel op, aangezien een verbroken SSH (secure shell)-sessie een agent op de voorgrond halverwege zijn werk kan afbreken. Richt het account in zoals u elk service-account zou inrichten, wat gebruikers met minimale privileges op een VPS in detail beschrijft.
FAQ
Kan Claude mijn serverlogs rechtstreeks lezen?
Niet uit zichzelf. De chatinterface ziet alleen de tekst die u erin plakt. Claude Code, uitgevoerd op de server als command-line tool, kan bestanden lezen en commando's uitvoeren met de rechten van de gebruiker die het heeft gestart; dit is een ingrijpendere beslissing wat betreft vertrouwen. Voor een standaard ondersteuningsvraag is het plakken van een geanonimiseerd fragment van 100 regels sneller en veiliger dan een agent shell-toegang geven.
Wat mag ik nooit vanaf een server plakken?
Private keys, .env-bestanden en andere credential stores, /etc/shadow, en alle gegevens die toebehoren aan uw gebruikers. Verwijder tokens uit logfragmenten voordat ze in de prompt terechtkomen. Een minder voor de hand liggend geval: de output van docker compose config bevat uw .env-waarden; gebruik daarom docker compose config -q, dat het bestand valideert zonder output te tonen.
Is het veilig om Claude commando's te laten uitvoeren op een productie-VPS?
Behandel het als een nieuwe beheerder zonder context: prima voor het lezen, maar controle is vereist voor het schrijven. Vraag op productie om uitleg en voer het commando zelf uit. Als u een agent wilt laten uitvoeren, geef deze dan een toegewezen account zonder privileges zonder algemene sudo-rechten, en begin op een staging-omgeving waar een fout slechts een herbouw kost in plaats van een uitval.
Waarom stelt Claude een flag voor die niet bestaat?
Omdat het model aannemelijke tekst voorspelt, en een aannemelijke flag ziet er hetzelfde uit als een echte. Dit gebeurt vooral bij vendor-CLI's en nieuwere subcommands, waar de documentatie achter het model beperkt is of inmiddels is gewijzigd. --help en man zijn de uiteindelijke bron van waarheid, en elk commando dat gegevens verwijdert of overschrijft, verdient eerst een dry run.
Hoe controleer ik een systemd-unit voordat ik deze inschakel?
Voer sudo systemd-analyze verify /etc/systemd/system/myapp.service uit. Dit parseert het bestand met de eigen parser van systemd, rapporteert onbekende richtlijnen met hun regelnummers en markeert een ExecStart-binary die ontbreekt of niet uitvoerbaar is. Voer daarna daemon-reload en start uit en lees systemctl status voordat u enable uitvoert, omdat een unit die correct laadt, bij de eerste uitvoering alsnog kan falen.