# Terraform Registry — Полное описание > Этот документ — точка входа для нового чата/агента. Содержит всё необходимое для понимания, сопровождения и доработки реестра провайдера. --- ## Что это такое Кастомный Terraform Registry Server для провайдера `nubes` (облако Nubes / ngcloud.ru). Когда разработчик пишет в своём `.tf`: ```hcl terraform { required_providers { nubes = { source = "terra.k8c.ru/nubes/nubes" version = "5.0.18" } } } ``` ...и выполняет `terraform init`, Terraform идёт к **этому** серверу за бинарниками провайдера. --- ## Структура папки ``` REGISTRY/ ├── server/ — Go-код HTTP-сервера реестра (АКТУАЛЬНЫЙ) ├── operator/ — Kubernetes Operator (CRD TerraformProviderRelease) + старая копия server-кода в cmd/registry/ ├── k8s/ — Kubernetes манифесты деплоя (namespace, ingress, deployment, service, TLS) ├── registrykeys/ — Go-модуль с публичным GPG-ключом (для верификации провайдера) ├── charts/ — Helm chart для деплоя registry-server └── scripts/ └── build-and-push-registry-server.sh — сборка Docker-образа и push в registry ``` **Важно:** `server/` и `operator/cmd/registry/` — дублирующийся код. Актуальный и полный — только `server/main.go`. В `operator/cmd/registry/main.go` нет health-эндпоинтов и не удалены darwin-платформы. При правках менять только `server/`. --- ## Как работает registry-server ### Реализованный протокол [Terraform Registry Protocol v1](https://developer.hashicorp.com/terraform/internals/provider-registry-protocol). | Эндпоинт | Назначение | |---|---| | `GET /.well-known/terraform.json` | Discovery — говорит Terraform, где API реестра | | `GET /v1/providers/{ns}/{name}/versions` | Список доступных версий и платформ | | `GET /v1/providers/{ns}/{name}/{version}/download/{os}/{arch}` | URL для скачивания бинарника | | `GET /v1/proxy?url=...` | Проксирование файлов из S3 (бинарники, SHA, GPG-сигнатура) | | `GET /docs/{ns}/{name}/{version}/...` | Документация провайдера (статический HTML из S3) | | `GET /healthz` | Health probe для Kubernetes | | `GET /readyz` | Readiness probe для Kubernetes | ### Как определяются версии Сервер листит S3 bucket в поиске файлов вида: ``` ////terraform-provider-__linux_amd64.zip ``` Из имён файлов парсит версию и платформы. Поддерживаемые платформы: `linux_amd64`, `linux_arm64`, `windows_amd64`. ### Переменные окружения | Переменная | Default | Назначение | |---|---|---| | `REGISTRY_HOSTNAME` | `localhost:8080` | Домен реестра (используется в URL ответов) | | `S3_ENDPOINT` | — | Хост S3 без схемы, например `s3.msk-1.ngcloud.ru` | | `S3_ACCESS_KEY` | — | S3 access key | | `S3_SECRET_KEY` | — | S3 secret key | | `S3_BUCKET` | `terraform-registry` | Имя бакета | | `S3_USE_SSL` | — | Если `true` — HTTPS (в коде Secure: true захардкожено) | ### S3 структура бакета ``` terraform-registry/ ← бакет └── terra.k8c.ru/ └── nubes/ └── nubes/ └── 5.0.18/ ├── terraform-provider-nubes_5.0.18_linux_amd64.zip ├── terraform-provider-nubes_5.0.18_windows_amd64.zip ├── terraform-provider-nubes_5.0.18_SHA256SUMS └── terraform-provider-nubes_5.0.18_SHA256SUMS.sig docs/ └── nubes/ └── nubes/ └── 5.0.18/ └── index.html (и другие файлы документации) ``` --- ## GPG-ключ Terraform верифицирует подпись провайдера через GPG. - Публичный ключ **встроен** в `server/main.go` (ASCII Armor, константа в коде). - Также хранится в `registrykeys/public_key.go` (отдельный go-модуль). - Приватный ключ — `secrets/private_key.asc` (НЕ в репо, gitignore). **При ротации ключей:** 1. Сгенерировать новую пару `gpg --gen-key` 2. Обновить ASCII Armor в `server/main.go` 3. Пересобрать и передеплоить Docker-образ 4. Перезалить все артефакты провайдера, подписанные новым ключом --- ## Деплой в Kubernetes ### Кластер и namespace - Namespace: `terra` - Домен: `terra.k8c.ru` (планируемая миграция → `registry.nubes.ru`, см. `../docs/ops/DOMAIN_MIGRATION.md`) - TLS: cert-manager с `letsencrypt-prod` issuer — **НЕ ТРОГАТЬ** сертификат руками! ### Что задеплоено | Ресурс | Kind | Образ | |---|---|---| | `registry-server` | Deployment | `naeel/terraform-registry-server:gpg-key-20260208` | | `registry-server` | Service | ClusterIP :8080 | | `registry-ingress` | Ingress | host: `terra.k8c.ru` | Credentials S3 — из секрета `s3-credentials` (ключи `access-key`, `secret-key`). ### Применение манифестов (только при смене конфигурации кластера) ```bash kubectl apply -f k8s/operator/manifests/00-namespace.yaml kubectl apply -f k8s/operator/manifests/00-rbac.yaml kubectl apply -f k8s/operator/manifests/02-crd.yaml kubectl apply -f k8s/operator/manifests/05-registry-server.yaml ``` ### Диагностика (read-only) ```bash kubectl -n terra get pods,svc,ingress,deploy kubectl -n terra logs -l app=registry-server --tail=50 kubectl -n terra get certificate registry-tls -o yaml ``` --- ## Сборка и публикация нового образа Скрипт: `scripts/build-and-push-registry-server.sh` ```bash cd REGISTRY ./scripts/build-and-push-registry-server.sh ``` Собирает Docker-образ из `server/` и пушит в Docker Hub (`naeel/terraform-registry-server:`). После push нужно обновить тег образа в `operator/manifests/05-registry-server.yaml` и применить `kubectl apply`. --- ## Когда registry НЕ нужно трогать Registry — stateless сервис. При выпуске новой версии провайдера (`nubes`) registry не меняется: ``` Новая версия провайдера: 1. go build → бинарники 2. devops/03_build_and_upload_provider.sh → бинарники в S3 3. devops/04_build_and_publish_docs.sh → документация в S3 ✅ Registry автоматически начинает отдавать новую версию ❌ kubectl не нужен ❌ код registry не меняется ❌ Docker-образ не пересобирается ``` Registry пересобирается только если меняется **сам сервер**: новые эндпоинты, логика, ротация GPG-ключа. --- ## Связь с основным репо провайдера Этот код был перемещён из основного репо `terraform/` в папку `REGISTRY/` для последующего выноса в отдельный репозиторий. Код провайдера и код реестра полностью независимы — нет общих go-модулей, нет импортов друг друга. --- ## Ограничения и правила работы - **Ручные правки `operator/cmd/registry/`** — не делать, это устаревшая копия. Актуальный код — только `server/`. - **Let's Encrypt cert-manager** (`letsencrypt-prod`) — не применять `kubectl apply` на Ingress-ресурсы без именённой необходимости (риск бана от CA). - **docker build** — только с явного разрешения разработчика. - **kubectl** — только read-only (`get`, `describe`, `logs`) без разрешения. - **S3 credentials** — никогда не коммитить в репо. Только через секреты k8s или переменные окружения.