CluPilotCloud/app/Livewire/Admin
nexxo 4debc79883 Eine hängende Sperre ist jetzt ein Knopf, kein SSH-Zugang
Am 4. August 2026 hielt ein einziger Aufruf — `timeout 45 docker compose
exec` ohne `--kill-after` — die Sperre stundenlang, und jeder folgende
Lauf wurde übersprungen. Behoben ist die Ursache in v1.6.5; was fehlte,
war der Griff für das nächste Mal. Er lag per SSH auf dem Wirt.

Die Konsole kann ihn nicht selbst führen: sie ist www-data in einem
Behälter, der Sperrenhalter ist ein Prozess auf dem WIRT. Also bittet
sie den Agenten, und der ruft den root-eigenen Helfer — dasselbe Muster
wie `apply-proxy-hosts`, mit eigener sudoers-Zeile.

Die Bitte liegt in einer EIGENEN Datei, und das ist keine
Geschmacksfrage: der Agent nimmt die Sperre in seinen ersten Zeilen,
lange bevor er den Postkasten ansieht. Ein blockierter Lauf steigt
vorher aus — eine Entsperr-Bitte im Postkasten erreichte ihn also genau
dann nie, wenn sie gebraucht wird. Dazu nimmt der Postkasten eine Bitte
zur Zeit an, und die dreißig Minuten, in denen dort eine wartende
Update-Anfrage liegt, sind die, in denen jemand entsperren will.

Der Dienstbenutzer sagt „gib die Sperre frei", nicht „töte 1234": welcher
Prozess das ist, sucht der Helfer selbst. Dürfte der Anrufer die Nummer
liefern, wäre die Freigabe das Recht, jeden beliebigen Prozess als root
zu beenden.

Beendet werden alle, die die Sperrdatei OFFEN halten — nicht nur der,
der das flock genommen hat. Ein flock hängt an der offenen
Dateibeschreibung, und die wird vererbt: stirbt der Agent, sein
hängendes `docker compose exec` aber nicht, bleibt die Sperre gehalten.
Genau das war der Vorfall. Verschont bleiben PID 1 und der Anrufer samt
Vorfahren — im Betrieb hält der blockierte Agent die Datei selbst offen
und ist zugleich der, der anruft.

Erst SIGTERM, fünf Sekunden, dann SIGKILL. Eine Frist ohne Nachdruck ist
keine Frist.

Bestätigt wird im Modal (R23), das VORHER nennt, was es beendet — PID,
Laufzeit und Kommandozeile aus dem Lebenszeichen. Eigene Berechtigung
`deployment.unblock`, nicht `site.manage`: wer aktualisieren darf, darf
damit nicht automatisch in einen laufenden Vorgang hineingreifen.

Der Helfer-Vertrag steigt auf 3, und update.sh verlangt ihn. Ohne das
wäre der Knopf auf einem Wirt, der install-agent.sh seither nicht mehr
gefahren hat, ein Knopf, der still nichts tut — und die Konsole sagt es
jetzt, statt den Betreiber dorthin zurückzuschicken, wo er ohne sie
schon war.

