# Bezpieczeństwo i wzmacnianie {#security-hardening}
SnapOtter przetwarza pliki w całości na twojej infrastrukturze. Domyślnie wysyła anonimową, pozbawioną treści analitykę produktu i raporty o awariach, aby pomóc ulepszać projekt. Nigdy nie wysyła twoich plików, nazw plików, zawartości plików, wyniku OCR, metadanych obrazów ani tekstu dokumentów. Opcjonalna informacja zwrotna jest wysyłana dopiero po jej przesłaniu przez użytkownika, tylko gdy analityka jest włączona, a pola kontaktowe są dołączane wyłącznie za wyraźną zgodą na kontakt. Administrator może wyłączyć analitykę i zbieranie informacji zwrotnej jednym kliknięciem w Ustawienia > System > Prywatność, bez konieczności przebudowy. Przetwarzanie plików zawsze pozostaje wewnątrz twojego kontenera.
Kontener działa jako dedykowany użytkownik nie-root (`snapotter`) z odrzuconymi wszystkimi uprawnieniami Linuksa poza minimalnym wymaganym zestawem. Po pełną politykę ujawniania podatności i architekturę bezpieczeństwa zobacz [SECURITY.md](https://github.com/snapotter-hq/SnapOtter/blob/main/SECURITY.md) na GitHub.
## Wzmacnianie kontenera {#container-hardening}
[Domyślny docker-compose.yml](https://github.com/snapotter-hq/SnapOtter/blob/main/docker/docker-compose.yml) zawiera produkcyjne wzmacnianie bezpieczeństwa. Oto rozbicie każdej opcji i wyjaśnienie, dlaczego ma znaczenie:
```yaml
services:
SnapOtter:
image:snapotter/snapotter:latest
ports:
# Bind to localhost only for internet-facing deployments:
### Dlaczego `no-new-privileges` nie jest ustawione {#why-no-new-privileges-is-not-set}
`security_opt: [no-new-privileges:true]` jest celowo pominięte. Punkt wejścia startuje jako root, aby naprawić własność wolumenów, a następnie schodzi do użytkownika `snapotter` przez [gosu](https://github.com/tianon/gosu), które wymaga setuid. Po ukończeniu obniżenia uprawnień proces działa jako `snapotter` z usuniętymi wszystkimi uprawnieniami poza pięcioma wymienionymi powyżej.
Jeśli używasz Kubernetes lub flagi `--user` Dockera, aby uruchomić bezpośrednio jako nie-root (omijając gosu), `no-new-privileges` można bezpiecznie włączyć.
### Dlaczego `read_only` nie jest ustawione {#why-read-only-is-not-set}
`read_only: true` nie jest ustawione, ponieważ remapowanie PUID/PGID zapisuje do `/etc/passwd` i `/etc/group` przy uruchamianiu. Jeśli używasz flagi `--user` Dockera lub `runAsUser` Kubernetes zamiast PUID/PGID, możesz bezpiecznie włączyć system plików root tylko do odczytu.
## Izolacja sieci {#network-isolation}
Podczas normalnej pracy kontener nawiązuje **zero wychodzących połączeń sieciowych**. Całe przetwarzanie plików odbywa się lokalnie z użyciem dołączonych bibliotek.
Jedynym wyjątkiem są **pobrania modeli AI**: gdy użytkownik instaluje pakiet funkcji AI przez interfejs, kontener pobiera gotowe archiwum pakietu z Hugging Face plus kilka pojedynczych plików modeli z GitHub Releases, Google Storage i PyPI. Te pobrania odbywają się raz na pakiet i są przechowywane w wolumenie `/data`.
**Zalecenia dotyczące zapory sieciowej:**
| Scenariusz | Reguła wychodząca |
|---|---|
| Odizolowany od sieci (bez AI) | Zablokuj cały ruch wychodzący z kontenera |
| Potrzebne pakiety AI | Zezwól na HTTPS do `huggingface.co`, `*.xethub.hf.co`, `cdn-lfs.huggingface.co`, `github.com`, `objects.githubusercontent.com`, `storage.googleapis.com`, `pypi.org`, `files.pythonhosted.org` podczas instalacji, następnie zablokuj |
| Po instalacji AI | Zablokuj cały ruch wychodzący, modele są buforowane lokalnie |
Archiwa pakietów są serwowane z pamięci masowej Xet Hugging Face, która przesyła przez punkty końcowe `*.xethub.hf.co` równolegle i to właśnie sprawia, że pobrania wielogigabajtowych pakietów są szybkie. Jeśli twoja zapora zezwala na `huggingface.co`, ale blokuje `*.xethub.hf.co`, instalacje nadal się powodzą, ale przechodzą na wolniejsze pobieranie jednostrumieniowe, więc dodaj hosty Xet do listy dozwolonych, aby pozostać na szybkiej ścieżce. W pełni offline instalacje mogą pominąć to wszystko i zamiast tego użyć [Importu pakietów offline](/pl/guide/deployment).
Po konfigurację reverse proxy (Nginx, Traefik, Caddy, Tunele Cloudflare) zobacz [Przewodnik wdrożenia](/pl/guide/deployment#reverse-proxy).
## Sekrety Docker {#docker-secrets}
Dla wdrożeń produkcyjnych unikaj przekazywania sekretów jako zmiennych środowiskowych w postaci zwykłego tekstu. Punkt wejścia obsługuje konwencję `_FILE` Dockera: zamontuj sekret jako plik i ustaw odpowiednią zmienną `_FILE` na jego ścieżkę.
Sekrety Docker Compose (bez Swarm) wymagają Compose v2.23 lub nowszego.
:::
## Wdrożenie Kubernetes {#kubernetes-deployment}
Punkt wejścia wykrywa, kiedy kontener już działa jako nie-root (np. przez `runAsUser` Kubernetes) i automatycznie pomija obniżenie uprawnień gosu. W takim przypadku nie może sam zmienić własności zamontowanych wolumenów przez chown, więc weryfikuje, czy są zapisywalne, i wcześnie kończy z praktycznymi wskazówkami, jeśli nie są, zobacz [Uprawnienia pamięci masowej](/pl/guide/deployment#storage-permissions) po `fsGroup` i konfiguracje z obcym UID (TrueNAS, OpenShift).
**Zalecany SecurityContext poda:**
```yaml
apiVersion:apps/v1
kind:Deployment
metadata:
name:snapotter
spec:
replicas:1
selector:
matchLabels:
app:snapotter
template:
metadata:
labels:
app:snapotter
spec:
securityContext:
runAsNonRoot:true
runAsUser:999
runAsGroup:999
fsGroup:999
containers:
- name:snapotter
image:snapotter/snapotter:latest
ports:
- containerPort:1349
securityContext:
allowPrivilegeEscalation:false
capabilities:
drop:[ALL]
resources:
requests:
cpu:"1"
memory:2Gi
limits:
cpu:"4"
memory:6Gi
livenessProbe:
httpGet:
path:/api/v1/health
port:1349
initialDelaySeconds:60
periodSeconds:30
timeoutSeconds:5
readinessProbe:
httpGet:
path:/api/v1/health
port:1349
initialDelaySeconds:10
periodSeconds:10
timeoutSeconds:5
volumeMounts:
- name:data
mountPath:/data
- name:workspace
mountPath:/tmp/workspace
volumes:
- name:data
persistentVolumeClaim:
claimName:snapotter-data
- name:workspace
emptyDir:
medium:Memory
sizeLimit:2Gi
```
Ponieważ `runAsUser: 999` jest ustawione na poziomie poda, punkt wejścia całkowicie pomija gosu. Pozwala to na uprawnienia `allowPrivilegeEscalation: false` i `drop: [ALL]` bez konfliktu.
Po dobór rozmiaru zasobów zobacz [Wymagania sprzętowe](/pl/guide/deployment#hardware-requirements).
## Kopie zapasowe i odzyskiwanie {#backup-and-recovery}
Trwały stan jest podzielony na dwa wolumeny:
| Wolumen | Zawartość | Krytyczny? |
|---|---|---|
| `SnapOtter-pgdata` | Baza danych PostgreSQL (użytkownicy, ustawienia, potoki, zadania, dziennik audytu) | Tak |
| `/data` (wolumen aplikacji) | Pliki przesłane przez użytkownika, modele AI, venv Pythona | Częściowo (patrz niżej) |
W obrębie wolumenu `/data`:
| Ścieżka | Zawartość | Krytyczna? |
|---|---|---|
| `/data/uploads/`, `/data/outputs/` | Pliki użytkownika i wyniki przetwarzania | Tak |
| `/data/ai/` | Pobrane pliki modeli AI | Nie (do ponownego pobrania) |
| `/data/venv/` | Wirtualne środowisko Pythona | Nie (odbudowywane przy starcie) |
### Kopia zapasowa bazy danych {#database-backup}
Użyj `pg_dump`, aby wykonać kopię zapasową bazy danych podczas działania stosu:
# Snapshot the app data volume (excluding re-downloadable AI models)
docker run --rm -v SnapOtter-data:/data -v $(pwd)/backup:/backup \
alpine tar czf /backup/snapotter-files.tar.gz \
--exclude='ai' --exclude='venv' -C /data .
```
Modele AI wynoszą łącznie do około 24 GB dla wszystkich pakietów. Ponieważ można je ponownie pobrać, wyłącz `/data/ai/` i `/data/venv/` z kopii zapasowych, aby zaoszczędzić miejsce. Tylko baza danych i pliki użytkownika są krytyczne.
## Artefakty zgodności {#compliance-artifacts}
Każde wydanie SnapOtter zawiera następujące artefakty bezpieczeństwa:
| Analiza statyczna | CodeQL (JS/TS + Python) | Zakładka [GitHub Security](https://github.com/snapotter-hq/SnapOtter/security), uruchamiana co tydzień + na każdy PR |
| Przegląd zależności | Natywny GitHub | Kontrola na PR, zawodzi przy dodaniach o wysokiej wadze |
| Audyt zależności Pythona | pip-audit | Log uruchomienia CI przy każdym push |
| Polityka bezpieczeństwa | Markdown | [SECURITY.md](https://github.com/snapotter-hq/SnapOtter/blob/main/SECURITY.md) w repozytorium |
| Aktualizacje zależności | Dependabot | Zautomatyzowane cotygodniowe PR dla npm, pip, Docker, Actions |
**Uruchamianie własnego skanu:**
Pobierz SBOM z wydania i przeskanuj go preferowanym narzędziem:
```bash
# Scan with Grype using the CycloneDX SBOM
grype sbom:snapotter-v1.17.2-sbom.cdx.json
# Scan with Trivy using the SPDX SBOM
trivy sbom snapotter-v1.17.2-sbom.spdx.json
# Scan the Docker image directly
trivy image snapotter/snapotter:1.17.2
```
::: info
SBOM i skan podatności odzwierciedlają dokładny obraz opublikowany dla tego wydania. Pakiety modeli AI zainstalowane po wdrożeniu nie są uwzględnione w SBOM, ponieważ są pobierane w czasie działania.