Migration von DigitalOcean zu Hetzner
(isayeter.com)- Eine Produktionsinfrastruktur für 1.432 US-Dollar pro Monat wurde auf einen dedizierten Server für 233 US-Dollar pro Monat umgezogen, wobei sogar das Betriebssystem gewechselt wurde und die Service-Kontinuität ohne Downtime erhalten blieb
- 30 MySQL-Datenbanken und 34 Nginx Virtual Hosts sowie GitLab EE, Neo4J, Supervisor und Gearman wurden auf dem neuen Server identisch eingerichtet; die Migration wurde anschließend mit Replikation in Echtzeit und finaler inkrementeller Synchronisierung abgeschlossen
- Der Kern der Datenbankmigration war die Kombination aus paralleler Verarbeitung mit mydumper·myloader und MySQL replication; dabei wurden auch Probleme mit dem
sys-Schema und Berechtigungen behoben, die beim Upgrade von MySQL 5.7 auf 8.0 auftraten - Das Cutover erfolgte in der Reihenfolge DNS-TTL reduzieren, Nginx auf dem alten Server in einen Reverse Proxy umwandeln und A-Records gesammelt ändern, sodass Anfragen an die alte IP während der DNS-Propagation weiterhin an den neuen Server weitergeleitet wurden
- Das Ergebnis: 1.199 US-Dollar weniger pro Monat, 14.388 US-Dollar weniger pro Jahr, dazu mehr CPU, Speicher und Storage sowie 0 Minuten Downtime
Hintergrund der Migration
- Beim Betrieb eines Softwareunternehmens in der Türkei stieg durch rasante Inflation und die Schwäche der türkischen Lira die Belastung durch in US-Dollar abgerechnete Infrastrukturkosten stark an
- Die bisherigen Serverkosten bei DigitalOcean lagen bei 1.432 US-Dollar pro Monat; die Konfiguration umfasste 192 GB RAM, 32 vCPU, 600 GB SSD, zwei 1-TB-Block-Volumes sowie Backups
- Das neue Ziel war ein dedizierter Server vom Typ Hetzner AX162-R mit AMD EPYC 9454P, 48 Kernen, 96 Threads, 256 GB DDR5 und 1,92 TB NVMe Gen4 RAID1
- Die monatlichen Kosten sanken auf 233 US-Dollar, was einer Ersparnis von 1.199 US-Dollar pro Monat bzw. 14.388 US-Dollar pro Jahr entspricht
- Mit der Zuverlässigkeit des bisherigen Servers oder der Developer Experience gab es zwar keine Probleme, für steady-state Workloads war das Preis-Leistungs-Verhältnis jedoch nicht mehr sinnvoll
Bisherige Betriebsumgebung
- Der Betriebs-Stack war keine einfache Testumgebung, sondern eine echte Produktionsumgebung
- 30 MySQL-Datenbanken mit insgesamt 248 GB Daten
- 34 Nginx Virtual Hosts über mehrere Domains hinweg
- GitLab EE inklusive 42 GB Backups
- Neo4J Graph DB mit 30 GB
- Verwaltung von Dutzenden Hintergrund-Workern mit Supervisor
- Einsatz von Gearman als Job-Queue
- Betrieb von Live-Mobile-Apps für Hunderttausende Nutzer
- Das Betriebssystem des alten Servers war CentOS 7, dessen Support bereits ausgelaufen war
- Auf dem neuen Server lief AlmaLinux 9.7, eine RHEL-9-kompatible Distribution und ein naheliegender Nachfolger für CentOS
- Die Migration diente daher nicht nur der Kostensenkung, sondern auch dem Ausstieg aus einem Betriebssystem, das seit Jahren keine Sicherheitsupdates mehr erhalten hatte
Strategie ohne Downtime
- Ein simples Ändern des DNS und ein Neustart der Services kamen nicht infrage; stattdessen wurde die Migration in einem 6-stufigen Verfahren ohne Downtime durchgeführt
-
Schritt 1: Gesamten Stack auf dem neuen Server installieren
- Nginx wurde mit denselben Flags wie bisher aus dem Source kompiliert und installiert
- PHP wurde über das Remi-Repo installiert, anschließend wurden dieselben
.ini-Dateien wie auf dem alten Server übernommen - MySQL 8.0, Neo4J Graph DB, GitLab EE, Node.js, Supervisor und Gearman wurden installiert und so konfiguriert, dass sie dem bisherigen Verhalten entsprachen
- Noch bevor DNS-Einträge angefasst wurden, war sichergestellt, dass alle Services auf dem neuen Server genauso funktionierten wie auf dem alten
- Die SSL-Zertifikate wurden übernommen, indem das komplette Verzeichnis
/etc/letsencrypt/per rsync vom alten Server kopiert wurde - Nachdem der gesamte Traffic auf den neuen Server umgeschaltet war, wurden die Zertifikate gesammelt mit
certbot renew --force-renewalzwangsweise erneuert
-
Schritt 2: Web-Dateien per rsync replizieren
- Das gesamte Verzeichnis
/var/www/htmlmit rund 65 GB und 1,5 Millionen Dateien wurde per SSH-basiertemrsyncrepliziert - Mit der Option
--checksumwurde die Integrität verifiziert - Unmittelbar vor dem Cutover folgte eine letzte inkrementelle Synchronisierung, um geänderte Dateien zu übernehmen
- Das gesamte Verzeichnis
-
Schritt 3: MySQL Master-Slave-Replikation
- Statt Datenbanken per Dump und Restore mit Unterbrechung zu migrieren, wurde Replikation in Echtzeit eingerichtet
- Der alte Server wurde als Master, der neue als read-only Slave konfiguriert
- Für das anfängliche Laden großer Datenmengen kam
mydumperzum Einsatz; anschließend begann die Replikation exakt ab der im Dump-Metadatenfile verzeichneten binlog-Position - Bis zum Cutover wurden beide Datenbankseiten in Echtzeit synchron gehalten
-
Schritt 4: DNS-TTL reduzieren
- Über ein Skript, das die DigitalOcean DNS API aufrief, wurde die TTL aller A/AAAA-Records von 3600 Sekunden auf 300 Sekunden reduziert
- MX- und TXT-Records wurden nicht geändert
- Die TTL der Mail-Records blieb unverändert, um keine Zustellprobleme zu riskieren
- Nachdem die alte TTL weltweit auslaufen konnte, war das Cutover nach einer Stunde Wartezeit innerhalb von fünf Minuten vorbereitet
-
Schritt 5: Nginx auf dem alten Server in einen Reverse Proxy umwandeln
- Ein Python-Skript analysierte die
server {}-Blöcke in allen 34 Nginx-Site-Konfigurationen - Die bestehende Konfiguration wurde gesichert und durch Proxy-Konfigurationen ersetzt, die auf den neuen Server zeigten
- So wurden Anfragen, die während der DNS-Propagation noch an der alten IP ankamen, unauffällig an den neuen Server weitergereicht
- Für Nutzer gab es dadurch keine sichtbare Unterbrechung
- Ein Python-Skript analysierte die
-
Schritt 6: DNS-Cutover und Abschaltung des alten Servers
- Ein Python-Skript rief die DigitalOcean API auf und änderte innerhalb weniger Sekunden alle A-Records auf die neue Server-IP
- Der alte Server blieb noch eine Woche lang als cold standby erhalten und wurde erst dann abgeschaltet
- Der Service antwortete während des gesamten Prozesses entweder direkt oder über den Proxy, sodass es keine Lücke in der Verfügbarkeit gab
MySQL-Migration
- Der komplexeste Teil des gesamten Vorhabens war die Migration von MySQL
-
Daten-Dump
- Statt des Standardtools
mysqldumpwurde mydumper verwendet - Durch parallelen Export/Import unter Nutzung der 48 CPU-Kerne des neuen Servers ließ sich eine Aufgabe, die mit dem Single-Thread-Tool
mysqldumpmehrere Tage gedauert hätte, auf wenige Stunden verkürzen - Zu den wichtigsten Optionen gehörten
--threads 32,--compress,--trx-consistency-only,--skip-definer,--chunk-filesize 256 - In der
metadata-Datei des Haupt-Dumps wurde die binlog-Position zum Zeitpunkt des Snapshots festgehaltenFile: mysql-bin.000004Position: 21834307
- Diese Werte dienten später als Startpunkt für die Replikation
- Statt des Standardtools
-
Übertragung des Dumps
- Nach Abschluss des Dumps wurde dieser per SSH-basiertem rsync auf den neuen Server übertragen
- Insgesamt wurden 248 GB komprimierte Chunks übertragen
- Die durch
mydumpervia--compresserzeugten komprimierten Chunks verbesserten die Geschwindigkeit der Netzwerkübertragung
-
Laden der Daten
- Verwendet wurde
myloader - Die wichtigsten Optionen waren
--threads 32,--overwrite-tables,--ignore-errors 1062,--skip-definer
- Verwendet wurde
-
Probleme beim Wechsel von MySQL 5.7 auf 8.0
- Wegen der CentOS-7-Umgebung war der alte Server bei MySQL 5.7 geblieben
- Vor der Migration wurde mit
mysqlcheck --check-upgradegeprüft, ob die Daten mit MySQL 8.0 kompatibel sind; das Ergebnis war unauffällig - Auf dem neuen Server wurde die aktuelle MySQL 8.0 Community-Version installiert
- Projektweit verkürzten sich die Query-Laufzeiten spürbar; im Original werden dafür der verbesserte Optimizer und die InnoDB-Verbesserungen in MySQL 8.0 genannt
- Durch den Versionssprung traten jedoch auch Probleme auf
- Nach dem Import hatte die Tabelle
mysql.usernicht wie erwartet 51, sondern nur 45 Spalten - In der Folge fehlte
mysql.infoschema, und es kam zu Problemen bei der Benutzerauthentifizierung
- Nach dem Import hatte die Tabelle
- Der erste Reparaturversuch erfolgte mit den folgenden Befehlen
systemctl stop mysqldmysqld --upgrade=FORCE --user=mysql &
- Der erste Versuch scheiterte mit dem Fehler
ERROR: 'sys.innodb_buffer_stats_by_schema' is not VIEW - Ursache war, dass das
sys-Schema als normale Tabelle statt als View importiert worden war - Gelöst wurde das Problem durch
DROP DATABASE sys;und ein erneutes Ausführen des Upgrades - Danach lief alles korrekt durch
Einrichtung der MySQL-Replikation
- Nachdem der Dump auf beiden Servern eingespielt war, wurde der neue Server als Replica des alten Servers eingerichtet
- In
CHANGE MASTER TOwurden die IP des alten Servers, der Replikationsbenutzer, Port 3306,MASTER_LOG_FILE='mysql-bin.000004'undMASTER_LOG_POS=21834307angegeben - Anschließend wurde
START SLAVE;ausgeführt - Fast sofort stoppte die Replikation mit error 1062 Duplicate Key
- Der Grund: Der Dump war in zwei Durchläufen erstellt worden, und zwischen diesen wurde in einige Tabellen geschrieben, sodass der importierte Dump und das Abspielen des binlog versuchten, dieselben Zeilen doppelt einzufügen
- Zur Behebung wurde folgende Konfiguration angewendet
SET GLOBAL slave_exec_mode = 'IDEMPOTENT';START SLAVE;
- Der IDEMPOTENT-Modus überspringt Duplicate-Key- und Missing-Row-Fehler stillschweigend
- Alle wichtigen Datenbanken synchronisierten sich danach fehlerfrei, und
Seconds_Behind_Masterfiel innerhalb weniger Minuten auf 0
Validierung vor dem Cutover
- Bevor DNS-Einträge geändert wurden, musste geprüft werden, ob auf dem neuen Server alle Services korrekt funktionierten
- Dafür wurde auf dem lokalen Rechner die Datei
/etc/hoststemporär angepasst, um die Domain auf die IP des neuen Servers zu mappen - Browser und Postman schickten dadurch Anfragen an den neuen Server, während externe Nutzer weiterhin den alten Server erreichten
- Es wurden API-Endpunkte, Admin-Panels und der Antwortstatus der einzelnen Services geprüft
- Erst nachdem alles bestätigt war, erfolgte das eigentliche Cutover
Problem mit SUPER-Berechtigungen
- Nachdem die Master-Slave-Replikation vollständig synchron war, fiel auf, dass auf dem neuen Server trotz
read_only = 1INSERT-Statements erfolgreich waren - Der Grund war, dass allen PHP-Applikationsbenutzern die SUPER-Berechtigung erteilt worden war
- In MySQL umgeht die SUPER-Berechtigung
read_only - Mit
SHOW GRANTS FOR 'some_db_user'@'localhost';wurde bestätigt, dass die BerechtigungSUPERenthalten war - Bei insgesamt 24 Applikationsbenutzern wurde wiederholt
REVOKE SUPER ON *.* FROM 'some_db_user'@'localhost';ausgeführt - Anschließend wurde
FLUSH PRIVILEGES;ausgeführt - Danach blockierte
read_only = 1Schreibzugriffe der Applikationsbenutzer korrekt, während die Replikation weiterhin erlaubt blieb
DNS-Vorbereitung
- Alle Domains wurden über DigitalOcean DNS verwaltet, die Nameserver waren bei GoDaddy angebunden
- Die Reduzierung der TTL wurde per Skript gegen die DigitalOcean API automatisiert
- Geändert wurden ausschließlich A- und AAAA-Records
- MX- und TXT-Records blieben unberührt
- Wegen möglicher Zustellprobleme bei Google Workspace wurde die TTL mailbezogener Records nicht geändert
- Nach einer Stunde Wartezeit zum Auslaufen der bisherigen TTL war das Cutover bereit
Umwandlung von Nginx auf dem alten Server in einen Reverse Proxy
- Statt 34 Konfigurationsdateien manuell zu bearbeiten, wurde die Umstellung per Python-Skript automatisiert
- Das Skript analysierte die
server {}-Blöcke aller Konfigurationsdateien, identifizierte die zentralen Content-Blöcke und ersetzte sie durch Proxy-Konfigurationen - Die Originalkonfigurationen wurden als
.backup-Dateien gesichert - In der Beispielkonfiguration kamen
proxy_pass https://NEW_SERVER_IP;,proxy_set_header Host $host;,proxy_set_header X-Real-IP $remote_addr;,proxy_read_timeout 150;zum Einsatz - Die entscheidende Option war
proxy_ssl_verify off- Denn das SSL-Zertifikat auf dem neuen Server war für die Domain gültig, aber nicht für die IP-Adresse
- Da in diesem Umfeld beide Enden kontrolliert wurden, war das Deaktivieren der Verifikation hier akzeptabel
Cutover-Ablauf
- Unmittelbar vor dem Cutover waren die Voraussetzungen
Seconds_Behind_Master: 0und ein vorbereiteter Reverse Proxy - Die Ausführungsreihenfolge war wie folgt
- Auf dem neuen Server
STOP SLAVE; - Auf dem neuen Server
SET GLOBAL read_only = 0; - Auf dem neuen Server
RESET SLAVE ALL; - Auf dem neuen Server
supervisorctl start all - Auf dem alten Server
nginx -t && systemctl reload nginx, um den Proxy zu aktivieren - Auf dem alten Server
supervisorctl stop all - Auf dem lokalen Mac
python3 do_cutover.py, um alle A-Records im DNS auf die IP des neuen Servers zu ändern - Etwa 5 Minuten auf die Propagation warten
- Auf dem alten Server alle Crontab-Einträge auskommentieren
- Auf dem neuen Server
- Das DNS-Cutover-Skript rief die DigitalOcean API auf und änderte alle A-Records in rund 10 Sekunden
Zusätzliche Arbeiten nach dem Cutover
- Nach Abschluss der Migration stellte sich heraus, dass zahlreiche GitLab-Projekt-Webhooks noch immer auf die IP des alten Servers zeigten
- Deshalb wurde ein Skript geschrieben und angewendet, das über die GitLab API alle Projekte durchsucht und die Webhooks gesammelt aktualisiert
Endergebnis
- Die monatlichen Kosten sanken von 1.432 US-Dollar auf 233 US-Dollar
- Die jährliche Ersparnis beträgt 14.388 US-Dollar
- Auch bei der Performance wurde ein stärkerer Server gewonnen
- Die CPU stieg von 32 vCPU auf 96 logische CPU
- Der RAM stieg von 192 GB auf 256 GB DDR5
- Der Storage wechselte von einer gemischten Konfiguration mit etwa 2,6 TB auf 2 TB NVMe RAID1
- Die Downtime betrug 0 Minuten
- Die gesamte Migration dauerte ungefähr 24 Stunden
- Es gab keine Auswirkungen auf die Nutzer
Zentrale Erkenntnisse
- MySQL replication ist das wichtigste Mittel für Migrationen ohne Downtime
- Sinnvoll ist es, die Replikation früh einzurichten, ausreichend aufholen zu lassen und erst dann das Cutover vorzunehmen
- Die Berechtigungen von MySQL-Benutzern sollten vor der Migration unbedingt geprüft werden
- Mit SUPER-Berechtigung wird
read_onlyumgangen, wodurch ein Slave-System faktisch nicht wirklich read-only ist
- Mit SUPER-Berechtigung wird
- DNS-Updates, Änderungen an Nginx-Konfigurationen und Anpassungen an Webhooks sollten skriptgesteuert erfolgen
- Wer mehr als 34 Sites manuell bearbeitet, riskiert hohen Zeitaufwand und mehr Fehler
- Die Kombination mydumper + myloader ist bei großen Datensätzen deutlich schneller als
mysqldump- Durch parallelen Dump und Restore mit 32 Threads wurden Aufgaben von mehreren Tagen auf wenige Stunden verkürzt
- Bei steady-state Workloads können Cloud-Anbieter teuer sein; ein dedizierter Server kann für geringere Kosten mehr Leistung liefern
GitHub-Skripte
- Alle für die Migration verwendeten Python-Skripte wurden auf GitHub veröffentlicht
- Enthaltene Skripte
do_list_domains_ttl.py- Listet A-Records, IPs und TTL aller DigitalOcean-Domains auf
do_ttl_update.py- Reduziert die TTL aller A/AAAA-Records gesammelt auf 300 Sekunden
do_to_hetzner_bulk_dns_records_import.py- Migriert alle DNS-Zonen von DigitalOcean zu Hetzner DNS
do_cutover_to_new_ip.py- Stellt alle A-Records von der alten Server-IP auf die neue um
nginx_reverse_proxy_update.py- Wandelt alle nginx-Site-Konfigurationen in Reverse-Proxy-Konfigurationen um
mysql_compare.py- Vergleicht die Row Counts aller Tabellen auf beiden MySQL-Servern
final_gitlab_webhook_update.py- Aktualisiert die Webhooks aller GitLab-Projekte auf die neue Server-IP
mydumper- Die mydumper-Bibliothek
- Alle Skripte unterstützen einen
DRY_RUN = True-Modus, der vor dem tatsächlichen Anwenden eine sichere Vorschau ermöglicht
1 Kommentare
Hacker-News-Kommentare
Ich habe vor ein paar Monaten zwei Server von Linode und DO zu Hetzner migriert und dabei die Kosten ähnlich drastisch gesenkt. Noch beeindruckender war, dass dort Dutzende Websites mit verschiedenen Sprachen, alten Bibliotheken sowie MySQL und Redis in einem chaotischen Stack zusammenhingen. Claude Code hat das alles aber komplett umgezogen und bei fehlenden Bibliotheken sogar Teile des Codes neu geschrieben. Solche komplexen Migrationen sind dadurch jetzt viel einfacher, und ich glaube, dass die Mobilität zwischen Anbietern in Zukunft deutlich zunehmen wird
Ich plane gerade einen Umzug von AWS zu Hetzner. Amazon verlangt im Vergleich zur Konkurrenz manchmal 20x höhere Preise, drängt einen für halbwegs vernünftige Preise in langfristige Bindungen und macht auch den Datenabzug extrem teuer, was sich sehr kundenfeindlich anfühlt. Man könnte meinen, dass die Egress-Gebühren Leute festhalten sollen, aber in Wirklichkeit erzeugen sie Druck, gleich alles zu migrieren, sobald man auch nur einen Teil zur Konkurrenz verlagert. Immerhin habe ich meine Plattform nicht auf Amazon-spezifischen Services aufgebaut, dadurch ist der Umzug etwas einfacher
Jedes Mal, wenn ich solche Texte sehe, wundere ich mich, dass kaum jemand über Redundanz oder Load Balancer spricht. Wenn ein einzelner Server ausfällt, können mehrere Dienste gleichzeitig offline gehen, und ich frage mich, ob die Leute das wirklich für akzeptabel halten. Vielleicht spart man Geld, aber dafür zahlt man am Ende mehr mit Wartungszeit und künftigen Problemen
Wir haben bei lithus.eu schon häufig Kunden von verschiedenen Clouds zu Hetzner migriert. Meist bauen wir Multi-Server-Setups, manchmal auch über mehrere AZs hinweg, und verteilen die Workloads mit Kubernetes, um HA bereitzustellen. Für einen einzelnen Node wäre Kubernetes womöglich zu viel, aber mit mehreren Nodes ergibt es deutlich mehr Sinn. Für Backups nutzen wir Velero zusammen mit Backups auf Anwendungsebene; bei Postgres etwa kommen WAL-Backups für PITR dazu. Zustandsdaten halten wir auf mindestens zwei Nodes, um HA sicherzustellen. Auch leistungsmäßig ist Bare Metal meistens besser, und im Vergleich zu AWS haben wir oft die Latenz halbiert. Ich glaube, das liegt weniger an der Virtualisierung selbst als an Randfaktoren wie NVMe, niedriger Netzwerklatenz und geringerer Cache Contention. Mehr dazu hatte ich schon einmal in einem HN-Beitrag geschrieben
Dieser Text war ziemlich schwer zu lesen. Es fühlte sich an, als hätte Claude die Migration gemacht und anschließend auch noch den Bericht darüber geschrieben. Wenn dank LLMs wirklich so viel gespart wurde, ist das großartig, aber wenn man so etwas veröffentlicht, sollte man es wenigstens redigieren und Wiederholungen sowie den LLM-Stil bereinigen
Bei Hetzner wäre ich vorsichtig. Früher mochte ich sie sehr, bin inzwischen aber weg. Sie haben rund 30 VMs aus unserer CI/CD-Pipeline komplett abgeschaltet wegen eines einzigen Abrechnungsstreits über 36 Dollar. Wir haben vollständige Zahlungsnachweise inklusive Bankunterlagen eingereicht, aber sie wollten sie nicht ansehen und haben uns trotz hektischer Kontaktversuche am Ende komplett ausgesperrt. Inzwischen sind wir zu Scaleway gewechselt
Vor ein paar Monaten habe ich für ein kleines SaaS-Nebenprojekt nach einer AWS-Alternative gesucht und mir Hetzner zunächst ernsthaft angesehen, sowohl zur Kostensenkung als auch zur Unterstützung einer EU-Cloud. Ich war bereit, mehr selbst zu machen, aber am Ende hat mich der Punkt IP-Reputation ausgebremst. Eine der gemanagten AWS-Firewall-Regeln in unserem Unternehmen blockierte viele, vielleicht sogar alle Hetzner-IPs, und selbst auf meinem Arbeitslaptop ließen sich Websites auf Hetzner-IPs wegen IT-Richtlinien nicht öffnen. Mit etwas wie Cloudflare wäre es vielleicht weniger problematisch, aber ich habe auch gelesen, dass der DDoS-Schutz schwächer sein soll. Am Ende habe ich mich für die DO App Platform in einer EU-Region entschieden, und auch die Managed-DB-Optionen waren ein großer Pluspunkt
Solche Migrationsberichte zu teilen, ist wirklich nützlich, und ich bin dankbar dafür. Ich sehe den Vergleich zwischen DO und Hetzner ungefähr als Trade-off zwischen DoorDash oder UberEats einschalten und das Abendessen selbst kochen. Auch das Kostenverhältnis fühlt sich ähnlich an. Ich arbeite mit den drei großen Clouds und On-Prem, gehe für Kleinkram oder PoC-Tests aber immer noch gern in die DigitalOcean-Konsole. Diese Bequemlichkeit, mit ein paar Klicks einen Server oder Bucket bereitzustellen, sinnvolle Defaults zu haben und Backups per Checkbox zu aktivieren, hat bei berücksichtigtem Zeitwert definitiv ihren Platz
Ich habe mich gefragt, wie die DB-Backups gemacht werden. Ob es Replicas oder Standbys gibt oder nur stündliche Backups. Bei so einer Einzelserver-Konfiguration kann ein Hardwaredefekt wie ein SSD-Ausfall die Anwendung sofort stoppen, und gerade wenn eine SSD stirbt, kann man schnell Stunden oder sogar Tage offline sein, während man alles neu aufsetzt
Das Meme-Bild im Header war von mir. Ich hatte es in diesem Beitrag verwendet, und ich fand es schön zu sehen, dass es jetzt schon zum zweiten Mal auftaucht