Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Полная автономия: работа в закрытом контуре
autonomy

Полная автономия: работа в закрытом контуре

Offline-развёртывание, зеркалирование репозиториев, управление зависимостями без доступа к интернету, air-gap стратегии.

Полная автономия: работа в закрытом контуре

Offline-развёртывание, зеркалирование репозиториев, управление зависимостями без доступа к интернету, air-gap стратегии

#Мотивация

Представьте: вы работаете в банке, государственной организации или оборонной компании. Ваша инфраструктура полностью изолирована от интернета — никаких внешних подключений, облаков, публичных репозиториев. Это air-gap (воздушный зазор) — физическая или логическая изоляция.

В таких условиях стандартные практики DevOps не работают:

  • npm install не выполнится без доступа к npm registry
  • docker pull не скачает образы без Docker Hub
  • git clone с GitHub невозможен

Эта тема — о том, как построить полностью автономную Git-платформу на базе Gitea для работы в закрытом контуре.

#Архитектура air-gap решения

┌─────────────────────────────────────────────────────────────────┐
│                    Интернет (внешний мир)                       │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐ │
│  │   GitHub    │  │  Docker Hub │  │  npm/pypi/maven registry│ │
│  └─────────────┘  └─────────────┘  └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
                              ↑
                    (синхронизация через промежуточный сервер)
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│                   Промежуточный сервер (DMZ)                    │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │  Кэш зеркал: git, docker, npm, pypi, maven                │  │
│  │  Скрипты синхронизации (по расписанию)                    │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
                              ↑
                    (односторонняя синхронизация)
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│                  Закрытый контур (внутренняя сеть)              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐  │
│  │    Gitea    │  │   Registry  │  │  Artifact Repository    │  │
│  │   сервер    │  │  образов    │  │  (npm/pypi/maven)       │  │
│  └─────────────┘  └─────────────┘  └─────────────────────────┘  │
│         ↑                                                       │
│         └────────────────────────────────────────────────────── │
│                    Внутренняя сеть организации                  │
└─────────────────────────────────────────────────────────────────┘

#Сценарий 1: Зеркалирование репозиториев с GitHub/GitLab

#1.1. Настройка зеркала в Gitea

Gitea имеет встроенную функцию зеркалирования репозиториев.

Шаги:

  1. Создание зеркала:

    • Войдите в Gitea
    • + → Импортировать репозиторий
    • URL: https://github.com/organization/repo.git
    • Выберите Зеркало (Mirror)
    • Нажмите Импортировать
  2. Настройка интервала синхронизации:

В app.ini (или через переменные окружения):

[repository] DEFAULT_MIRROR_INTERVAL = 60 # минут
  1. Ручная синхронизация:
# Через веб-интерфейс: репозиторий → Настройки → Зеркало → Синхронизировать # Через API curl -X POST http://gitea/api/v1/repos/{owner}/{repo}/mirror-sync \ -H "Authorization: token YOUR_TOKEN"

#1.2. Миграция через git clone --mirror

Для разового переноса без автоматической синхронизации:

# На машине с доступом к интернету git clone --mirror https://github.com/organization/repo.git cd repo.git git push --mirror ssh://git@gitea.internal:2222/team/repo.git

Разбор команд:

  • --mirror — клонирует все refs (ветки, теги, remote-tracking)
  • push --mirror — отправляет все refs на удалённый сервер

#1.3. Массовая миграция скриптом

migrate_all.sh:

#!/bin/bash GITEA_HOST="git.internal.company.ru" GITEA_PORT="2222" ORG_NAME="internal" # Список репозиториев для миграции REPOS=( "https://github.com/org/backend-api" "https://github.com/org/frontend-web" "https://github.com/org/shared-lib" ) for repo_url in "${REPOS[@]}"; do repo_name=$(basename "$repo_url" .git) echo "Миграция: $repo_name" # Клонирование зеркала git clone --mirror "$repo_url" "$repo_name.git" cd "$repo_name.git" # Создание репозитория в Gitea через API curl -X POST "http://$GITEA_HOST/api/v1/org/$ORG_NAME/repos" \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "{ \"name\": \"$repo_name\", \"private\": true, \"auto_init\": false }" # Push зеркала git push --mirror "ssh://git@$GITEA_HOST:$GITEA_PORT/$ORG_NAME/$repo_name.git" # Очистка cd .. rm -rf "$repo_name.git" echo "✓ $repo_name завершено" done

#Сценарий 2: Локальный Docker Registry

#2.1. Развёртывание Registry в закрытом контуре

docker-compose.registry.yml:

