Pełna instalacja ręczna: od świeżo zakupionego VPS do działającego panelu, krok po kroku.
Przygotowanie serwera, utworzenie witryny, baza danych, config.php i SSL są opisane tutaj.
Polecenia dla każdego narzędzia zabezpieczeń i dla cron znajdują się w
materiałach FAQ, odnośniki w tekście.
Najważniejsza zasada: zmieniając SSH lub zaporę, nie zamykaj bieżącego połączenia, dopóki nie sprawdzisz nowego w osobnym oknie. Jeśli mimo to utracisz dostęp — niemal wszyscy hostingodawcy udostępniają awaryjną konsolę (VNC/Recovery) w panelu zarządzania.
01. Kupiłem VPS z Ubuntu/Debian — od czego zacząć
Po zakupie hoster przesyła: adres IP, nazwę użytkownika (zwykle root) i hasło (lub klucz SSH). To wystarczy do zalogowania. Kolejność działań (każdy krok — sekcja poniżej):
Połącz się z serwerem przez SSH;
Zaktualizuj system, ustaw nazwę hosta i strefę czasową;
Utwórz zwykłego użytkownika z uprawnieniami sudo (nie pracuj jako root);
Skonfiguruj logowanie kluczem SSH i wyłącz logowanie hasłem;
Włącz zaporę i automatyczną ochronę;
(opcjonalnie) zainstaluj panel zarządzania HestiaCP — serwer WWW, bazę danych i pocztę „od ręki”.
02. Pierwsze połączenie przez SSH
SSH to bezpieczny terminal do serwera. W miejsce 203.0.113.10 proszę wpisać własny adres IP.
203.0.113.10 to przykład, adres nieistniejący (zarezerwowany do dokumentacji). Proszę nie wpisywać go dosłownie — należy zastąpić go prawdziwym adresem IP serwera z wiadomości od hostingodawcy. Inaczej połączenie się nie powiedzie.
Windows 10/11: proszę otworzyć PowerShell lub „Terminal” i użyć wbudowanego ssh (albo klientów PuTTY / MobaXterm). macOS / Linux: proszę otworzyć „Terminal”.
# Logowanie jako root (hasło przysłał hostingodawca):
ssh root@203.0.113.10
# Jeśli hostingodawca dał plik klucza zamiast hasła:
ssh -i ścieżka/do/klucza root@203.0.113.10
Przy pierwszym połączeniu SSH zapyta o „authenticity of host” — proszę wpisać yes. Hasło podczas wpisywania nie jest wyświetlane (to normalne). Jeśli hostingodawca dał hasło tymczasowe — proszę zmienić je poleceniem passwd.
03. Aktualizacja systemu i konfiguracja podstawowa
Na początek zaktualizuj wszystkie pakiety oraz ustaw nazwę hosta i strefę czasową.
Lista stref czasowych — timedatectl list-timezones. Jeśli na końcu aktualizacji pojawi się niebieskie okno „Daemons using outdated libraries” — zaznacz wszystkie usługi (spacja) i naciśnij OK, jest to bezpieczne.
04. Tworzenie użytkownika z sudo
Stała praca jako root jest niebezpieczna. Proszę utworzyć zwykłego użytkownika i nadać mu uprawnienia sudo (uruchamianie poleceń administratora w razie potrzeby). Proszę zastąpić deploy dowolną nazwą.
# Utwórz użytkownika (ustawi hasło i zapyta o dane — można Enter):
adduser deploy
# Dodaj do grupy sudo:
usermod -aG sudo deploy
# Sprawdź (jako root):
su - deploy
sudo whoami # powinno wypisać: root
exit
Następnie proszę logować się na serwer już jako ten użytkownik: ssh deploy@203.0.113.10, a polecenia administratora uruchamiać z przedrostkiem sudo.
05. Klucze SSH i wyłączenie logowania hasłem
Logowanie kluczem jest bezpieczniejsze niż hasłem: hasło można odgadnąć, klucza — praktycznie nie. Najpierw tworzymy klucz na własnym komputerze, kopiujemy go na serwer, sprawdzamy logowanie — i dopiero potem wyłączamy hasło.
Krok 1. Utwórz klucz na własnym komputerze (Windows PowerShell / macOS / Linux):
ssh-keygen -t ed25519 -C "my-laptop"
# Enter przy każdym pytaniu (klucz trafi do ~/.ssh/id_ed25519)
Krok 3. Sprawdź logowanie kluczem w nowym oknie — powinno wpuszczać bez hasła:
ssh deploy@203.0.113.10
Nie wykonuj Wariantu B, dopóki logowanie kluczem nie zostanie sprawdzone i nie zadziała (Kroki 1–3), i nie zamykaj bieżącej sesji. Wyłącza on logowanie hasłem dla wszystkich użytkowników, łącznie z root. Bez działającego klucza całkowicie utraci Pan dostęp do serwera — przywrócić go będzie można tylko przez konsolę hostingu. Nie ma klucza — wybierz Wariant A.
Krok 4. Zaostrz dostęp przez SSH. Ustawienia umieszczamy w osobnym pliku, głównej konfiguracji nie ruszamy. Wybierz wariant odpowiedni do sytuacji:
Wariant A — tylko zablokuj root, hasło pozostaw. Klucz nie jest potrzebny, dostępu Pan nie utraci:
Wariant B — pełne wzmocnienie. Wyłącz logowanie hasłem i pozostaw root tylko przez klucz. Wykonaj to tylko po upewnieniu się, że logowanie kluczem działa:
sudo tee /etc/ssh/sshd_config.d/00-hardening.conf >/dev/null <<'EOF'
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
KbdInteractiveAuthentication no
EOF
sudo systemctl restart ssh
W obu wariantach root przez hasło jest zablokowany. PermitRootLogin no całkowicie zabrania logowania root, prohibit-password — pozostawia logowanie tylko przez klucz (do administrowania loguj się jako deploy i używaj sudo). Jeśli chce Pan zmienić port SSH — dodaj wiersz Port 2222, ale najpierw otwórz nowy port w zaporze (następny rozdział) i sprawdź logowanie, inaczej odetnie Pan sobie dostęp.
06. Podstawowa zapora i automatyczna ochrona
Zablokuj wszystko, co zbędne, za pomocą zapory i włącz fail2ban (banuje próby łamania hasła po SSH). Najpierw zezwól na SSH, w przeciwnym razie po włączeniu UFW utracisz dostęp.
# Zezwól na SSH (lub własny port, jeśli był zmieniony) oraz web:
sudo ufw allow OpenSSH
sudo ufw allow 80,443/tcp
# Włącz zaporę:
sudo ufw enable
sudo ufw status verbose
# fail2ban — ochrona SSH przed łamaniem hasła (profil podstawowy aktywny od razu):
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
To niezbędne minimum. Robocze ustawienia fail2ban, lista blokad ipsum, rozszerzone UFW i pozostałe narzędzia znajdziesz w grupie „Narzędzia bezpieczeństwa” w informatorze. Sam panel Arcivéo Monitor przejrzyście pokaże status tego wszystkiego.
07. Instalacja panelu HestiaCP (opcjonalnie)
HestiaCP — bezpłatny panel zarządzania hostingiem: instaluje i konfiguruje serwer WWW (nginx + apache), PHP, bazę danych (MariaDB), pocztę, DNS oraz certyfikaty SSL, udostępnia interfejs webowy dla witryn. Wygodny, gdy nie chce się Pan/Pani konfigurować wszystkiego ręcznie i planuje hostować witryny (w tym sam panel Arcivéo Monitor).
Instaluj HestiaCP na czystym serwerze (świeży, wspierany Ubuntu/Debian, minimum ~1–2 GB RAM), przed instalacją innych serwerów WWW i baz danych — inaczej wystąpią konflikty. Instalacja trwa 10–20 minut i zrestartuje serwer.
# Pobierz instalator i uruchom:
wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh
sudo bash hst-install.sh
Instalator zapyta o email i nazwę hosta, następnie zainstaluje cały stos. Po restarcie panel będzie dostępny pod adresem https://YOUR_IP:8083 (login i hasło instalator pokaże na końcu).
HestiaCP samodzielnie zarządza UFW i fail2ban — nie trzeba ich konfigurować osobno, zrobi to sama. Klucze SSH i wyłączenie hasła (poprzedni rozdział) i tak proszę wykonać.
08. Wymagania systemowe i ionCube
Panel to aplikacja PHP działająca na typowym stosie LAMP/LEMP:
System: Linux (zalecane Ubuntu/Debian);
Serwer WWW: nginx lub Apache z PHP-FPM;
PHP 8.0+ z rozszerzeniami: pdo_mysql, openssl, curl, json, mbstring;
ionCube Loader — rozszerzenie PHP niezbędne do działania panelu;
Baza danych: MySQL 5.7+ lub MariaDB 10.3+;
HTTPS — obowiązkowo (logowanie i WebAuthn działają tylko przez https);
sudo dla użytkownika serwera WWW (wąski zestaw — krok 13).
# Sprawdź wersję PHP i rozszerzenia:
php -v
php -m | grep -iE 'pdo_mysql|openssl|curl|mbstring|ioncube'
Instalacja ionCube Loader (jeśli jeszcze nie jest zainstalowany). Na hostingu z panelem (HestiaCP, cPanel) ionCube włącza się polem wyboru w ustawieniach PHP. Ręcznie na Ubuntu/Debian:
# Sprawdź wersję PHP i katalog rozszerzeń:
php -v
EXTDIR=$(php -r 'echo ini_get("extension_dir");'); PHPVER=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
# Pobierz i rozpakuj loadery (64-bit):
cd /tmp
wget -q https://downloads.ioncube.com/loader_downloads/ioncube_loaders_lin_x86-64.tar.gz
tar xzf ioncube_loaders_lin_x86-64.tar.gz
# Skopiuj loader dla Pana wersji PHP do katalogu rozszerzeń:
sudo cp ioncube/ioncube_loader_lin_${PHPVER}.so "$EXTDIR"/
# Podłącz (CLI + PHP-FPM) i uruchom ponownie:
echo "zend_extension=ioncube_loader_lin_${PHPVER}.so" | sudo tee /etc/php/${PHPVER}/mods-available/ioncube.ini
sudo phpenmod ioncube
sudo systemctl restart php${PHPVER}-fpm
# Weryfikacja — w wyniku pojawi się wiersz "with the ionCube PHP Loader":
php -v
Wersja loadera musi być zgodna z wersją PHP (np. ioncube_loader_lin_8.1.so dla PHP 8.1). Jeśli używa Pan kilku wersji PHP — podłącz loader dla każdej z nich.
09. Domena i DNS
Aby otwierać panel pod adresem w rodzaju monitor.example.com i uzyskać bezpłatny SSL — potrzebna jest domena wskazująca na Pana serwer. W panelu zarządzania DNS proszę utworzyć rekord A:
Typ: A
Nazwa: monitor (subdomena → monitor.example.com)
lub @ (korzeń domeny → example.com)
Wartość: 203.0.113.10 ← IP Pana serwera
TTL: 3600
Po kilku minutach proszę sprawdzić, czy domena wskazuje na serwer:
dig +short monitor.example.com # powinien zwrócić Pana IP
# lub, jeśli nie ma dig:
getent hosts monitor.example.com
Certyfikat SSL Let's Encrypt jest wydawany wyłącznie na domenę — DNS musi wskazywać na serwer przed wydaniem certyfikatu.
10. Utwórz witrynę i wgraj pliki panelu
Apache: DocumentRoot — na katalog główny panelu, NIE na public/. Style (CSS/JS), sw.js, manifest.json znajdują się w assets/ obok public/ i są pobierane z katalogu głównego witryny. Główny .htaccess to front-controller. Jeśli w Apache ustawi się DocumentRoot na public/, panel otworzy się bez stylów. W czystym nginx jest odwrotnie: katalogiem głównym jest public/, a assets/ są udostępniane osobną regułą (patrz blok nginx poniżej).
Pliki panelu (archiwum dystrybucji) pobiera się po zakupie w panelu my.arciveo.com → „Pobieranie”. Rozpakuj archiwum przed wgraniem.
1) Utwórz katalog panelu i wgraj do niego zawartość dystrybucji (aby w środku znalazły się public/, assets/, config.php itd.):
sudo mkdir -p /var/www/monitor
# następnie wgraj pliki dystrybucji do /var/www/monitor (FileZilla / WinSCP / scp)
2) Skonfiguruj serwer WWW.Apache: DocumentRoot — na katalog główny panelu (NIE na /public); AllowOverride All jest wymagany. Ścieżka do gniazda PHP-FPM jest wykrywana automatycznie. Blok wkleja się do terminala w całości:
nginx: nginx nie ma .htaccess, dlatego katalogiem głównym bierzemy public/, a assets/, sw.js, manifest.json (poziom wyżej) udostępniamy osobną regułą:
PHPSOCK=$(ls -1 /run/php/php*-fpm.sock 2>/dev/null | head -1) # automatyczne wykrywanie gniazda PHP-FPM
sudo tee /etc/nginx/sites-available/monitor.conf > /dev/null <<'EOF'
server {
listen 80;
server_name monitor.example.com;
root /var/www/monitor/public;
index index.php;
# assets, service worker i manifest znajdują się poziom wyżej niż public/
location ~ ^/(assets/|sw\.js|manifest\.json) { root /var/www/monitor; }
location / { try_files $uri $uri/ /index.php?$query_string; }
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:__PHPSOCK__;
}
}
EOF
sudo sed -i "s#__PHPSOCK__#${PHPSOCK}#" /etc/nginx/sites-available/monitor.conf
sudo ln -s /etc/nginx/sites-available/monitor.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Wgrywanie plików — SFTP/SCP (FileZilla, WinSCP) lub scp:
# Przykład przez scp z komputera lokalnego:
scp -r ./monitor/* deploy@203.0.113.10:/var/www/monitor/
Ustaw uprawnienia do plików — to krok obowiązkowy. Jeśli wgrywano jako root lub przez SFTP, pliki należą do root i serwer WWW (www-data) nie będzie mógł ich odczytać — panel otworzy się pusty lub z błędem 403 (w logu: .htaccess unreadable / directory not executable). Poniższe polecenie to naprawia:
# Normalizujemy uprawnienia całego webroota: katalog utworzony przez root jest niedostępny
# dla serwera WWW (www-data) — bez tego panel zwraca pustą stronę lub 403.
# Apache działa jako www-data; jeśli masz innego użytkownika WWW — zamień.
cd /var/www/monitor
# Foldery robocze tworzymy PRZED chown — inaczej nowe katalogi pozostaną root:root
# i przy chmod 750 serwer WWW (www-data) nie będzie mógł w nich zapisywać.
sudo mkdir -p data/lynis data/logwatch tmp logs
sudo chown -R www-data:www-data /var/www/monitor
sudo find /var/www/monitor -type d -exec chmod 755 {} \;
sudo find /var/www/monitor -type f -exec chmod 644 {} \;
sudo chmod 640 /var/www/monitor/config.php
sudo chmod 750 data tmp logs
3) Proszę otworzyć sobie wgrywanie plików przez SFTP. Po powyższym poleceniu wszystkie pliki należą do www-data, a FileZilla / WinSCP łączą się na własnym użytkowniku — wgrywanie zakończy się wtedy błędem SSH_FX_PERMISSION_DENIED (Permission denied). Logowanie jako root w celu wgrania plików nie wchodzi w grę — logowanie root wyłączono w kroku 05. Proszę wybrać jeden z dwóch wariantów.
Wariant A — ACL tylko dla własnego użytkownika (zalecany). Prawo zapisu otrzymuje wyłącznie użytkownik; serwer WWW nadal nie może nadpisać kodu panelu:
sudo apt install -y acl
# Prawo zapisu dla własnego użytkownika do całego katalogu panelu:
sudo setfacl -R -m u:deploy:rwX /var/www/monitor
# Ta sama reguła domyślnie — dla plików i katalogów utworzonych później:
sudo setfacl -R -d -m u:deploy:rwX /var/www/monitor
Wariant B — przez grupę www-data. Prostszy, ale prawo zapisu do plików panelu dostaje również serwer WWW: przy podatności w PHP kod dałoby się podmienić. Kolejność poleceń ma znaczenie — config.php i katalogi robocze zamyka się na końcu:
sudo usermod -aG www-data deploy
# Zapis dla grupy + setgid (bit 2): pliki wgrane przez SFTP pozostają
# w grupie www-data — inaczej panel nie będzie mógł ich nadpisać.
sudo find /var/www/monitor -type d -exec chmod 2775 {} \;
sudo find /var/www/monitor -type f -exec chmod 664 {} \;
sudo chmod 640 /var/www/monitor/config.php
sudo chmod 2750 /var/www/monitor/data /var/www/monitor/tmp /var/www/monitor/logs
Po wariancie B proszę połączyć się ponownie w FileZilli (Serwer → Rozłącz, następnie zalogować się na nowo) — nowa grupa działa dopiero przy nowym logowaniu, wcześniej uprawnień nadal nie będzie. Sprawdzenie: id deploy — na liście grup musi pojawić się www-data; ls -ld /var/www/monitor — uprawnienia drwxrwsr-x, litera s zamiast x oznacza, że setgid jest ustawiony.
11. Baza danych
Proszę utworzyć bazę i użytkownika, a następnie zaimportować schemat. Blok wkleja się do terminala w całości. monitor_db i monitor_user to nazwy przykładowe, może Pan/Pani ustawić dowolne własne; proszę zapamiętać nazwę bazy, użytkownika i hasło — wpisze je Pan/Pani w config.php w następnym kroku:
# 1. Baza danych. Hasło ustawia się RAZ w DBPASS i jest podstawiane do wszystkich linii.
# Blok wkleja się do terminala W CAŁOŚCI; sudo mysql loguje root przez gniazdo unix
# (hasło root nie jest potrzebne). NIE używaj interaktywnego `sudo mysql -u root -p`
# z kopiuj-wklej — przy wklejaniu linie SQL trafią do zapytania o hasło i przepadną.
DBPASS='CHOOSE_A_PASSWORD' # ← zmień tylko tę linię
sudo mysql <<SQL
CREATE DATABASE IF NOT EXISTS monitor_db CHARACTER SET utf8mb4;
CREATE USER IF NOT EXISTS 'monitor_user'@'localhost' IDENTIFIED BY '$DBPASS';
GRANT ALL ON monitor_db.* TO 'monitor_user'@'localhost';
FLUSH PRIVILEGES;
SQL
# Sprawdzenie (powinno pokazać monitor_db):
mysql -u monitor_user -p"$DBPASS" -e "SHOW DATABASES;"
# To samo hasło wpisz w config.php → DB_PASS.
Schematu nie trzeba importować — panel sam tworzy tabele i konto admin przy pierwszym wejściu w przeglądarce (z database/db.sql), jeśli baza jest pusta. Ręczny import schematu jest potrzebny tylko wtedy, gdy automatyczna inicjalizacja nie zadziałała.
Jeśli użyto przeglądarkowego instalatora public/start_db.php — proszę go usunąć zaraz po instalacji: pozwala on bez autoryzacji odtworzyć bazę. Dopóki plik znajduje się w katalogu głównym panelu lub w public/, panel wyświetla czerwone ostrzeżenie.
12. Konfiguracja config.php
config.php w katalogu głównym panelu (/var/www/monitor/config.php) to jedyny plik, który trzeba edytować ręcznie. Wszystkie ustawienia panelu są w nim zdefiniowane jako stałe define(). Proszę otworzyć go w edytorze:
sudo nano /var/www/monitor/config.php
Proszę wstawić własne wartości w podświetlonych miejscach; resztę proszę zostawić bez zmian:
// --- Baza danych (z kroku 11) ---
define('DB_HOST', 'localhost'); // zostawić
define('DB_NAME', 'db_name'); // utworzona w kroku 11
define('DB_USER', 'user'); // utworzony w kroku 11
define('DB_PASS', 'db_password'); // ustawione w kroku 11
define('DB_CHARSET', 'utf8mb4'); // zostawić
// --- Aplikacja ---
define('APP_URL', 'https://monitor.example.com'); // adres panelu, bez ukośnika na końcu
define('TIMEZONE', 'Europe/Warsaw'); // Pana/Pani strefa czasowa
// --- Czas sesji ---
define('SESSION_LIFETIME', 28800); // bezczynność do ponownego logowania, s (28800 = 8 h)
Co zmienić:
DB_NAME, DB_USER, DB_PASS — dokładnie te same nazwa bazy, użytkownik i hasło, które ustawiono przy tworzeniu bazy w kroku 11 (jeśli pozostawiono przykłady — monitor_db / monitor_user). DB_HOST i DB_CHARSET proszę zostawić bez zmian.
APP_URL — pełny adres panelu z https://, bez ukośnika na końcu i bez www. Musi być zgodny z domeną, na której aktywuje się licencję (krok 16), inaczej klucz zostanie odrzucony.
TIMEZONE — Pana/Pani strefa czasowa (lista — timedatectl list-timezones). Wpływa tylko na to, jak panel wyświetla daty; na czas uruchamiania zadań cron nie wpływa (tam obowiązuje strefa systemu).
SESSION_LIFETIME — po ilu sekundach bezczynności panel poprosi o ponowne logowanie (domyślnie 8 godzin). Np. 3600 = 1 godzina, 86400 = doba.
Proszę zapisać plik (Ctrl+O, Enter, następnie Ctrl+X) i uruchomić ponownie PHP-FPM — inaczej zmiany nie zostaną zastosowane przez OPcache:
sudo systemctl restart php*-fpm
config.php — plik tajny (zawiera hasło bazy danych). Znajduje się w katalogu głównym panelu, który jest zarazem katalogiem głównym serwera WWW, ale jest zabezpieczony: uprawnienia 640 (ustawione w kroku 10) i jawny zakaz w głównym .htaccess. Proszę nie umieszczać go w publicznych repozytoriach i nie przekazywać do wsparcia z prawdziwym hasłem.
PHP działa jako użytkownik serwera WWW, który nie ma uprawnień do poleceń systemowych. Dostęp przyznaje się wąsko: punktowe sudo na konkretne narzędzia oraz odczyt logów przez grupy (bez sudo). Włamanie do warstwy WWW nie daje roota.
W przykładach www-data to standardowy użytkownik Apache. Jeśli u Pana jest inny (w niektórych panelach PHP działa pod odrębnym użytkownikiem) — proszę zamienić wszędzie. Sprawdzenie: ps -o user= -C php-fpm | sort -u.
# UFW — status i reguły (strona „Zapora”)
www-data ALL=(ALL) NOPASSWD: /usr/sbin/ufw status, /usr/sbin/ufw status verbose, /usr/sbin/ufw status numbered
www-data ALL=(ALL) NOPASSWD: /usr/sbin/ufw allow [0-9]*, /usr/sbin/ufw deny [0-9]*, /usr/sbin/ufw --force delete [0-9]*
# Fail2ban — status, ban i unban (banned zwraca bany wszystkich jaili jednym poleceniem;
# ban/unban potrzebne przyciskom panelu)
www-data ALL=(ALL) NOPASSWD: /usr/bin/fail2ban-client status, /usr/bin/fail2ban-client status *, /usr/bin/fail2ban-client banned, /usr/bin/fail2ban-client set * banip *, /usr/bin/fail2ban-client set * unbanip *
# Aktualizacje zabezpieczeń (karta „Aktualizacje”). Tylko odczyt, ale właśnie od roota:
# cache apt (~70 MB) dostępny jest tylko rootowi, użytkownik nie-root przebudowuje go przy każdym wywołaniu
# (4.2 s CPU wobec 0.01 s). Bez wildcarda — dokładnie to jedno polecenie, niczego nie instaluje.
www-data ALL=(ALL) NOPASSWD: /usr/bin/apt list --upgradable
# IPset (mapa ataków, dashboard)
www-data ALL=(ALL) NOPASSWD: /usr/sbin/ipset list -t ipsum
# CrowdSec
www-data ALL=(ALL) NOPASSWD: /usr/bin/cscli decisions list *, /usr/bin/cscli alerts list *, /usr/bin/cscli bouncers list *, /usr/bin/cscli scenarios list *
# Auditd — wyszukiwanie zdarzeń + odczyt ostatnich wierszy dziennika (dokładna ścieżka)
www-data ALL=(ALL) NOPASSWD: /usr/sbin/ausearch -m *
www-data ALL=(ALL) NOPASSWD: /usr/bin/tail -n 300 /var/log/audit/audit.log
# Monit / ModSecurity / AppArmor / PSAD
www-data ALL=(ALL) NOPASSWD: /usr/bin/monit status
www-data ALL=(ALL) NOPASSWD: /usr/sbin/apache2ctl -M
www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-modsec
www-data ALL=(ALL) NOPASSWD: /usr/sbin/aa-status
www-data ALL=(ALL) NOPASSWD: /usr/sbin/psad --Status
# Otwarte porty (dzienniki jądra/SSH/Falco czytane są BEZ sudo — przez grupę
# systemd-journal, patrz p.2; sudo dla journalctl NIE trzeba dawać i jest to niebezpieczne)
www-data ALL=(ALL) NOPASSWD: /usr/bin/ss -tuln, /usr/sbin/ss -tuln, /bin/ss -tuln
# PostgreSQL (tylko jeśli używane) — stały skrypt read-only,
# utworzyć wg FAQ „PostgreSQL się nie wyświetla”; bez niego proszę usunąć wiersz
www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-pgstat
2. Dostęp do logów i dziennika systemd. Moduły czytają /var/log/fail2ban.log, auth.log, ufw.log, apache2/*, aide bezpośrednio (na Debian/Ubuntu logi te należą do grupy adm). Zdarzenia jądra, SSH i Falco pobierane są z journald poleceniem journalctlbez sudo, przez grupę systemd-journal. Proszę dodać użytkownika WWW do obu grup i zrestartować PHP-FPM:
sudo usermod -aG adm,systemd-journal www-data
sudo systemctl restart php*-fpm # obowiązkowo, inaczej grupy się nie zastosują
3. Jeśli ClamAV lub Suricata piszą logi nie do grupy adm (bywa root:root) — proszę nadać dostęp przez ACL:
4. Nakładka ModSecurity. Dziennik audytu WAF (/var/log/apache2/modsec_audit.log) należy do roota z prawami 640, użytkownik WWW nie może go czytać bezpośrednio. Strona ModSecurity pobiera tryb silnika, zdarzenia i listę aktywnych reguł przez stały skrypt read-only — to on jest dozwolony w sudoers wierszem powyżej:
Bez pliku /etc/modsecurity/modsecurity.conf sam WAF nie działa: pakiet umieszcza tylko modsecurity.conf-recommended, a silnik reguł pozostaje wyłączony — jak go włączyć, patrz FAQ → „Instalacja ModSecurity”.
Użytkownik we wszystkich wierszach sudoers musi zgadzać się z użytkownikiem puli FPM: na zwykłym Apache/Debian jest to www-data, w HestiaCP pula witryny działa od właściciela witryny (np. admin) — proszę sprawdzić grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf.
5. Jeśli przed Apache stoi Nginx (HestiaCP, ISPmanager i inne panele — tam Nginx proksuje PHP do Apache, a statykę serwuje sam). Katalogi służbowe są zabezpieczone plikami .htaccess, ale Nginx ich nie czyta: dowolny plik statyczny (.json, .txt, .log, .dat) zwróci bezpośrednio, z pominięciem Apache. Na zewnątrz wyciekną cache panelu i dane — na przykład tmp/modsec_cache.json ze zdarzeniami WAF i IP atakujących. Proszę dodać blokadę do konfiguracji witryny Nginx:
Prefiks ^~ jest obowiązkowy: jest wybierany wcześniej niż reguła wyrażenia regularnego dla statyki wewnątrz location /, inaczej blokada nie zadziała.
W HestiaCP proszę umieścić to jako osobny plik /home/<user>/conf/web/<domain>/nginx.ssl.conf_deny (oraz nginx.conf_deny dla HTTP) — konfiguracja witryny dołącza nginx.ssl.conf_* i przy przebudowie takich plików nie nadpisuje. Zastosowanie: sudo nginx -t && sudo systemctl reload nginx.
Sprawdzenie: curl -s -o /dev/null -w '%{http_code}\n' https://monitor.example.com/tmp/modsec_cache.json — powinno być 403. Jeśli Apache działa bez Nginx (nasłuchuje 80/443 sam), nic dodawać nie trzeba — .htaccess wystarczy.
Ścieżki do plików binarnych proszę sprawdzić przez which (np. which ufw cscli ausearch ss). Sudoers proszę edytować wyłącznie przez visudo. Listę wszystkich baz MySQL włącza się osobnym GRANT (FAQ → „Widoczna tylko jedna baza”).
14. Ograniczenie dostępu według IP
Proszę ograniczyć dostęp do monitora według adresu IP — nawet jeśli adres URL stanie się znany, strona logowania się nie otworzy. Można to zrobić na poziomie serwera WWW (przykład dla nginx poniżej) lub w samym panelu („Ustawienia” → „Ograniczenie dostępu według IP”). Jeśli używa Pan Apache, proszę skorzystać z ograniczenia w panelu.
Jeśli witryna nginx jest już skonfigurowana według kroku 10, nie należy dodawać drugiegolocation / — proszę wpisać wiersze allow/deny do już istniejącego bloku. Dwa jednakowe location / w jednym server { } to błąd konfiguracji i nginx się nie zrestartuje.
# W konfiguracji nginx (wewnątrz server { }):
# Ścieżkę ACME Let's Encrypt zostawiamy otwartą z pominięciem ograniczenia IP —
# aby wystawianie i automatyczne odnawianie SSL (krok 15) nie zależały od filtra IP.
location ^~ /.well-known/acme-challenge/ { allow all; }
location / {
allow 203.0.113.10; # ← proszę wpisać swój IP
allow 10.0.0.0/8; # sieć lokalna (jeśli potrzebne)
deny all;
try_files $uri $uri/ /index.php?$query_string;
}
# Przeładuj nginx:
sudo nginx -t && sudo systemctl reload nginx
15. Wystawianie certyfikatu SSL (HTTPS)
Panel działa wyłącznie przez HTTPS. Sesja logowania korzysta z zabezpieczonego cookie, a WebAuthn (2FA) działa tylko na HTTPS. Przez http:// nie można się zalogować.
Certyfikat jest darmowy (Let's Encrypt). DNS domeny musi już wskazywać na serwer. Polecenie zależy od serwera WWW:
# Apache:
sudo certbot --apache -d monitor.example.com
# nginx — TYLKO jeśli używasz właśnie nginx. Na Apache NIE uruchamiaj:
# apt pobierze nginx i zajmie port 80, konflikt z Apache.
# sudo apt install python3-certbot-nginx
# sudo certbot --nginx -d monitor.example.com
# certbot sam wpisze HTTPS do konfiguracji i skonfiguruje automatyczne odnawianie
O co zapyta certbot: e-mail → zgoda na Terms (Y) → przekazanie e-maila do EFF (według uznania). Następnie sam wystawi certyfikat, wpisze <VirtualHost *:443>, skonfiguruje przekierowanie http→https oraz automatyczne odnawianie.
DNS musi wskazywać na serwer PRZED uruchomieniem certbot (weryfikacja własności przez port 80). Sprawdzenie: dig +short monitor.example.com → IP serwera. Porty 80/443 otwarte: sudo ufw allow 80,443/tcp.
Po wystawieniu: https://monitor.example.com otwiera się z kłódką, http:// przekierowuje na https:// (APP_URL w config.php ustawiono już w kroku 12).
16. Logowanie i konfiguracja początkowa
Proszę otworzyć https://monitor.example.com, zalogować się admin / useradmin i przejść listę kontrolną:
Zmień hasło admin — sekcja „Użytkownicy” w menu.
Włącz WebAuthn (2FA) — „Klucze WebAuthn” → zarejestruj klucz/passkey (wymaga HTTPS). Proszę od razu zarejestrować dwa: w razie utraty jedynego klucza logowanie przy jego użyciu będzie niemożliwe. Więcej.
Ogranicz dostęp według IP — „Ustawienia” → „Ograniczenie dostępu według IP” (proszę wpisać swój IP przed włączeniem, inaczej odetnie sobie Pan/Pani dostęp).
Wprowadź licencję — kod ARCIVEO-… z panelu klienta proszę aktywować na swojej domenie i wkleić klucz w „Ustawienia” → „Licencja”. Więcej.
Skonfiguruj powiadomienia — Telegram i/lub Email w „Ustawienia”. Więcej.
Usuń instalatorpublic/start_db.php, jeśli pozostał (krok 11).
17. Narzędzia bezpieczeństwa (opcjonalnie)
Panel już działa. Narzędzia instaluje się według potrzeb — instaluje Pan/Pani to, co potrzebne, a panel od razu pokaże status. Polecenia instalacji każdego z nich znajdują się w dokumentacji (osobne sekcje dla poszczególnych narzędzi):
To wersja demonstracyjna Arcivéo Security Monitor przeznaczona tylko do podglądu — wszelkie zmiany są wyłączone. Proszę wdrożyć ją na własnym serwerze, aby zarządzać rzeczywistymi danymi bezpieczeństwa.