Blog

Konfigurujemy serwer

PodstawyProgramowanie

#server#linux#nginx#konfiguracja#instalacja

Опубліковано 2.12.2024

Konfigurujemy serwer

Praktycznie od początków istnienia Nerdistry, sięgających jeszcze czasów starej, utraconej wersji, odgrażałem się, że przygotuję poradnik instalacji Strapi na własnym serwerze. Uwaga - oto nadszedł ten dzień!

No dobrze, może jeszcze nie tak do końca. Poradnik postanowiłem podzielić na kilka części, żeby nie rozrósł się do niebotycznych rozmiarów. Dziś będzie część pierwsza, czyli przygotowanie serwera.

Co potrzebujemy i co będziemy robić? Na początek, jak się łatwo domyślić, potrzebujemy serwera z obsługą Node. Ja posiadam VPS od OVH z postawionym na nim Ubuntu - i na jego przykładzie będę przeprowadzał konfigurację.

Mamy już serwer, co dalej? Będziemy potrzebować czegoś do uruchomienia naszego serwisu www - czyli do obsługi HTTP. Kolejno trzeba będzie przygotować obsługę naszej domeny i zainstalować certyfikat SSL. Następnie przyda się git, żeby móc wygodnie pobrać repozytorium z backendem. Na sam koniec dodamy Dockera wraz z docker compose, żeby nasz serwis odpalić w kontenerze.

Czy dwa ostatnie kroki są niezbędne? Oczywiście, że nie. Ale moim zdaniem bardzo ułatwiają pracę - dlaczego więc nie skorzystać.

Wspomniałem o czymś do obsługi HTTP. W moim przypadku wybór padł na Nginx, choć Apache też pewnie będzie dobrym pomysłem.

Skoro już wszystko ustaliliśmy, to możemy zaczynać.

Pierwsze kroki

Zakładam, że zalogowaliście się na serwer przez ssh. Warto przed przystąpieniem do pracy zrobić jeszcze jedną rzecz - ustawić klucze. Wpłynie to pozytywnie zarówno na wygodę korzystania z serwera, jak i na bezpieczeństwo.

Co nam da ustawienie kluczy ssh? Tym, co odczujemy najbardziej, będzie brak konieczności używania hasła do połączenia z serwerem.

Ale zaraz, zaraz - przecież to miało wpłynąć na bezpieczeństwo, a teraz mówimy o logowaniu bez hasła? No tak. Nie jestem ekspertem, dlatego nie będę wchodził w szczegóły. Ogólnie do logowania używamy w takiej sytuacji pary kluczy - klucza publicznego oraz prywatnego. Klucze są powiązane z urządzeniem, z którego się logujemy i jeśli do siebie pasują, to stanowi to wystarczający sposób autoryzacji.

No dobrze, to jak te klucze ustawić. Zasadniczo są dwa sposoby - prostszy i bardziej skomplikowany. Efekt dają taki sam, więc skoncentrujmy się na tym pierwszym.

W tym miejscu przyjmijmy kilka założeń. Otóż załóżmy, że nasz użytkownik nazywa się admin, a nasz serwer ma adres 1.2.3.4

W pierwszej kolejności trzeba sprawdzić, czy posiadamy jakiś klucz, żeby go wysłać. W tym celu wpisujemy w konsoli

$ ls -al ~/.ssh

Powinniście zobaczyć listę wszystkich plików, jakie znajdują się w waszym folderze ssh. Jeśli widzicie plik z rozszerzeniem .pub, to znaczy, że wszystko jest ok. Jeśli nie, klucze trzeba utworzyć.

Służy do tego polecenie ssh-keygen. Jego pełen opis można znaleźć na przykład tutaj. Ja utworzę teraz klucz przy użyciu algorytmu ed25519:

ssh-keygen -t ed25519

Kiedy mamy już nową parę kluczy, musimy dodać nasz klucz do usługi ssh-agent:

Get-Service -Name ssh-agent | Set-Service -StartupType Manual
Start-Service ssh-agent

Jeśli kiedykolwiek konfigurowaliście dostęp przez ssh do GitHuba, to powyższe kroki powinny wyglądać znajomo.