version: '3.8' services: registry: image: registry:2 container_name: docker-registry restart: unless-stopped ports: - "5000:5000" volumes: - ./registry-data:/var/lib/registry - ./registry-config:/etc/docker/registry environment: - REGISTRY_STORAGE_DELETE_ENABLED=true networks: - internal-net registry-ui: image: joxit/docker-registry-ui:latest container_name: registry-ui restart: unless-stopped ports: - "8080:80" environment: - DOCKER_REGISTRY_URL=http://registry:5000 - SHOW_CONTENT_DIGEST=true - NGINX_PROXY_PASS_URL=http://registry:5000 depends_on: - registry networks: - internal-net networks: internal-net: driver: bridge

#2.2. Синхронизация образов с Docker Hub

На промежуточном сервере (с доступом к интернету):

# Список необходимых образов IMAGES=( "gitea/gitea:latest" "postgres:15-alpine" "nginx:alpine" "node:20-alpine" "python:3.11-slim" ) # Скачивание и сохранение for image in "${IMAGES[@]}"; do docker pull "$image" safe_name=$(echo "$image" | sed 's/\//_/g' | sed 's/:/-/g') docker save -o "./images/${safe_name}.tar" "$image" done

Перенос в закрытый контур:

# Через съёмный носитель или scp scp ./images/*.tar user@internal-server:/opt/registry/import/

Загрузка в локальный Registry:

cd /opt/registry/import for tar_file in *.tar; do docker load -i "$tar_file" # Получение имени образа из метаданных image_name=$(docker inspect --format='{{.RepoTags}}' "$(docker images -q | head -1)" | tr -d '[]' | cut -d',' -f1) # Тегирование для локального registry docker tag "$image_name" "localhost:5000/$image_name" # Push в registry docker push "localhost:5000/$image_name" echo "✓ Загружено: $image_name" done

#2.3. Настройка Docker для использования локального Registry

/etc/docker/daemon.json на всех узлах:

{ "insecure-registries": ["registry.internal:5000"], "registry-mirrors": ["http://registry.internal:5000"] }

Перезапуск Docker:

sudo systemctl restart docker

#Сценарий 3: Менеджеры пакетов (npm, pip, Maven)

#3.1. Nexus Repository Manager для артефактов

Nexus — универсальное хранилище артефактов с поддержкой npm, PyPI, Maven, Docker.

docker-compose.nexus.yml:

version: '3.8' services: nexus: image: sonatype/nexus3:latest container_name: nexus restart: unless-stopped ports: - "8081:8081" volumes: - ./nexus-data:/nexus-data environment: - INSTALL4J_ADD_VM_PARAMS=-Xms2g -Xmx4g -XX:MaxDirectMemorySize=2g networks: - internal-net networks: internal-net: driver: bridge

Первоначальная настройка Nexus:

  1. Получение пароля администратора:
docker exec nexus cat /nexus-data/admin.password
  1. Вход: http://nexus:8081 (admin / пароль из файла)

  2. Создание репозиториев:

    • npm-proxy → прокси к https://registry.npmjs.org
    • npm-hosted → для внутренних пакетов
    • npm-group → объединяет proxy + hosted

#3.2. Настройка npm для работы с Nexus

.npmrc в проекте:

registry=http://nexus.internal:8081/repository/npm-group/

Глобальная настройка:

npm config set registry http://nexus.internal:8081/repository/npm-group/

#3.3. Синхронизация npm-пакетов

На промежуточном сервере:

# Использование verdaccio как кэша docker run -d --name verdaccio -p 4873:4873 verdaccio/verdaccio # Настройка .npmrc для скачивания через verdaccio echo "registry=http://localhost:4873/" > ~/.npmrc # Установка пакетов (кэширование) npm install lodash express react --prefix /tmp/cache # Экспорт кэша cp -r /usr/local/share/.cache/verdaccio /opt/npm-cache/

Перенос в закрытый контур:

# Копирование кэша scp -r /opt/npm-cache user@internal:/opt/nexus/import/ # Импорт в Nexus (через API или UI)

#3.4. PyPI (Python) зеркало

