Chcel som migrovať z Nginx na Caddy

Do nedávna som s potešením používal Nginx ako reverzný proxy server. S fungovaním som bol veľmi spokojný. V mojom predošlom blogovom článku zistíš, prečo som chcel vymeniť nginx za caddy. Okrem iného, základné zručnosti s Nginx mám, tak prečo neskúsiť niečo nové a popri tom sa voľačo naučiť. V tomto blogu sa dozvieš ako som chcel prejsť z Nginx na Caddy.

Na caddy som aj skutočne prešiel a zdalo sa že všetko fungovalo, ale v používaní mi bránila vysoká odozva na wordpress weboch. Zatiaľ neviem čo vysokú odozvu spôsobuje (resp. viem), ale je to dosť problém, keď klient musí čakať na načítanie webu 5-7 sekúnd. Ďalšie podstránky sa už otvárali rýchlejšie radovo v stovkách milisekúnd čo je kvázi štandard. V ďalšej časti blogu popisujem postup migrácie resp. inštaláciu caddy. Nedovolím si napísať, že problém je v caddy, pretože nie wordpress weby fungujú veľmi rýchlo. problém môže byť na strane wordpress, alebo z mojej strany, niekde v konfigurácii. Ale takto to fungovať určite nemôže (pozri vývojársky nástroj vo Firefoxe (všimni si červené rámčeky)).

Obsah

Niečo o Caddy

Podľa oficiálneho webu je caddy výkonný open source webový server pripravený na podnikanie s automatickým HTTPS napísaným v jazyku Go. Hlavné vlastnosti caddy 2 (prebrané z github).

  • Easy configuration with the Caddyfile
  • Powerful configuration with its native JSON config
  • Dynamic configuration with the JSON API
  • Config adapters if you don’t like JSON
  • Automatic HTTPS by default
    • ZeroSSL and Let’s Encrypt for public names
    • Fully-managed local CA for internal names & IPs
    • Can coordinate with other Caddy instances in a cluster
    • Multi-issuer fallback
  • Stays up when other servers go down due to TLS/OCSP/certificate-related issues
  • Production-ready after serving trillions of requests and managing millions of TLS certificates
  • Scales to hundreds of thousands of sites as proven in production
  • HTTP/1.1, HTTP/2, and HTTP/3 all supported by default
  • Highly extensible modular architecture lets Caddy do anything without bloat
  • Runs anywhere with no external dependencies (not even libc)
  • Written in Go, a language with higher memory safety guarantees than other servers
  • Actually fun to use
  • So much more to discover

Caddy server bude postavený na linuxovom kontejnery LXC debian-12-standard_12.0-1_amd64. Inštalácia takého kontajnere zaberie cez web rozhranie Proxmoxu asi 2-3 minúty (cez web shell asi 10-15 sekund (pokiaľ máš pripravený skript)). Ako obvykle LXC je nasadený v DMZ sieti oddelený od LAN.

V mojom konkretnom prípade som to riešil tak, že pôvodný reverzný proxy server je stále v prevádzke. Nový caddy 2 server som dočasne postavil na novej lokálnej IP adrese, kde som ho konfiguroval, resp. testoval. V tomto prípade je potrebné nastaviť firewall tak aby ma nič neblokovalo. Mne sa napr. stalo to, že po inštalácii mi v LXC nefungoval internet. Trvalo mi niekoľko minút kým som sa dopracoval k tomu, že novu IP adresu v DMZ musím pridať do aliasu pre servery (po ukončení testovania je dobré túto IP adresu z aliasu odstrániť).

Lokálna IP adresa pre caddy server bude 192.168.20.20

Nepovinné nastavenia

Základné procedúry, ktoré vykonám po každej novej inštalácii LXC. Tieto úkony robim ešte cez web shell Proxmoxu. Po aktualizácii nastavím lokalizáciu a časové pásmo. Vytvorím užívateľa a pridám ho do skupiny sudo. Často zvyknem používať MC, takže ho tiež nainštalujem.

pct enter <ID-LXC>
apt update  && apt upgrade -y
localectl set-locale LANG=sk_SK.UTF-8 && localectl set-locale LANG=en_US.UTF-8
timedatectl set-timezone Europe/Bratislava
apt install sudo -y && adduser <user_name> && usermod -aG sudo <user_name>
apt install mc -y
exit

Ďalej odporúčam namiesto prihlasovania sa pomocu SSH použiť ssh-key a nie heslo. Čiže na server pošlem id_rsa.pub a po zadaní správneho hesla sa môžem druhým príkazom prihlásiť.

ssh-copy-id 192.168.20.20
ssh <user_name>@192.168.20.20

Niekto zvykne používať na prihlasovanie netradičný port, čiže v LXC sa to robi následovne (samozrejme zakážeme prihlasovanie roota).

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
sudo sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/#Port 22/Port 3388/' /etc/ssh/sshd_config
sudo systemctl mask ssh.socket
sudo systemctl mask sshd.socket
sudo systemctl disable sshd
sudo systemctl enable ssh
sudo systemctl restart ssh.service

Teraz sa už na server môžem prihlasovať pomocou neštandardného portu a bez hesla, čo je omnoho rýchlejšie a bezpečnejšie.

ssh <user_name>@192.168.20.20 -p 3388

Caddy

Caddy sa v súčasnosti štandardne dodáva ako binárka, alebo balik pre OS linux založené na Debian, Red Hat, Arch, alebo platformu Docker. Distribuje sa len s dvoma modulmi a to http a tls. Ak potrebujeme aby caddy fungoval s nejakým ďalším modulom, tak máme 2 možnosti. V mojom prípade potrebujem caddy s cloudflare DNS modulom (ktorý bude riešiť výzvu DNS-01). Podľa komunitnej podpory môžeme postupovať takto.