Geprüft wird ausgeführt, nicht begutachtet: der Helfer läuft im Test
gegen eine echte Sperrdatei mit echten Prozessen daran. Das hat gleich
einen Fehler gefunden — der Helfer erbt den Deskriptor und hielt seine
eigenen Kommandosubstitutionen für Halter, sodass die Runde nie zum Ende
gekommen wäre.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 10:07:24 +02:00
..
Capacity.php Ein angehefteter Host umging die Reservierung 2026-08-01 18:53:11 +02:00
CheckResult.php Pruefergebnis als Modal statt am Seitenende 2026-07-31 21:36:43 +02:00
CloseDunningCase.php Mahnwesen: Einstellungen und die zwei Eingriffe von Hand 2026-07-31 22:43:52 +02:00
ConfirmDeleteDatacenter.php fix(admin): authorize datacenter modal mounts; stale threshold uses step maxDuration 2026-07-25 18:23:44 +02:00
ConfirmDeleteIncident.php Let an incident be deleted, and start measuring whether the hosts answer 2026-07-29 15:16:48 +02:00
ConfirmDeletePlanDraft.php feat(admin): a console for creating, pricing and scheduling plans 2026-07-26 12:41:51 +02:00
ConfirmDeleteVpnPeer.php feat(vpn): ownership, a Developer role, and password-gated config retrieval 2026-07-25 22:31:54 +02:00
ConfirmDisableTwoFactor.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
ConfirmEndOtherSessions.php Show where an account is signed in, and let it sign the other places out 2026-07-28 23:38:17 +02:00
ConfirmForgetSecret.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
ConfirmGenerateSshKey.php Hetzner-Cloud-DNS, Bereitschaftsseite aus sich heraus behebbar 2026-07-31 19:50:01 +02:00
ConfirmPublishDpa.php Deliver the processing agreement, and hold the proof it was accepted 2026-07-30 16:56:57 +02:00
ConfirmReissueVpnPeer.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
ConfirmReleaseBlock.php Sperren sehen und aufheben: Portalseite fuer den Inhaber, Abschnitte in der Konsole 2026-08-03 15:53:24 +02:00
ConfirmReleaseReservation.php Ein reservierter Host gehoert seinem Kunden 2026-08-01 16:06:14 +02:00
ConfirmReleaseUpdateLock.php Eine hängende Sperre ist jetzt ein Knopf, kein SSH-Zugang 2026-08-04 10:07:24 +02:00
ConfirmRemoveHost.php feat(admin): staff RBAC (spatie) + admin settings page 2026-07-25 15:47:42 +02:00
ConfirmRestartInstance.php Restart a machine, enforce the quota that was sold, end a route that ended 2026-07-29 18:28:28 +02:00
ConfirmSaveEnv.php Add a raw .env editor to the Integrations page, with a net under it 2026-07-29 01:51:27 +02:00
ConfirmSaveSecret.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
ConfirmSwitchMode.php Put the switch where it governs, and say when it is thrown 2026-07-30 15:09:38 +02:00
ConfirmSyncCatalogue.php Hetzner-Cloud-DNS, Bereitschaftsseite aus sich heraus behebbar 2026-07-31 19:50:01 +02:00
CustomerDetail.php Jede Mail faehrt wieder ueber ihren eigenen Mailer 2026-08-03 20:36:20 +02:00
Customers.php Ask whether they are a consumer, and let one change their mind 2026-07-29 21:06:06 +02:00
Datacenters.php Let a datacenter code be corrected while nothing depends on it, and say which building 2026-07-28 22:25:21 +02:00
EditCustomer.php Take the address by field, fix the customer type, ask why they leave 2026-07-30 16:41:32 +02:00
EditDatacenter.php Let a datacenter code be corrected while nothing depends on it, and say which building 2026-07-28 22:25:21 +02:00
EditExportTarget.php Let a destination say how it is laid out and how long anything stays 2026-07-29 03:08:27 +02:00
EditInvoiceSeries.php Give the console a Finance tab: company details, VAT rate, invoice series 2026-07-29 01:18:43 +02:00
EditMailTemplate.php Show the customer, and write the answers once 2026-07-29 22:37:30 +02:00
EditPlanFamily.php Move each plan's marketing copy from the controller into the console 2026-07-29 14:31:44 +02:00
ExtendDunningDeadline.php Mahnwesen: Einstellungen und die zwei Eingriffe von Hand 2026-07-31 22:43:52 +02:00
Finance.php Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +02:00
GrantPlan.php Interne Pakete verschwinden aus dem Laden und bleiben in der Konsole 2026-08-01 15:31:46 +02:00
HostCreate.php Host anlegen: die Seite beschrieb das Rettungssystem und startete die Pipeline 2026-08-02 01:38:48 +02:00
HostDetail.php fix(security): Aufheben einer Sperre sagt die Wahrheit und wird nachgeholt 2026-08-03 17:28:28 +02:00
HostTerminal.php Terminal: keine Fehlerseite mehr, ein Knopf auf jeder Zeile, eine Buehne statt roter Zeilen 2026-08-02 19:27:35 +02:00
Hosts.php Host-Liste holt sich ihren Stand selbst; die Ausstattung braucht keine Zeile nur fuer die Adresse 2026-08-02 17:00:30 +02:00
Inbox.php Read the mailbox password where it actually is, and let the console test it 2026-07-30 13:12:29 +02:00
Incidents.php Let an incident be deleted, and start measuring whether the hosts answer 2026-07-29 15:16:48 +02:00
InstanceAdminAccess.php Send an operator with an expired session to sign in, not a 500 2026-07-28 18:09:22 +02:00
Instances.php Deliver the storage a customer actually buys 2026-07-29 19:13:10 +02:00
Integrations.php Pruefergebnis als Modal statt am Seitenende 2026-07-31 21:36:43 +02:00
Invoices.php Take the invoice year off the storage clock too 2026-07-29 02:28:34 +02:00
Mail.php Die Mailseite fragt drei Fragen statt eine Wand zu zeigen 2026-08-03 22:06:50 +02:00
MailLog.php Keep a register of what was sent, and answer the customer from here 2026-07-29 21:02:36 +02:00
MailPace.php Der Versandtakt nennt die Mails beim Namen 2026-08-04 00:52:04 +02:00
MailPreview.php Hetzner-Cloud-DNS, Bereitschaftsseite aus sich heraus behebbar 2026-07-31 19:50:01 +02:00
MailTemplates.php Say that a click landed, and make moving one actually move it 2026-07-29 23:06:30 +02:00
Maintenance.php Move the console's identity out of the customer table 2026-07-28 10:31:43 +02:00
NewInvoice.php Write an invoice for work that came off no price list 2026-07-29 20:12:26 +02:00
OpenWork.php Offene Punkte: nach Dringlichkeit gruppiert, in der Formensprache der Bereitschaftsseite 2026-08-02 16:35:14 +02:00
Overview.php Sperren sehen und aufheben: Portalseite fuer den Inhaber, Abschnitte in der Konsole 2026-08-03 15:53:24 +02:00
PaymentProblems.php Ein Waechter, der aufraeumt — und die vier offenen Punkte aus dem Betrieb 2026-08-03 09:43:33 +02:00
PlanVersions.php Schalter je Paket, ehrliche Statusanzeige, Reste der alten Leiter 2026-08-01 17:53:06 +02:00
Plans.php Schalter je Paket, ehrliche Statusanzeige, Reste der alten Leiter 2026-08-01 17:53:06 +02:00
ProcessingAgreements.php Store the agreement where the web process can actually read it 2026-07-30 17:19:39 +02:00
Provisioning.php Ein Waechter, der aufraeumt — und die vier offenen Punkte aus dem Betrieb 2026-08-03 09:43:33 +02:00
ProxyHosts.php Fill the hostname page from the installation, not from a blank form 2026-07-31 00:53:12 +02:00
Readiness.php Die Bereitschaftsseite meldet eine Spur, die steht 2026-08-03 18:37:20 +02:00
RecordWithdrawal.php Charge the price the website shows, and hand a withdrawal back in full 2026-07-29 22:42:02 +02:00
ReissueTakeover.php Release v1.3.82 — Übernahme-Befehlszeile neu ausstellen 2026-08-01 01:00:53 +02:00
ResolveFailedCheckout.php R20: Begruendung im Modal, und der Waechter sieht jetzt auch Listenzeilen 2026-07-31 22:09:05 +02:00
Revenue.php Skip the invoice for a full gift, keep it out of revenue, hide its price 2026-07-29 12:41:32 +02:00
Roles.php Zwei Attrappen: ein Banner ohne Hintergrund und Rechte, die ihren Schluessel statt ihrer Beschreibung zeigten 2026-08-02 16:47:15 +02:00
Sessions.php Show where an account is signed in, and let it sign the other places out 2026-07-28 23:38:17 +02:00
Settings.php Eine hängende Sperre ist jetzt ein Knopf, kein SSH-Zugang 2026-08-04 10:07:24 +02:00
Setup.php Die Seitenleiste fragt zuerst, ob etwas auf dich wartet 2026-08-04 02:51:35 +02:00
TwoFactorSetup.php Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +02:00
Vpn.php Release v1.3.84 — VPN-Zugänge nach Personen und Hosts getrennt 2026-08-01 02:34:15 +02:00
VpnConfigAccess.php Send an operator with an expired session to sign in, not a 500 2026-07-28 18:09:22 +02:00