Certbot fails renewal with http-01 challenge on NGINX: Connection refused

Apr 14 2019

The problem

This has been bothering me for more than half of a year. You might be unable to automatically renew certificates if the following conditions are true:

  • You're using the python-certbot-nginx plugin to install certificates and handle their renewal on your webserver.
  • You're using different location for acme-challenge than the actual folder inside installation root - this is most likely if you're using NGINX as a proxy for a different service.

During the renewal process you will most likely receive the following error:

Attempting to renew cert (example.com) from /etc/letsencrypt/renewal/example.com.conf produced an unexpected error: Failed authorization procedure. example.com (http-01): urn:ietf:params:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching https://www.example.com/.well-known/acme-challenge/1hDMJJfjSOPJENxVmuXdDiphrVlEgRGXfHWB7Z8: Connection refused

However testing the connection with curl or wget from any location predictably gives just a 404 error. To fix it, I had to delete the old certificate configuration and reinstall it with the certbot-nginx plugin each time. This would allow http-01 challenge to pass successfully.

After pulling my hair for a while and playing with the --dry-run option, I've finally noticed the following message:

Plugins selected: Authenticator webroot, Installer nginx

This is wrong. It should be:

Plugins selected: Authenticator nginx, Installer nginx

The reason for the failure appears to be the alternate acme-challenge folder location. Webroot authenticator doesn't handle it and it will attempt to verify using regular sub-folder in webroot.

The solution

Open /etc/cron.d/certbot file and add --nginx option to the renew command, the python-certbot-nginx should be adding it automatically but it doesn't.

Přátelské upozornění od Facebook

Apr 05 2019

S Facebookem obecně nerad sdílím jakékoliv informace v míře větší, než je minimum nutné pro fungování. Jednou z takových neposkytnutých informací bylo do nedávna moje telefonní číslo. Nicméně už objevili metodu, jak mě donutit prozradit jim ho:

Kamarád Facebook

A k čemu vlastně potřebuje Facebook tak přesně poznat, že jsem to skutečně já (a kde se nacházím)? To je vedlejší, je to prostě v zájmu veřejného blaha. Teď si určitě můžou být jisti, že mi nějaký hacker nezcizil účet :)

Cassandra Reaper

Mar 18 2019

Do WebMedea jsme letos zapojili nové datacentrum. Udržovat Cassandru synchronizovanou pro nás ale s jeho přidáním znamená lineární nárůst práce. Kontroly logů, zda některá tabulka či schéma neprošly opravou, už nejsou časově únosné. Opravy databáze jsme se proto rozhodli automatizovat. Při rešerši možných řešení Pepa objevil aplikaci Cassandra Reaper, jejíž popis nádherně plní všechny naše potřeby:

  • periodické spouštění oprav
  • segmentované běhy oprav
  • historie a výsledek jednotlivých běhů.

Po menších obtížích s konfigurací webového UI jsme ji úspěšně nasadili k testování v následujících týdnech.

Změna schéma WebMedea databáze

Jan 27 2019

WebMedea již eviduje přes miliardu odkazů mezi weby. Tato data v naší Cassandra databázi zabírají již přes 110 GB. Společně s rostoucím množstvím dat jsme narazili na neustále se zvyšující vytížení RAM, CPU a diskové IO našich serverů právě od Cassandry. Její požadavky se zdá, že nejde ukojit. To nás přivedlo k zamyšlení se nad naším současným datovým modelem. Zhodnotili jsme, že nám nezbývá nic jiného než upravit způsob, jakým WebMedea ukládá odkazy mezi weby.

Cassandra, stejně jako relační databáze, umožňuje ukládat jako primární klíč tabulky skupinu více sloupců. Takový primární klíč se u Cassandry nazývá kompozitní (Composite key) a rozlišuje se na dvě důležité části - oddílový (Partition key) a třídící klíč (Clustering key). Oddílový klíč říká Cassandře do jakých celků (oddílů) ukládat bloky dat - tyto oddíly jsou vytvářeny na základě hodnoty sloupců, které jsou součástí klíče a cílem je vyhnout se příliš malým (stovky záznamů) nebo naopak příliš velkým oddílům (stovky MB dat). Třídící klíč, jak můj pokus o překlad napovídá, pak slouží ke třídění dat v rámci jednoho oddílu.

Při ukládání odkazů ve WebMedea jsme preventivně rozdělili cílové domény odkazů na jednotlivé úrovně oddělené tečkou a v oddílovém klíči je vedeme jako samostatné sloupce. Ukazuje se nám ale, že to nestačí. Největší české weby jako Heuréka.cz a Nova.cz jsou schopny vytvářet v naší databázi oddíly do velikosti až několika GB. Jejich "mikrostránky" jako produktroku.cz pak nejsou daleko pozadu.

Abychom předešli tomuto problému upravujeme náš oddílový klíč aby obsahoval také údaje o datumu nalezení odkazu. Tato změna má navíc benefit v tom, že urychlí zobrazování nejnovějších odkazů na výstupu z WebMedea. Jak ale provést takový zásah do 110 GB dat, která jsou neustále upravována, rozšiřována a čtena našimi klienty?

Pro tento úkol jsme přidali do WebMedea dva nové servery, které sídlí v datacentru Wedosu v Hluboké nad Vltavou. Tyto servery na svých instancích Cassandry replikují pouze nově vytvořené databázové schéma a s ním i novou strukturu uložení odkazů. Původní formát odkazů je postupně překládán na nový persistentní službou. Tím se zvedá zátěž na naše servery v ostrém provozu jen minimálně, protože nemusí zapisovat novou strukturu dat. Paralelně k tomu upravujeme naši těžbu odkazů tak, aby ukládala do obou formátů naráz. Posledním krokem pak bude přepnutí schématu v klientských aplikacích a změna replikačního faktoru nového schématu, aby se nový formát dat rozšířil do celé sítě WebMedea.

Aktualizace Echo pro Bludit

Dec 19 2018

Bludit je super CMS systém pro blog, zápisník nebo i velmi jednoduché webové stránky. Nepotřebuje žádný databázový systém, vše ukládá do struktury textových souborů. Oslovil mě natolik, že jsem se stal sponzorem a vydávám pro něj sám grafickou šablonu, kterou jsem během pár posledních večerů opět aktualizoval. Ke stažení (a zkritizování) je dostupná (zatím ještě) na GitHub.

Teď jen najít chvíli a aktualizovat ji tady u sebe na blogu :)