Dostęp do serwera tylko do odczytu
Dotyczy tylko aplikacji na własnym serwerze (Ubuntu / Debian). Przy Vercelu, Netlify czy Lovable nie ma czego przygotowywać.
Konto SSH tylko do odczytu
Osobne konto audyt: bez sudo do dowolnych komend, poza grupami administracyjnymi, bez dostępu do plików .env, logowanie wyłącznie kluczem, wygasa samo po 30 dniach. Około 15 minut — instrukcja poniżej. Nie znasz się na serwerach? Przejdziemy to razem na Meet, około 20 minut: udostępniasz ekran i sam wpisujesz komendy, a ja mówię, co wpisać, i od razu sprawdzam wynik — nie dostaję przy tym dostępu do serwera. Nie możesz dać konta wcale? Zadzwoń — ustalimy to indywidualnie.
Z konta korzystam ja i agent AI, z którym prowadzę audyt — wyłącznie do odczytu, bez dostępu do plików .env. Zanim agent się połączy, sam sprawdzam, co konto widzi. Dostęp dajesz dopiero po podpisaniu zgody na audyt i NDA. Wszystkie komendy wykonujesz Ty, na swoim koncie administratora.
Niczego ode mnie nie potrzebujesz
Mój klucz publiczny SSH jest już wpisany w komendę z kroku 5 — to nie jest sekret, można go pokazać każdemu. Datę wygaśnięcia komenda wylicza sama: dostęp wygasa 30 dni po wgraniu klucza. Wszystkie komendy wklejasz bez zmian, poza ścieżkami oznaczonymi wprost jako przykładowe.
Hasła nie ustawiamy i nigdzie go nie przesyłamy — logowanie wyłącznie kluczem.
Sprawdź, czy sekrety nie leżą w plikach czytelnych dla wszystkich
Nowe konto zobaczy każdy plik, który ma prawo odczytu „dla wszystkich”. Zanim je założysz, upewnij się, że nie ma wśród nich plików z hasłami i kluczami:
sudo find /var/www /srv /opt /home /etc -xdev -type f -perm -o=r \
-not -path '*/node_modules/*' -not -path '*/migrations/*' \
\( -name '.env*' -o -name '*.key' -o -name '*secret*' -o -name '*backup*' \
-o -name '*.dump' -o -name '*.sql' -o -name '*.cron' -o -name 'ecosystem.config*' \) \
-not -name '.env.example' 2>/dev/nullDruga komenda szuka kluczy prywatnych — publiczne certyfikaty pomija:
sudo find /var/www /srv /opt /home /etc -xdev -type f -perm -o=r -name '*.pem' \
-exec grep -l 'PRIVATE KEY' {} + 2>/dev/nullKażdy wynik to plik, który konto audytowe mogłoby przeczytać. Jeśli zawiera sekret — odbierz odczyt innym użytkownikom albo usuń plik, jeśli jest zbędny:
sudo chmod o-r /sciezka/do/plikuTypowe miejsca, w których sekret ląduje poza .env: kopie crontaba, stare zrzuty bazy, pliki konfiguracyjne menedżera procesów (np. ecosystem.config.js w pm2), skrypty wdrożeniowe. Crontaby użytkowników są chronione, ale /etc/crontab i pliki w /etc/cron.d/ może czytać każdy — sekretów nie trzymaj ani tam, ani w kopiach crontaba.
Ta kontrola i tak jest częścią audytu — lepiej, żeby wynik był pusty, zanim ktokolwiek się zaloguje.
Załóż konto audyt
sudo adduser --disabled-password --gecos "" audyt
sudo gpasswd -d audyt users
id audytNowsze wersje Ubuntu same dopisują konto do grupy users — druga linia je z niej usuwa (jeśli konta tam nie ma, zobaczysz komunikat o błędzie i to jest w porządku). Wynik id ma pokazywać tylko grupę audyt. Konta nie dodawaj do żadnej z grup:
| Grupa | Dlaczego nie |
|---|---|
| sudo, admin, wheel | pełne uprawnienia administratora |
| docker, lxd | dostęp do Dockera to w praktyce dostęp roota |
| adm, systemd-journal | odczyt logów — w logach są adresy IP i dane użytkowników aplikacji |
| grupa użytkownika aplikacji (np. www-data, ubuntu) | odczyt plików aplikacji, w tym .env, jeśli ma prawa dla grupy |
Zablokuj kontu odczyt plików .env
Pliki .env i .env.* są dla konta audyt zamknięte niezależnie od tego, jakie mają prawa dla grupy i dla wszystkich — blokadę zakłada lista ACL. Sprawdź, czy masz narzędzie:
command -v setfacl || sudo apt install aclPotem zablokuj wszystkie takie pliki na serwerze — komenda wypisze każdy, który objęła:
sudo find / -xdev -type f \( -name '.env' -o -name '.env.*' \) \
-exec setfacl -m u:audyt:--- {} + -printKontrola dla jednego pliku (ścieżkę podmień na swoją) — wynik ma zawierać user:audyt:---:
getfacl /var/www/aplikacja/.env | grep audytBlokada obejmuje pliki, które istnieją teraz. Jeśli w trakcie audytu wdrożenie utworzy nowy plik .env, powtórz komendę wyżej.
Wgraj klucz z datą ważności
Wklej komendy bez zmian — klucz jest mój, a datę wygaśnięcia (30 dni od dziś) wylicza date. Wpis jest pocięty na krótkie kawałki, bo długa linia łamie się przy wklejaniu do terminala:
sudo install -d -m 700 -o audyt -g audyt /home/audyt/.ssh
printf '%s%s%s%s%s\n' \
'expiry-time="' "$(date -d '+30 days' +%Y%m%d)" '",no-port-forwarding,' \
'no-agent-forwarding,no-X11-forwarding ' \
'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhfddecDgwE2AoGebHohtqn8lqxSbxgjSbFTRjYlBVx vibeaudit-audytor' \
| sudo tee /home/audyt/.ssh/authorized_keys
sudo wc -l /home/audyt/.ssh/authorized_keys
sudo chown audyt:audyt /home/audyt/.ssh/authorized_keys
sudo chmod 600 /home/audyt/.ssh/authorized_keys
sudo chage -E "$(date -d '+30 days' +%F)" audytwc -l ma pokazać 1. Więcej linii oznacza, że wpis się złamał — logowanie kluczem nie zadziała, wklej komendę jeszcze raz.
Dwie blokady czasowe: expiry-time wyłącza klucz, a chage -E całe konto — w tym samym dniu, nawet jeśli zapomnisz je usunąć.
expiry-time wymaga OpenSSH 8.2 lub nowszego (Ubuntu 20.04+, Debian 11+). Wersję sprawdzisz komendą ssh -V.
Sprawdź, czy w konfiguracji SSH jest lista dozwolonych użytkowników:
sudo sshd -T | grep -Ei '^(allowusers|allowgroups)'Pusty wynik = brak listy, nic nie robisz. Jeśli lista jest, poniższa komenda dopisze do niej audyt w osobnym pliku /etc/ssh/sshd_config.d/90-audyt.conf — istniejących wpisów nie zmienia, przed przeładowaniem SSH sprawdza składnię (sshd -t), a przy błędzie usuwa swój plik. Najpierw sprawdza, czy konfiguracja SSH wczytuje pliki z tego katalogu; jeśli nie, albo lista stoi w bloku Match, niczego nie zmienia i prosi o telefon. Na końcu wypisuje listę — ma na niej być audyt obok dotychczasowych kont:
if ! sudo sshd -T | grep -qi '^allowusers '; then
echo 'Brak listy AllowUsers - nic nie zmieniam'
elif ! sudo awk '{l=tolower($0)} l~/^[[:space:]]*match[[:space:]]/{m=1} l~/^[[:space:]]*include[[:space:]]/&&index(l,"sshd_config.d")&&!m{i=1} l~/^[[:space:]]*allowusers[[:space:]]/&&m{a=1} END{exit !(i&&!a)}' /etc/ssh/sshd_config; then
echo 'Nietypowa konfiguracja SSH - zadzwoń do mnie, dopiszemy konto razem'
else
echo 'AllowUsers audyt' | sudo tee /etc/ssh/sshd_config.d/90-audyt.conf
if sudo sshd -t; then sudo systemctl reload ssh || sudo systemctl reload sshd; else sudo rm /etc/ssh/sshd_config.d/90-audyt.conf; fi
sudo sshd -T | grep -i '^allowusers'
fiJeśli pierwsza komenda pokazała allowgroups, konto musiałoby trafić do jednej z tych grup — zadzwoń, ustalimy to razem.
Na koniec sprawdź, czy SSH wpuszcza konto audyt do próby logowania. Pierwsza komenda zakończy się Permission denied — to w porządku, bo mój klucz jest tylko u mnie. Druga pokazuje wpis serwera o tej próbie:
ssh -o BatchMode=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
-p "$(sudo sshd -T | awk '/^port /{print $2; exit}')" audyt@localhost true
sudo journalctl -u ssh -u sshd --since '-2 min' --no-pager | grep audytWpis z not allowed because not listed in AllowUsers albo expired oznacza, że konto jest zablokowane — wróć do komend wyżej. Wpis bez tych słów (np. Connection closed by authenticating user audyt) jest prawidłowy.
Zrób jednorazowy zrzut ustawień serwera
Część ustawień widzi tylko administrator: faktyczna konfiguracja SSH, reguły firewalla, kto może łączyć się z bazą, zadania w harmonogramie. Zamiast dawać kontu sudo, uruchamiasz raz mój skrypt i przesyłasz mi plik z wynikiem. Skrypt wyłącznie czyta standardowe pliki systemowe — nie zagląda do katalogów aplikacji, plików .env ani logów, z bazy PostgreSQL odczytuje tylko listę kont i baz (bez danych), a hasła i tokeny w wyniku zamazuje. Druga komenda pokazuje jego treść, zanim go uruchomisz (wyjście z podglądu: q):
curl -fsSLO https://vibeaudit.pl/zrzut-admin.sh
less zrzut-admin.sh
sudo bash zrzut-admin.sh > zrzut-admin.txt
wc -l zrzut-admin.txtSkrypt wypisuje też uprawnienia sudo zwykłych kont użytkowników. Jeśli aplikację wdraża konto systemowe (np. deploy bez powłoki logowania), podaj jego nazwę przy uruchomieniu:
sudo bash zrzut-admin.sh deploy > zrzut-admin.txtWolisz uruchamiać komendy ze swojego komputera? Użyj ssh -t — bez -t sudo nie zapyta o hasło, a podgląd nie zadziała. admin@adres-serwera zamień na swoje konto administratora i adres serwera. Kolejno: pobranie i podgląd skryptu, uruchomienie, pobranie wyniku na komputer:
ssh -t admin@adres-serwera 'curl -fsSLO https://vibeaudit.pl/zrzut-admin.sh && less zrzut-admin.sh'
ssh -t admin@adres-serwera 'sudo bash zrzut-admin.sh > zrzut-admin.txt && wc -l zrzut-admin.txt'
scp admin@adres-serwera:zrzut-admin.txt .Plik zrzut-admin.txt pobierz na swój komputer (np. scp albo przez program, którym łączysz się z serwerem) i prześlij mi go w kroku 8 — jako plik, nie wklejony do maila, bo wklejka łamie linie. Możesz go przejrzeć przed wysłaniem.
Bez tego kroku punkty „firewall”, „konfiguracja SSH”, „dostęp do bazy” i „harmonogram zadań” trafią do raportu jako niesprawdzone.
Sprawdź, co konto widzi
Zanim prześlesz mi dane dostępowe, sprawdź konto sam. Ścieżkę do .env podmień na swoją:
sudo -l -U audyt
sudo -u audyt cat /var/www/aplikacja/.env
sudo -u audyt ls /rootOczekiwany wynik: sudo -l mówi, że konto nie może używać sudo, a dwie kolejne komendy kończą się Permission denied. Jeśli .env się wyświetla — wróć do kroku 4 i sprawdź ponownie.
Konto zobaczy
- wersję systemu i listę oczekujących aktualizacji
- otwarte porty i działające procesy
- konfigurację nginx / Apache i SSH
- konfigurację SSH, firewalla i bazy — z pliku z kroku 6, nie z konta
- uprawnienia katalogów aplikacji
- pliki czytelne dla wszystkich — stąd krok 2
Konto nie zobaczy
- plików .env i sekretów aplikacji
- crontabów innych użytkowników
- zawartości bazy danych
- logów systemowych i logów aplikacji
- kluczy prywatnych i certyfikatów
- katalogów domowych innych użytkowników
Prześlij mi dane dostępowe
Wystarczą cztery rzeczy: adres serwera, port SSH i nazwa konta (audyt) oraz plik zrzut-admin.txt z kroku 6 — na kontakt@vibeaudit.pl. Żadnych haseł, kluczy prywatnych ani plików .env — jeśli czegoś potrzebuję, poproszę o to wprost.
Po audycie usuń konto
sudo rm -f /etc/ssh/sshd_config.d/90-audyt.conf
sudo sshd -t && (sudo systemctl reload ssh || sudo systemctl reload sshd)
sudo pkill -u audyt
sudo userdel -r audyt
rm zrzut-admin.sh zrzut-admin.txtBlok usuwa też plik z listą dozwolonych użytkowników SSH, jeśli komenda z kroku 5 go utworzyła (jeśli nie — nic się nie stanie), i przeładowuje SSH. Potwierdzenie usunięcia odnotowuję w dokumentacji audytu.
Nawet jeśli tego nie zrobisz, klucz i konto wygasną same w dniu ustawionym w kroku 5.
Instrukcja dotyczy serwerów z systemem Ubuntu lub Debian; na innych systemach nazwy pakietów i ścieżki mogą się różnić. Coś nie działa? Zadzwoń albo napisz — przejdziemy przez to razem. Więcej pytań: FAQ.