Bitaxe überwachen: Ausfälle, Hitze und falsche Auszahlung erkennen, ohne Fehlalarme
12. Oktober 2026 · 21 Min. Lesezeit
Ein Bitaxe läuft wochenlang ohne Aufsicht. Meistens geht das gut. Wenn nicht, merkt man es spät: am lauten Lüfter, an einer Hashrate, die seit Tagen zu niedrig ist, oder gar nicht, weil der Miner still auf den Fallback-Pool gewechselt ist. Dieser Artikel zeigt, was sich überwachen lässt, welche Schwellen ohne Fehlalarme auskommen und welches Werkzeug zu wie vielen Geräten passt. Grundlage sind der Quellcode von AxeOS 2.15.3 und NerdOS 1.1.0.1, die Vardiff-Logik von ckpool und eigene Rechnungen.
/api/system/info abfragt. Es sieht, was der Pool nicht sieht: Temperatur, Lüfter, Netzteil, Fallback-Pool und ob die Coinbase überhaupt an deine Adresse zahlt. Die Blockchance rettet Monitoring dagegen kaum: Zwei Ausfalltage im Monat kosten einen Bitaxe Gamma rechnerisch rund einen Euro im Jahr. Was ein Ausfall kostet und wofür Monitoring wirklich gut ist
Die erste Frage ist nüchtern: Wie viel kostet es, wenn ein Miner einen Tag lang nichts tut? Beim Solo-Mining hängt die Blockchance nur an der Zeit, in der gerechnet wird. Ein Bitaxe Gamma mit 1,2 TH/s kommt bei der Difficulty vom 12. Oktober 2026 (rund 132,7 Billionen, Block 971.119) auf eine Chance von 1 zu 5,5 Millionen pro Tag und 1 zu rund 15.000 pro Jahr. Bei 3,125 BTC Blocksubvention, ohne Transaktionsgebühren, ist der Erwartungswert 20.747 sats im Jahr, beim Kurs von 73.860 € also gut 15 €.
Zwei Ausfalltage pro Monat, 24 im Jahr, kosten davon 6,6 %: 1.364 sats oder rund einen Euro. Ein Miner, der hängt und dabei weiter 17 W zieht, verbraucht am Tag 0,41 kWh, bei 0,30 € je kWh sind das 12 Cent. Wer überwacht, um die Rendite zu retten, überwacht das Falsche. Die Rechnung zur Blockchance steht ausführlich in Bitaxe Block finden.
Teuer werden andere Dinge. Sie lassen sich alle an Werten erkennen, die AxeOS ohnehin meldet:
| Ereignis | Folge | Woran erkennbar | Dringlichkeit |
|---|---|---|---|
| Lüfter fällt aus, Kühler verstaubt | Chip und Spannungsregler heizen auf; AxeOS stoppt und läuft danach dauerhaft gedrosselt | fanrpm, vrTemp, overheat_mode | sofort |
| Miner auf dem Fallback-Pool oder mit fremder Adresse | Ein Blockfund zahlt an die Adresse, die dort steht, und die ist ab Werk nicht deine | isUsingFallbackStratum, stratumUser, coinbaseValueUserSatoshis | sofort |
| Netzteil oder Kabel zu schwach | Neustarts, Abstürze, auf Dauer warme Stecker | resetReason, voltage | am selben Tag |
| Schleichender Leistungsverlust | Hashrate dauerhaft unter „Expected“ | hashRate_10m, expectedHashrate, frequency | in Ruhe |
| Kompletter Ausfall | keine Shares, keine Blockchance | Pool-Alarm, keine Antwort der API | in Ruhe |
Drei Blickwinkel: Gerät, Pool und Netz
Jede Überwachung schaut aus einer von drei Richtungen auf den Miner, und jede sieht etwas anderes. Das Gerät selbst kennt alle Messwerte, kann aber nichts mehr melden, wenn es hängt. Der Pool sieht nur, ob Shares ankommen. Ein Ping zeigt, ob das Gerät im Netz ist, nicht ob es rechnet.
| Quelle | Sieht | Sieht nicht | Zugang ins Heimnetz nötig |
|---|---|---|---|
| AxeOS- oder NerdOS-API | Temperaturen, Lüfter, Spannung, Hashrate, Shares, Pool-Einstellungen, Coinbase | nichts mehr, sobald das Gerät nicht antwortet | ja |
| Pool (API, Telegram-Bot) | ob Shares ankommen, Hashrate aus Shares, Best Share | Temperatur, Ursachen; ein Wechsel auf den Fallback sieht aus wie ein Ausfall | nein |
| Ping, Router | ob das Gerät im Netz ist | ob es rechnet | ja |
Am stabilsten ist eine Kombination aus zwei Richtungen: die Pool-Sicht als unabhängige Kontrolle, die auch dann meldet, wenn im Heimnetz alles ausfällt, und die Geräte-Sicht für die Ursachen.
Die AxeOS-API: Zugriff, Endpunkte, Felder
Kein Passwort, aber nur aus privaten Netzen
AxeOS hat keinen Login. Stattdessen prüft die Firmware bei jeder API-Anfrage, woher sie kommt. Ohne Origin-Header, also bei curl, Skripten oder Home Assistant, muss der Absender aus den privaten Adressbereichen 10.0.0.0/8, 172.16.0.0/12 oder 192.168.0.0/16 stammen. Schickt ein Browser einen Origin-Header mit, muss dieser auf eine private Adresse, einen Namen auf .local oder einen Namen ohne Punkt zeigen. Alles andere beantwortet AxeOS mit „401 Unauthorized“. Nur solange der Miner sein eigenes Einrichtungs-WLAN aufspannt, ist die API offen. So steht es in is_network_allowed() in http_server.c.
Daraus folgt dreierlei. Erstens darf jeder Rechner im selben privaten Netz alles: lesen, aber auch Pool und Adresse ändern (PATCH /api/system) oder Firmware schreiben (POST /api/system/OTA). Zweitens scheitern gewöhnliche Abfragen aus dem Internet, etwa von einem gemieteten Server oder einem Cloud-Uptime-Dienst, selbst mit Portfreigabe. Ein Schutz gegen Angreifer ist das trotzdem nicht: Die Prüfung soll vor allem fremde Webseiten im Browser abhalten, und ein gezielt gebauter Aufruf kommt durch, sobald der Miner aus dem Internet erreichbar ist. Drittens kommt es bei VPN-Zugängen darauf an, mit welcher Adresse die Anfrage beim Miner ankommt. Ein Tailscale-Subnet-Router schreibt die Absenderadresse standardmäßig auf seine eigene LAN-Adresse um (SNAT); dann klappt es. Wer SNAT mit --snat-subnet-routes=false abschaltet, kommt mit einer Adresse aus 100.64.0.0/10, und AxeOS lehnt ab. Bei anderen VPNs gilt dieselbe Regel: Entscheidend ist die Adresse, mit der die Anfrage beim Miner ankommt. Ein WireGuard-Tunnel mit Adressen aus 10.x funktioniert deshalb auch ohne Umschreiben.
Die Nerd-Firmware prüft ebenfalls auf private Adressbereiche. Lesen geht dort ohne weiteren Schutz, Ändern verlangt einen Einmalcode, wenn die Zwei-Faktor-Absicherung (OTP) eingeschaltet ist. AxeOS hat keine vergleichbare Sperre.
Die Endpunkte, die fürs Monitoring zählen
| Endpunkt | Methode | Wofür |
|---|---|---|
/api/system/info | GET | Gesamtzustand in einem JSON, die Grundlage jeder Überwachung |
/api/ws/live | WebSocket | dieselben Daten live: beim Verbinden einmal komplett, danach nur Änderungen |
/api/system/statistics?columns=… | GET | der Verlauf, den das Gerät selbst speichert (Diagramm im Dashboard) |
/api/system/asic | GET | Chip-Daten und erlaubte Takt- und Spannungsstufen |
/api/ws | WebSocket | Log-Ausgabe wie auf der Seite Logs |
/api/system/restart, /pause, /resume | POST | Neustart, Mining pausieren und fortsetzen |
/api/system | PATCH | Einstellungen ändern |
Für den Anfang reicht ein einziger Aufruf mit curl und jq:
curl -s http://192.168.1.50/api/system/info | jq '{hashRate_10m, expectedHashrate, temp, vrTemp, fanrpm, sharesAccepted, isUsingFallbackStratum, coinbaseValueUserSatoshis, resetReason}' Die Felder, die wirklich etwas aussagen
Die Antwort von /api/system/info hat in AxeOS 2.15.3 über hundert Felder. Für die Überwachung zählen diese:
| Feld | Bedeutung | Einheit | Auffällig |
|---|---|---|---|
hashRate_10m | gleitendes Mittel über 10 Minuten (dazu hashRate_1m, hashRate_1h) | GH/s | dauerhaft unter 85 bis 90 % von Expected |
expectedHashrate | Takt mal Rechenkerne mal Chips | GH/s | sinkt, wenn der Takt sinkt |
errorPercentage | vom Chip gemeldeter Anteil fehlerhafter Hashes | % | steigt dauerhaft; unter 0,1 % ist sehr gut |
sharesAccepted, sharesRejected, sharesRejectedReasons | Zähler seit dem Start, Ablehnungsgründe als Liste | Anzahl | Zähler steht still, Ablehnungen über 1 % |
poolDifficulty | Difficulty, die der Pool gerade vergibt | Zahl | bestimmt, wie lange „kein Share“ normal ist |
temp, temp2, vrTemp | Chip, zweiter Sensor, Spannungsregler | °C | Chip über 70, Regler über 95 |
fanrpm, fanspeed, autofanspeed | Drehzahl, Stellwert, Automatik an oder aus | U/min, %, 0/1 | Drehzahl 0 bei Stellwert über 0; Automatik plötzlich aus |
voltage, nominalVoltage | Eingangsspannung, Nennspannung | mV, V | unter 94,9 % des Nennwerts |
power_fault, hardware_fault | erscheinen nur bei einem Fehler, etwa „Fan Control Failed“ | Text | jede Meldung |
overheat_mode | Überhitzungsschutz läuft gerade | 0/1 | 1 |
uptimeSeconds, resetReason | Laufzeit seit dem Start, Grund des letzten Neustarts | s, Text | Laufzeit springt zurück |
isUsingFallbackStratum, stratumUser | Fallback aktiv, eingetragener Benutzer | 0/1, Text | Fallback aktiv; Benutzer weicht ab |
coinbaseValueTotalSatoshis, coinbaseValueUserSatoshis, coinbaseOutputs | Wert der Coinbase des aktuellen Jobs und der Teil, der an deine Adresse geht | sats | eigener Anteil 0 bei einem Solo-Pool |
wifiRSSI | WLAN-Signalstärke | dBm | dauerhaft unter −75 |
miningPaused | Mining pausiert | true/false | für Ausnahmen in der eigenen Logik |
Die Nerd-Firmware liefert unter demselben Pfad weitgehend dieselben Namen, mit Unterschieden: hostip statt ipv4, lastResetReason statt resetReason, asicTemps als Liste je Chip, kein expectedHashrate (rechnerisch Takt mal smallCoreCount mal asicCount durch 1000) und keine Coinbase-Felder. Den Fallback meldet sie in stratum.usingFallback, die Temperatur, bei der sie abschaltet, in overheat_temp und je Lüfterkanal in fans[].overheatTemp. Dazu kommt eine eigene Coinbase-Prüfung mit Alarm, mehr dazu unten.
Sechs Prüfungen, die echte Probleme finden
1. Erreichbarkeit und Neustarts
Antwortet die API dreimal in Folge nicht, ist der Miner weg. Ein Neustart zeigt sich daran, dass uptimeSeconds kleiner ist als bei der letzten Abfrage. Den Grund liefert resetReason gleich mit, und der ist oft schon die Diagnose:
Text in resetReason | Typische Ursache | Was tun |
|---|---|---|
| Reset due to power-on event | Strom war weg: Steckdose, Stromausfall, Wackelkontakt | einmal ist kein Problem; bei Häufung Stecker und Leiste prüfen |
| Software reset via esp_restart | Neustart über AxeOS oder die API, nach einem Firmware-Update oder geänderten Einstellungen | normal, wenn du es warst |
| Brownout reset (software or hardware) | Eingangsspannung kurz eingebrochen | Netzteil und Kabel prüfen, siehe Netzteil für Bitaxe |
| Reset due to task watchdog; Reset (software or hardware) due to interrupt watchdog | Firmware hing | Übertaktung zurücknehmen, Firmware aktualisieren |
| Software reset due to exception/panic; Reset due to CPU lock up (double exception) | Absturz | Firmware aktualisieren, bei Häufung das Log sichern |
| Reset due to power glitch detected | Spannungsspitze oder Einbruch | Netzteil prüfen |
2. Shares: der empfindlichste Ausfall-Indikator
Steigt sharesAccepted nicht mehr, rechnet der Miner nicht oder seine Arbeit kommt nicht an. Das ist der zuverlässigste Ausfall-Indikator, weil Shares an ckpool-basierten Solo-Pools wie pool.bitaxe.de im Sekundentakt kommen. Wie schnell genau, steht im nächsten Abschnitt. Den Anteil abgelehnter Shares bewertest du über eine Stunde. Liegt er über einem Prozent, verraten die Gründe in sharesRejectedReasons die Ursache; was sie bedeuten, steht im Abschnitt zu abgelehnten Shares in Bitaxe mined nicht trotz WLAN.
Von außen prüfst du dasselbe über die Pool-API: https://pool.bitaxe.de/api/v1/address/ mit deiner Adresse liefert je Worker lastshare und Hashrate-Mittel über 1 Minute bis 7 Tage. Für Ausfälle taugt nur lastshare: Die Hashrate-Felder von ckpool fallen nach einem Ausfall nicht auf null, sie bleiben stehen, bis wieder Shares kommen.
3. Hashrate gegen Expected
expectedHashrate ist Takt mal Rechenkerne mal Chips: beim BM1370 mit 2.040 Kernen und 525 MHz also 1.071 GH/s. Ein gesunder Miner liegt im Stundenmittel bei mindestens 95 % davon; warum, erklärt Hashrate Error beim Bitaxe. Für einen Alarm nimmt man das 10-Minuten-Mittel hashRate_10m mit einer großzügigeren Schwelle von 85 %, die eine Viertelstunde lang unterschritten sein muss, und lässt die ersten 15 Minuten nach einem Start aus, in denen sich Mittelwerte erst füllen.
Die Hashrate, die der Pool anzeigt, eignet sich dafür weniger. Er schätzt sie aus den Shares, und das rauscht: Ein Gamma liefert mit AxeOS-Voreinstellung etwa 1.000 Shares pro Stunde, das Stundenmittel des Pools schwankt damit um rund ±3 %. Bei Difficulty 32.768 sind es nur rund 30 Shares pro Stunde und ±18 %.
4. Temperatur, Lüfter, Netzteil
AxeOS warnt im Dashboard ab 70 °C am Chip. Bei über 75 °C am Chip oder über 105 °C am Spannungsregler greift der Überhitzungsschutz. Für den Dauerbetrieb gut sind bis 65 °C am Chip und bis 85 °C am Regler. Ein Alarm bei 70 °C Chip und 95 °C Regler meldet sich also, bevor der Schutz greift. Die Nerd-Firmware schaltet dagegen schon bei ihrer „Abschalt-Temperatur“ die Kernspannung ab, ab Werk bei 70 °C am Chip; Geräte mit zwei Lüfterkanälen schalten zusätzlich bei 80 °C am Spannungsregler ab. Eine eigene Meldung dafür hat die API von NerdOS 1.1.0.1 nicht, man sieht es nur daran, dass keine Shares mehr kommen. Die Alarmgrenze gehört deshalb 5 °C unter die Abschalt-Temperatur. Dreht der Lüfter nicht (fanrpm 0, fanspeed über 0), ist er defekt oder das Kabel lose. Das ist ein Alarm, der nicht warten kann. hardware_fault meldet zum Beispiel „Fan Control Failed“, power_fault einen Fehler des Spannungsreglers. Die Eingangsspannung ist auffällig, sobald sie unter 94,9 % des Nennwerts fällt: beim Gamma unter 4,75 V, bei 12-V-Geräten unter 11,4 V. Ab dort zeigt auch AxeOS „Danger: Low Voltage“.
5. Auszahlung: Fallback, Benutzer, Coinbase
Steht isUsingFallbackStratum auf 1, rechnet der Miner für den Fallback-Pool. Das ist harmlos, solange dort deine Adresse steht. Ab Werk steht im Fallback, wie im Hauptpool, eine voreingestellte Adresse. Wer nur beim Hauptpool die eigene Adresse einträgt, lässt einen Block im Fallback an diese Adresse auszahlen. Prüfe außerdem, ob stratumUser noch dem Wert entspricht, den du eingetragen hast.
Die stärkste Einzelprüfung ist die Coinbase. AxeOS 2.15.3 entschlüsselt die Coinbase jedes Jobs (Option „Decode Coinbase Tx“ in den erweiterten Pool-Einstellungen, ab Werk an) und meldet in coinbaseValueUserSatoshis, wie viele Satoshi an Ausgänge gehen, deren Adresse am Anfang von stratumUser steht. Bei einem Solo-Pool ohne Gebühr ist das die ganze Coinbase. Steht dort 0, baut der Pool Blöcke, die dich nicht bezahlen: Tippfehler, falscher Pool, manipulierte Einstellung. Das Dashboard zeigt denselben Wert als Anteil und warnt bei 0 % mit „You don't have a share in the mining reward“, unter 95 % mit „Your share of the mining reward is only …“. Die Warnung sieht aber nur, wer das Dashboard öffnet. Bei den meisten geteilten Pools zahlt die Coinbase an den Pool; dort ist 0 normal, und die Prüfung gehört abgeschaltet. Bei SOLO Groups auf pool.bitaxe.de teilt die Coinbase einen Block unter den Mitgliedern auf, ein Anteil unter 100 % ist dort gewollt. Was hinter der Warnung steckt, beantwortet auch die FAQ in Bitaxe verbunden, aber mined nicht.
6. Einstellungen, die sich von selbst ändern
Diese Prüfung fehlt in fast jeder Anleitung. Greift der Überhitzungsschutz, stoppt AxeOS 2.15.3 das Mining, stellt den Lüfter auf manuell 100 % und wartet mindestens 30 Sekunden, bis der Regler unter 95 °C und der Chip, soweit messbar, unter 45 °C liegt. Dann startet es mit 100 MHz weniger Takt und 100 mV weniger Spannung neu und speichert beides. Die Lüfterautomatik bleibt aus. Zurückgesetzt wird nichts davon von selbst.
Ein Gamma mit 625 MHz, so wie wir ihn ausliefern, läuft danach mit 525 MHz und erwartet 1,07 statt 1,28 TH/s, 16 % weniger. Mit den Original-Werten von AxeOS, 525 MHz, fällt er auf 425 MHz und 0,87 TH/s, 19 % weniger. Ein Monitoring, das sich den Ausgangswert von frequency und autofanspeed merkt, sieht das sofort. Behebe zuerst die Ursache, also Staub, Lüfter oder Aufstellort, und stelle dann in den Einstellungen Takt, Spannung und Lüfterautomatik zurück. Wie man den Lüfter danach wieder leise bekommt, steht in Bitaxe leiser machen.
Ab wann ist „kein Share“ ein Ausfall?
Die meisten Fehlalarme kommen von einer falschen Schwelle für „kein Share seit …“. Die richtige Schwelle hängt am Share-Takt, und den kannst du für deinen Miner ausrechnen. Ein Share der Difficulty D braucht im Mittel D × 232 Hashes. Der mittlere Abstand zwischen zwei Shares ist also D × 4.294.967.296 geteilt durch die Hashrate in H/s. D zeigt das Dashboard in der Karte mit den Pool-Daten unter „Difficulty“, die API im Feld poolDifficulty.
Bei ckpool-Pools wie pool.bitaxe.de vergibt die Vardiff die Difficulty. Sie zielt auf 0,3 Shares pro Sekunde und lässt die Difficulty in Ruhe, solange der Takt zwischen 0,15 und 0,4 liegt. Nach unten begrenzt sie der Vorschlag des Miners: AxeOS schlägt nach der Anmeldung 1000 vor (Pool-Einstellung, in der API stratumSuggestedDifficulty). Ein Gamma mit 1,2 TH/s schafft rechnerisch 279 Shares der Difficulty 1 pro Sekunde, bei Difficulty 1000 also 0,28 Shares pro Sekunde, einen alle 3,6 Sekunden. Größere Miner treiben die Difficulty hoch, bis sie bei etwa einem Share alle 2,4 Sekunden landen.
Shares kommen zufällig. Die Wahrscheinlichkeit, dass ein gesunder Miner t Sekunden lang keinen findet, ist e−r·t bei r Shares pro Sekunde. Auf ein Jahr gerechnet kommen bei einem Gamma rund 8,8 Millionen Lücken zwischen zwei Shares zusammen. Schon eine Minute ohne Share kommt dabei im Mittel seltener als einmal im Jahr vor. Als Faustregel reichen 16 mittlere Abstände ohne Share plus zwei Minuten Puffer für Neustarts; damit bleibt es bei jedem Miner bei weniger als einem Fehlalarm im Jahr.
Hoch wird die Difficulty nur, wenn du es so einstellst. Port 4334 von pool.bitaxe.de ist ein High-Difficulty-Port für große ASICs und gemietete Hashrate und gibt jedem Miner zunächst eine Untergrenze von 32.768. Ein Bitaxe mit AxeOS-Voreinstellung landet dort trotzdem bei 1000, denn ckpool übernimmt den Vorschlag des Miners an jedem Port. So steht es in der Funktion suggest_diff() von ckpool, und so arbeitet auch unser Pool. Die 32.768 bleiben nur stehen, wenn du den Vorschlag in AxeOS auf 0 setzt. Dann liefert ein Gamma nur noch einen Share alle 117 Sekunden, und ein Alarm nach 15 Minuten würde ihn rund 125-mal im Jahr fälschlich melden, zweimal pro Woche. Dasselbe passiert, wenn du selbst eine hohe Difficulty vorschlägst.
| Gerät | TH/s | AxeOS-Standard: ein Share alle | Schwelle | Difficulty 32.768: ein Share alle | Schwelle |
|---|---|---|---|---|---|
| Ältere Bitaxe, z. B. Ultra | 0,5 | 8,6 s | 130 s | 282 s | 55 min |
| Bitaxe Gamma | 1,2 | 3,6 s | 57 s | 117 s | 24 min |
| Bitaxe GT | 2,15 | 2,4 s | 39 s | 65 s | 14 min |
| Nerdaxe Gaia | 2,6 | 2,4 s | 39 s | 54 s | 12 min |
| NerdQaxe++ | 4,8 | 2,4 s | 39 s | 29 s | 7 min |
| NerdOctaxe | 12 | 2,4 s | 39 s | 12 s | 3 min |
„Schwelle“ heißt: Ab dieser Dauer ohne Share meldet ein gesunder Miner im Mittel seltener als einmal im Jahr einen Fehlalarm. In der Praxis legst du noch etwas drauf, weil Neustarts, Firmware-Updates und WLAN-Wechsel ein bis zwei Minuten dauern. Mit AxeOS-Voreinstellung empfehlen wir 10 Minuten. Bei Difficulty 32.768 reichen 30 Minuten für einen Gamma; ältere Modelle mit rund 0,5 TH/s brauchen eine Stunde, mit 30 Minuten kämen dort rund 190 Fehlalarme im Jahr zusammen. Andere Pools vergeben die Difficulty anders; dort liest du poolDifficulty ab und rechnest mit derselben Formel. Das Wach-Skript weiter unten macht das von selbst.
Werkzeuge im Vergleich
| Lösung | Alarm | Gerätewerte | ohne Zugang ins Heimnetz | Aufwand |
|---|---|---|---|---|
| AxeOS Swarm | nein | ja, als Übersicht | nein | keiner |
| Pool-Alarm @bitaxepool_bot | Telegram | nein | ja | eine Minute |
| NerdOS-Alarme | Discord | teilweise | das Gerät sendet selbst | gering |
| Wach-Skript (unten) | ntfy | ja | nein, läuft im Heimnetz | eine halbe Stunde |
| Home Assistant | alle Kanäle von HA | ja | nein | mittel |
| InfluxDB und Grafana | Grafana-Alerts | ja, mit Verlauf | nein | hoch |
AxeOS Swarm: Übersicht, aber kein Wächter
Die Seite Swarm in AxeOS sucht im Netz des Geräts nach weiteren Minern, und zwar nur im /24-Bereich, also den 254 Adressen um die eigene. Geräte in einem anderen Subnetz fügst du von Hand per Adresse hinzu. Swarm erkennt AxeOS, NerdOS und Bitforge, aktualisiert standardmäßig alle 30 Sekunden und speichert die Liste im Browser, nicht auf dem Miner. Es läuft also nur, solange die Seite offen ist, und alarmiert nie. Als Übersicht ist es ideal, als Wächter ungeeignet. Wie die übrigen Seiten von AxeOS funktionieren, steht in AxeOS erklärt.
Pool-Alarm per Telegram
Der Bot von pool.bitaxe.de braucht nur deine Adresse: /watch mit Adresse an @bitaxepool_bot schicken, fertig. Er meldet, wenn ein Worker keinen Share mehr liefert, standardmäßig nach 30 Minuten, umstellbar mit /alerts offline 15, 30, 60 oder off. Dazu kommen Meldungen, wenn der Worker wieder liefert, bei einem neuen Best Share, einem Rangaufstieg und einem Blockfund, montags die Wochenbilanz. Mit AxeOS-Voreinstellung taugen auch 15 Minuten. Hast du in AxeOS eine hohe Difficulty eingestellt, lässt du die 30 Minuten stehen, bei älteren Modellen nimmst du 60. Weil der Bot auf der Pool-Seite sitzt, meldet er auch dann, wenn zu Hause Strom und Internet weg sind. Ein Wechsel auf den Fallback-Pool fällt ihm ebenfalls auf, weil dann beim eigenen Pool keine Shares mehr ankommen. Temperatur und Lüfter sieht er nicht. Mehr zum Pool in Bitaxe Pool.
Nerd-Firmware: Alarme und InfluxDB eingebaut
NerdOS 1.1.0.1 bringt zwei Dinge mit, die AxeOS fehlen. In den Einstellungen lässt sich ein Discord-Webhook hinterlegen, an den das Gerät selbst meldet: einen Neustart des Watchdogs, wenn eine Stunde lang kein Share kam, einen Blockfund, eine neue Best Difficulty und eine fehlgeschlagene Coinbase-Prüfung. Die prüft, ob deine Adresse in der Coinbase steht und ob die Pool-Gebühr ein eingestelltes Limit überschreitet. Außerdem schreibt NerdOS auf Wunsch direkt in eine InfluxDB (URL, Port, Token, Organisation, Bucket, Präfix). Einen eigenen Abfrage-Dienst braucht es dann nicht mehr.
Home Assistant
Wer Home Assistant ohnehin betreibt, fragt die API mit dem eingebauten REST-Sensor ab und baut Alarme als Automation. Ein Abruf pro Minute genügt; die Felder sind dieselben wie oben.
rest:
- resource: http://192.168.1.50/api/system/info
scan_interval: 60
sensor:
- name: "Bitaxe Hashrate 10 min"
value_template: "{{ value_json.hashRate_10m | round(0) }}"
unit_of_measurement: "GH/s"
- name: "Bitaxe Spannungsregler"
value_template: "{{ value_json.vrTemp }}"
unit_of_measurement: "°C"
binary_sensor:
- name: "Bitaxe auf Fallback-Pool"
value_template: "{{ value_json.isUsingFallbackStratum == 1 }}" InfluxDB und Grafana
Wer Verläufe über Monate auswerten will, etwa Temperatur gegen Raumtemperatur oder Hashrate je Firmware-Version, schreibt alle 30 bis 60 Sekunden einen Datensatz in eine Zeitreihen-Datenbank und baut Alarme in Grafana. Nerd-Geräte schreiben selbst, für AxeOS braucht es einen Abrufer, zum Beispiel Telegraf mit HTTP-Eingang und JSON-Auswertung. Für drei Geräte ist das viel Aufwand. Ab zehn Geräten oder bei Messreihen lohnt er sich.
Ein Wach-Skript für mehrere Miner
Das folgende Skript erledigt die sechs Prüfungen für beliebig viele AxeOS- und NerdOS-Geräte. Es braucht Python 3 und sonst nichts, läuft auf einem Raspberry Pi, einem NAS oder jedem Rechner im selben Netz und meldet per ntfy aufs Handy. Es merkt sich seinen Zustand in einer Datei, meldet ein Problem einmal und sagt Bescheid, wenn es behoben ist. Solange ein Miner nicht antwortet, bleiben alte Probleme offen statt als behoben zu gelten. Die Schwelle für fehlende Shares rechnet es aus der Pool-Difficulty, bei NerdOS-Geräten setzt es die Temperaturgrenzen 5 °C unter die Abschalt-Temperaturen, und von Hand gestartet zeigt es, warum ein Gerät nicht antwortet. Getestet ist es gegen nachgestellte Antworten in allen Fällen, die es meldet.
#!/usr/bin/env python3
"""bitaxe-wache.py: prüft Bitaxe- und Nerd-Miner über die lokale API und meldet Probleme per ntfy.
Läuft einmal pro Aufruf; per cron oder systemd-Timer jede Minute starten. Nur Python-Standardbibliothek.
Der Rechner muss im selben privaten Netz stehen wie die Miner (AxeOS antwortet nur auf private Adressen).
"""
import base64
import json
import pathlib
import sys
import time
import urllib.request
MINER = ["192.168.1.50", "192.168.1.51"] # IP-Adressen oder Namen wie bitaxe.local
NTFY = "https://ntfy.sh/hier-ein-langes-zufaelliges-thema"
ZUSTAND = pathlib.Path.home() / ".bitaxe-wache.json"
# Coinbase nur bei Solo-Pools prüfen: bei geteilten Pools zahlt sie meist an den Pool
SOLO_POOL = True
GRENZEN = {
"offline_runden": 3, # so viele Abfragen in Folge ohne Antwort
"ohne_share_s": 600, # Untergrenze; bei hoher Pool-Difficulty rechnet das Skript länger
"hashrate_anteil": 0.85, # 10-Minuten-Mittel unter diesem Anteil von Expected ...
"hashrate_runden": 15, # ... so viele Abfragen in Folge
"chip_c": 70, # NerdOS: 5 °C unter seiner Abschalt-Temperatur, siehe unten
"regler_c": 95,
"wlan_dbm": -75,
"wlan_runden": 10,
"spannung_anteil": 0.949, # wie die Warnung "Danger: Low Voltage" in AxeOS 2.15
}
def lies(host):
with urllib.request.urlopen(f"http://{host}/api/system/info", timeout=5) as antwort:
return json.load(antwort)
def melde(titel, text, prio="default"):
# Titel nach RFC 2047 kodiert, damit Umlaute unverfälscht ankommen (empfohlen in der ntfy-Doku)
titel_kodiert = "=?UTF-8?B?" + base64.b64encode(titel.encode("utf-8")).decode("ascii") + "?="
anfrage = urllib.request.Request(NTFY, data=text.encode("utf-8"),
headers={"Title": titel_kodiert, "Priority": prio})
try:
urllib.request.urlopen(anfrage, timeout=10).close()
except OSError as fehler:
print(f"Meldung nicht zugestellt: {fehler}")
def erwartet(info):
"""Erwartete Hashrate in GH/s: AxeOS liefert sie, bei NerdOS aus Takt x Kernen x Chips."""
if info.get("expectedHashrate"):
return info["expectedHashrate"]
if info.get("frequency") and info.get("smallCoreCount"):
return info["frequency"] * info["smallCoreCount"] * info.get("asicCount", 1) / 1000
return None
def pruefe(host, info, z, jetzt):
"""Liefert eine Liste (Schlüssel, Priorität, Text) der Probleme, die gerade bestehen."""
probleme = []
uptime = info.get("uptimeSeconds", 0)
# 1. Neustart: Laufzeit kleiner als bei der letzten Abfrage
if uptime < z.get("uptime", 0):
grund = info.get("resetReason") or info.get("lastResetReason") or "unbekannt"
ernst = any(w in grund for w in ("Brownout", "watchdog", "panic", "glitch", "lock up"))
probleme.append((f"neustart-{jetzt}", "high" if ernst else "default", f"Neu gestartet: {grund}"))
z["shares_ts"] = jetzt
z["uptime"] = uptime
# 2. Keine neuen angenommenen Shares. Die Schwelle wächst mit der Pool-Difficulty: Ein Share braucht
# im Mittel Difficulty x 2^32 Hashes, und 16 mittlere Abstände ohne Share sind seltener als 1x im Jahr.
akzeptiert = info.get("sharesAccepted", 0)
if akzeptiert != z.get("shares") or "shares_ts" not in z:
z["shares"], z["shares_ts"] = akzeptiert, jetzt
rate = (erwartet(info) or info.get("hashRate_10m") or 0) * 1e9
abstand = (info.get("poolDifficulty") or 0) * 2**32 / rate if rate else 0
grenze = min(max(GRENZEN["ohne_share_s"], 16 * abstand + 120), 4 * 3600)
stille = jetzt - z["shares_ts"]
if stille > grenze and not info.get("miningPaused"):
probleme.append(("shares", "high", f"Seit {stille // 60} Minuten kein angenommener Share"))
# 3. Hashrate unter Expected (erst 15 Minuten nach dem Start bewerten)
soll, ist = erwartet(info), info.get("hashRate_10m")
if soll and ist is not None and uptime > 900 and ist < GRENZEN["hashrate_anteil"] * soll:
z["wenig"] = z.get("wenig", 0) + 1
else:
z["wenig"] = 0
if z["wenig"] >= GRENZEN["hashrate_runden"]:
probleme.append(("hashrate", "default", f"Hashrate {ist:.0f} GH/s, erwartet {soll:.0f} GH/s"))
# 4. Temperatur, Lüfter, Hardware- und Netzteilfehler. NerdOS schaltet je Lüfterkanal bei
# "overheatTemp" ab (Chip ab Werk 70 °C, Regler bei zwei Kanälen 80 °C): 5 °C vorher warnen.
kanaele = info.get("fans") or []
abschalt_chip = (kanaele[0].get("overheatTemp") if kanaele else None) or info.get("overheat_temp")
abschalt_regler = kanaele[1].get("overheatTemp") if len(kanaele) > 1 else None
chip = max([info.get("temp") or 0] + (info.get("asicTemps") or []))
if chip > min(GRENZEN["chip_c"], (abschalt_chip or 999) - 5):
probleme.append(("chip", "high", f"Chip {chip:.0f} °C"))
regler = info.get("vrTemp") or 0
if regler > min(GRENZEN["regler_c"], (abschalt_regler or 999) - 5):
probleme.append(("regler", "high", f"Spannungsregler {regler:.0f} °C"))
if info.get("overheat_mode"):
probleme.append(("ueberhitzt", "urgent", "Überhitzungsschutz aktiv, Mining gestoppt"))
if info.get("fanspeed", 0) > 0 and info.get("fanrpm", 1) == 0:
probleme.append(("luefter", "urgent", "Lüfter dreht nicht"))
for feld in ("hardware_fault", "power_fault"):
if info.get(feld):
probleme.append((feld, "urgent", f"{feld}: {info[feld]}"))
nenn = info.get("nominalVoltage")
if nenn and info.get("voltage"):
nenn_mv = nenn * 1000 if nenn < 100 else nenn
if info["voltage"] < GRENZEN["spannung_anteil"] * nenn_mv:
probleme.append(("spannung", "high", f"Eingangsspannung {info['voltage'] / 1000:.2f} V"))
# 5. Auszahlung: Fallback-Pool, geänderte Adresse, Coinbase ohne eigenen Ausgang
stratum = info.get("stratum") if isinstance(info.get("stratum"), dict) else {} # NerdOS
if info.get("isUsingFallbackStratum") or stratum.get("usingFallback"):
probleme.append(("fallback", "high", "Miner arbeitet auf dem Fallback-Pool"))
benutzer = info.get("stratumUser")
z.setdefault("benutzer", benutzer)
if benutzer != z["benutzer"]:
probleme.append((f"benutzer-{benutzer}", "urgent", f"Stratum-User geändert auf {benutzer}"))
gesamt, eigen = info.get("coinbaseValueTotalSatoshis"), info.get("coinbaseValueUserSatoshis")
if SOLO_POOL and gesamt and eigen == 0:
probleme.append(("coinbase", "urgent", "Die Coinbase zahlt nicht an deine Adresse"))
# 6. Einstellungen weg vom Ausgangswert (z. B. nach dem Überhitzungsschutz)
z.setdefault("takt", info.get("frequency"))
z.setdefault("autofan", info.get("autofanspeed"))
if info.get("frequency") and z["takt"] and info["frequency"] < z["takt"] - 50:
probleme.append(("takt", "default", f"Takt {info['frequency']:.0f} MHz statt {z['takt']:.0f} MHz"))
if info.get("autofanspeed") != z["autofan"]:
probleme.append(("autofan", "default", "Lüftersteuerung umgestellt"))
# WLAN: nur dauerhaft schwaches Signal melden
rssi = info.get("wifiRSSI")
z["schwach"] = z.get("schwach", 0) + 1 if rssi is not None and rssi < GRENZEN["wlan_dbm"] else 0
if z["schwach"] >= GRENZEN["wlan_runden"]:
probleme.append(("wlan", "low", f"WLAN schwach: {rssi} dBm"))
return probleme
def main():
try:
zustand = json.loads(ZUSTAND.read_text())
except (OSError, ValueError):
zustand = {}
jetzt = int(time.time())
for host in MINER:
z = zustand.setdefault(host, {})
info = {}
try:
info = lies(host)
except (OSError, ValueError) as fehler:
if sys.stdout.isatty():
print(f"{host}: {fehler}") # von Hand gestartet: Grund zeigen, z. B. HTTP Error 401
z["fehlt"] = z.get("fehlt", 0) + 1
probleme = [("offline", "high", "Miner antwortet nicht")] if z["fehlt"] >= GRENZEN["offline_runden"] else []
else:
z["fehlt"] = 0
probleme = pruefe(host, info, z, jetzt)
erreichbar = z["fehlt"] == 0
name = info.get("hostname") or host
offen = z.get("offen", {})
aktuell = {s: text for s, _, text in probleme if not s.startswith("neustart")}
if not erreichbar:
# Ohne Antwort ist nicht klar, ob alte Probleme behoben sind: offen lassen
aktuell = {**{s: t for s, t in offen.items() if s != "offline"}, **aktuell}
for schluessel, prio, text in probleme:
if schluessel not in offen:
melde(f"{name}: Problem", text, prio)
for schluessel in offen.keys() - aktuell.keys():
melde(f"{name}: wieder in Ordnung", f"Behoben: {offen[schluessel]}", "low")
z["offen"] = aktuell
ZUSTAND.write_text(json.dumps(zustand, indent=1))
if __name__ == "__main__":
main() - Das Skript als
bitaxe-wache.pyspeichern,MINERmit den Adressen deiner Geräte füllen. Am besten vergibst du im Router feste Adressen oder nimmst die Namen auf.local. - Bei
NTFYein langes, zufälliges Thema eintragen und es in der ntfy-App abonnieren. Themen auf ntfy.sh sind nicht geschützt; wer den Namen errät, liest mit. - Bei einem geteilten Pool
SOLO_POOL = Falsesetzen.ohne_share_sist nur die Untergrenze; bei hoher Pool-Difficulty wartet das Skript von selbst länger. - Mit cron jede Minute starten:
* * * * * /usr/bin/python3 /home/pi/bitaxe-wache.py - Testen: einen Miner vom Strom nehmen. Nach drei Minuten kommt „Miner antwortet nicht“, nach dem Einstecken „Neu gestartet: Reset due to power-on event“ und die Entwarnung.
Beim ersten Lauf merkt sich das Skript Benutzer, Takt und Lüfterautomatik jedes Geräts. Änderst du diese Werte absichtlich, löschst du danach ~/.bitaxe-wache.json, damit es die neuen Werte übernimmt.
Typische Fehlalarme und echte Probleme
- Nachts kurz offline: Der Router startet neu oder wechselt den WLAN-Kanal, oder der Miner hat eine neue Adresse bekommen. Feste Adresse im Router oder den Namen auf
.localverwenden. - Alle paar Stunden ein Neustart mit „Brownout“: Die Spannung bricht ein. Bei 5-V-Geräten kosten schon ein langes, dünnes Kabel oder ein müdes Netzteil die nötigen Zehntel Volt.
- Hashrate 16 % niedriger, Lüfter laut: Der Überhitzungsschutz hat gegriffen und gedrosselt. Ursache beheben, dann Takt, Spannung und Lüfterautomatik zurückstellen.
- Pool meldet offline, Dashboard sieht normal aus: Der Miner arbeitet auf dem Fallback-Pool (
isUsingFallbackStratum1), oder Benutzer- und Worker-Name stimmen nicht. - Das Skript meldet „Miner antwortet nicht“, das Dashboard läuft aber: Starte das Skript von Hand, dann zeigt es den Grund. Steht dort „HTTP Error 401“, kommt die Anfrage nicht aus einem privaten Netz, typischerweise über ein VPN ohne SNAT.
- Swarm findet ein Gerät nicht: Es steht in einem anderen Subnetz. Von Hand per Adresse hinzufügen.
- Mehr abgelehnte Shares direkt nach einem neuen Block: Shares, die zum alten Block unterwegs waren, kommen zu spät an. Kurze Spitzen sind normal. Bleibt der Anteil hoch, helfen die Gründe in
sharesRejectedReasonsweiter. - Hashrate dauerhaft knapp unter Expected bei normaler Temperatur: Takt und Spannung passen nicht zusammen; die Schritte stehen im Overclocking-Guide. Bleibt es auch auf Werkseinstellungen so, hilft die Miner-Diagnose.
Monitoring ohne neue Angriffsfläche
Überwachung darf den Miner nicht angreifbarer machen, als er ist. Vier Regeln reichen:
- Keine Portfreigabe. Die Absenderprüfung von AxeOS ist kein Passwort. Ist der Miner aus dem Internet erreichbar, kann ihn umstellen, wer weiß, wie. Von unterwegs genügt der Pool-Alarm; Gerätewerte holst du über ein VPN mit SNAT.
- Wer im Heimnetz ist, darf alles. Das gilt auch für Gäste und Smart-Home-Geräte mit fragwürdiger Firmware. Ein eigenes Gastnetz hält sie fern. Die Coinbase-Prüfung macht eine geänderte Adresse sofort sichtbar.
- Fremde Apps bekommen dieselben Rechte wie du. Eine App, die deine Miner überwacht, kann sie auch umstellen. Lokale, quelloffene Werkzeuge sind deshalb die bessere Wahl.
- Die Verbindung zum Pool verschlüsseln. Mit Stratum V2 kann niemand unterwegs die Jobs austauschen; die Einrichtung steht in Stratum V2 am Bitaxe einrichten.
Häufige Fragen
Hat die AxeOS-API ein Passwort?
Kann ich meinen Bitaxe von unterwegs überwachen?
Wie erkenne ich, warum mein Bitaxe neu gestartet ist?
Warum zeigt der Pool noch Hashrate, obwohl mein Miner aus ist?
Warum ist mein Bitaxe nach einer Überhitzung langsamer und lauter?
Kann ein Bitaxe selbst Alarme senden?
Was bedeutet coinbaseValueUserSatoshis?
Ändert der High-Difficulty-Port etwas an der Alarmschwelle?
Gibt es eine App, um den Bitaxe zu überwachen?
Wie binde ich einen Bitaxe in Home Assistant ein?
Ab welcher Temperatur sollte ich mir Sorgen machen?
Quellen
- AxeOS 2.15.3: Zugriffsprüfung der API, Felder von /api/system/info und Neustart-Gründe, Überhitzungsschutz, Warnungen im Dashboard
- NerdOS 1.1.0.1: Discord-Alarme, Abschaltung je Lüfterkanal, Felder der API
- ckpool: Vardiff und suggest_diff() in stratifier.c
- Tailscale: Subnet-Router und SNAT, ntfy: Nachrichten senden, Home Assistant: REST-Integration
Passende Produkte
Weiterlesen
Nerdaxe Gaia: Was der BM1373-Miner kann, welche Firmware passt und für wen er sich lohnt
Ein einzelner BM1373 im vertrauten Nerdaxe-Format: Werkseinstellungen aus dem Quellcode, Hashrate und Verbrauch mit allen belegten Werten, 12-Volt-Netzteil, OSM-OS aus dem Flasher, Einrichtung, Übertakten bis zur Stromgrenze, Blockchance und Stromkosten, dazu der Vergleich mit Nerdaxe Gamma, Bitaxe GT und NerdQaxe++.
Guides & WissenStratum V2 am Bitaxe einrichten: verschlüsselt solo minen in fünf Feldern
Seit AxeOS 2.14 spricht jeder Bitaxe Stratum V2, seit September 2026 auch der Bitaxe Pool. Diese Anleitung geht Feld für Feld durch, was du in AxeOS einträgst, wie du Fallback und Prüfung richtig aufsetzt und woran es hakt, wenn keine Shares ankommen. Für Bitaxe, NerdQaxe und große ASICs.
Guides & WissenNerdQaxe++ im Test: 4,8 TH/s aus vier BM1370 und für wen sich der Umstieg vom Bitaxe lohnt
Vier BM1370 auf einem Board, ab Werk 4,9 TH/s erwartet, rund 76 W, zwei Lüfter und NerdOS im Browser: Wir ordnen den NerdQaxe++ ein. Werkswerte aus der Firmware, Revisionen, Lautstärke, Stromkosten, Blockchance, Einrichtung in NerdOS und der Vergleich mit Bitaxe Gamma, GT und 702, Copper Pro, Hydro, NerdQX und NerdOctaxe.