Nexus PyPI proxy:

  1. В Nexus создайте репозиторий:
    • pypi-proxy (type: pypi proxy, remote: https://pypi.org)
    • pypi-hosted (type: pypi hosted)
    • pypi-group (type: pypi group, объединяет proxy + hosted)

Настройка pip:

~/.config/pip/pip.conf:

[global] index-url = http://nexus.internal:8081/repository/pypi-group/simple trusted-host = nexus.internal

Синхронизация пакетов:

# На промежуточном сервере pip download -d /opt/pypi-packages -r requirements.txt # Перенос scp /opt/pypi-packages/*.whl user@internal:/opt/nexus/import/pypi/ # Загрузка в Nexus через API for pkg in /opt/nexus/import/pypi/*.whl; do curl -u admin:password --upload-file "$pkg" \ "http://nexus.internal:8081/repository/pypi-hosted/" done

#Сценарий 4: Полная изоляция (без промежуточного сервера)

#4.1. Развёртывание из офлайн-архивов

Подготовка архива на внешней машине:

# Создание полного бэкапа mkdir /tmp/gitea-offline # Docker образы docker save gitea/gitea:latest > /tmp/gitea-offline/gitea.tar docker save postgres:15-alpine > /tmp/gitea-offline/postgres.tar # Бэкап Gitea docker exec gitea gitea dump -F /tmp/gitea-offline/gitea-dump.zip # Конфигурация cp /opt/gitea/docker-compose.yml /tmp/gitea-offline/ cp /opt/gitea/app.ini /tmp/gitea-offline/ # Архивация tar -czf gitea-offline-$(date +%Y%m%d).tar.gz -C /tmp/gitea-offline .

Восстановление в закрытом контуре:

# Распаковка tar -xzf gitea-offline-20260319.tar.gz # Загрузка образов docker load -i gitea.tar docker load -i postgres.tar # Развёртывание docker compose up -d # Восстановление из бэкапа docker exec gitea gitea restore --from /data/gitea-dump.zip

#4.2. Обновление в air-gap режиме

Процесс обновления:

1. Тестирование новой версии на изолированном стенде
2. Создание полного архива (образы + бэкап)
3. Перенос в закрытый контур
4. Бэкап текущей системы
5. Развёртывание новой версии
6. Проверка работоспособности
7. Откат при проблемах

Скрипт обновления:

update-airgap.sh:

#!/bin/bash set -e VERSION="1.21.5" BACKUP_DIR="/opt/gitea/backups/$(date +%Y%m%d_%H%M%S)" echo "=== Обновление Gitea до версии $VERSION ===" # 1. Бэкап echo "[1/4] Создание бэкапа..." mkdir -p "$BACKUP_DIR" docker exec gitea gitea dump -F "$BACKUP_DIR/gitea-dump.zip" docker compose cp db:/var/lib/postgresql/data "$BACKUP_DIR/postgres-data" # 2. Загрузка нового образа echo "[2/4] Загрузка образа..." docker load -i "gitea-$VERSION.tar" # 3. Обновление docker-compose.yml echo "[3/4] Обновление конфигурации..." sed -i "s/gitea\/gitea:.*/gitea\/gitea:$VERSION/" docker-compose.yml # 4. Перезапуск echo "[4/4] Перезапуск сервисов..." docker compose down docker compose up -d # Проверка sleep 30 curl -f http://localhost:3000/api/health || { echo "❌ Ошибка запуска! Выполняется откат..." # Откат (удаление нового образа, восстановление бэкапа) exit 1 } echo "✓ Обновление завершено успешно"

#Безопасность в air-gap среде

#Контрольный список безопасности

  • Физическая изоляция — нет прямого подключения к интернету
  • Промежуточный сервер в DMZ — буферная зона для синхронизации
  • Антивирусная проверка — сканирование переносимых файлов
  • Подпись образов — использование Docker Content Trust
  • Аудит действий — логирование всех операций импорта/экспорта
  • Регулярное обновление — ежемесячная синхронизация патчей безопасности

#Проверка целостности образов

# Генерация хэша на внешней машине sha256sum gitea.tar > gitea.tar.sha256 # Проверка в закрытом контуре sha256sum -c gitea.tar.sha256

#Метрики и мониторинг автономности

МетрикаЦелевое значениеКак измерить
Актуальность зеркалНе старше 7 днейGitea API: /repos/{owner}/{repo}
Доступность образов100% критических образовdocker images + сверка со списком
Время синхронизации< 4 часовЛогирование скриптов
Целостность данных100% совпадение хэшейSHA256 проверка

#Резюме

  • Зеркалирование — встроенная функция Gitea + git clone --mirror
  • Docker Registry — локальный кэш образов через registry:2
  • Менеджеры пакетов — Nexus Repository Manager для npm, PyPI, Maven
  • Air-gap обновление — перенос архивов через промежуточный сервер
  • Безопасность — проверка целостности, антивирус, аудит

Следующий шаг: Безопасность и комплаенс (152-ФЗ, GDPR)

Далее: Безопасность и комплаенс (152-ФЗ, GDPR)