Bootstrapping infrastruktury kryptowalutowej shellem i config managementem
Historia z okopów o postawieniu infrastruktury stojącej za projektem kryptowalutowym — demony monet, portfele i obsługa kluczy — odtwarzalnie, skryptami shell i Ansible. Lekcje bezpieczeństwa, których uczy tylko system obsługujący pieniądze.
Prowadzenie infrastruktury dla projektu kryptowalutowego to zwykła administracja systemami z podkręconą stawką. Demony to po prostu długo działające procesy; serwery to po prostu maszyny Linux. Ale każdy z tych procesów może ruszyć pieniądze, każdy serwer trzyma lub dotyka kluczy, a pomyłka to nie wycofana transakcja — to środki przepadłe na dobre. Ta różnica zmienia sposób budowania wszystkiego. Oto historia z okopów o bootstrappingu tej infrastruktury odtwarzalnie i lekcje, których uczy tylko system obsługujący pieniądze.
Problem: wiele demonów, zero miejsca na płatki śniegu
Kształt systemu to kilka demonów monet (Bitcoin i garść altcoinów), każdy długo działający proces wystawiający interfejs JSON-RPC, plus portfel, monitoring i maszyneria backupów wokół nich. Każdy demon potrzebował tego samego zdyscyplinowanego traktowania: zahartowanego hosta, zsynchronizowanego łańcucha, zamkniętego RPC, monitorowanej żywotności i backupowanych danych portfela.
Pokusą, pod deadline’em, jest zalogowanie się przez SSH i ustawienie każdego ręcznie. Już nauczyliśmy się, gdzie ta droga się kończy — flota serwerów-płatków śniegu, których nikt nie odtworzy, każdy subtelnie inny, każdy zagadką pół roku później. Z pieniędzmi na szali „chyba ten jest skonfigurowany poprawnie” nie wystarcza. Wszystko musiało być kodem: odtwarzalne, recenzowalne i odbudowywalne od zera.
Shell do bootstrapu, Ansible do konwergencji
Podzieliliśmy pracę wzdłuż linii, która od tamtej pory dobrze nam służy. Skrypty shell obsługują goły bootstrap — garść imperatywnych kroków, by przeprowadzić świeżą maszynę z niczego do „Ansible może nią zarządzać”: ustaw hostname, utwórz użytkownika deploy, zainstaluj Pythona i klucz SSH. Krótkie, głupie, uruchomione raz.
#!/usr/bin/env bash
set -euo pipefail # zawiedź głośno — nigdy nie konfiguruj w połowie maszyny z pieniędzmi
apt-get update
apt-get install -y python sudo
useradd -m -s /bin/bash deploy
install -d -m 700 /home/deploy/.ssh
echo "$DEPLOY_KEY" > /home/deploy/.ssh/authorized_keys
chmod 600 /home/deploy/.ssh/authorized_keys
set -euo pipefail na górze to nie boilerplate — to reguła bezpieczeństwa. Na
maszynie, która będzie trzymać klucze, skrypt orzący dalej po błędzie to sposób, w
jaki kończysz z maszyną skonfigurowaną w połowie, którą myślisz, że zahartowałeś.
Zawiedź głośno, zawiedź wcześnie.
Wszystko po bootstrapie to Ansible — idempotentne role konwergujące każdy host do zadeklarowanego stanu: zahartowany sshd, firewall, demon monety, jego konfiguracja, jego monitoring. Podział pracy: shell doprowadza cię do stanu zarządzanego raz; Ansible trzyma cię tam na zawsze i dowodzi tego przy każdym przebiegu.
Demony jako zarządzane usługi, nie ręcznie odpalone procesy
Demon monety, którego ktoś odpalił ręcznie w sesji screen, to ryzyko — nie przeżyje restartu, nikt nie zna dokładnych flag, z jakimi go uruchomiono, a jego zachowanie przy restarcie jest tym, co akurat zrobiła powłoka. Każdy demon poszedł pod porządny init/supervisor z zadeklarowaną konfiguracją, więc definicja usługi jest dokumentacją:
# renderowane z szablonu Ansible, jedno na monetę
[program:dogecoind]
command=/usr/local/bin/dogecoind -conf=/etc/coins/dogecoin.conf -printtoconsole
user=coin
autostart=true
autorestart=true
stdout_logfile=/var/log/coins/dogecoin.log
Teraz restart przywraca każdy demon dokładnie jak skonfigurowany, awaria go restartuje, a flagi uruchomienia żyją w kontroli wersji, nie w czyjejś pamięci. Dane łańcucha oczywiście żyją na dedykowanym, backupowanym wolumenie — nigdy na efemerycznym dysku root — z dokładnie tych powodów, których nauczyło nas już uruchamianie tych węzłów w kontenerach: proces jest jednorazowy, dane nie.
Obsługa kluczy: część, która nie pozwala spać
Tu infrastruktura krypto przestaje być normalną administracją. Klucze kontrolujące środki nie mogą być traktowane jak zwykła konfiguracja. Reguły wykute w bólu:
- Hot i cold to różne światy. Tylko minimum potrzebne do codziennej operacji (hot wallet z ograniczonymi środkami) żyje na maszynie podłączonej do internetu. Gros siedzi w cold storage — klucze generowane i trzymane na maszynie, która nigdy nie dotknęła sieci. Żadna ilość hartowania serwera nie zastąpi po prostu nieposiadania kluczy w zasięgu.
- Sekrety nigdy nie żyją w repo. Infrastruktura to kod i jest publiczna dla zespołu; sekrety nie. Hasła RPC, frazy portfeli i klucze API są wstrzykiwane przy deployu z zaszyfrowanego składu (Ansible Vault), nigdy commitowane w czystym tekście, nigdy echowane do logów czy listy procesów.
- RPC jest osiągalne z niczego, z czego nie musi. Ta sama lekcja, co przy uruchamianiu pojedynczego węzła, teraz nie do negocjacji w całej flocie: port P2P jest publiczny, port RPC związany z localhostem lub prywatnym interfejsem, firewall odmawia domyślnie i pozwala przez wyjątek. Interfejs ruszający pieniędzmi wystawiony na internet to nie ryzyko, to ostateczna pewność straty.
- Backupy są szyfrowane, zautomatyzowane i testowane. Backup portfela to instrument na okaziciela — kto go ma, ma środki — więc backupy są szyfrowane w spoczynku, a odtworzenie jest testowane, bo nietestowany backup to zgadywanie.
Monitorowanie żywotności i rozbieżności
Dla zwykłych usług monitorujesz uptime i opóźnienia. Dla demonów monet monitorujesz też rzeczy specyficzne dla domeny, bo „proces działa” to nie to samo, co „węzeł jest zdrowy”. Sprawdzenia, które zasłużyły na swoje miejsce:
- Czy działa i odpowiada na RPC? Demon może być włączony, ale zaklinowany.
- Czy wysokość bloku dotrzymuje kroku sieci? Węzeł, który po cichu utknął lub się rozwidlił, jest gorszy niż martwy — daje pewnie błędne odpowiedzi.
- Czy dysk się zapełnia? Łańcuchy tylko rosną; pełny dysk kładzie demona twardo.
- Czy port RPC kiedykolwiek stał się osiągalny z zewnątrz? Alarmuj na to jako regresję bezpieczeństwa, nie tylko awarię.
To działało w harmonogramie i pagowało przy porażce, bo koszt późnego odkrycia, że host portfela zdryfował, nie był wolnym pagiem — był potencjalną stratą.
Czego nauczył nas projekt
Pozbawiony specyfiki kryptowalut, to był intensywny kurs dyscypliny infrastrukturalnej, a lekcje generalizują się na wszystko, gdzie pomyłki są drogie:
- Odtwarzalność to właściwość bezpieczeństwa, nie tylko wygoda. Maszyna, którą możesz odbudować z kodu, to maszyna, o której możesz rozumować; płatek śniegu to niewiadoma, a niewiadome blisko pieniędzy są nie do przyjęcia.
- Oddzielaj to, co jednorazowe, od tego, co cenne — proces od danych, hot od cold, kod od sekretów — i projektuj cykl życia każdego świadomie.
- Zawiedź głośno.
set -euo pipefail, firewalle deny-by-default, alerty na regresje bezpieczeństwa: gdy minus jest trwały, system zatrzymujący się przy pierwszym znaku kłopotu bije ten, który usłużnie orze dalej.
Przenieśliśmy tę postawę do każdego projektu od tamtej pory, krypto czy nie. Kontekst kryptowalutowy po prostu usunął siatkę bezpieczeństwa, która gdzie indziej czyni niechlujstwo przeżywalnym — a praca bez tej siatki, przez jakiś czas, uczyniła nas znacznie lepszymi w budowaniu infrastruktury, która zasługuje na zaufanie czymś, co ma znaczenie.