Idź na socjal

Idź na socjal – tak właśnie można przetłumaczyć GoToSocial, czyli nazwę serwera ActivityPub napisanego w Golangu. Czyli serwera, by zaistnieć w Fediverse. Bo Mastodon może i jest popularny, ale nie jest jedyny.

GoToSocial był moim wyborem do zabawy z Fediverse już dawno temu, jednak wymagania nieco odstraszały. Głównie te związane z VPSem i jego parametrami. Co prawda niby powinno działać na mniej niż 1 GB RAM i kilkanaście GB dysku, ale jakoś nie miałem gdzie tego wcisnąć na istniejących maszynkach. Zwłaszcza, że chodzi wyłącznie o zabawę.

Jak wspominałem we wpisie o Sesji Linuksowej, wygrałem talon na VPS mikr.us. I niedawno go zrealizowałem na potrzeby innego projektu. Zasobów jest tam dużo za dużo, więc idealny moment, by pobawić się GoToSocial. Tym bardziej, że VPS na mikr.us nie pozwala na uruchomienie kontenerów LXC. W każdym razie mi się nie udało, a konsultacja na Discordzie potwierdziła, że się nie da. Za to działa docker.

Nie jestem fanem dockera. Zdarza mi się go używać, ale raczej nie jest pierwszym wyborem. Jednak i Uptime Kuma, i GoToSocial dają obrazy i sensowną – na pierwszy rzut oka – dokumentację. Postanowiłem spróbować.

Z dokumentacji GoToSocial dowiedziałem się, że potrzebuję otwartego portu 443 oraz osobnej domeny dla instancji. Ogólnie wymagania są nieco dziwne. Po pierwsze, nie można wykorzystać dowolnego portu. Na mikrusie to problem, bo o ile możemy sobie przekierować kilka portów, to są to inne porty niż 443. Po drugie, domena jest trwale przywiązana do instancji (a w zasadzie kluczy), co oznacza, że nie można zmienić oprogramowania serwera na tej samej domenie.

Wziąłem zatem darmową (sub)domenę, którą wykorzystam tylko do tego jednego celu i tylko do testu. Mikrus daje normalny dostęp po IPv6, bez konieczności przekierowywania portów, a większe serwery działają w dual stack, wiec stwierdziłem, że instancja będzie dostępna wyłącznie po IPv6.

Ostateczny setup na który się zdecydowałem to: GoToSocial w dockerze (tylko IPv4), nginx na froncie, robiący za reverse proxy, nasłuchujący na porcie 443 i adresie IPv6. TLS od Let’s Encrypt z wykorzystaniem certbota, terminowany na nginx. Dla domeny ustawiłem wyłącznie rekord AAAA. Czemu tak? Bo tak jest najwygodniej i standardowo. Mógłbym pominąć nginx, ale straciłbym wszystkie dodatkowe możliwości typu bezproblemowy rate limit. I musiałbym włączyć IPv6 w dockerze.

Uruchomienie nie było bezproblemowe. Już sama konfiguracja i start dockera sprawiły trudności. Przyczyną były oczywiście uprawnienia do katalogów. Niby jest to pokazane w logach, ale zachowanie jest nieco dziwne, zwł. w kwestii tworzenia nieistniejących katalogów. Jednak w końcu docker ruszył.

Dla odmiany z nginx poszło łatwo. Przykładowy konfig zadziałał niemal od kopa, drobnego dostosowania wymagała jedynie obsługa http2 w starszej wersji nginx. Uroki Ubuntu 24.04 LTS. Gdy już wszystkie znaki na niebie i ziemi wskazywały, że powinno działać, przyszła pora na dodanie użytkownika.

Tu nastąpiło moje lekkie zdziwienie, bo GoToSocial nie oferuje żadnego panelu, jedynie API. Użytkowników zakłada się z wiersza poleceń. Nieco dziwny wybór i raczej nie przysporzy popularności rozwiązaniu, w każdym razie nie poza grupą geeków. Kolejną konsekwencją jest konieczność połączenia się jakimś klientem, bo nie ma interfejsu WWW.

Czyli kolejny problem, bo okazało się, że nie mam dostępu do IPv6 z domu. Ani korzystając z internetu w domu od ISP, ani na telefonie, po wyłączeniu WiFi. To ostatnie mnie zdziwiło, byłem przekonany, że GSM to głównie IPv6. Na szczęście jest Pinafore, czyli klient dostępny w przeglądarce. Do tego tunel SSH do VPSa z IPv6[1], rozwiązywanie nazw DNS po socks proxy i… mogłem zobaczyć swoje konto i napisać coś.