Pora dodać nasz klucz na serwer:

ssh-copy-id admin@1.2.3.4

Jeśli mamy tylko jeden klucz, to nie ma problemu. Jeśli jednak kluczy mamy więcej (na przykład do kilku usług), to musimy wskazać, który konkretnie klucz chcemy przesłać:

ssh-copy-id -i ~/.ssh/id_ed25519 admin@1.2.3.4

Serwer poprosi nas o podanie hasła - i jak dobrze pójdzie, to będzie to ostatni raz, kiedy to hasło będziemy musieli wpisywać.

Wszedłem na serwer, co teraz?

Dobrą praktyką jest dbanie, żeby serwer był zawsze zaktualizowany. Dlatego, szczególnie przy pierwszym logowaniu, warto dopilnować, żeby lista pakietów na serwerze była tą najnowszą. Robi się to w banalny sposób (polecenie działa dla serwerów opartych na Ubuntu/Debianie):

apt update
apt upgrade

Jeśli nasz serwer działa na CentOS/RedHat, to pakiety zaktualizujemy poleceniem

yum update
yum upgrade

W przyszłości będę podawał polecenia dla serwera stojącego na Ubuntu, jednak wszystkie są dostępne także na CentOS/RedHat.

Safety first

W kolejnym kroku warto zadbać o podstawy bezpieczeństwa. Jak już wspomniałem - ekspertem nie jestem, ale z tego, co najczęściej widziałem wynika, że konta administratora powinno się używać wyłącznie w sytuacji, w której jest to niezbędne. Do codziennej pracy z serwerem korzystać zaś z konta zwykłego użytkownika.

W tym celu należy je najpierw utworzyć:

sudo adduser ziutek

Serwer w odpowiedzi poprosi o kilka dodatkowych informacji o użytkowniku, z których wymaganą (i najważniejszą jest hasło):

New password:
Retype new password:

Gratulacje, właśnie utworzyliśmy konto użytkownika ziutek! Możemy się na nie przełączyć poleceniem

sudo su ziutek

Aby dodatkowo zabezpieczyć nasz serwer, można pokusić się o konfigurację zapory sieciowej oraz Fail2ban. W tym celu polecam lekturę poradnika OVH.

Nginx, czyli zaczyna się magia

Nadszedł czas, żeby włączyć obsługę HTTP. W tym celu wykorzystamy Nginxa.

Jak zwykle najpierw musimy go zainstalować. Jednak wcześniej powinniśmy się zastanowić, której wersji potrzebujemy. Najpopularniejsze to:

  • nginx-core – minimalna wersja, nie zawiera praktycznie żadnego modułu,
  • nginx-full – wersja zawierające wszystkie opcje dostępne w nginxie,
  • nginx-extras – najbogatsza wersja, zawierająca zewnętrzne moduły, nietworzone przez twórców nginxa.

Ja wybrałem wersję full.

apt install nginx-full

Gotowe! Można się jeszcze dodatkowo upewnić, że Ngnix poprawnie się uruchomił.

netstat -plntu

Warto w tym miejscu wyjaśnić, co robią poszczególne flagi w powyższym poleceniu:

  • p – pokazuje nazwę programu, który jest na danym porcie,
  • l – skrót od listen, czyli co słucha,
  • n – bez rozwijania nazw serwerów,
  • t – TCP,
  • u – UDP.

Na sam koniec można jeszcze za pomocą curl-a upewnić się, że nasz serwer działa poprawnie:

curl https://www.google.com

Jeśli w odpowiedzi otrzymaliśmy kod html strony głównej google.com to znaczy, że wszystko przebiegło poprawnie.

I jesteśmy (prawie) w domu

Bardzo fajnie, że nasz serwer działa i obsługuje HTTP. Ale wywoływanie go za pomocą adresu IP jest mało praktyczne. Czas więc podpiąć domenę!

Posłużmy się tutaj domeną tej strony, czyli nerdistry.pl. W pierwszym kroku należy przekierować naszą domenę na adres serwera. Standardowo można to zrobić w ustawieniach DNS domeny, za pomocą rekordu A.

Dobrze, mamy domenę i przekierowaliśmy ją na nasz serwer. Teraz musimy jeszcze tę domenę na serwerze skonfigurować.

