Tani VPS od zera: nginx, Docker i certyfikat SSL krok po kroku
Pierwszy login, użytkownik z sudo, klucze SSH, zapora ufw, nginx, Docker i certyfikat Let's Encrypt. Komendy dla Ubuntu 24.04 i Debiana 12/13 z objaśnieniami.
Redakcja serwisu Dealownia · ceny i fakty ze stron dostawców, jak sprawdzamy
VPS, na który logujesz się kluczem SSH jako zwykły użytkownik z sudo, z zaporą wpuszczającą tylko SSH i ruch WWW, z nginx serwującym stronę statyczną przez HTTPS i z Dockerem gotowym na narzędzia (analityka, monitoring, zbieranie błędów) – od czystego systemu, krok po kroku. Oprogramowanie nic nie kosztuje – płacisz tylko za VPS i domenę. Układ jest prosty: nginx na hoście, narzędzia w kontenerach, certyfikaty z Let’s Encrypt odnawiane automatycznie. Komendy działają na Ubuntu 24.04 LTS oraz na Debianie 12 i 13 – tam, gdzie systemy się różnią, piszemy to wprost. Na ten poradnik powołują się pozostałe poradniki o VPS-ie („serwer przygotowany jak w poradniku od zera”).
Czego potrzebujesz
- VPS z Ubuntu 24.04 LTS albo Debianem 12 lub 13. Na stronę statyczną wystarczy 1 vCPU, 1 GB RAM i 10–20 GB dysku. Jeśli planujesz Docker z kilkoma narzędziami (Umami, Uptime Kuma, GlitchTip z bazą Postgres), weź co najmniej 2 GB RAM, a wygodniej 4 GB.
- Domenę (w przykładach
example.pl) z rekordem A (i AAAA, jeśli masz IPv6) wskazującym adres serwera. - Komputer z klientem OpenSSH (Linux, macOS, Windows 10/11 mają go wbudowanego).
- Adres IP i dane pierwszego logowania z panelu dostawcy.
Pełne porównanie planów znajdziesz w rankingu VPS, a darmowe plany na stronie darmowe.
Krok 1. Pierwsze logowanie i aktualizacja systemu
Zaloguj się kontem podanym przez dostawcę – zwykle to root, na Ubuntu czasem ubuntu, na Debianie czasem debian:
Debian: obrazy Debiana często nie mają sudo. Jeśli sudo -V kończy się błędem „command not found”, zainstaluj je raz jako root (na Ubuntu ten krok pomiń):
Zaktualizuj system i ustaw strefę czasową (logi i zadania cron będą wtedy w polskim czasie):
Jeśli aktualizacja zainstalowała nowe jądro, istnieje plik /var/run/reboot-required – wtedy wykonaj sudo reboot i zaloguj się ponownie.
Krok 2. Własny użytkownik z sudo
Praca na koncie root sprawia, że każda pomyłka ma pełne uprawnienia. Załóż zwykłego użytkownika i daj mu sudo:
adduser zapyta o hasło – będzie potrzebne przy sudo, nie do logowania przez SSH. Grupa sudo istnieje w Ubuntu i w Debianie, więc te dwie komendy są takie same na obu systemach.
Krok 3. Klucz SSH
Na swoim komputerze wygeneruj klucz ed25519 (dokumentacja Ubuntu poleca ten algorytm) i skopiuj go na serwer:
ssh-copy-id loguje się na konto deploy hasłem. Jeśli dostawca wyłączył logowanie hasłem (część obrazów chmurowych tak ma) i klucz dodałeś w panelu przy zakładaniu serwera, skopiuj go z konta, na które się logujesz – z pierwszej sesji na serwerze:
Na Windowsie ssh-copy-id nie ma, więc dopisz klucz ręcznie z pierwszej sesji na serwerze:
Teraz, w nowym oknie terminala, bez zamykania starej sesji, sprawdź logowanie:
Opcja -t przydziela terminal – bez niej sudo nie może zapytać o hasło i kończy się błędem. Podaj hasło z kroku 2. Dopiero gdy zobaczysz deploy i SUDO_OK, idź dalej. Stara sesja to Twoja droga powrotu, gdyby coś poszło źle.
Krok 4. Wyłączenie logowania hasłem i konta root
Ustawienia dopisz w osobnym pliku w sshd_config.d, żeby aktualizacja pakietu nie nadpisała Twoich zmian:
Nazwa zaczyna się od 00- celowo: sshd bierze pierwszą znalezioną wartość opcji, a wiele obrazów chmurowych ma plik 50-cloud-init.conf z PasswordAuthentication yes. Plik o nazwie 90-... zostałby po cichu zignorowany. Ostatnia komenda musi pokazać permitrootlogin no i passwordauthentication no.
Krok 5. Zapora ufw
Najpierw reguła dla SSH, potem włączenie zapory – w odwrotnej kolejności odetniesz sobie dostęp:
--force pomija pytanie o potwierdzenie, które ufw zadaje przy włączaniu przez SSH. Więcej o zaporze, fail2ban i automatycznych aktualizacjach jest w liście kontrolnej zabezpieczenia VPS.
Krok 6. nginx i strona statyczna
Utwórz plik /etc/nginx/sites-available/example.pl:
try_files z $uri/index.html obsługuje strony generowane w formacie katalogów (Astro, Hugo, Eleventy). Włącz konfigurację, usuń domyślną stronę i przeładuj nginx:
nginx -t sprawdza składnię przed przeładowaniem – rób to po każdej zmianie.
Krok 7. Certyfikat Let’s Encrypt
Certbot z wtyczką nginx sam dopisze konfigurację HTTPS i przekierowanie z HTTP:
Oficjalna instrukcja certbota poleca instalację przez snap (sudo snap install --classic certbot); pakiet z repozytorium Ubuntu albo Debiana też działa i instaluje timer systemd, który dwa razy dziennie sprawdza, czy trzeba odnowić certyfikat. Nie mieszaj obu instalacji. Certyfikat wildcard (*.example.pl) wymaga walidacji DNS-01 – to temat na osobny poradnik o certbocie.
Krok 8. Docker i Compose
Instalacja z oficjalnego repozytorium Dockera (wersja z repozytorium systemu bywa starsza i nie ma wtyczki compose). Docker ma osobne repozytoria dla Ubuntu i Debiana – poniższe komendy same wybierają właściwe na podstawie /etc/os-release:
Powinno się wyświetlić ubuntu noble, debian bookworm (Debian 12) albo debian trixie (Debian 13). Inny wynik oznacza system, którego ten poradnik nie obejmuje. Potem:
Ogranicz rozmiar logów kontenerów, bo domyślny sterownik json-file potrafi zapełnić dysk:
Wyloguj się i zaloguj ponownie, potem docker run --rm hello-world. Pamiętaj, że grupa docker daje w praktyce uprawnienia roota – dodawaj do niej tylko swoje konto.
Najczęstsze problemy
- Nie da się zalogować po zmianie SSH. Wróć do starej sesji (dlatego jej nie zamykasz) albo do konsoli w panelu dostawcy. Sprawdź
sudo sshd -T | grep -i pubkeyi uprawnienia:~/.sshmusi mieć 700,authorized_keys600, właścicielem musi być użytkownik, nie root. - Logowanie hasłem nadal działa. Twój plik ma dalszą kolejność niż
50-cloud-init.conf. Zmień nazwę na00-...i zrestartujssh. - Kontener z portem
-p 3000:3000jest dostępny z internetu mimo ufw. Docker dopisuje własne reguły iptables i według swojej dokumentacji opublikowane porty omijają ufw. Publikuj porty tylko na pętli zwrotnej:127.0.0.1:3000:3000, a na zewnątrz wystawiaj usługę przez nginx. - Certbot kończy się błędem
Timeout during connectalbounauthorized. Rekord A nie wskazuje jeszcze serwera (sprawdźdig +short example.pl) albo port 80 jest zamknięty w ufw lub w zaporze w panelu dostawcy. Walidacja HTTP-01 zawsze idzie przez port 80. - nginx zwraca 403. Brak
index.htmlw katalogu albo nginx (użytkownikwww-data) nie może czytać plików – sprawdźls -l /var/www/example.pli uprawnienia katalogów nadrzędnych.
Co dalej
Masz bazę, na której postawisz narzędzia: Umami zamiast Google Analytics, Uptime Kuma albo cały stack w jednym pliku compose. Zanim wrzucisz tam cokolwiek ważnego, przejdź listę kontrolną zabezpieczeń i ustaw kopie zapasowe.