/var/www/app/
├── releases/
│ ├── 20260227_120000/ ← nowa wersja
│ ├── 20260226_120000/ ← poprzednia
│ └── 20260225_120000/ ← starsza
├── current → releases/20260227_120000/ ← symlink
└── shared/
├── .env
├── storage/
└── vendor/
- Snapshot serwera (Hetzner:
hcloud server create-image)
- Backup bazy danych
- Sprawdź wolne miejsce na dysku (>20%)
- Sprawdź health endpoint aktualnej wersji
- Sprawdź health endpoint nowej wersji
- Sprawdź logi (brak 500 errors)
- Sprawdź metryki CPU (brak spike)
- Jeśli błąd → rollback (symlink na poprzednią wersję)
# Przełącz symlink na poprzedni release
ln -sfn /var/www/app/releases/PREVIOUS /var/www/app/current
# Restart PHP-FPM
sudo systemctl restart php8.2-fpm
# Verify
curl -s https://app.example.com/health
# Pełny dump z kompresją
mysqldump -u user -p'password' --single-transaction --routines --triggers database | gzip > backup_$(date +%Y%m%d_%H%M%S).sql.gz
# Weryfikacja integralności
gzip -t backup_*.sql.gz && echo "OK" || echo "CORRUPTED"
# Restore
gunzip < backup.sql.gz | mysql -u user -p'password' database
| Typ |
Częstotliwość |
Przechowywanie |
| Daily |
co 24h |
7 dni |
| Weekly |
co niedzielę |
4 tygodnie |
| Monthly |
1. dnia miesiąca |
12 miesięcy |
// Dump przez API
await ovh.requestPromised('POST', '/hosting/web/{svc}/database/{name}/dump', {
date: 'now' // 'now', 'daily.1', 'weekly.1'
});
// Lista dostępnych dumpów
const dumps = await ovh.requestPromised('GET', '/hosting/web/{svc}/database/{name}/dump');
| Metryka |
OK |
Uwaga |
Alarm |
| Dysk |
< 70% |
70–85% |
> 85% |
| RAM |
< 75% |
75–90% |
> 90% |
| Load (16 vCPU) |
< 8 |
8–14 |
> 14 |
| Wiek backupu |
< 7h |
7–12h |
> 12h |
| SSL expiry |
> 30d |
14–30d |
< 14d |
| 5xx errors/h |
0 |
1–10 |
> 10 |
| DB quota (OVH) |
< 80% |
80–90% |
> 90% |
# VPS — metryki systemowe
ssh deploy@46.225.114.176 'df -h && free -m && uptime'
# Hetzner API — metryki
hcloud server metrics data-collector-1 --type cpu,disk,network
# OVH — status hostingu
# (przez SDK, CLI nie obsługuje /hosting/web)
# Logi błędów
ssh deploy@HOST 'tail -50 /var/log/nginx/error.log'
ssh deploy@HOST 'tail -50 /var/www/app/current/storage/logs/laravel.log'
- Sprawdź ping:
ping 46.225.114.176
- Sprawdź port 22:
nc -zv 46.225.114.176 22
- Hetzner:
hcloud server describe data-collector-1 → status
- Jeśli status=off →
hcloud server poweron data-collector-1
- Jeśli status=running ale brak SSH → Rescue mode:
hcloud server enable-rescue data-collector-1 --type linux64
hcloud server reboot data-collector-1
# SSH do rescue → mount /dev/sda1 /mnt → diagnozuj
- Eskaluj do Orchestratora/Piotra jeśli nie rozwiązane w 30 min
- Sprawdź status:
systemctl status mysql
- Sprawdź logi:
tail -100 /var/log/mysql/error.log
- Jeśli corrupted → restore z ostatniego dumpa
- Jeśli brak dumpa → Hetzner snapshot → rebuild
# Sprawdź datę wygaśnięcia
echo | openssl s_client -connect HOST:443 2>/dev/null | openssl x509 -noout -dates
# Odnów certbot
sudo certbot renew
# OVH (shared hosting) — przez API
# POST /hosting/web/{svc}/ssl/regenerate
| Element |
Standard |
| SSH |
Port 22, key-only, PermitRootLogin=no, MaxAuthTries=3 |
| UFW |
DENY incoming, ALLOW 22,80,443 |
| Fail2ban |
SSH: maxretry=3, bantime=3600 |
| Aktualizacje |
unattended-upgrades enabled (security only) |
| MySQL |
bind-address=127.0.0.1, strong passwords |
| Redis |
bind 127.0.0.1, no public access |
| PHP |
expose_php=Off, display_errors=Off (prod) |
Po każdej operacji:
- Konsola — pełny raport (dla użytkownika)
- #ops — podsumowanie na Rocket.Chat
- Twenty CRM — zaktualizuj status taska
- Krytyczne → eskalacja do Orchestratora natychmiast
Runbooks: ops/devops-team/.claude/runbooks/
Skills: ops/devops-team/.claude/skills/
Ostatnia aktualizacja: 2026-02-27