SSD Nodes Learn Hosting plans →
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-28

Instalacja Discourse na VPS z Docker krok po kroku

Instrukcja instalacji Discourse na serwerze VPS przy użyciu oficjalnego skryptu launcher. Konfiguracja pliku app.yml, zarządzanie pamięcią RAM, swap oraz certyfikatami TLS.

Instalacja Discourse na VPS: jeden kontener, jeden plik konfiguracyjny

Aby zainstalować Discourse na serwerze VPS, należy uruchomić własny instalator projektu, odpowiedzieć na pytania krótkiego kreatora i poczekać na zakończenie budowania obrazu. Discourse jest dostarczany jako pojedynczy kontener Docker zawierający aplikację Rails, PostgreSQL, Redis oraz nginx. Wszystkie późniejsze zmiany wprowadza się w jednym pliku, /var/discourse/containers/app.yml, a każda modyfikacja wymaga przebudowania instancji.

Oficjalna metoda instalacji to discourse_docker: skrypt powłoki launcher oraz zestaw szablonów YAML. Discourse nie wspiera własnych plików Compose, a kontenera nie należy dzielić ręcznie. Jeśli użytkownik jest przyzwyczajony do uruchamiania usług na VPS za pomocą Docker Compose, należy spodziewać się innej struktury. W tym przypadku nie używa się docker compose up -d, a procesem wdrażania zarządza ./launcher rebuild app.

Wymagania wstępne dla Discourse

Cztery wymagania często sprawiają trudności i każde z nich musi zostać spełnione przed uzyskaniem dostępu do strony logowania.

  • Pamięć RAM. Jeden kontener uruchamia PostgreSQL, Redis, Sidekiq oraz serwer WWW Ruby. Proces budowania kompiluje zasoby i wymaga więcej pamięci niż działająca witryna.
  • Prawdziwa nazwa domeny. Dostarczona przykładowa konfiguracja jasno określa: "Discourse nie będzie działać z samym adresem IP".
  • Ścieżka poczty wychodzącej. Aktywacja konta, resetowanie haseł, zaproszenia administratora oraz podsumowania mailowe są wysyłane przez SMTP (simple mail transfer protocol).
  • Wolne porty 80 oraz 443 na hoście, chyba że celowo umieścisz Discourse za działającym już proxy.
ChartDiscourse published hardware requirements (official install docs, August 2026)
The data behind this chart
[
  {
    "label": "Documented minimum",
    "ram_gb": 1,
    "storage_gb": 10
  },
  {
    "label": "Documented recommended",
    "ram_gb": 2,
    "storage_gb": 20
  }
]

Oficjalna dokumentacja instalacji określa minimum na 1 GB pamięci RAM wraz ze swap oraz 10 GB miejsca na dysku, zalecając jednocześnie 2 GB pamięci RAM oraz 20 GB miejsca na dysku. Pierwszą wartość należy traktować jako niezbędną do zakończenia instalacji, a nie jako konfigurację docelową dla działającej społeczności. Różnica jest istotna, ponieważ szczytowe zapotrzebowanie na pamięć występuje podczas budowania, a nie obsługi ruchu.

Skierowanie domeny na serwer przed instalacją

Należy utworzyć rekord A dla używanej nazwy hosta, a następnie zweryfikować go z poziomu serwera.

dig +short forum.example.com
curl -4 -s https://ifconfig.co

Oba polecenia muszą zwrócić ten sam adres. Muszą być one zgodne, ponieważ kreator konfiguracji wykonuje test połączenia z nazwą hosta, a rekord wskazujący w inne miejsce spowoduje niepowodzenie tego testu. Rekord utworzony przed chwilą może być nadal w pamięci podręcznej, dlatego należy odczekać czas wygaśnięcia starego TTL (time to live), zamiast wymuszać działanie kreatora.

Należy teraz zdecydować, czy rekord będzie obsługiwany przez CDN. Rekord objęty proxy ukrywa adres serwera, co powoduje niepowodzenie żądania certyfikatu dla kontenera, ponieważ wyzwanie ACME (automatic certificate management environment) jest odbierane przez proxy, a nie przez Discourse. Podczas pierwszej instalacji rekord powinien pozostać bez włączonego proxy.

Uruchomienie oficjalnego instalatora

Jedno polecenie instaluje git, instaluje Docker za pomocą oficjalnego skryptu instalacyjnego, klonuje discourse_docker do /var/discourse oraz uruchamia kreator konfiguracji.

wget -qO- https://raw.githubusercontent.com/discourse/discourse_docker/main/install-discourse | sudo bash

