Skip to content

Mailserver mx.studio60.cz

⚠️ NEZAMĚŇOVAT s s60-mail. s60-mail je kontejner (NestJS + BullMQ, port 3010) běžící na hubu a produkci, který odesílá transakční maily přes Resend. Tohle je samostatný stroj — plnohodnotný mailserver pro firemní poštu. Viz services/mail/INDEX.md pro tu druhou věc.

Owner stroje infra
Owner monitoringu sentinel (rozhodl Libor 2026-08-26)
Stack mailcow 2026-07b, 18 kontejnerů, Hetzner CX33
Veřejná IP 178.104.15.77 ⚠️ (dřív cortex — viz níž)
Tailscale 100.121.32.32, tag:postmaster, DNS postmaster (HostName stroje je mail)
Compose /opt/mailcow-dockerized
Runbook (infra) s60-infra/docs/runbooks/mailcow-mailserver.md

🔴 Kritičnost: HIGH

Od 2026-08-25 tudy chodí příchozí pošta domén aetv.cz, alteredu.cz a byznys-partak.cz (MX 10 mx.studio60.cz, ověřeno reálnou poštou: spf/dkim/dmarc pass). Výpadek není jen nedostupný webmail — odesílatelé opakují doručení běžně 24–72 h a pak zprávu vzdají, takže delší výpadek znamená skutečně ztracenou poštu, ne odloženou. Alerty eskalovat i v noci.

Odesílání jde přes Amazon SES relay (Hetzner blokuje odchozí 25 i 465), příjem je vlastní MX.

Monitoring (sentinel)

scripts/monitoring/mail-monitor.py — cron */10, SSH read-only ze sentinelu, Telegram + denní mail digest, cooldown 30 min.

kontrola práh proč
postfix fronta >20 zpráv, nebo cokoli starší 60 min nejdůležitější — „běží, ale nedoručuje"
relay chyby na SES jakýkoli deferred/bounced/SASL za 15 min SASL = neplatné SES credentials
počet kontejnerů ≠ 18 po zkušební obnově zůstal watchdog-mailcow Exited a nic to nenahlásilo
stáří zálohy >26 h od posledního hotovo: cron 02:30 denně
Storage Box reálný zápis, ne jen mountpoint sshfs umí viset připojený a nezapisovat
disk ≥80 % vmail poroste s migrací z Gmailu

Kuma monitory (95–98): TCP :25, :587, :993 přes Tailscale IP + HTTP webmail.studio60.cz s hlídáním expirace certifikátu.

Proč porty přes Tailscale a ne přes veřejnou IP

mailcow netfilter při opakovaných neúspěšných přihlášeních zahodí z dané IP úplně všechno — včetně HTTPS a ICMP. Vypadá to přesně jako výpadek stroje a v nginx logu po oběti nezůstane stopa. Tailnet (100.64.0.0/10) je ve whitelistu, takže sondy odtud jsou v bezpečí.

Kontrola banu (API na aktivní bany neodpovídá, vrací konfiguraci):

nft list ruleset | grep <IP>
redis-cli HGETALL F2B_ACTIVE_BANS

⚠️ Past: health check přes API nefunguje

GET /api/v1/get/domain/all vrací bez API klíče HTTP 200 s prázdným tělem (ověřeno 2026-08-26). Jako health check je tedy bezcenný — hlídal by kód, který o zdraví služby nevypovídá. V monitoringu se schválně nepoužívá.

Pozn.: volání na 127.0.0.1 z hosta Docker přepíše na gateway bridge (172.22.1.1) a API ho odmítne — volat přes Tailscale IP i lokálně: --resolve mx.studio60.cz:443:100.121.32.32.

⚠️ Veřejná IP byla dřív cortex

178.104.15.77 patřila zaniklému cortexu. Po jeho vyřazení ji Hetzner přiřadil tomuhle stroji, čímž se na něj tiše přenesly přístupy cortexu — pg_hba na všechny databáze, UFW 5432/6432 na pg-alfě, hub UFW 443. Odstraněno 2026-08-26. Viz [[feedback_ip_reuse_stale_allowlists]].

Zatím nehlídáno

Prahy účtu SES (sesv2.get_account(): SendQuota, EnforcementStatus, ProductionAccessEnabled). Credentials jsou na cerebru (/root/secrets/aws-ses.env, správcovský klíč s explicitním DENY na odesílání). SES shodí účet bez varování při bounce rate ≥ 4 % nebo complaint ≥ 0,08 %; při objemu jednotek mailů měsíčně stačí pár odražených zpráv. K doplnění.