Niektórym to może wystarczyć, jednak idea jest nieco inna. Powinna być możliwa interakcja z innymi instancjami. Wyszukałem jakieś konto w Pinafore, wybrałem follow, powtórzyłem dla kilku innych i… żadnego efektu. Informacja o oczekiwaniu na zatwierdzenie. Tylko te konta nie wymagały zatwierdzania. Sprawdziłem na swoim podstawowym koncie, na którym dla odmiany wymagam zatwierdzenia obserwacji. Ten sam efekt – pokazywało, że czeka na zgodę, ale nie dostałem zapytania o zgodę. No i nie mogłem z podstawowego konta wyszukać konta na testowej instancji. Czyli coś nie działa.

Diagnostyka tego zajęła sporo czasu, usłyszałem, że z IPv6-only bywają problemy, dostałem niepocieszające opisy problemów z GoToSocial i forwardowaniem portów przy NAT i w zasadzie już miałem stwierdzić, że gdzieś zrobiłem błąd, gdy skutecznie zaobserwowałem konto na instancji, która miała tylko adres IPv4 i korzystała z GoToSocial. Natomiast konta na serwerach Mastodon pozostawały niedostępne. Także na tych, które miały tylko IPv4.

Ostatecznie znalazłem instancję Mastodona, posiadającą zarówno adres IPv4 jak i IPv6, gdzie mogłem normalnie obserwować konta[2]. Dostrzegłem też w gąszczu logów błędy 503 przy próbach interakcji z innymi instancjami (subskrybcji). Czyli jakiś problem z kompatybilnością softów GoToSocial i Mastodon, nie u mnie z konfiguracją.

Jak już było wiadomo czego szukać, to ustaliłem, że z Mastodon v4.8.0-alpha.1 działa (dual stack), za to nie działa z v4.8.0-nightly.2026-08-27 (też dual stack) ani v4.7.0 (wyłącznie IPv4). Z kronikarskiego obowiązku, używana przeze mnie wersja to 0.22.1+git-fdff42b.

Co dalej? Pewnie nic. Może jeszcze coś mi przyjdzie do głowy, zasobów na VPS nie potrzebuję, więc zabawek nie zbieram. Przy okazji obserwacja: wymagania podawane przez dokumentację GoToSocial wyglądają na zawyżone, ale może to być kwestia obliczania pod ilość userów i interakcji zewnętrznych. Do samego postawienia opisanego setupu wystarczy spokojnie 0,5 GB RAM, na Ubuntu.

Natomiast w kwestii rozważań o selfhostingu, własnej instancji itp. – wygląda, że rozwiązanie nie robi i ciężko stwierdzić dokładnie, dlaczego. Kolejna lekcja to konieczność posiadania adresu IPv4, co skreśla mikrusa. Może być ciężko podłączyć się do instancji bez takiego adresu. Teoretycznie rozwiązaniem mógłby być Cloudflare, ale na takie eksperymenty zupełnie mi odeszła ochota, skoro nie działa zasadnicza część.

UPDATE: Trochę mi to nie dawało spokoju, więc sprawdziłem większą ilość serwerów. Nie wszystko działa, ale coś tam działa. Problem jest chyba tylko z serwerami Mastodon, ale niestety są to duże instancje, co przekreśla sens rozwiązania. Posty z nich widzę, profile widzę, ale nie mogę obserwować kont.

Nieco rozrywki/stan oprogramowania. Mój GoToSocial obecnie przedstawia się home to 0 users who have written 2 posts; peered with 29 other instances. Off by one?
Przy 11 obserwowanych.

[1] Zupełnym przypadkiem tego samego, na którym działa serwer GoToSocial, ale to bez znaczenia.
[2] Popularne Dziesiony. Szacun dla administratorów.

Optymalizacja strony

Kolejny wpis, który przeleżał wiele czasu jako szkic. Nie znalazłem na niego czasu, a teraz sprawdziłem i dobrze się zestarzał, więc opublikuję to, co mam, choć nie pociągnąłem do końca tematu, którym jest optymalizacja stron WWW, tym razem bardziej od strony serwera, niż WordPressa, o którym wtedy napisałem.

