Vandaag heeft Wendy, mijn PCPal-Personal Agent, een nieuwe vaardigheid gekregen. Ze kan sinds vanmiddag zelfstandig virtuele servers uitrollen op mijn eigen hypervisor. Geen schermpjes klikken, geen handleiding erbij, geen halfuur wachten. Ik typ dat ik een server wil, en een minuut later staat hij te draaien met het juiste IP-adres, de juiste gebruiker en mijn sleutels erin.
Hieronder staat wat er precies gebeurd is, hoe het werkt, en waarom ik het op deze manier heb ingericht en niet op de makkelijke manier.
Eerst even: wat is Proxmox?
Proxmox VE is een open source virtualisatieplatform. Je installeert het op fysieke hardware, en die machine wordt daarmee een hypervisor: een computer die andere computers herbergt. Binnen dat ene apparaat draai je losse virtuele machines, elk met een eigen besturingssysteem, eigen netwerkkaart, eigen schijf. Ze weten niet van elkaars bestaan.
Bij mij draait Proxmox op de CyberMonster, een AMD Ryzen 7 5800X met 128 GB geheugen. Daarop staan onder andere de Nextcloud-server, de Anoiksis-omgeving en wat kleinere containers. Het is in feite mijn eigen datacenter, dan zonder het datacenter, de koeling en het abonnement.
Het aardige aan Proxmox is dat alles wat je in de webinterface kunt doen, ook via een REST API kan. Elke knop in dat scherm is onder water gewoon een HTTP-aanroep. En daar begint dit verhaal.
De use case
Ik bouw regelmatig een server. Voor een klant die iets wil testen, voor mezelf om te kijken of een pakket doet wat het belooft, voor een demo. Dat kostte me elke keer hetzelfde halfuur: image kiezen, machine aanmaken, geheugen en cores instellen, netwerk goedzetten, installeren, wachten, inloggen, locale en tijdzone rechtzetten, sleutels erin, updaten. Werk dat ik al honderden keren gedaan heb en dat geen enkele beslissing van me vraagt.
Dat is precies het soort werk waar een agent voor is. Niet het nadenken, wel het herhalen. Ik wilde kunnen zeggen: geef me een testserver. En dan een IP-adres terugkrijgen waar ik op kan inloggen.
Hoe het werkt
De vaardigheid heet proxmox-beheer en bestaat uit twee dingen: een beschrijving voor de agent van wat ze wel en niet mag, en een Python-script dat met de Proxmox-API praat. Dat script gebruikt uitsluitend de standaardbibliotheek, dus er valt niets stuk bij een update van een of ander pakket.
De harde regel eronder: de agent praat nooit rechtstreeks met de hypervisor. Geen SSH naar de host, geen qm, geen pct. Alles gaat via de API, en dat is geen esthetische keuze. Elke API-aanroep belandt in de takenlijst van Proxmox, met tijdstip, gebruiker en resultaat. Als ik over drie maanden wil weten wie die machine heeft aangemaakt en wanneer, dan staat dat er gewoon. Een SSH-sessie laat dat spoor niet na.
Ze logt bovendien in met een eigen API-token, wendy@pve!automation, niet met mijn beheerdersaccount. Dat token heeft bewust een aantal rechten niet. Ze kan de host niet herconfigureren, niet herstarten en geen permissies uitdelen. Ze kan wel machines maken, starten, stoppen en bekijken. Ik heb het token gemaakt door net zo lang rechten weg te halen tot iets stukging, en dat laatste stukje terug te zetten.
Het certificaat van mijn Proxmox is zelfondertekend. De luie oplossing daarvoor is certificaatcontrole helemaal uitzetten, en dat zie je in nagenoeg elk voorbeeldscript op internet. Dat betekent dat je met iedereen praat die zich voordoet als je server. In plaats daarvan staat de vingerafdruk van het certificaat in de configuratie, en het script vergelijkt die bij elke verbinding. Zelfondertekend, maar wel geverifieerd.
De werkwijze: sjabloon en kloon
Een nieuwe server installeren vanaf nul duurt lang. Een bestaande kopiëren duurt seconden. Daarom staat er een sjabloonmachine klaar: een Ubuntu-server die één keer volledig is ingericht en daarna is gegeneraliseerd, wat wil zeggen dat alle unieke kenmerken eruit zijn gehaald. De machine-identiteit, de SSH-hostsleutels, de cloud-init-geschiedenis. Wat overblijft is een schone afdruk.
Van dat sjabloon maakt de agent een volledige kloon, zet er via de API een vast IP-adres in, en start hem. Tijdens de eerste start regelt cloud-init de rest: gebruikersnaam, sleutels, netwerk, DNS. Vanaf het commando tot een server waar ik op kan inloggen zit ongeveer een minuut.
Twee dingen die eerst niet werkten
Het eerste: de API weigert het uploaden van cloud-init-configuratiebestanden. Je mag installatie-images uploaden en containersjablonen, maar geen snippets. Dat is geen fout in mijn script, dat is hoe Proxmox het heeft dichtgezet. Dus doen we het anders: alleen de velden gebruiken die de API wél accepteert, en de rest van de inrichting via een gewone SSH-verbinding naar de nieuwe machine zelf. Dat is normaal serverbeheer op een server die ik zelf heb aangemaakt. Het spoor van aanmaken, starten en stoppen blijft volledig via de API lopen.
Het tweede was vervelender. De eerste testmachine kwam elke keer op een DHCP-adres binnen in plaats van het vaste adres dat ik had opgegeven. De configuratie klopte, de gegenereerde netwerkinstellingen klopten, en toch stond hij op het verkeerde adres. Het bleek een race condition: Ubuntu probeert de netwerkkaart tijdens het opstarten te hernoemen van ens18 naar eth0, en als de kaart op dat moment al in gebruik is, mislukt dat stilletjes. De netwerkconfiguratie verwijst dan naar een naam die niet bestaat, en de machine valt terug op DHCP. Zonder foutmelding.
De oplossing was het uitzetten van die hele hernoemmachinerie. Geen voorspelbare interfacenamen meer, gewoon eth0 vanaf het begin. Die aanpassing zit nu in het sjabloon, dus elke kloon komt automatisch goed op. Dit soort dingen kost een uur zoeken en drie regels om op te lossen, en daarna staat het in de vaardigheidsbeschrijving zodat niemand het nog een keer hoeft uit te zoeken.
De demo
Om te laten zien dat het werkt heb ik gevraagd om een demoserver. Wat er gebeurde: kloon van het sjabloon, vast adres op 192.168.0.213, twee cores, acht gigabyte geheugen, veertig gigabyte schijf, starten. Binnen een minuut een werkende Ubuntu-server, met de guest-agent actief, cloud-init netjes afgerond en mijn sleutels erin.
Inloggen gaat met gebruikersnaam ubuntu en uitsluitend met een sleutel. Wachtwoordauthenticatie staat uit in het cloud-image, en dat laat ik zo.
Waar de rem zit
Autonomie zonder grenzen is geen autonomie, dat is een ongeluk dat wacht op een aanleiding. Dus er staan grenzen in, en die zijn expliciet.
Zelfstandig, zonder te vragen: status opvragen, machines klonen binnen haar eigen nummerbereik, haar eigen machines starten en stoppen, geheugen of schijf naar boven bijstellen, snapshots maken.
Altijd eerst vragen: iets verwijderen. Wat dan ook. Een machine, een snapshot, een schijf. Ook als ze hem zelf heeft aangemaakt, ook als het duidelijk wegwerpspul is. Verder: iets aanraken buiten haar eigen nummerbereik, een schijf verkleinen, netwerk of opslag van de host wijzigen, de node herstarten.
De nummerbereiken doen het meeste werk. Mijn eigen machines staan op 100 tot 199, die van haar op 200 tot 299, de sjablonen op 900 en hoger. Een grens die je kunt zien is een grens waar je je aan houdt.
Een stap verder: een complete Nextcloud in een commando
Een lege server is nog geen dienst. De vraag die meteen daarna komt is: geef me een server die ook iets doet. Dus is er een tweede vaardigheid bijgekomen, die op de eerste voortbouwt. Ik vraag om een Nextcloud, en ik krijg een werkende Nextcloud.
Nextcloud is de zelfgehoste tegenhanger van Dropbox of Google Drive. Bestanden, agenda, contacten, delen met anderen, alleen dan op je eigen hardware in plaats van die van iemand die er een verdienmodel omheen bouwt. Ik draai het al jaren. Alleen: het opzetten ervan is een halve middag. Webserver, database, een handvol PHP-modules, rechten goedzetten, de installatie via de commandoregel afronden, caching aan, de achtergrondtaken instellen.
Dat hele traject zit nu in de vaardigheid. Ze kloont de machine, zet het adres, start hem, wacht tot hij klaar is met opstarten, en gaat dan naar binnen om Apache, MariaDB, PHP en de laatste Nextcloud-release te installeren. Database aanmaken, virtuele host inrichten, de installatie afronden, geheugencache aanzetten, de achtergrondtaak in de crontab, nette URL’s zonder index.php erin. Aan het eind krijg ik een adres en een inlog.
De wachtwoorden
Dit is het stuk waar het bij dit soort automatisering meestal misgaat. Scripts die een standaardwachtwoord zetten, of erger, het wachtwoord in het script laten staan waar iedereen het kan lezen.
Hier worden ze bij elke uitrol vers gegenereerd. Vierentwintig tekens, letters en cijfers, uit de generator die daar echt voor bedoeld is en niet uit een gewone toevalsfunctie. Bewust geen leestekens, want die breken de commando’s die de database en de installatie aansturen. Ze komen een keer voorbij in de chat, en verder staan ze in een bestand op de machine thuis dat alleen door mijn eigen account te lezen is. Niet in de synchronisatie, niet in het logboek, niet in de takenlijst van de hypervisor. Dat logboek noteert dat er een server is ingericht, niet waarmee je erin komt.
Twee keer bewust afgeweken
Mijn eigen handleiding begint met het volledig bijwerken van het systeem. Dat is op zich netjes, maar het sjabloon is vers en zo’n complete bijwerkronde kost tijd en kan halverwege om een herstart vragen. Midden in een uitrol is dat precies wat je niet wil. Dus alleen de pakketlijst verversen en gericht installeren.
Het tweede: de firewall. Poort 22 en 80 gaan open, maar de firewall wordt niet daadwerkelijk ingeschakeld tijdens de uitrol. Wie dat wel doet terwijl hij zelf via een verbinding op poort 22 binnen zit te werken, sluit zichzelf buiten en mag opnieuw beginnen. Dat is het soort fout dat een script vrolijk maakt en waar een mens dan een uur mee bezig is.
Het resultaat
Van niets naar een draaiende Nextcloud met een inlogscherm, zonder dat ik ertussen hoefde te zitten. Geen installatiewizard doorklikken, geen rechten rechtzetten, geen zoeken waarom de achtergrondtaak niet loopt. Een adres, een gebruikersnaam, een wachtwoord.
En dat is waar dit interessant wordt. De eerste vaardigheid gaf me een lege machine. De tweede gaf me een dienst. Wat daarna komt is meer van hetzelfde: elke installatie die ik vaker dan twee keer doe, is een kandidaat om zo vast te leggen. Niet omdat ik het niet zelf kan, maar omdat het de honderdste keer is dat ik het doe en er geen enkele beslissing meer in zit.
Waarom dit mij bevalt
Dit is geen chatbot die me vertelt hoe ik een server maak. Dit is een agent die er een maakt, in mijn eigen rek, op mijn eigen hardware, binnen grenzen die ik zelf heb getrokken en die zij niet kan oprekken. Er gaat geen creditcard mee naar een cloudprovider en er verlaat geen byte mijn netwerk totdat ik dat wil.
Ownership by design, zoals dat bij PCPal heet. Niet omdat de cloud slecht is, maar omdat het uitmaakt wie de knoppen bezit. Ik heb liever een agent met beperkte rechten op mijn eigen ijzer dan onbeperkte rechten op dat van iemand anders.
Maar vooral: het scheelt me een half uur per server. Dat is het echte argument.