Wir entwickeln Software, die Unternehmen voranbringt. VantixOps aus Bremen steht für individuelle Software, leistungsfähige Webanwendungen, moderne Buchungssysteme und digitale Plattformen. Wir entwickeln nicht von der Stange. Wir entwickeln für echte Anforderungen.
Wir bauen Lösungen, die zu realen Abläufen passen. Büroautomatisierung ergänzt unser Angebot: Sie reduziert Routinearbeit und schafft Freiraum für das eigentliche Geschäft.
Unser technisches Fundament: Softwareentwicklung, Linux, Self-Hosting, WordPress und n8n.
🌐 vantix-ops.de · ✉️ kontakt@vantix-ops.de
Wir entwickeln nicht nur Software. Wir übernehmen Verantwortung für ihre Qualität. Wir betreiben eigene Systeme, untersuchen technische Fehler und veröffentlichen nachvollziehbare Lösungen. Bugs melden wir dort, wo sie behoben werden können. Erkenntnisse aus realen Entwicklungs- und Betriebsproblemen dokumentieren wir offen – damit andere daraus lernen und dieselben Fehler vermeiden können.
Software statt Standardlösungen. Unser Schwerpunkt liegt auf maßgeschneiderter Software und digitalen Produkten:
- Individuelle Anwendungen: Software, die konkrete Anforderungen und Prozesse abbildet.
- Webanwendungen und digitale Plattformen: moderne Lösungen für Browser und mobile Geräte.
- Buchungs- und Verwaltungssysteme: digitale Abläufe für Dienstleister, Studios und Unternehmen.
- Büroautomatisierung: weniger Routinearbeit durch vernetzte Systeme und gezielte Automatisierung – als Ergänzung unserer Softwareentwicklung.
Unsere Kundenprojekte und internen Systeme sind nicht automatisch öffentlich. Hier auf GitHub zeigen wir ausgewählte technische Arbeiten und Beiträge zur Entwicklergemeinschaft.
Unser Anspruch: Wir bauen belastbare Software, prüfen Ergebnisse und teilen technische Erkenntnisse, die anderen Entwicklern weiterhelfen.
Die meisten teuren Fehler bei uns waren still: kein roter Test, kein Fehlercode, alles sah grün aus. Daraus sind diese Regeln entstanden.
- Eine Null braucht eine Gegenprobe. „0 Treffer“ heißt oft „nicht gemessen“: falscher Pfad, abgebrochener Befehl, falsches Werkzeug. Vor jeder Null-Aussage denselben Befehl auf etwas ansetzen, das es sicher gibt.
- Grün ist kein Beleg. HTTP 200, „success“,
activeoder ein bestandener Test sagen, dass etwas geantwortet hat, nicht dass es gewirkt hat. Das Ergebnis dort nachlesen, wo es ankommen soll. - Nach einem Update erst die Vorversion probieren. Das trennt in Minuten „das Programm ist kaputt“ von „mein System ist kaputt“, bevor man an Einstellungen dreht.
- Den Rückweg testen, solange man ihn nicht braucht. Eine Sicherung, die sich im Ernstfall nicht findet oder nicht öffnet, ist schlimmer als keine, weil man sich auf sie verlässt.
- Nur löschen, was man selbst angelegt hat, und zwar nach Liste statt nach Muster. Ein Stern (
*) trifft auch Dateien aus früheren Läufen und anderen Sitzungen. - Eine Prüfung ist selbst Code. Neu gebaute Prüfungen enthalten Fehler wie alles andere. Einmal absichtlich einen Fehler einbauen und schauen, ob die Prüfung ihn meldet.
- Warnungen im Log gegen einen funktionierenden Stand halten, bevor man sie meldet. Was auch dort auftaucht, ist nicht die Ursache. Eine falsche Spur kostet die Entwickler mehr Zeit als gar keine.
set -ebeendet das Skript schon beix=$(befehl), wenn der Befehl scheitert. Ein$?in der Zeile danach wird nie gelesen.- Zusammen mit
pipefailbrichtX=$(… | grep -c muster)das Skript ab, sobald es 0 Treffer gibt, weilgrep -cdann mit Status 1 endet. Ausgerechnet Prüfungen nach dem Muster „0 Fehler ist gut“ sterben so mitten im Lauf. if befehl; then …; fi; rc=$?liefert immer 0: Einifohneelsehat selbst den Status 0.befehl | tailmeldet den Status vontail, nicht vonbefehl. Abhilfe:set -o pipefailoder${PIPESTATUS[0]}.grep … | wc -lmeldet0mit Status 0, auch wenn die Datei gar nicht existiert.- Eine ungesetzte Variable unter
set -ubeendet bash ohne den ERR-Trap auszulösen. Im Cron sieht das aus wie Erfolg; nur ein EXIT-Trap mit Ende-Marke bemerkt es. exitin einer Funktion, die per$(…)gerufen wird, beendet nur die Subshell. Das Skript läuft weiter.- Bei
sudo ls /root/datei-*löst die eigene Shell den Stern auf, nicht root. Ohne Leserecht bleibt er wörtlich stehen, und die Meldung heißt „Datei nicht gefunden“. Richtig:sudo sh -c 'ls /root/datei-*'. pkill -fdurchsucht die ganze Befehlszeile und trifft fremde Prozesse und das eigene Skript gleich mit. Vorherpgrep -afansehen.awkrechnet unter deutscher Locale mit0.18als0. Vor RechnungenLC_ALL=Csetzen.
- Cron startet mit minimalem
PATH. Programme aus~/.local/binfehlen dort, das Skript scheitert still. - Cron holt verpasste Läufe nicht nach. Ein Wächter, der prüft, wann ein Job zuletzt erfolgreich war, findet das.
OnCalendar=04:00..09:45/5heißt nicht „alle 5 Minuten von 4 bis 9:45“. Der Schritt gilt für die Sekunden. Jeden Ausdruck mitsystemd-analyze calendarprüfen.- Ein Timer steht auf
active, solange er feuert. Ob der Job lief, steht inResult/ExecMainStatusder Unit. systemctl showfür eine Unit, die es gar nicht gibt, liefert Status 0 und Standardwerte. ImmerLoadStatemitlesen.- Mehrere systemd-Drop-ins werden nach Dateinamen geladen, das letzte gewinnt. Vor dem Neustart
systemctl show DIENST -p Environmentgegen die Sollwerte halten. rsync -animmt die Dateirechte der Quelle mit. Danach als Dienstnutzer prüfen, ob der Dienst seinen Code noch lesen kann, vor dem Neustart.rsync --deleteeine Ebene zu hoch angesetzt löscht die Nachbarordner. Erst mit-n -vlaufen lassen und diedeleting-Zeilen lesen.- rclone:
--max-age 18mheißt 18 Minuten, Monate sindM. - Snap:
snap revertholt die Vorversion zurück. Ohnesnap refresh --hold=<dauer>spielt snapd das Update nach wenigen Stunden still wieder ein. Die Sperre immer mit Ablaufdatum setzen.
.gitignorewirkt nur auf Dateien, die noch nicht versioniert sind. Schon eingecheckte Dateien bleiben drin, bis mangit rm --cachedausführt.git diffsieht keine untrackten Dateien. Vor dem Löschen eines Branchesgit status --porcelainohne Pfadfilter.- Ein Branchname sagt nichts über den Inhalt. Vor dem Merge
git log main..branchCommit für Commit lesen.
- Ein Webhook, der sofort mit 200 antwortet, bestätigt nur den Empfang, nicht die Verarbeitung. Falsche Feldnamen ergeben dann leere Mails mit Erfolgsmeldung. Beleg ist das Ergebnis, etwa die Größe der gesendeten Nachricht.
- Nach einem n8n-Upgrade erst
healthzabwarten, bevor abhängige Module neu gestartet werden.
- Bei Single-Page-Apps beweist HTTP 200 nichts, weil der Fallback jeden Pfad mit 200 beantwortet. Der
Content-Typesagt, ob die Datei wirklich da ist. - Hinter einem CDN verhalten sich
HEADundGETunterschiedlich, und ein?cb=umgeht den Cache. Den Besucherweg misst man mitGETohne Query, mehrfach, mit Blick aufcf-cache-statusundage. - Zwischen Deploy und Cache-Ablauf kann die Seite altes HTML mit schon neuen Bildern ausliefern. Hängt die Zulässigkeit eines Inhalts am umgebenden Text, bekommt er einen neuen Dateinamen.
wp evalläuft ohne angemeldeten Benutzer. Plugin-Funktionen mit Rechteprüfung kehren dann still zurück. Abhilfe:--user=1, danach den Wert zurücklesen.overflow:hidden+border-radiusschneidet Text in der Ecke ab, ohne dass die Box einen Überlauf meldet. Das findet nur ein Blick aufs Bild.
- Eine Textsuche in der PDF-Datei selbst ist blind, weil die Inhalte komprimiert sind. Den Text mit
pdftotextherausziehen. pdftotextohne-layoutverschluckt den Bindestrich am Zeilenende. Aus Kennungen und URLs wird dann etwas anderes.- Formularfelder nur mit Wert und ohne Darstellung (
/AP) sehen im Browser gut aus und drucken in Ghostscript leer. Der Renderer des Empfängers entscheidet.
- Ein Test, der gar nicht startet, schützt nichts. Die Zahl der gelaufenen Dateien mitlesen, nicht nur „passed“.
- Bei Mutationstests hält Python den Bytecode-Cache der mutierten Fassung, wenn Änderung und Rückbau in dieselbe Sekunde fallen.
__pycache__danach löschen. py_compileprüft nur die Syntax. Erst der echte Import zeigt, ob das Modul lädt.- Ein
importführt den ganzen Modulcode aus. Fehlt der__main__-Wächter, schreibt er womöglich Dateien. - Frisch angelegte Test-Datensätze über „ID größer als vorher“ prüfen, nicht über „der neueste“. Sonst besteht der Test mit einem alten Datensatz.
English: VantixOps develops custom software, web applications, booking systems and digital platforms in Bremen, Germany. Business process automation complements our development services. We investigate bugs, contribute fixes and share practical engineering lessons.