Na początek polecam wpis Yzoji o optymalizacji bloga. I komentarze do niego. Tak, wpis jest sprzed trzech lat. Tak, jest aktualny, a wszystko co tu znajdziesz powstało właśnie wtedy. Raczej postaram się napisać uzupełnienie, niż powtarzać rady z tamtego wpisu.

Efekty

Nie mam niestety porównania sprzed wprowadzania zmian, ale żeby było wiadomo o czym rozmawiamy. Efekty optymalizacji strony bloga, wg PageSpeed Insights, przedstawiają się następująco:

Wynik optymalizacji strony wg PageSpeed dla desktop - performance 100%
Wynik dla desktop
Wynik optymalizacji strony wg PageSpeed wynik dla mobile - performance 9%
Wynik dla mobile

Kompresja

Na przyspieszenie działania bloga pomogło zmniejszenie poziomu kompresji w nginx. Tak, dobrze czytacie, zmniejszenie, nie zwiększenie. Dlaczego? Otóż tekst kompresuje się dobrze tak czy inaczej. A różnice w szybkości działania kompresji gzip są znaczne. Czyli mamy mininalnie większą ilość przesyłanych danych, ale odpowiedź jest wysyłana znacznie szybciej! Być może to kwestia relatywnie słabego VPSa, ale skoro nie widać różnicy, po co przepłacać? W każdym razie w konfiguracji nginx mam:

gzip_comp_level 1;

Lazy loading

Kolejną rzeczą, która przyspieszyła działanie tego bloga było wyłączenie lazy loading. Było o tym u Yzoji, ale warto powtórzyć, bo znowu, jest to nieintuicyjne. W dodatku wszyscy mantrują, że włączenie lazy loadingu jest dobre dla szybkości ładowania. No i teoretycznie mają rację. Ale nie jest to prawdą na stronach, gdzie ilość załączanych grafik jest niewielka. Więc jak mam jedną czy w porywach dwie skromne grafiki na wpis, to lazy loading tylko spowolni ładowanie. Gdyby grafik było więcej lub były większe – pewnie włączenie lazy loadingu mógłoby pomagać.

Google

Wyłączenie zabawek Google. Firma ta prezentuje pewną dwumyślność. Z jednej strony chce, by strona działała szybko. Z drugiej strony, sama dostarcza rozwiązania, które fatalnie wpływają na wydajność strony i stwarzają problemy w ich własnym scoringu! Google Analytics – wydajnościowe zło. Fonty Google – kolejne wydajnościowe zło. Google AdSense też drastycznie pogorszy szybkość działania strony.

Rozwiązanie, jeśli nie chcemy całkiem pozbywać się Google? W przypadku AdSense można zrezygnować z wyświetlania reklam wszędzie i ograniczyć ich obecność do wpisów, na których jest największy ruch. Taki kompromis – strony z reklamami będą ładować się dłużej, ale większość stron będzie działać szybko. Oczywiście wiąże się to z rezygnacją z reklam na głównej. Nieco upierdliwe, bo oznacza to ręczne zarządzanie kodem JS odpowiedzialnym za wyświetlanie reklam na poziomie konkretnych wpisów, ale dla mnie OK. Zamiast Google Analytics polecam Matomo. Z fontów Google zrezygnowałem, zamiast tego pewnie można serwować je lokalnie.

Klucz RSA

Kolejna nieoczywista sprawa – rozmiar klucza wykorzystywanego przy SSL/TLS. Miałem podejście security is our priority i klucz RSA o długości 4096 bitów. Tyle tylko, że póki co 2048 bity są także uznawane za bezpieczne. No i na tym blogu nie ma nic wrażliwego. Najbardziej wrażliwe jest hasło, które przesyłam przy logowaniu, więc zmniejszyłem rozmiar klucza i… Pomogło to skrócić czas nawiązywania połączenia z serwerem. Znowu, może kwestia stosunkowo słabego VPSa. Przy tej okazji polecę jeszcze wpis o tym jak zrobić sobie certyfikat SSL/TLS z oceną A+ na nginx.

Jak widać, optymalizacja stron WWW nie jest oczywista i warto do tematu podejść kompleksowo.

Pomigracyjnie

W poprzednim wpisie pisałem o planowanej migracji na Oracle Cloud. Jak widać blog stoi już w nowej lokalizacji, więc operacja jest zakończona i mogę napisać kilka słów z perspektywy.

Migracja