Przechodzimy zatem do katalogu /etc/nginx/

cd ./etc/nginx/

gdzie znajdują się dwa katalogi, do których trafią nasze pliki konfiguracyjne: sites-enabled oraz sites-available. Wchodzimy do tego drugiego i zaczynamy zabawę.

cd sites-available
nano nerdistry.pl

Przykładowy plik (objaśnienia poniżej)

server {
	listen 80 default_server;
	listen [::]:80 default_server;

        root /var/www/nerdistry;

        index index.html index.htm;
        server_name _;

        location / {
			try_files $uri $uri/ =404;
		}
}
  • default_server – oznaczenie informujące, że jest to domyślna domena serwera, czy jeśli np. ktoś wpisze w pasek adresu IP serwera, to wyświetli się właśnie to, co skonfigurowaliśmy w tym pliku,
  • listen 80 – nasłuch na porcie 80 dla IPv4,
  • listen [::]:80 – nasłuch na porcie 80 dla IPv6,
  • root – wskazanie katalogu, w którym mamy pliki strony/aplikacji,
  • index – dyrektywa wskazująca, który plik będzie indexem strony, czyli plikiem startowym w katalogu wskazanego w root; przeszukiwanie jest kaskadowe, czyli jeśli pierwszy plik istnieje to kończy pracę, jeśli nie, to przechodzi do kolejnego,
  • server_name _; – nzawa domeny; podkreślenie oznacza serwer domyślny, czyli wszystkie domeny są akceptowane,
  • location / – to blok chwytający requesty.

Skonfigurowaną w taki sposób domenę trzeba jeszcze aktywować. Robimy to poprzez powiązanie utworzonego przed chwilą pliku symlinkiem do katalogu sites-enabled.

cd /etc/nginx/sites-enabled/
ln -s ../sites-available/nerdistry

Zanim przejdziemy dalej, dobrze się upewnić, że w pliku konfiguracyjnym nie zrobiliśmy jakichś błędów (które by np. wywaliły nasz serwer).

nginx -t

Jeśli wszystko działa poprawnie, czas zrestartować ngnixa.

nginx -s reload

Pamiętaj, żeby w katalogu /var/www/nerdistry umieścić plik index.html (lub index.htm) - wówczas po w pisaniu w przeglądarkę ustawionego w pliku konfiguracyjnego adresu powinniśmy zobaczyć naszą stronę.

Ale czy to bezpieczne?

Czas zabezpieczyć naszą stronę certyfikatem ssl. Skorzystamy do tego z darmowego Let’s encrypt. Bo za darmo to uczciwa cena.

Klasycznie - najpierw musimy zainstalować Let’s encrypt na serwerze. Podobnie, jak w przypadku ngnixa mamy do wyboru kilka wersji, które możemy przejrzeć:

apt search cerbot

Ja wybrałem wersję python3:

apt install certbot python3-certbot-nginx
certbot --nginx -d nerdistry.pl -d www.nerdistry.pl

Warto też sprawdzić, czy firewall zezwala na połączenie przez https:

sudo ufw status

Prawdopodobnie zobaczymy następujące wartości:

Output
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx HTTP                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

Aby odblokować połączenie przez https wystarczą poniższe komendy:

sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'

Wówczas po sprawdzeniu powinniśmy otrzymać poniższy wynik:

Output
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx Full                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx Full (v6)            ALLOW       Anywhere (v6)

Kolejnym krokiem powinno być upewnienie się, że certyfikat został poprawnie zainstalowany oraz, że automatyczne odnowienie działa bez problemów:

sudo systemctl status snap.certbot.renew.service
sudo certbot renew --dry-run

I to wszystko. Od teraz można połączyć się z naszym serwerem poprzez https://nerdistry.pl lub https://www.nerdisty.pl.

W kontener go i git!

Jeśli nie chcemy wrzucać na nasz serwer plików ręcznie, możemy się posłużyć znanym i lubianym gitem. Ponownie - musimy go najpierw zainstalować.

sudo apt-get install git

Zweryfikować poprawność instalacji możemy za pomocą sprawdzenia wersji:

git --version