Jeśli Docker jest już zainstalowany na serwerze i wymagana jest weryfikacja każdego kroku, należy wykonać te same czynności ręcznie.

sudo -s
git clone https://github.com/discourse/discourse_docker.git /var/discourse
cd /var/discourse
./discourse-setup

Polecenie należy uruchomić z uprawnieniami root. Uruchomienie przez zwykłego użytkownika powoduje natychmiastowe zatrzymanie discourse-setup z komunikatem This script must be run as root. Please sudo or log in as root first.. W przypadku braku zainstalowanego Dockera proces zatrzymuje się z komunikatem Docker is not installed. Please install Docker first., ponieważ ręczne klonowanie nie instaluje żadnych zależności.

O co pyta kreator konfiguracji i co zapisuje

Według stanu na sierpień 2026 discourse-setup jest lekką nakładką. Uruchamia discourse/setup-wizard:release jako kontener z dostępem do sieci hosta i zamontowanym gniazdem Docker, dzięki czemu kreator może przeprowadzić inspekcję maszyny, którą konfiguruje. Narzędzie pyta o nazwę hosta i adresy e-mail administratora, a następnie o dane serwera SMTP. Zapisuje plik containers/app.yml, a następnie przeprowadza przebudowę.

Przed rozpoczęciem warto poznać dwa zachowania systemu. Jeśli maszynie brakuje pamięci i nie posiada partycji swap, kreator przerywa pracę i proponuje jej utworzenie: nakładka tworzy wówczas plik /swapfile o rozmiarze 2 GB, dodaje go do /etc/fstab, ustawia vm.swappiness = 10 w /etc/sysctl.d/30-discourse-swap.conf i ponownie uruchamia kreatora. Po zakończeniu pracy kreator wyświetla Rebuilding app in 5 seconds (Ctrl+C to cancel)... i uruchamia ./launcher rebuild app na hoście. Budowa ta zajmuje kilka minut na małym VPS, przy czym pierwsza jest najwolniejsza, ponieważ wszystkie zasoby są kompilowane od zera.

./discourse-setup --help zawiera listę flag istotnych w przypadku wystąpienia problemów. --skip-rebuild zapisuje konfigurację bez budowania, a --skip-connection-test pomija testy DNS oraz portów. Używaj --skip-connection-test tylko wtedy, gdy znasz przyczynę niepowodzenia testu, na przykład gdy host znajduje się za kontrolowanym przez Ciebie firewallem sieciowym.

Przed pierwszym przebudowaniem przeczytaj plik app.yml

Kreator tworzy plik, za którego utrzymanie odpowiadasz teraz Ty. Otwórz go za pomocą sudo nano /var/discourse/containers/app.yml. Poniższe sekcje decydują o niemal wszystkich parametrach.

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
  ## Uncomment these two lines if you wish to add Lets Encrypt (https)
  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

expose:
  - "80:80"   # http
  - "443:443" # https

env:
  DISCOURSE_HOSTNAME: "forum.example.com"
  DISCOURSE_DEVELOPER_EMAILS: "you@example.com"
  DISCOURSE_SMTP_ADDRESS: smtp.example.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: user@example.com
  DISCOURSE_SMTP_PASSWORD: "your-smtp-password"

DISCOURSE_HOSTNAME to adres, pod którym odpowiada witryna; Discourse buduje na jego podstawie swoje odnośniki, więc błędna wartość spowoduje, że strona załaduje się raz, a następnie przekieruje użytkownika w inne miejsce. DISCOURSE_DEVELOPER_EMAILS to lista adresów oddzielonych przecinkami; adresy te automatycznie uzyskują uprawnienia administratora przy pierwszej rejestracji. Wpisz tam swój adres i zarejestruj się przy jego użyciu, ponieważ w ten sposób tworzone jest pierwsze konto administratora.

Plik przechowuje hasło SMTP w postaci jawnej, dlatego ogranicz dostęp do katalogu za pomocą sudo chmod 700 /var/discourse/containers. Jest to format YAML, co oznacza, że znaki odstępu są częścią konfiguracji: źle wyrównany klucz spowoduje błąd parsowania podczas budowania i brak działającej witryny. Jedna z pułapek została opisana w samym przykładowym pliku. Znak # wewnątrz nieobjętego cudzysłowem hasła rozpoczyna komentarz, dlatego każde hasło zawierające ten znak należy ująć w cudzysłów.

Konfiguracja poczty elektronicznej jest etapem, który najczęściej przerywa instalację

