Serwer VPS — pierwsze uruchomienie (faza 0)
Dokument prowadzi przez przygotowanie serwera Hostinger KVM 8 pod aplikację po migracji z Cloudflare (plan: docs/plans/migracja-vps-sqlite-coolify.md, pkt 4.13, 7 i „Faza 0”). Część serwerowa jest zautomatyzowana skryptem deploy/bootstrap-vps.sh; reszta to kliknięcia w hPanelu, Coolify i Cloudflare Zero Trust, opisane krok po kroku.
👤 Instrukcja krok po kroku
1. hPanel Hostingera (przed pierwszym logowaniem)
- System: Ubuntu 24.04 LTS (szablon czysty, bez preinstalowanego Coolify — instaluje go skrypt, dzięki czemu wersja i konfiguracja są powtarzalne).
- Klucz SSH: VPS → Settings → SSH keys → Add SSH key. Na swoim komputerze:
Wklej zawartość plikussh-keygen -t ed25519 -C "imie@acepark.pl"cat ~/.ssh/id_ed25519.pub
.pubi zaznacz instalację na tym VPS. Sprawdź:ssh root@<IP>wchodzi bez hasła. - Firewall hPanel (VPS → Firewall) — opcjonalny, warstwa dodatkowa: reguła
Accept TCP 22z Twojego adresu IP i nic więcej. Porty 80/443/8000 nie mogą być otwarte na świat, ale samego hPanela nie trzeba używać: skrypt zamyka je na maszynie regułą w łańcuchuDOCKER-USER(patrz „Firewall” niżej). Reguła hPanel z allowlistą IP ma sens tylko przy stałym adresie — przy dynamicznym odetnie Cię przy pierwszej zmianie IP. - Backupy: włącz dzienny backup VPS (dodatek do planu) — obejmie konfigurację Coolify, GlitchTip i wolumeny.
2. Skrypt bootstrap (jedno polecenie jako root)
ssh root@<IP>
apt-get install -y git
git clone --depth 1 --branch develop https://github.com/DMT-Softwares/Acepark_Rezerwacje.git /root/acepark
cd /root/acepark
DEPLOY_USER=deploy \
SSH_PUBLIC_KEY="ssh-ed25519 AAAA... imie@acepark.pl" \
ADMIN_IPS="<Twoje IP>" \
./deploy/bootstrap-vps.sh
Skrypt trwa 5–10 minut (instalator Coolify pobiera obrazy). Na końcu wypisuje dalsze kroki. Można go uruchamiać wielokrotnie — każdy krok sprawdza swój stan.
Co robi:
| Krok | Efekt |
|---|---|
| Pakiety | apt upgrade, ufw, fail2ban, unattended-upgrades, curl, git, jq, sqlite3, htop |
| Strefa czasu | host w UTC (kontenery też, TZ=UTC — cały kod dat używa date-fns-tz) |
Użytkownik deploy | sudo bez hasła, klucz z SSH_PUBLIC_KEY (ten sam klucz zostaje u roota — Coolify zarządza hostem przez SSH roota z własnym kluczem) |
sshd | tylko klucze, PermitRootLogin prohibit-password, 4 próby, keepalive |
ufw | deny incoming, allow outgoing, 22 tylko z ADMIN_IPS (bez listy: 22 z limitem prób) |
fail2ban | jail sshd: 5 prób / 10 min → ban na 1 h |
| Aktualizacje | automatyczne poprawki bezpieczeństwa, bez automatycznego restartu |
| Wolumeny | /data/acepark/{dev,qa,prod} i …/backups, właściciel uid 1000 (użytkownik node w obrazie aplikacji) |
| Coolify | oficjalny instalator (cdn.coollabs.io/coolify/install.sh) — instaluje Dockera i podnosi Coolify na localhost:8000; pomijany, gdy już działa |
cloudflared na hoście | tylko gdy podasz CLOUDFLARE_TUNNEL_TOKEN — usługa systemd; docelowo to ten tunel obsługuje cały ruch (konfiguracja w /etc/cloudflared/config.yml), nie kontener w Coolify — patrz docs/infrastruktura-vps.md |
3. Coolify — pierwsze logowanie i ustawienia
- Panel nie jest wystawiony na świat. Zaloguj się przez tunel SSH:
i otwórzssh -L 8000:localhost:8000 deploy@<IP>
http://localhost:8000. Załóż konto administratora (pierwsze konto jest właścicielem instancji). - Settings → Instance: nazwa
acepark-vps, 2FA dla konta administratora, Concurrent builds = 1 (build na tym samym hoście co produkcja, pkt 7). - Sources → GitHub App: utwórz aplikację GitHub dla organizacji
DMT-Softwaresz dostępem doAcepark_Rezerwacje(deploy na push, preview deployments). - Servers → localhost → Proxy: zostaw Traefik. Certyfikaty Let's Encrypt nie są potrzebne — TLS kończy się w Cloudflare (pkt 4.13).
4. Cloudflare Tunnel i Access
- Zero Trust → Networks → Tunnels → Create tunnel (
acepark-vps, typ Cloudflared). Skopiuj token. - W Coolify: Projects → acepark-infra → Add resource → Cloudflared (szablon usługi), wklej token jako sekret
TUNNEL_TOKEN, sieć: ta sama cocoolify-proxy. Deploy. - W tunelu dodaj hostname'y (Zero Trust tworzy rekordy CNAME sam):
coolify.acepark.pl→http://coolify:8000, polityka Access: SSO Google, tylko wskazane konta;dev.acepark.pl,qa.acepark.pl,qa-panel.acepark.pl,klient.acepark.pl,panel.acepark.pl→http://coolify-proxy:80(Access opcjonalnie dladev);glitchtip.acepark.plihc.acepark.pl→http://coolify-proxy:80, Access z bypassem dla/api/*(GlitchTip) i/ping/*(Healthchecks).
- Cloudflare → SSL/TLS: tryb Full (nie „Full (strict)”). Domeny w Coolify wpisuj jako
https://…— inaczej pętla przekierowań. - Od tej chwili panel Coolify jest dostępny pod
https://coolify.acepark.plza Access; tunel SSH z kroku 3 zostaje jako droga awaryjna.
5. GlitchTip i Healthchecks
- Add resource → GlitchTip (szablon): domena
https://glitchtip.acepark.pl, SMTP SendGrid (EMAIL_URL=smtp://apikey:<klucz>@smtp.sendgrid.net:587),GLITCHTIP_DOMAIN, rejestracja zamknięta. Projektaceparkz osobnymi środowiskami; DSN do zmiennych aplikacji w fazie 3. - Add resource → Healthchecks (szablon):
https://hc.acepark.pl, SMTP jak wyżej, projekt per środowisko;PING_KEYkażdego projektu trafi doHEALTHCHECKS_PING_URLkonteneracron(http://healthchecks-<uuid>:8000/ping/<PING_KEY>— siecią Dockera, patrzinfrastruktura-vps.md), klucz API doHEALTHCHECKS_API_KEY, aHEALTHCHECKS_API_URLto bazahttp://healthchecks-<uuid>:8000(dlanode dist/cron.js list --sync-healthchecks; przezhc.acepark.plAPI jest za Access).
6. Backupy poza hostem
- Cloudflare R2: bucket
acepark-backups, token API z dostępem tylko do tego bucketu. - Coolify: Settings → Backup (instance backup → S3/R2, codziennie) oraz backup bazy GlitchTip i Healthchecks (zasób → Backups → S3).
- Litestream dla
acepark.dbkonfigurowany w fazie 3 (Compose każdego środowiska), z tym samym bucketem i prefiksem per środowisko.
7. Lista kontrolna po bootstrapie
-
ssh deploy@<IP>działa,ssh root@<IP>działa kluczem, hasło odrzucane. -
sudo ufw statuspokazuje tylko port 22;sudo iptables -L DOCKER-USER -npokazujeRETURNdlaESTABLISHED,RELATEDiDROP. -
docker pspokazujecoolify,coolify-db,coolify-redis,coolify-proxy. -
https://coolify.acepark.plprzechodzi przez Access,http://<IP>:8000nie odpowiada. -
ls -la /data/acepark— trzy katalogi środowisk z właścicielem uid 1000. - GlitchTip i Healthchecks odpowiadają przez tunel; testowy ping
curl https://hc.acepark.pl/ping/<PING_KEY>/test?create=1tworzy check.
🛠 Dokumentacja techniczna
Dlaczego skrypt, a nie szablon „Coolify” z hPanelu
Szablon Hostingera instaluje Coolify na obrazie, którego wersji i ustawień nie kontrolujemy (użytkownik, firewall, sshd). Skrypt w repozytorium jest przeglądany jak kod, wersjonowany i powtarzalny — ten sam bootstrap zadziała na innym dostawcy, co było jednym z założeń wyboru jednego serwera (łatwa przeprowadzka po migracji).
Firewall: ufw, DOCKER-USER i hPanel
ufw chroni sam host (SSH). Docker wpina własne reguły iptables przed łańcuchem, którym rządzi ufw, więc port opublikowany przez kontener (80/443 Traefika, 8000 panelu Coolify) jest osiągalny z internetu mimo deny incoming.
Skrypt zamyka to na maszynie: wstawia do łańcucha DOCKER-USER regułę odrzucającą ruch przychodzący z interfejsu zewnętrznego (przepuszczając połączenia zestawione), a docker-firewall.service nakłada ją ponownie po każdym starcie Dockera — Docker przebudowuje swoje łańcuchy przy starcie i inaczej reguła by znikała. Weryfikacja: iptables -L DOCKER-USER -n pokazuje RETURN dla ESTABLISHED,RELATED i DROP poniżej.
Firewall hPanel jest wobec tego warstwą dodatkową, a nie warunkiem koniecznym. Ruch do aplikacji wchodzi wyłącznie tunelem, który jest połączeniem wychodzącym z serwera.
Dostęp roota
Coolify zarządza „localhost” przez SSH jako root z kluczem, który sam generuje i dopisuje do /root/.ssh/authorized_keys. Stąd PermitRootLogin prohibit-password zamiast no. Logowanie hasłem jest wyłączone globalnie.
Idempotencja
Każdy krok sprawdza stan: użytkownik tworzony tylko gdy nie istnieje, klucz dopisywany tylko gdy go nie ma, ufw --force reset odtwarza reguły od zera, instalator Coolify jest pomijany, gdy kontener coolify już działa, cloudflared instalowany tylko bez binarki. Ponowne uruchomienie po przerwanym kroku jest bezpieczne.
Co skrypt celowo pomija
- Konfigurację Coolify (konta, GitHub App, zasoby) — to stan w bazie Coolify, robiony przez UI lub API (
https://coolify.acepark.pl/api/v1, token z Keys & Tokens). - Tunel aplikacji — jako usługa w Coolify, żeby restart i logi były w jednym miejscu z resztą zasobów.
- Litestream i Compose środowisk — faza 3 planu (
Dockerfile,docker-compose.yml,litestream.yml).