Poszło niemal bezproblemowo. Backup w zasadzie zadziałał. Był problem z detalami typu lista zainstalowanych pakietów i crony. W sumie nieistotne i/lub poprawione. Xpil opisał swoją migrację VPSa i po tej lekturze miałem silne postanowienie zamknięcia wszystkiego w kontenerach LXC. To nieco wydłużyło proces migracji i dodało trochę zadań. Co prawda nadal nie jest to taka separacja jak w dockerach czyli per usługa, ale mariadb + nginx + całe WWW w osobnym VPSie też jest OK.

Konieczne było lekkie przemeblowanie. Musiałem rozdzielić skrypty cron do właściwych kontenerów. Okazało się też, że wynik działania jednego kontenera (Planeta Joggera) musi trafić nie do hypervisora, tylko do innego kontenera, a ten nie ma dostępu. Skrypt w cronie na hypervisorze załatwił sprawę.
Podobnie niezbyt elegancko rozwiązany jest backup bazy danych. Dump robię teraz w LXC, a następnie cały kontener jest backupowany. W ten sposób zawartość bazy jest zdublowana. Mam pomysł jak to rozwiązać, nie wiem, czy potrzebuję. Tyle o samej migracji, a efekty i hosting?

Efekty

Przede wszystkim jest szybciej, przynajmniej wg GTmetrix. Niestety nie zrobiłem testu tuż przed migracją i od razu po niej. Mam tylko ten link z twardymi danymi, ale w międzyczasie się poprawiło, więc polegam głównie na pamięci. Ale tak dobrze to nigdy nie było:

Blog GTmetrix w Oracle Cloud
GTmetrix w Oracle Cloud

Hosting

Pewnie w sporej części to kwestia przejścia z jednego VPSa na dwa, w dodatku z widocznymi dwoma rdzeniami w systemie. W Arubacloud było:

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 79
model name      : Intel(R) Xeon(R) CPU E5-2650L v4 @ 1.70GHz
stepping        : 1
microcode       : 0xb000038
cpu MHz         : 1699.999
cache size      : 35840 KB
physical id     : 0
siblings        : 1
core id         : 0
cpu cores       : 1
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts nopl tsc_reliable nonstop_tsc cpuid pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx hypervisor lahf_lm 3dnowprefetch pti arat
bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit
bogomips        : 3399.99
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual

Teraz jest (pojedynczy rdzeń):

processor       : 1
vendor_id       : AuthenticAMD
cpu family      : 23
model           : 1
model name      : AMD EPYC 7551 32-Core Processor
stepping        : 2
microcode       : 0x1000065
cpu MHz         : 1996.249
cache size      : 512 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 1
apicid          : 1
initial apicid  : 1
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm rep_good nopl cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy svm cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext perfctr_core ssbd ibpb vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 rdseed adx smap clflushopt sha_ni xsaveopt xsavec xgetbv1 xsaves clzero xsaveerptr virt_ssbd arat npt nrip_save arch_capabilities
bugs            : sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass
bogomips        : 3992.49
TLB size        : 1024 4K pages
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual

Blog zawsze dominował, jeśli chodzi o obciążenie, ale teraz ma całe zasoby dla siebie. Z drugiej strony bieżący VPS ma sporo wolniejszy dysk (3000 IOPS, 24 MB/s). Można tym jakoś sterować, ale zakładałem na domyślnych wartościach. No i nie widzę potrzeby zmiany.

Wady

Żeby nie było, że wszystko jest fajnie – port 25 TCP w Oracle Cloud jest zablokowany na twardo, w obie strony. Czyli ani maila nie przyjmę, ani nie wyślę. Znalazłem, że trzeba pisać do supportu o odblokowanie. Napisałem i zobaczymy. O ile do monitoringu poczta nie jest mi potrzebna, bo powiadomienia mogę wysyłać Telegramem, to przy blogu jest to jakby kluczowe. Potwierdzanie subskrybcji komentarzy itp. Z drugiej strony widzę, że nie było to jakoś mocno wykorzystywane… Zobaczę co odpowiedzą i wtedy pomyślę, co dalej.

Ogólnie sporo rzeczy w Oracle Cloud jest załatwianych przez support. Ustawienie PTR – support (działa!). Inny obraz dysku dla arm64 – support (tak powiedzieli na czacie, odpuściłem).

UPDATE: Port 25 nie został odblokowany, bo free tier. Nie jest to duży problem – wystarczy skonfigurować SMTP relay u któregoś z dostawców.