Od sierpnia 2026 roku kreator pozwala pominąć konfigurację SMTP i użyć logowania przez Discourse ID, a app.yml zawiera odpowiadający mu przełącznik DISCOURSE_SKIP_EMAIL_SETUP, opisany jako pominięcie walidacji ustawień poczty. Pominięcie tego kroku jest uzasadnione przy pierwszym zapoznaniu się z oprogramowaniem. Jest to jednak złe rozwiązanie dla społeczności, ponieważ bez wychodzącej poczty nikt nie aktywuje konta ani nie zresetuje hasła.

Praktycznym problemem jest fakt, że większość dostawców VPS blokuje wychodzący port 25, więc standardowy serwer pocztowy na maszynie nie będzie dostarczał wiadomości. Należy użyć uwierzytelnionego przekaźnika (relay) na porcie 587 lub na porcie 465 z użyciem implicit TLS (transport layer security). Dla portu 465 należy ustawić DISCOURSE_SMTP_FORCE_TLS: true, co jest zalecane w przykładowej konfiguracji dla tego portu. Przed przebudową (rebuild) należy przetestować dostępność z poziomu hosta.

nc -vz smtp.example.com 587

Poprawny wynik to pojedyncza linia kończąca się succeeded!. Polecenie, które zawiesza się, a następnie przekracza limit czasu, oznacza, że port jest blokowany na drodze wychodzącej z VPS i żadne ustawienie w Discourse tego nie naprawi. Należy przejść na port dozwolony przez dostawcę lub poprosić dostawcę o jego odblokowanie.

Gdy witryna będzie działać, należy wysłać wiadomość testową z poziomu strony Email w panelu Admin, a następnie sprawdzić zakładki Skipped oraz Bounced na tej samej stronie. W tych zakładkach Discourse rejestruje pocztę, której odmówił wysłania, oraz wiadomości odrzucone przez przekaźnik, wraz z podaniem przyczyny, co jest szybsze niż analiza logów.

TLS: pozwól kontenerowi na uzyskanie własnego certyfikatu

Jeśli Discourse obsługuje porty 80 oraz 443, należy skorzystać z wbudowanego mechanizmu wydawania certyfikatów. Odkomentuj dwie linie szablonu SSL pokazane powyżej, a następnie przebuduj aplikację. Szablon steruje acme.sh, przechowuje certyfikaty w udostępnionym wolumenie w lokalizacji /shared/ssl, odnawia je zgodnie z harmonogramem wewnątrz kontenera oraz konfiguruje Discourse tak, aby wymuszał HTTPS.

Aby to zadziałało, port 80 musi pozostać dostępny z Internetu, ponieważ to tam następuje odpowiedź na wyzwanie HTTP challenge. Firewall zezwalający wyłącznie na ruch przez port 443 spowoduje, że proces budowy zakończy się sukcesem, ale certyfikat nigdy nie zostanie wydany. Sprawdź wynik operacji za pomocą ./launcher logs app bezpośrednio po przebudowie.

Czy należy umieścić Nginx lub Caddy przed aplikacją?

Jeśli Discourse jest jedyną usługą WWW na serwerze VPS, nie należy tego robić. Kontener zawiera już zoptymalizowany Nginx, a dodatkowe proxy wprowadza kolejny przeskok, konieczność odnawiania certyfikatu oraz ryzyko błędów w nagłówkach.

Zastosuj proxy, gdy ten sam serwer VPS obsługuje inne witryny. Dodaj templates/web.socketed.template.yml do listy szablonów, zakomentuj obie linie expose i pozostaw oba szablony SSL jako zakomentowane. Kontener będzie wtedy nasłuchiwał na gnieździe unixowym pod adresem /var/discourse/shared/standalone/nginx.http.sock i nie zajmie żadnych portów, co zwolni porty 80 oraz 443 dla własnego proxy.