xCaddy

Nám nebude stačiť nainštalovať caddy z repozitárov (napr. v debiane pomocou apt), ale my potrebujeme kvázi skompilovať caddy s cloudflare pluginom. Nástroj na kompiláciu takýchto binariek sa volá xcaddy. Najprv však nainštalujeme jazyk GO (resp. GoLang), pretože je potrebný pre kompiláciu caddy. Stiahneme si poslednú ver. jazyka GO.

wget https://go.dev/dl/go1.21.0.linux-amd64.tar.gz

Ak nám zostali nejaké pozostatky z predošlej verzie GO, tak to zo systému vymažeme a novo stiahnutý balík rozbalíme do príslušného adresára. Nasledne pridáme PATH /usr/local/go/bin do premennej prostredia a skontrolujeme verziu GO

sudo rm -rf /usr/local/go && tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
go version
go version go1.21.0 linux/amd64

Teraz môžeme inštalovať xcaddy (ja som v LXC nemal nainštalovaný curl, tak ešte som ho doinštaloval (to je prvý príkaz)).

sudo apt install curl
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-xcaddy-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/xcaddy/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-xcaddy.list
sudo apt update
sudo apt install xcaddy
xcaddy version
v0.3.5 h1:XyC3clncb2Q3gTQC6hOJerRt3FS9+vAljW1f8jlryZA=

Teraz nám nebráni nič v kompilácii caddy s pluginom, ktorý potrebujeme. V mojom prípade pôjde o mudul DNS cloudflare.

xcaddy build --with github.com/caddy-dns/cloudflare

Ak požadujeme zahrnúť do caddy viac pluginov, tak použijeme viac sekvencii --with. Do kompilácie bude zahrnutá najnovšia ver. caddy. Kompilácia bude chvíľu trvať, ale potom máme hotový caddy na použitie.

sudo mv caddy /usr/bin/
caddy version
v2.7.4 h1:J8nisjdOxnYHXlorUKXY75Gr6iBfudfoGhrJ8t7/flI=

Bolo by dobré aby caddy bežal ako systémová služba, preto odporúčam vytvoriť systemd skript, ktorý sa o spustenie, reload a zastavenie služby postará. Najprv vytvoríme skupinu a užívateľa caddy

sudo groupadd --system caddy
sudo useradd --system \
    --gid caddy \
    --create-home \
    --home-dir /var/lib/caddy \
    --shell /usr/sbin/nologin \
    --comment "Caddy web server" \
    caddy

sudo chown root:root /usr/bin/caddy
sudo chmod 755 /usr/bin/caddy

sudo nano /etc/systemd/system/caddy.service

Takto bude vyzerať systemd skript pre štart, stop, status, prip. reload služby.

# caddy.service
#
# For using Caddy with a config file.
#
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
#
# See https://caddyserver.com/docs/install for instructions.
#
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# `caddy run` command or use the caddy-api.service file instead.

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

sudo mkdir /etc/caddy/
sudo chown -R root:caddy /etc/caddy

Caddyfile

Teraz už môžeme vytvoriť Caddyfile. V mojom prípade sa bude jednať len o nastavenie pre reverzný proxy server. Toto je základné nastavenie v ktorom povieme serveru caddy aby adresu v url bez www presmeroval na adresu s www. V ďalších blokoch bude caddy hľadať adresu na backendovej IP adrese (porte) a doména (vrátane wildcard) bude opatrená Let’s Encrypt certifikátom. Následujúci caddyfile ukazuje konfiguráciu pre jednu doménu. Ak máme domén viac, tak pridáme ďalšie bloky.

sudo nano /etc/caddy/Caddyfile
example.com {
    redir https://www.example.com{uri}
}
 
www.example.com {
    tls {
        dns cloudflare <CLOUDFLARE_API_TOKEN>
    }
    reverse_proxy 192.168.20.11:80
}
 
*.example.com {
    tls {
        dns cloudflare <CLOUDFLARE_API_TOKEN>
    }
    reverse_proxy 192.168.20.11:80
}

CLOUDFLARE_API_TOKEN nie je Global Api key, ale vygenerovaný API token. Tento API token si vytvorime pomocou návodu ako je popísané napr. na githube. Upozorňujem, že ak tam zadáme Global API key, tak nám generovanie certifikátov nebude fungovať.

sudo systemctl daemon-reload
sudo systemctl enable caddy
sudo systemctl start caddy

Caddy povolíme a spustíme ho ako službu. Nasledujúce príkazy budú vedieť skontrolovať či služba beží, resp. načíta službu (bez prestoja) po zmene konfigurácie, alebo službu zastaví.

sudo systemctl status caddy
sudo systemctl reload caddy
sudo systemctl stop caddy

Záver

Server caddy 2, funguje automaticky s HTTP/3 a nie je potrebné nič nastavovať. Pre HTTP/3 je potrebné zabezpečiť (a to je veľmi dôležite), aby bol protokol v NAT nastavený okrem TCP aj na UDP.

Konfiguračný súbor caddyfile si môžeme obohatiť o rôzné nastavenia ako napr. lógovanie, debug, pridanie emailu pre komunikáciu s CA Let’s Encrypt atď. Možností ako nastaviť caddyfile je mnoho, chce to len testovať a sledovať ako sa caddy správa.

V každom prípade tento článok nie je kompletný návod a tiež napr. nerieši zabezpečenie servera firewallom. Čo sa týka firewallu, tak základné nastavenie pre webové servery hovorí „otvor port 80 http a 443 https„. Pokojne sa na to môže použiť UFW. Nezabúdať na SSH port (v našom prípade 3388), lebo inak sa odstrihneme od SSH.

Leave a Reply

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *