Jak zainstalować Node.js i PM2 na Ubuntu: Kompletny przewodnik produkcyjny
Node.js to asynchroniczne, sterowane zdarzeniami środowisko uruchomieniowe JavaScript zbudowane na silniku V8 Chrome, zaprojektowane do wykonywania kodu JavaScript po stronie serwera z wysoką przepustowością. PM2 to menedżer procesów klasy produkcyjnej dla aplikacji Node.js, który zapewnia daemonizację, automatyczne odzyskiwanie po awarii, agregację logów, równoważenie obciążenia w trybie klastra oraz generowanie skryptów startowych — wszystko z poziomu jednego interfejsu CLI.
Ten przewodnik obejmuje każdą metodę instalacji, opcję konfiguracji i wzorzec operacyjny potrzebny do niezawodnego uruchamiania aplikacji Node.js na Ubuntu 20.04, 22.04 lub 24.04 LTS w środowisku produkcyjnym.
Wymagania wstępne
Przed kontynuowaniem potwierdź następujące kwestie:
- System operacyjny: Ubuntu 20.04, 22.04 lub 24.04 LTS (serwer lub desktop)
- Uprawnienia użytkownika: `sudo` lub dostęp root
- Dostęp do sieci: Wychodzące HTTPS do pobierania pakietów i skryptów
- Zainstalowany curl: Uruchom `sudo apt install curl -y` jeśli nie jest jeszcze zainstalowany
Jeśli uruchamiasz to na serwerze w chmurze, środowisko VPS Hosting jest najczęstszym celem wdrożenia dla obciążeń Node.js i wszystko w tym przewodniku ma bezpośrednie zastosowanie.
Krok 1: Aktualizacja pakietów systemowych
Zawsze synchronizuj indeks pakietów i stosuj oczekujące aktualizacje przed instalacją nowego oprogramowania. Nieaktualne metadane pakietów są częstym źródłem konfliktów zależności.
“`bash
sudo apt update
sudo apt upgrade -y
“`
Po zakończeniu aktualizacji uruchom ponownie system, jeśli jądro zostało zaktualizowane:
“`bash
sudo reboot
“`
Krok 2: Instalacja Node.js — wybór właściwej metody
Istnieją trzy podstawowe metody instalacji Node.js na Ubuntu. Każda z nich ma wyraźne kompromisy pod względem kontroli wersji, izolacji i dostępności w całym systemie.
Porównanie metod
| Funkcja | NodeSource (apt) | NVM | Systemowy apt (universe) |
|---|
| — | — | — | — |
|---|
| Kontrola wersji | Pojedyncza przypięta wersja główna | Wiele wersji na użytkownika | Zazwyczaj przestarzałe LTS |
|---|
| Instalacja systemowa | Tak | Nie (domyślnie per użytkownik) | Tak |
|---|
| Przełączanie wersji | Wymaga ponownego uruchomienia skryptu konfiguracyjnego | `nvm use <version>` | Nieobsługiwane |
|---|
| Najlepsze dla | CI/CD, serwery z jedną wersją | Programowanie, wiele projektów | Tylko szybkie testy |
|---|
| sudo wymagane dla globalnych npm | Tak | Nie | Tak |
|---|
| Przydatność produkcyjna | Wysoka | Średnia | Niska |
|---|
Metoda 1: Instalacja Node.js przez NodeSource (zalecana dla serwerów)
NodeSource utrzymuje aktualne repozytoria Debian/Ubuntu dla każdej aktywnej linii wydań Node.js. Jest to preferowane podejście dla serwerów produkcyjnych, gdzie wymagana jest jedna, stabilna wersja w całym systemie.
Dodaj repozytorium NodeSource dla bieżącego wydania LTS:
“`bash
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash –
“`
Ten skrypt wykonuje kilka czynności: wykrywa wersję Ubuntu, dodaje odpowiednie repozytorium apt NodeSource, importuje klucz podpisywania GPG i uruchamia `apt-get update`. Flaga `-E` zachowuje zmienne środowiskowe podczas eskalacji do sudo, co ma znaczenie, jeśli masz skonfigurowane ustawienia proxy.
Zainstaluj Node.js i npm:
“`bash
sudo apt install nodejs -y
“`
Pakiet NodeSource zawiera zarówno `node` jak i `npm` w jednym pakiecie `nodejs`. W przeciwieństwie do pakietu Ubuntu universe, nie rozdziela ich.
Zweryfikuj instalację:
“`bash
node -v
npm -v
“`
Przykładowe oczekiwane wyjście:
“`
v20.14.0
10.7.0
“`
Przypinanie do konkretnej wersji głównej: Jeśli potrzebujesz Node.js 18 zamiast bieżącego LTS, zastąp `setup_lts.x` przez `setup_18.x` w poleceniu curl. Dostępne strumienie to `setup_18.x`, `setup_20.x` i `setup_22.x`.
Metoda 2: Instalacja Node.js przez NVM (zalecana dla środowisk deweloperskich i wielowersyjnych)
NVM (Node Version Manager) instaluje Node.js w katalogu domowym użytkownika, nie wymagając uprawnień root ani dla samego Node.js, ani dla globalnie instalowanych pakietów npm. Eliminuje to problemy z uprawnieniami, które często pojawiają się podczas uruchamiania `npm install -g` na systemowo zainstalowanym Node.js.
Zainstaluj NVM:
“`bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
“`
Sprawdź oficjalne repozytorium NVM pod kątem najnowszego tagu wydania przed uruchomieniem tego polecenia — numer wersji w URL zmienia się z każdym wydaniem.
Przeładuj środowisko powłoki:
“`bash
source ~/.bashrc
“`
Jeśli używasz Zsh, zamiast tego załaduj `~/.zshrc`. Instalator NVM dołącza swój blok inicjalizacyjny do wykrytego pliku konfiguracyjnego powłoki.
Zainstaluj najnowszą wersję LTS Node.js:
“`bash
nvm install –lts
“`
Zainstaluj konkretną wersję obok LTS:
“`bash
nvm install 18
nvm install 20
“`
Przełączaj się między zainstalowanymi wersjami:
“`bash
nvm use 20
nvm alias default 20
“`
Polecenie `alias default` ustawia wersję aktywowaną w nowych sesjach powłoki, co jest kluczowe dla skryptów i zadań cron, które nie ładują interaktywnego profilu powłoki.
Weryfikacja:
“`bash
node -v
npm -v
“`
Krytyczna pułapka NVM dla produkcji: Ponieważ NVM jest ograniczony do użytkownika, skrypty startowe PM2 i jednostki systemd nie będą miały dostępu do binarnego pliku Node.js zarządzanego przez NVM, chyba że jawnie skonfigurujesz ścieżkę. Zobacz Krok 5, aby dowiedzieć się, jak prawidłowo to obsłużyć.
Krok 3: Instalacja PM2
PM2 jest dystrybuowany jako pakiet npm i powinien być zainstalowany globalnie, aby jego CLI było dostępne w całym systemie.
Zainstaluj PM2:
“`bash
sudo npm install -g pm2
“`
Jeśli zainstalowałeś Node.js przez NVM, pomiń `sudo`:
“`bash
npm install -g pm2
“`
Zweryfikuj instalację:
“`bash
pm2 -v
“`
Zainstaluj konkretną wersję PM2 (przydatne przy przypinaniu infrastruktury):
“`bash
sudo npm install -g pm2@5.3.1
“`
PM2 w wersji 5.x to bieżąca stabilna linia. Wprowadził znaczące ulepszenia do panelu webowego (pm2 plus), rotacji logów i systemu modułów w porównaniu do v4.
Krok 4: Zarządzanie aplikacjami Node.js za pomocą PM2
Uruchamianie aplikacji
Przejdź do katalogu aplikacji i uruchom ją:
“`bash
cd /var/www/my-app
pm2 start app.js –name "my-app"
“`
Zawsze przypisuj flagę `–name`. Bez niej PM2 używa nazwy pliku jako nazwy procesu, co staje się niejednoznaczne, gdy masz wiele usług.
Uruchamianie z dodatkowymi opcjami:
“`bash
pm2 start app.js –name "my-app" –watch –max-memory-restart 300M
“`
- `–watch`: Restartuje proces po zmianie plików źródłowych (przydatne na staging, niezalecane na produkcji)
- `–max-memory-restart 300M`: Automatycznie restartuje proces, jeśli przekroczy 300 MB pamięci RSS — krytyczne zabezpieczenie przed wyciekami pamięci
Przeglądanie uruchomionych procesów
“`bash
pm2 list
“`
Wyświetla tabelę pokazującą ID procesu, nazwę, tryb (fork/cluster), PID, status, użycie CPU, zużycie pamięci i liczbę restartów.
Dla panelu w czasie rzeczywistym:
“`bash
pm2 monit
“`
Sterowanie procesami
“`bash
pm2 restart my-app # Graceful restart
pm2 reload my-app # Zero-downtime reload (cluster mode only)
pm2 stop my-app # Stop without removing from process list
pm2 delete my-app # Stop and remove from process list
“`
Różnica między `restart` a `reload`: `restart` zabija proces i uruchamia nowy, powodując krótką przerwę w działaniu. `reload` (dostępne tylko w trybie klastra) cyklicznie wymienia pracowników jeden po drugim, utrzymując dostępność przez cały czas. Zawsze używaj `reload` w produkcyjnych wdrożeniach klastrowych.
Zarządzanie logami
“`bash
pm2 logs # Stream logs from all processes
pm2 logs my-app # Stream logs for a specific process
pm2 logs my-app –lines 200 # Show last 200 lines
pm2 flush # Clear all log files
“`
PM2 domyślnie przechowuje logi w `~/.pm2/logs/`. W przypadku serwerów produkcyjnych zainstaluj moduł rotacji logów, aby zapobiec wyczerpaniu miejsca na dysku:
“`bash
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 10
pm2 set pm2-logrotate:compress true
“`
Rotuje logi po osiągnięciu 50 MB, zachowuje 10 skompresowanych archiwów i zapobiega niekontrolowanemu wzrostowi logów — częsty problem na długo działających serwerach, który jest często pomijany do momentu wyczerpania miejsca na dysku.
Krok 5: Konfiguracja PM2 do uruchamiania przy starcie systemu
PM2 musi być skonfigurowany tak, aby przeżywał restarty serwera. Odbywa się to poprzez jednostkę usługi systemd generowaną przez sam PM2.
Wygeneruj polecenie startowe:
“`bash
pm2 startup
“`
PM2 wyświetli polecenie dostosowane do twojego systemu init i bieżącego użytkownika. Wygląda to tak:
“`
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu –hp /home/ubuntu
“`
Skopiuj i wykonaj to dokładne polecenie. Nie modyfikuj go — ścieżka do binarnego pliku PM2 i katalog domowy muszą odpowiadać konfiguracji twojego systemu.
Konfiguracja startowa specyficzna dla NVM: Jeśli zainstalowałeś Node.js przez NVM, ścieżka w wygenerowanym poleceniu będzie wskazywać na twój binarny plik zarządzany przez NVM. Jest to poprawne, ale musisz upewnić się, że wersja NVM jest ustawiona jako domyślna przed uruchomieniem `pm2 startup`:
“`bash
nvm alias default 20
pm2 startup
“`
Zapisz bieżącą listę procesów:
“`bash
pm2 save
“`
Zapisuje listę procesów do `~/.pm2/dump.pm2`. Po restarcie jednostka systemd odczytuje ten plik i przywraca wszystkie zapisane procesy. Jeśli później dodasz lub usuniesz aplikacje, uruchom ponownie `pm2 save`, aby zaktualizować migawkę.
Zweryfikuj, czy jednostka systemd jest aktywna:
“`bash
systemctl status pm2-ubuntu
“`
Zastąp `ubuntu` swoją rzeczywistą nazwą użytkownika.
Krok 6: Wdrożenie produkcyjne z plikami ekosystemu PM2
W przypadku czegokolwiek wykraczającego poza aplikację jednego skryptu, użyj pliku konfiguracyjnego ekosystemu PM2. Zapewnia on odtwarzalne, kontrolowane wersjonowaniem definicje procesów i eliminuje potrzebę zapamiętywania długich flag CLI.
Generowanie pliku ekosystemu
“`bash
pm2 ecosystem
“`
Tworzy `ecosystem.config.js` w bieżącym katalogu.
Gotowa do produkcji konfiguracja ekosystemu
“`javascript
module.exports = {
apps: [
{
name: 'api-server',
script: './src/server.js',
instances: 'max',
exec_mode: 'cluster',
watch: false,
max_memory_restart: '500M',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
error_file: '/var/log/pm2/api-server-error.log',
out_file: '/var/log/pm2/api-server-out.log',
merge_logs: true,
env: {
NODE_ENV: 'development',
PORT: 3000
},
env_production: {
NODE_ENV: 'production',
PORT: 8080
}
},
{
name: 'worker',
script: './src/worker.js',
instances: 2,
exec_mode: 'fork',
cron_restart: '0 2 * * *',
env_production: {
NODE_ENV: 'production'
}
}
]
};
“`
Wyjaśnienie kluczowych decyzji konfiguracyjnych:
- `instances: 'max'`: PM2 automatycznie uruchamia jednego pracownika na każdy logiczny rdzeń CPU. Na serwerze 4-rdzeniowym tworzy to 4 procesy Node.js, w pełni wykorzystując sprzęt.
- `exec_mode: 'cluster'`: Używa wbudowanego modułu klastra Node.js. Wszystkie instancje współdzielą ten sam port poprzez równoważenie obciążenia gniazd systemu operacyjnego.
- `exec_mode: 'fork'`: Uruchamia proces jako samodzielny proces potomny. Wymagane dla aplikacji, które nie są serwerami HTTP (pracownicy kolejek, zaplanowane zadania, serwery WebSocket z lepkimi sesjami).
- `merge_logs: true`: Łączy stdout ze wszystkich instancji klastra w jeden plik logów, znacznie ułatwiając analizę logów.
- `cron_restart`: Planuje automatyczne restarty przy użyciu składni cron. Przydatne dla pracowników, którzy gromadzą stan lub do stosowania nocnych zmian konfiguracji.
Uruchamianie z plikiem ekosystemu
“`bash
pm2 start ecosystem.config.js –env production
pm2 save
“`
Przepływ pracy wdrożenia bez przestojów
Podczas wdrażania nowej wersji aplikacji:
“`bash
git pull origin main
npm install –production
pm2 reload ecosystem.config.js –env production
“`
`pm2 reload` wysyła `SIGINT` do każdego pracownika po kolei, czeka aż nowy pracownik będzie gotowy, a następnie kończy stary. Twoja aplikacja musi obsługiwać `SIGINT` w sposób elegancki i sygnalizować gotowość za pomocą `process.send('ready')`, aby to działało poprawnie.
Obsługa eleganckie zamknięcia w twojej aplikacji:
“`javascript
process.on('SIGINT', () => {
server.close(() => {
console.log('HTTP server closed');
process.exit(0);
});
});
“`
Krok 7: Monitorowanie i obserwowalność PM2
Wbudowane monitorowanie
“`bash
pm2 monit
“`
Wyświetla wykresy CPU i pamięci w czasie rzeczywistym dla każdego procesu w terminalu.
Informacje o procesie
“`bash
pm2 show my-app
“`
Wyświetla szczegółowe metadane: czas działania, liczbę restartów, wersjonowanie, ścieżkę interpretera, zmienne środowiskowe i lokalizacje plików logów.
Panel webowy PM2 (PM2 Plus)
PM2 oferuje hostowany panel monitorowania na pm2.io. Połącz swój serwer:
“`bash
pm2 link <secret_key> <public_key>
“`
Zapewnia to historyczne metryki, alerty i zdalne zarządzanie procesami — szczególnie cenne przy zarządzaniu wieloma serwerami lub gdy potrzebujesz widoczności bez dostępu SSH.
Krok 8: Aktualizacja Node.js i PM2
Aktualizacja PM2
“`bash
sudo npm install -g pm2@latest
pm2 update
“`
`pm2 update` jest niezbędne po aktualizacji binarnego pliku PM2 — aktualizuje działający demon PM2 bez przerywania uruchomionych procesów.
Aktualizacja Node.js przez NodeSource
Ponownie uruchom skrypt konfiguracyjny dla nowej wersji głównej:
“`bash
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash –
sudo apt install nodejs -y
“`
Po aktualizacji Node.js uruchom ponownie PM2, aby upewnić się, że używa nowego pliku binarnego:
“`bash
pm2 restart all
“`
Aktualizacja Node.js przez NVM
“`bash
nvm install 22
nvm alias default 22
nvm use 22
pm2 restart all
“`
Jeśli zmieniłeś domyślną wersję NVM, wygeneruj ponownie skrypt startowy PM2, aby zaktualizować ścieżkę binarną w jednostce systemd:
“`bash
pm2 unstartup
pm2 startup
pm2 save
“`
Zagadnienia dotyczące wzmocnienia bezpieczeństwa
Uruchamianie aplikacji Node.js w produkcji wymaga uwagi wykraczającej poza zarządzanie procesami:
- Uruchamiaj jako użytkownik bez uprawnień root: Nigdy nie uruchamiaj PM2 ani Node.js jako root. Utwórz dedykowanego użytkownika systemowego (`adduser –system –group nodeapp`) i uruchamiaj PM2 na tym koncie.
- Zarządzanie zmiennymi środowiskowymi: Nie umieszczaj sekretów na stałe w `ecosystem.config.js`. Użyj pliku `.env` ładowanego przez `dotenv` lub wstrzykuj sekrety przez potok wdrożeniowy. Plik ekosystemu jest zazwyczaj zatwierdzany do kontroli wersji.
- Odwrotne proxy: Umieść Nginx lub Caddy przed aplikacją Node.js. Obsługuje to zakończenie TLS, serwowanie plików statycznych, ograniczanie szybkości i buforowanie żądań. Połącz to z rozwiązaniem Certyfikaty SSL, aby wymusić HTTPS.
- Reguły zapory sieciowej: Zablokuj bezpośredni dostęp do portu Node.js (np. 3000, 8080) z publicznego internetu. Tylko odwrotne proxy powinno komunikować się z Node.js.
- Limity zasobów: Ustaw `max_memory_restart` w PM2 i skonfiguruj systemowe wartości `ulimit`, aby zapobiec destabilizacji serwera przez jeden niekontrolowany proces.
W przypadku produkcyjnych wdrożeń o dużym ruchu, gdzie izolacja zasobów jest krytyczna, środowisko Serwery dedykowane zapewnia pełną kontrolę nad sprzętem i eliminuje problem hałaśliwego sąsiada charakterystyczny dla współdzielonej infrastruktury.
Wybór odpowiedniego środowiska hostingowego dla Node.js
| Obciążenie | Zalecane środowisko | Uzasadnienie |
|---|
| — | — | — |
|---|
| Projekty osobiste, staging | [VPS Hosting](https://alexhost.com/pl/vps/) | Opłacalne, pełny dostęp root, skalowalne |
|---|
| API o dużym ruchu | [Serwery dedykowane](https://alexhost.com/pl/dedicated-servers/) | Przewidywalna wydajność, brak rywalizacji o zasoby |
|---|
| Wnioskowanie ML + Node.js | [GPU Hosting](https://alexhost.com/pl/gpu-hosting/) | Odciążenie zadań intensywnych obliczeniowo do pracowników GPU |
|---|
| Zarządzany panel sterowania | [VPS z cPanel](https://alexhost.com/pl/vps/control-panels/cpanel-vps/) | Zarządzanie procesami i plikami przez GUI |
|---|
Lista kontrolna decyzji technicznych
Użyj tej listy kontrolnej przed wdrożeniem Node.js i PM2 na produkcję:
- [ ] Node.js zainstalowany przez NodeSource (serwer) lub NVM (programowanie) — nie przez pakiet Ubuntu universe
- [ ] PM2 zainstalowany globalnie z odpowiednimi uprawnieniami dla twojej metody instalacji
- [ ] Aplikacja uruchomiona z flagą `–name` i zdefiniowanym progiem `–max-memory-restart`
- [ ] Tryb klastra włączony dla serwerów HTTP; tryb fork używany dla pracowników w tle
- [ ] `pm2 startup` wykonane i wygenerowane polecenie uruchomione z sudo
- [ ] `pm2 save` uruchomione po skonfigurowaniu wszystkich procesów
- [ ] Moduł rotacji logów zainstalowany i skonfigurowany
- [ ] Nginx lub Caddy skonfigurowany jako odwrotne proxy z TLS
- [ ] Aplikacja obsługuje `SIGINT` w sposób elegancki dla przeładowań bez przestojów
- [ ] Sekrety zarządzane poza `ecosystem.config.js`
- [ ] Jednostka systemd PM2 zweryfikowana za pomocą `systemctl status pm2-<username>`
- [ ] Zapora sieciowa blokuje bezpośredni dostęp do portów Node.js z publicznego internetu
FAQ
Jaka jest różnica między trybem fork a trybem klastra w PM2?
Tryb fork uruchamia aplikację jako pojedynczy proces potomny — jedna instancja, jeden rdzeń CPU wykorzystany. Tryb klastra używa natywnego modułu klastra Node.js do uruchamiania wielu procesów roboczych, które wszystkie współdzielą ten sam port TCP, umożliwiając prawdziwe wielordzeniowe wykorzystanie i przeładowania bez przestojów. Używaj trybu klastra dla serwerów HTTP/HTTPS i trybu fork dla pracowników, zadań cron lub aplikacji, które utrzymują wewnętrzny stan niekompatybilny z wieloprocesowym współdzieleniem.
Dlaczego PM2 nie restartuje się po restarcie serwera, mimo że uruchomiłem `pm2 startup`?
Najczęstszą przyczyną jest to, że `pm2 save` nie zostało uruchomione po skonfigurowaniu procesów, więc plik zrzutu jest pusty lub brakuje go. Drugą najczęstszą przyczyną jest niezgodność ścieżki NVM: jeśli domyślna wersja NVM została zmieniona po wygenerowaniu skryptu startowego, jednostka systemd wskazuje na nieistniejący plik binarny. Rozwiąż to, uruchamiając `pm2 unstartup`, ustawiając poprawną domyślną wersję NVM, a następnie ponownie uruchamiając `pm2 startup` i `pm2 save`.
Czy PM2 może zarządzać procesami innymi niż Node.js?
Tak. PM2 może zarządzać dowolnym plikiem wykonywalnym poprzez określenie interpretera. Na przykład: `pm2 start script.py –interpreter python3`. Dzięki temu PM2 jest przydatny jako ogólny nadzorca procesów dla architektur mikroserwisów w wielu językach.
Jak uruchomić wiele aplikacji Node.js na różnych portach za jednym serwerem?
Zdefiniuj każdą aplikację jako oddzielny wpis w `ecosystem.config.js` z odrębnymi zmiennymi środowiskowymi `PORT`. Skonfiguruj Nginx jako odwrotne proxy z oddzielnymi blokami `server` lub dyrektywami `location` kierującymi do każdego portu. Wszystkie aplikacje współdzielą ten sam demon PM2 i są zarządzane przez jeden widok `pm2 list`.
Czy powinienem używać NVM czy NodeSource dla produkcyjnego VPS?
NodeSource jest generalnie preferowany dla serwerów produkcyjnych. Instaluje Node.js jako pakiet systemowy, udostępniając go wszystkim użytkownikom i usługom systemowym bez zależności od inicjalizacji powłoki. Model aktywacji NVM per użytkownik, per powłoka wprowadza subtelne tryby awarii w jednostkach systemd, zadaniach cron i potokach CI/CD uruchamianych poza interaktywną sesją powłoki. Zarezerwuj NVM dla lokalnych maszyn deweloperskich, gdzie jednoczesne zarządzanie wieloma wersjami Node.js jest rzeczywistym wymaganiem.