server {
  listen 443 ssl;
  server_name forum.example.com;

  location / {
    proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
    proxy_set_header Host $http_host;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

Końcowy dwukropek po .sock jest wymagany przez składnię gniazd unixowych w Nginx, a sudo nginx -t odrzuci konfigurację bez niego. Parametr X-Forwarded-Proto również nie jest opcjonalny. Discourse generuje linki bezwzględne, więc bez tego nagłówka wysyła linki http:// na stronie HTTPS, co powoduje blokowanie ich przez przeglądarki jako treści mieszanych (mixed content). Po przeniesieniu kontenera na gniazdo, obsługa TLS staje się zadaniem administratora, więc należy wydać certyfikat na hoście zgodnie z instrukcją Certbot na Ubuntu 24.04 i Nginx. Jeśli wybór proxy nie został jeszcze dokonany, porównanie Nginx, Caddy i Traefik przedstawia różnice między tymi rozwiązaniami.

Przebudowy, aktualizacje i polecenia, które faktycznie będą używane

cd /var/discourse
./launcher rebuild app

rebuild niszczy działający kontener, tworzy nowy na podstawie app.yml i uruchamia go. Strona jest niedostępna przez cały czas trwania procesu, dlatego każdą zmianę konfiguracji należy traktować jako planowaną przerwę techniczną trwającą kilka minut.

Zmiana wartości wyłącznie w sekcji env: nie wymaga tego procesu. ./launcher destroy app && ./launcher start app odtwarza kontener z już zbudowanego obrazu, co zajmuje kilka sekund. Każda zmiana w templates: lub hooks: modyfikuje sam obraz, dlatego wymaga pełnej przebudowy.

Aktualizacje są dostarczane na dwa sposoby. Wydania punktowe są stosowane z poziomu interfejsu WWW pod adresem /admin/upgrade, co zapewnia wtyczka docker_manager, którą app.yml klonuje podczas budowania. Zmiany w obrazie bazowym lub szablonach pochodzą z git.

cd /var/discourse
git pull
./launcher rebuild app

Przebudowy to moment, w którym małe serwery ulegają awarii, ponieważ kompilacja zasobów stanowi szczytowe obciążenie pamięci dla całego systemu. Proces budowania, który zatrzymuje się w połowie, a dmesg wyświetla linię typu Out of memory: Killed process wskazującą na proces ruby, oznacza brak pamięci podczas budowania, nawet jeśli sama strona działała wcześniej poprawnie. Należy dodać swap i ponownie uruchomić przebudowę.

./launcher logs app
./launcher enter app
./launcher cleanup

logs wyświetla wyjście kontenera, enter otwiera powłokę wewnątrz niego, a cleanup usuwa kontenery, które były zatrzymane przez ponad 24 godziny. Warto od czasu do czasu uruchamiać cleanup, ponieważ każda przebudowa pozostawia stary kontener, co na małym VPS może prowadzić do cichego wyczerpania miejsca na dysku.

Kopie zapasowe i pliki, których kopia nie zawiera

Kopie zapasowe wykonuje się z poziomu strony Backups w panelu Admin. Archiwum trafia na hosta do lokalizacji /var/discourse/shared/standalone/backups/default/. To samo zadanie można uruchomić z poziomu powłoki.

cd /var/discourse
./launcher enter app
discourse backup

Polecenie discourse restore <filename> przywraca kopię, jednak proces jest blokowany do momentu wykonania discourse enable_restore. To zabezpieczenie chroni przed przypadkowym nadpisaniem działającego forum przez błędną komendę.

Istnieją dwa braki, które należy uzupełnić samodzielnie. Archiwum zawiera bazę danych oraz przesłane pliki tylko wtedy, gdy w ustawieniach kopii zapasowej włączono opcję uwzględniania załączników; należy zweryfikować to ustawienie przed poleganiem na kopii. Archiwum nigdy nie zawiera pliku app.yml, więc przywrócenie danych na nowy serwer VPS nadal wymaga ręcznego skonfigurowania nazwy hosta oraz parametrów SMTP, co oznacza konieczność skopiowania tego pliku poza serwer.

Archiwum znajduje się na tym samym dysku co chroniona witryna, co nie stanowi pełnoprawnej kopii zapasowej. Należy regularnie przenosić pliki w inne miejsce zgodnie z harmonogramem.

rsync -avz root@forum.example.com:/var/discourse/shared/standalone/backups/default/ ~/discourse-backups/

Koszt pamięci RAM dla aktywnego forum

Proces bootstrap ustawia UNICORN_WORKERS oraz db_shared_buffers na podstawie wykrytej pamięci i procesora, a przykładowa konfiguracja ogranicza shared buffers do jednej czwartej całkowitej pamięci. Każdy proces typu unicorn worker jest pełnym procesem Ruby, a Sidekiq wykonuje zadania w tle obok nich, więc zużycie pamięci zależy od liczby jednoczesnych żądań, a nie od liczby zarejestrowanych użytkowników. Spokojne forum z kilkuset członkami nie stanowi dużego obciążenia. Zazwyczaj ważniejsze jest to, co jeszcze współdzieli zasoby serwera; jeśli jest to biblioteka zdjęć, zmierzone minimalne wartości RAM w porównaniu PhotoPrism i Immich wskażą, czy podczas przebudowy Discourse nadal pozostaje wystarczający zapas pamięci.

Nie należy dobierać rozmiaru serwera na podstawie liczb z artykułów, w tym niniejszego. Należy przeprowadzić własne pomiary.

free -m
docker stats --no-stream

Stałe użycie swap w połączeniu z wolnym ładowaniem stron oznacza niedobór pamięci RAM. Stabilne zużycie pamięci przy wolnych stronach zazwyczaj oznacza inny problem, dlatego przed zakupem droższego planu należy zapoznać się z ./launcher logs app. Warto również dodać monitorowanie z zewnątrz, ponieważ forum, któremu zabraknie pamięci o godzinie 3 nad ranem, przestaje działać bez powiadomienia: samodzielnie hostowany monitor statusu Uptime Kuma na oddzielnym serwerze poinformuje o tym fakcie, zanim zrobią to użytkownicy.

Kiedy Discourse nie jest właściwym wyborem

Discourse to rozbudowana aplikacja o wymagającym procesie instalacji oraz konieczności przebudowy (rebuild) przy każdej zmianie ustawień znajdujących się w app.yml. Koszt ten pozwala uzyskać zaawansowane narzędzia moderacji oraz wyszukiwarkę, która pozostaje wydajna przy dużych archiwach. Dla trzydziestoosobowej grupy potrzebującej miejsca do dyskusji jest to rozwiązanie zbyt zasobożerne w stosunku do potrzeb. Należy najpierw zapoznać się z porównaniem oprogramowania forum do samodzielnego hostowania i wybrać Discourse ze względu na oferowane funkcje, a nie dlatego, że jest to nazwa już znana.

FAQ

Czy mogę zainstalować Discourse na VPS bez nazwy domenowej?

Nie. Dostarczona konfiguracja zakłada, że Discourse nie będzie działać z samym adresem IP, a DISCOURSE_HOSTNAME jest wymagane. Discourse tworzy bezwzględne linki na podstawie tej nazwy hosta, więc adres IP powoduje uszkodzenie odnośników i blokuje wystawianie certyfikatów. Przed rozpoczęciem utwórz rekord A i potwierdź za pomocą dig +short forum.example.com, że wskazuje on na adres Twojego serwera.

Czy muszę skonfigurować SMTP, aby zakończyć instalację?

Od sierpnia 2026 można to pominąć. Kreator konfiguracji oferuje logowanie przez Discourse ID, a app.yml zawiera przełącznik pomijający walidację konfiguracji poczty. W przypadku użytkowania wykraczającego poza pierwsze testy, należy ją skonfigurować, ponieważ aktywacja konta oraz resetowanie haseł odbywają się drogą mailową. Użyj uwierzytelnionego przekaźnika na porcie 587 lub 465, ponieważ większość dostawców VPS blokuje wychodzący port 25.

Dlaczego proces rebuild w Discourse kończy się niepowodzeniem?

Najczęstszą przyczyną jest brak pamięci. Kompilacja zasobów podczas budowania wymaga więcej pamięci niż działająca witryna, więc serwer, który poprawnie obsługuje forum, może nie poradzić sobie z jego przebudową. Jeśli dmesg wskazuje Out of memory: Killed process w odniesieniu do procesu ruby, dodaj swap (plik wymiany tworzony przez kreator ma 2 GB) i uruchom ./launcher rebuild app ponownie. Budowanie, które zatrzymuje się z powodu błędu YAML, wskazuje na błąd wcięć w app.yml.

Czy Discourse powinien działać za własnym nginx lub Caddy?

Tylko wtedy, gdy VPS obsługuje również inne witryny. Jeśli serwer jest dedykowany, pozwól kontenerowi zająć porty 80 i 443 oraz samodzielnie wystawiać certyfikaty, co ogranicza liczbę elementów wymagających obsługi. Aby współdzielić maszynę, dodaj templates/web.socketed.template.yml, zakomentuj linie expose i przekieruj ruch do gniazda unix pod adresem /var/discourse/shared/standalone/nginx.http.sock. Przekaż X-Forwarded-Proto, w przeciwnym razie Discourse wygeneruje linki http:// na stronie HTTPS.

Jak wykonać kopię zapasową samodzielnie hostowanego Discourse?

Użyj strony Backups w panelu administratora lub uruchom discourse backup po ./launcher enter app. Archiwa trafiają na hosta do /var/discourse/shared/standalone/backups/default/. Potwierdź, że ustawienie uwzględniające przesyłane pliki jest włączone, skopiuj /var/discourse/containers/app.yml wraz z archiwum i przenieś oba elementy na inną maszynę, ponieważ kopia zapasowa na tym samym dysku co witryna nie przetrwa awarii, przed którą ma chronić.