Mój blog // Cyfrowe archiwum

Myśli, projekty i notatki techniczne

Pierwotnie mój setup bloga był planowany jako projekt wyłącznie IPv6 przez WireGuard, ponieważ całość działa na serwerze domowym (darmowe adresy IPv6 można nawiasem mówiąc uzyskać na route64.org). Aby zwiększyć dostępność, dodałem teraz zewnętrzny serwer proxy IPv4 (podziękowania dla @Larvitz).

Pojawiły się jednak natychmiastowe problemy z SSL: Ponieważ pierwotnie zarówno rekord A, jak i AAAA przechodziły przez proxy, walidacja Let's Encrypt na moim serwerze kończyła się niepowodzeniem.

Rozwiązanie: „IPv6-Hack”

Rozwiązaniem było jawne skierowanie rekordu AAAA bezpośrednio na adres IP WireGuard mojego serwera, zamiast prowadzenia go również przez proxy.

  • Domena: blog.burningboard.org
  • Rekord A (Proxy): 194.28.98.217
  • Rekord AAAA (Serwer): 2a11:6c7:f05:a8::2 (WireGuard)

Dzięki temu bezpośredniemu wpisowi AAAA na mój adres IP WireGuard, Let’s Encrypt nadal dociera do mojego serwera bezpośrednio przez IPv6 (ponieważ rekord AAAA jest domyślnie priorytetyzowany) i wystawia certyfikat SSL. Ruch IPv4 jest przekazywany do mnie przez proxy w formie zaszyfrowanej.

Finałowa konfiguracja

Aby komunikacja przebiegała bez zakłóceń, musieliśmy dostosować serwery Caddy:

1. Na moim serwerze (NixOS, blog.nix)

Aby prawdziwe adresy IP odwiedzających docierały poprawnie i nie były nadpisywane przez IP serwera proxy, musi on zostać oznaczony jako zaufany:

services.caddy.globalConfig = ''
  servers {
      trusted_proxies static 2a06:9801:1c:1000::10
  }
'';

2. Na zewnętrznym serwerze proxy (Caddy)

Aby proxy poprawnie łączyło się z moim serwerem przez HTTPS, musi przesyłać nazwę hosta (SNI):

reverse_proxy [https://[2a11:6c7:f05:a8::2]:443](https://[2a11:6c7:f05:a8::2]:443) {
    header_up Host {host}
    transport http {
        tls_server_name blog.burningboard.org
    }
}

Blog jest teraz dostępny przez IPv4 i IPv6, bezpiecznie zaszyfrowany, a mój domowy adres IP pozostaje prywatny! 🚀

Najważniejsza informacja na początek: podstawą pozostają znajome pliki Markdown – po prostu jestem wielkim fanem tego nieskomplikowanego rozwiązania. Jednak pod maską sporo się zmieniło:

Trochę pogrzebałem w konfiguracji:

📂 Pliki MD: Struktura bloga pozostaje prosta, oparta na formacie Markdown.

