diff --git a/Dockerfile b/Dockerfile index b8fa3bb..0d803e0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,9 @@ RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/gateway FROM alpine:3.19 RUN apk add --no-cache ca-certificates wget \ && addgroup -S gateway -g 65532 \ - && adduser -S -u 65532 -G gateway gateway + && adduser -S -u 65532 -G gateway gateway \ + && mkdir -p /var/lib/telemt-gateway \ + && chown gateway:gateway /var/lib/telemt-gateway COPY --from=build /out/gateway /gateway USER gateway:gateway EXPOSE 8080 diff --git a/docs/GEOIP.md b/docs/GEOIP.md index d9655b6..22e761f 100644 --- a/docs/GEOIP.md +++ b/docs/GEOIP.md @@ -35,6 +35,14 @@ geoip: - Если локального файла нет, а указан соответствующий `*_download_url`, при старте выполняется загрузка. - URL с суффиксом **`.gz`** обрабатываются как gzip; иначе тело ответа пишется в файл как есть (подходит для GitHub raw `.mmdb`). +### Права на каталог (permission denied) + +Загрузка пишет файл во **всех** родительские каталоги `database_path` / `asn_database_path` (создаёт их через `mkdir`, если возможно). Процесс шлюза должен иметь право **создавать каталог** и **писать** в него. + +- **Docker-образ** этого репозитория создаёт `/var/lib/telemt-gateway` и отдаёт его пользователю `gateway` — пути из примера выше подходят из коробки. +- Если вы монтируете свой volume на этот путь, убедитесь, что uid/gid совпадают с пользователем контейнера (например `65532`) или задайте в конфиге путь внутри уже доступного тома. +- Для быстрого теста без `/var/lib` можно указать, например, **`/tmp/telemt-gateway/GeoLite2-City.mmdb`** (учтите, что `/tmp` может очищаться). + ## Лицензия GeoLite2 распространяется MaxMind на условиях [лицензии](https://dev.maxmind.com/geoip/geolite2-free-data-feed). Сторонние зеркала и репозитории используйте на свой риск; для продакшена часто нужен свой ключ MaxMind и обновление БД. diff --git a/internal/geoip/download.go b/internal/geoip/download.go index cf62260..dcfb80e 100644 --- a/internal/geoip/download.go +++ b/internal/geoip/download.go @@ -38,11 +38,11 @@ func downloadRawMMDB(ctx context.Context, client *http.Client, url, destPath str } dir := filepath.Dir(destPath) if err := os.MkdirAll(dir, 0o755); err != nil { - return fmt.Errorf("geoip mkdir: %w", err) + return fmt.Errorf("geoip mkdir %q: %w (directory must exist or be creatable by the process)", dir, err) } tmp, err := os.CreateTemp(dir, "geolite-*.mmdb.part") if err != nil { - return err + return fmt.Errorf("geoip temp file in %q: %w", dir, err) } tmpPath := tmp.Name() _, copyErr := io.Copy(tmp, resp.Body) @@ -87,11 +87,11 @@ func downloadGzippedMMDB(ctx context.Context, client *http.Client, url, destPath dir := filepath.Dir(destPath) if err := os.MkdirAll(dir, 0o755); err != nil { - return fmt.Errorf("geoip mkdir: %w", err) + return fmt.Errorf("geoip mkdir %q: %w (directory must exist or be creatable by the process)", dir, err) } tmp, err := os.CreateTemp(dir, "geolite-*.mmdb.part") if err != nil { - return err + return fmt.Errorf("geoip temp file in %q: %w", dir, err) } tmpPath := tmp.Name() _, copyErr := io.Copy(tmp, gzr)