## Docker Compose ### Основной файл docker-compose.yml ```yaml version: '3.8' services: gitea: image: gitea/gitea:latest container_name: second_mind_gitea environment: - USER_UID=1000 - USER_GID=1000 - GITEA__database__DB_TYPE=postgres - GITEA__database__HOST=db:5432 - GITEA__database__NAME=gitea - GITEA__database__USER=gitea - GITEA__database__PASSWORD=sG7hZXBQDAtRab9A - GITEA__server__SSH_DOMAIN=git.aepif.ru - GITEA__server__SSH_PORT=2222 volumes: - gitea_data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro depends_on: - db networks: - default - proxy labels: - traefik.enable=true # HTTP routing - traefik.http.routers.gitea.rule=Host(`git.aepif.ru`) - traefik.http.routers.gitea.tls.certresolver=letsencrypt - traefik.http.services.gitea.loadbalancer.server.port=3000 # TCP routing for SSH - traefik.tcp.routers.gitea-ssh.rule=HostSNI(`*`) - traefik.tcp.routers.gitea-ssh.entrypoints=ssh - traefik.tcp.services.gitea-ssh.loadbalancer.server.port=22 restart: unless-stopped db: image: postgres:14 container_name: second_mind_db environment: - POSTGRES_USER=gitea - POSTGRES_PASSWORD=sG7hZXBQDAtRab9A - POSTGRES_DB=gitea volumes: - postgres_data:/var/lib/postgresql/data networks: - default restart: unless-stopped nginx: image: nginx:alpine container_name: second_mind_nginx volumes: - ./quartz_build:/usr/share/nginx/html:ro - ./nginx.conf:/etc/nginx/nginx.conf:ro networks: - default - proxy labels: - traefik.enable=true - traefik.http.routers.obsidian.rule=Host(`notes.aepif.ru`) - traefik.http.routers.obsidian.tls.certresolver=letsencrypt - traefik.http.routers.obsidian.middlewares=authelia@docker - traefik.http.services.obsidian.loadbalancer.server.port=80 restart: unless-stopped quartz-webhook: build: . container_name: second_mind_webhook volumes: - /root/.ssh:/root/.ssh - ./obsidian_repo:/obsidian - ./quartz_build:/public environment: - WEBHOOK_SECRET=MHtue5Zclp/dr69OFdwquGzCVHUGiEHP - GITEA_REPO_URL=http://gitea:3000/admin/second-mind-aep.git networks: - default - proxy labels: - traefik.enable=true - traefik.http.routers.webhook.rule=Host(`webhook.aepif.ru`) - traefik.http.routers.webhook.tls.certresolver=letsencrypt - traefik.http.services.webhook.loadbalancer.server.port=3000 restart: unless-stopped volumes: gitea_data: postgres_data: networks: proxy: external: true default: driver: bridge ``` ## Dockerfile для webhook сервиса ```dockerfile FROM node:22 WORKDIR /app # Установка Git и SSH клиента RUN apt-get update && apt-get install -y git openssh-client && rm -rf /var/lib/apt/lists/* # Создание .ssh директории и настройка SSH RUN mkdir -p /root/.ssh && chmod 700 /root/.ssh # Добавление SSH ключа для доступа к git.aepif.ru (будет примонтирован как volume) # Настройка SSH для автоматического принятия ключей хоста RUN echo "Host git.aepif.ru\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile=/dev/null" > /root/.ssh/config # Клонирование кастомного Quartz репозитория RUN git clone ssh://git@git.aepif.ru:2222/aep/quartz.git /quartz WORKDIR /quartz RUN npm install # Копирование и настройка webhook сервиса COPY webhook-server/ /webhook/ WORKDIR /webhook RUN npm install EXPOSE 3000 WORKDIR /webhook CMD ["node", "server.js"] ``` ## Конфигурация Nginx ### nginx.conf ```nginx events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; gzip on; server { listen 80; root /usr/share/nginx/html; index index.html; # Основная обработка запросов location / { try_files $uri $uri/ $uri.html =404; } # Кэширование статических файлов location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } } } ``` ## Переменные окружения ### .env файл ```bash # Основной домен DOMAIN=aepif.ru # Настройки Gitea GITEA_ADMIN_USER=admin GITEA_ADMIN_PASSWORD=Creonila1 GITEA_DB_PASSWORD=sG7hZXBQDAtRab9A GITEA_SECRET=okPnnPYzdKkkpO6oS8LqI5PHm7fH/OCl # Webhook настройки WEBHOOK_SECRET=MHtue5Zclp/dr69OFdwquGzCVHUGiEHP # Репозиторий заметок REPO_NAME=second-mind-aep ``` ## Webhook сервис ### package.json ```json { "name": "quartz-webhook", "version": "1.0.0", "main": "server.js", "dependencies": { "express": "^4.18.0" } } ``` ### server.js (основные моменты) Webhook сервис включает: - Обработчик POST `/webhook` для получения уведомлений от Gitea - Health check endpoint GET `/health` - Функцию автоматической сборки с этапами: 1. Проверка наличия Git репозитория 2. `git pull` для обновления локальной копии 3. Создание `index.md` если отсутствует 4. Запуск `npm run quartz build` с указанием исходной директории 5. Очистка целевой папки `/public` 6. Копирование собранного сайта из `/quartz/public` ## Настройки Quartz ### quartz.config.ts (основные параметры) ```typescript const config: QuartzConfig = { configuration: { pageTitle: "AEP Second Mind", pageTitleSuffix: "", enableSPA: true, enablePopovers: true, locale: "ru-RU", baseUrl: "notes.aepif.ru", ignorePatterns: ["private", "templates", ".obsidian"], defaultDateType: "modified", theme: { typography: { header: "Schibsted Grotesk", body: "Source Sans Pro", code: "IBM Plex Mono", }, }, }, // ... плагины и эмиттеры } ``` ## SSH конфигурация ### Настройка доступа к репозиториям ```bash # В ~/.ssh/config Host git.aepif.ru Port 2222 User git IdentityFile ~/.ssh/id_ed25519 StrictHostKeyChecking no ``` ### Known hosts для автоматического принятия ключей ```bash # Добавление отпечатков сервера ssh-keyscan -p 2222 git.aepif.ru >> ~/.ssh/known_hosts ``` ## Traefik Labels ### Основные метки для маршрутизации ```yaml # HTTP с SSL - traefik.http.routers.service-name.rule=Host(`domain.aepif.ru`) - traefik.http.routers.service-name.tls.certresolver=letsencrypt - traefik.http.services.service-name.loadbalancer.server.port=PORT # TCP для SSH (только для Gitea) - traefik.tcp.routers.gitea-ssh.rule=HostSNI(`*`) - traefik.tcp.routers.gitea-ssh.entrypoints=ssh - traefik.tcp.services.gitea-ssh.loadbalancer.server.port=22 # Middleware для защиты (Authelia) - traefik.http.routers.obsidian.middlewares=authelia@docker ``` ## Безопасность ### Уровни защиты 1. **Gitea**: Собственная авторизация пользователей 2. **Notes**: Защита через Authelia middleware 3. **Webhook**: Проверка секретного токена в запросах 4. **SSH**: Доступ только по ключам 5. **SSL**: Автоматические сертификаты через Let's Encrypt ### Секреты и пароли Все чувствительные данные хранятся в: - `.env` файле для Docker Compose - Environment переменных контейнеров - Примонтированных SSH ключах Следующий документ: [[Развертывание]]