🌍 Bardziej globalnie niż kiedykolwiek: Mój blog obsługuje teraz tłumaczenia na 43 języki. Tak, wliczając w to klingoński! 🖖 (Qapla'!)

Planowałem w pełni automatyczne tłumaczenie w czasie rzeczywistym oparte na rozpoznawaniu języka w przeglądarce. Spoiler: zadziałało to tylko częściowo. Widać, że AI jest imponująca, ale jeszcze nie do końca „tam”, gdzie byśmy chcieli.

Rozwiązanie: Teraz po prostu tłumaczę każdy wpis z wyprzedzeniem na wszystkie zdefiniowane języki, co jest również znacznie lepsze dla wyszukiwarek (SEO). Jeśli automatyczne rozpoznawanie zawiedzie, możecie ręcznie ustawić preferowany język za pomocą ikony globu, który zostanie następnie zapisany w prosty sposób w pliku cookie.

Tłumaczenia są teraz wykonywane za pomocą Gemini 3 Flash, co daje zdumiewająco dobre wyniki. Należy jednak patrzeć AI na ręce: w pierwszym przebiegu zbiorczym błędnie przetłumaczono również tagi, co oczywiście nie było zamierzone.

Kod jest nadal dostępny (jeśli jesteście zainteresowani, po prostu napiszcie do mnie wiadomość) 👍 Pamiętajcie jednak, że system wymaga teraz własnego klucza API Gemini 🔑.

Bez zbędnego zwlekania przeniosłem mój blog z WriteFreely na własne rozwiązanie: MD-Blog (MD oznacza oczywiście Markdown). Powodem była nieudana aktualizacja starego systemu – ostatecznie stało się to jednak idealnym impulsem, aby radykalnie wszystko uprościć i zyskać pełną kontrolę nad designem.

Sercem projektu są proste pliki Markdown w folderze data/, które są konwertowane na nowoczesny HTML w czasie rzeczywistym. Rezultat jest błyskawiczny, nie wymaga bazy danych i dzięki własnemu systemowi projektowania (w tym trybowi ciemnemu) wygląda teraz dokładnie tak, jak sobie wymarzyłem. Nawet nowoczesny przycisk udostępniania na Mastodonie jest teraz dostępny bezpośrednio na stronie.

Jeśli jesteście zainteresowani kodem lub tą minimalistyczną konfiguracją, odezwijcie się do mnie na Mastodonie!

Właściwie pomysł stojący za #Winboat jest doskonały, ale realizacja wydaje się obecnie jeszcze nieco niestabilna. Od czasu instalacji na początku roku system działał, ale dzisiaj oprogramowanie całkowicie odmówiło posłuszeństwa.

Obraz nagle zgłosił niewystarczającą ilość pamięci operacyjnej (RAM). Próbowałem jeszcze naprawić problem ręcznie, co jednak niestety ostatecznie sprawiło, że system stał się bezużyteczny. Zamiast inwestować więcej czasu w szukanie błędów, przeszedłem bezpośrednio na obraz Windows od Dockurr – stanowi on i tak techniczną podstawę Winboat.

Komunikat o błędzie

1. Przygotowanie

Ponieważ używam Podmana, najpierw utworzyłem wymagane katalogi w moim systemie macierzystym. Dzięki temu integralność danych zostanie zachowana, jeśli kontener będzie musiał zostać utworzony na nowo:

mkdir -p $HOME/Windows/System
mkdir -p $HOME/Windows/Shared

2. Polecenie uruchomienia

Ważna uwaga: W zmiennych -e USERNAME i -e PASSWORD zastąp symbole zastępcze swoimi osobistymi danymi logowania.

podman run -d \
  --name windows \
  -p 8006:8006 \
  --device=/dev/kvm \
  --cap-add NET_ADMIN \
  -e RAM_SIZE="8G" \
  -e USERNAME="Carsten" \
  -e PASSWORD="1234" \
  -e LANGUAGE="German" \
  -v $HOME/Windows/System:/storage:Z \
  -v $HOME/Windows/Shared:/shared:Z \
  --stop-timeout 120 \
  dockurr/windows

Gdy tylko kontener stanie się aktywny, możesz uzyskać dostęp do instancji Windows bezpośrednio przez przeglądarkę:

http://127.0.0.1:8006

Uruchomiony kontener

3. Podsumowanie

Powyższe polecenie musiałem wykonać tylko raz. W codziennej eksploatacji środowiskiem Windows można teraz bardzo wygodnie sterować za pomocą tych krótkich poleceń:

  • Uruchamianie: podman start windows
  • Zatrzymywanie: podman stop windows (lub wyłączenie bezpośrednio wewnątrz systemu Windows)
  • Sprawdzanie statusu: podman ps -a

Przydatne linki:

Zainstalowałem własny blog — przede wszystkim po to, aby lepiej poznać #NixOS. O dziwo, wszystko poszło całkiem sprawnie.

WriteFreely świetnie się do tego nadaje: jest minimalistyczne, szybkie w konfiguracji i pozbawione zbędnych dodatków. Idealne, aby po prostu zacząć i przy okazji czegoś się nauczyć. Konfiguracja jest przyjemnie przejrzysta. Kilka ustawionych opcji, przygotowany katalog, Reverse Proxy przed tym — i gotowe.

Tak wygląda moja aktualna konfiguracja NixOS dla tego projektu:

{ config, pkgs, ... }:

{
  services.writefreely = {
    enable = true;
    host = "blog.burningboard.org"; 
    settings = {
      server = {
        port = 8080;
        min_log_level = "debug";
      };
      app = {
        host = "https://blog.burningboard.org";
        single_user = true;
        landing = "/read";
        wf_modesty = true;
        federation = true;
        public_stats = true;
        theme = "write";
      };
    };
    stateDir = "/opt/writefreely";
  };

  # Poprawka dla generowania kluczy ActivityPub: federacja wymaga openssl
  systemd.services.writefreely.path = [ pkgs.openssl ];

  # Automatyczne tworzenie katalogu danych z poprawnymi uprawnieniami
  systemd.tmpfiles.rules = [
    "d /opt/writefreely 0700 writefreely writefreely -"
  ];

  services.caddy.virtualHosts."blog.burningboard.org".extraConfig = ''
    reverse_proxy 127.0.0.1:8080 {
      header_up Host {host}
      header_up X-Real-IP {remote_host}
      header_up X-Forwarded-For {remote_host}
      header_up X-Forwarded-Proto {scheme}
    }
  '';
}

To w zasadzie wszystko. NixOS sprawia, że czysta konfiguracja takich usług i utrzymanie ich w sposób reprodukowalny jest naprawdę proste.