Można oczywiście połączyć serwer z naszym GitHubem i logować się przez SSH. Procedura jest analogiczna, jak przy tworzeniu kluczy parujących konto z komputerem i można ją znaleźć w oficjalnej dokumentacji GitHuba.

Teraz dodamy do serwera obsługę Node. Polecam do tego użyć Node Version Manager (nvm).

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash

Teoretycznie nvm powinien być gotowy, ale prawdopodobnie nasz terminal nadal nie będzie go widział. Aby to naprawić, można wylogować się z serwera i zalogować ponownie lub użyć poniższej komendy:

source ~/.bashrc

Można (ponownie) zweryfikować instalację

command -v nvm

i przejść do instalacji samego Node.

Nvm oferuje nam bardzo dużo opcji zarządzania naszym Node, które znajdziecie w linku zamieszczonym wyżej. Ja zainstaluję najnowszą dostępną wersję:

nvm install node

I gotowe! Możemy jeszcze, jak zwykle, sprawdzić, czy wszytko jest w porządku.

node -v
npm -v

Świetnie. Czas na instalację dockera.

Najprawdopodobniej będziemy musieli przed samą instalacją wykonać kilka dodatkowych kroków:

Instalujemy wstępne pakiety, które pozwolą korzystać z paczek przez HTTPS:

sudo apt install apt-transport-https ca-certificates curl software-properties-common

Kolejno dodajemy klucz GPG dla oficjalnego repozytorium Dockera do serwera:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Dodajemy repozytorium Dockera do źródeł APT:

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Aktualizujemy istniejącą listę pakietów, aby dodatek został rozpoznany:

sudo apt update

Warto upewnić się, że instalujemy z repozytorium Dockera, a nie z domyślnego repozytorium Ubuntu:

apt-cache policy docker-ce

Powinniśmy zobaczyć poniższą odpowiedź (numer wersji dla Dockera może być inny):

docker-ce:
  Installed: (none)
  Candidate: 5:20.10.14~3-0~ubuntu-jammy
  Version table:
     5:20.10.14~3-0~ubuntu-jammy 500
        500 https://download.docker.com/linux/ubuntu jammy/stable amd64 Packages
     5:20.10.13~3-0~ubuntu-jammy 500
        500 https://download.docker.com/linux/ubuntu jammy/stable amd64 Packages

I teraz już możemy przejść do zainstalowania samego Dockera:

sudo apt install docker-ce

Tak, zgadliście. Czas zweryfikować instalację:

sudo systemctl status docker

Jeśli zobaczycie coś takiego

Output
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2022-04-01 21:30:25 UTC; 22s ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 7854 (dockerd)
      Tasks: 7
     Memory: 38.3M
        CPU: 340ms
     CGroup: /system.slice/docker.service
             └─7854 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

to znak, że jesteśmy w domu.

Na sam koniec dodamy jeszcze narzędzie docker-compose, które pozwoli nam łatwiej zarządzać kontenerami.

mkdir -p ~/.docker/cli-plugins/
curl -SL https://github.com/docker/compose/releases/download/v2.3.3/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose

Kolejno ustawimy uprawnienia, niezbędne do poprawnego działania

chmod +x ~/.docker/cli-plugins/docker-compose

Wiem, powtarzam się. Ale każdorazowa weryfikacja po instalacji pakietu pozwoli w razie czego od razu zauważyć problemy. Dlatego sprawdzamy poprawność pakietu:

docker compose version

Jeśli odpowiedź wygląda podobnie do tej

Output
Docker Compose version v2.3.3

to gratuluję, serwer został poprawnie skonfigurowany i mamy na nim wszystkie najpotrzebniejsze narzędzia, z których będziemy w przyszłości korzystać.

Czy to wszystko?

Na dzisiaj tak, ale w przyszłości pojawią się nowe odcinki dotyczące zarządzania serwerem.

Raz jeszcze - traktujcie to jak podstawy podstaw, które w żadnym razie nie zrobią z was DevOpsów. Ale mogą być ciekawą umiejętnością - zarówno do CV, jak i do zabawy z własnymi projektami.

Tymczasem tradycyjnie zapraszam na mojego twixera 😊

Do następnego!