# WALKTHROUGH — GoToSocial (капитанский журнал) Хронология реализации. Цель — воспроизводимость с нуля. ## 2026-09-06 — Инициализация проекта ### Задача Развернуть GoToSocial (федiverse-нода ActivityPub) в Docker: /opt/gotosocial, OpenSpec workflow, первое change на развёртывание, git (gitverse истина + gitea зеркало), бэкап на Яндекс.Диск, мониторинг — post-MVP. ### Решения пользователя (ответы на вопросы) - БД: SQLite - Схема: split-domain (host=social.dedinit.ru, account-domain=dedinit.ru), доступ к созданию файлов на apex есть - Имя инстанса: dedinit.ru; admin: estorozhenko; название сервера: dedinit(); описание: «Нода для обычных людей»; email: kpa39l@yandex.ru - SMTP: smtp.jino.ru:587 STARTTLS, ящик social@dedinit.ru (пароль в .env) - Бэкап: SQLite consistent + медиа - Мониторинг бэкапов/дашборд Grafana/импорт из Telegram — post-MVP - Метрики/логи: отдельный job (не включать в общий) - vps02 — только прокси, сервис на bigbox - Git: последний стабильный тег с фиксацией, ручное обновление - Секреты в .env, в git исключён - Первый коммит — сразу с начальными изменениями (не ждать готового сервиса) ### Исследование - Документация установки в контейнере (v0.22.1): https://docs.gotosocial.org/en/v0.22.1/getting_started/installation/container/ - Скачаны refs: ref-container.md, ref-docker-compose.yml, ref-host-account-domain.md, ref-metrics-config.yaml, ref-metrics.md, ref-observability.md, ref-storage.md - Официальный example docker-compose: https://codeberg.org/superseriousbusiness/gotosocial/raw/branch/main/example/docker-compose/docker-compose.yaml (важно: путь НЕ example/docker-compose.yml — это 404) - Метрики: OpenTelemetry → Prometheus: `metrics-enabled: true` + env `OTEL_METRICS_PRODUCERS=prometheus`, `OTEL_METRICS_EXPORTER=prometheus`. Эндпоинт /metrics: go_goroutines, gin_, bun_* - Логи: log-format: json → promtail → Loki - Split-domain: аккаунты @user@dedinit.ru при host=social.dedinit.ru; требует .well-known редиректы на apex; НЕОБРАТИМО после старта ### Инфраструктура (проверено) - bigbox (10.8.0.2 через WG): сервисы в /opt/, стек мониторинга (Prometheus :9090, Grafana :3001, Loki :3100, node_exporter + textfile /var/lib/prometheus/node-exporter/) - vps02 87.242.100.206: Caddy 2 (контейнер caddy:alpine, host net), слушает 80/443, паттерн `домен { reverse_proxy 10.8.0.2: }` - SSH vps02: `ssh -i /mnt/yandex-disk/.ssh_box/cloudruVPS estorozhenko@87.242.100.206` (sudo работает); root/другие ключи НЕ подходят - Яндекс.Диск: mount /mnt/yandex-disk, бэкапы в /mnt/yandex-disk/backup/-backups/ - DNS: social.dedinit.ru A → 87.242.100.206 (создан пользователем), apex dedinit.ru → 81.177.135.38 (Jino) ### OpenSpec workflow ```bash cd /opt/gotosocial openspec init --tools hermes --force --no-animation # CLI 1.12.0, бинарь /opt/hermes/.hermes/node/bin/openspec openspec new change deploy-gotosocial ``` - config.yaml (context + rules) — инфра-специфичный - proposal.md, specs/gotosocial-deploy/spec.md + specs/gotosocial-backup/spec.md, design.md, tasks.md - **Питфол:** OpenSpec требует `#### Scenario:` блоки (GIVEN/WHEN/THEN) ВНУТРИ каждой requirement — просто Verification-блок не проходит validate. Исправлено, `openspec validate deploy-gotosocial` → valid. ### Рабочие файлы - docker-compose.yml: image superseriousbusiness/gotosocial:v0.22.1 (фикс. тег), container_name gotosocial, user 1000:1000, restart unless-stopped, env OTEL_METRICS_*, env_file .env, ports 8080:8080, volumes ./data:/gotosocial/storage + ./config.yaml:/gotosocial/config.yaml:ro, network gotosocial 172.29.0.0/16 - config.yaml: host social.dedinit.ru, account-domain dedinit.ru, protocol https, port 8080, trusted-proxies [127.0.0.1/32, ::1, 172.29.0.1/16], log json, db-type sqlite, db-address /gotosocial/storage/sqlite.db, storage-local-base-path /gotosocial/storage, SMTP smtp.jino.ru:587 (пароль пустой в config — берётся из .env? **TODO: проверить, как GtS читает пароль из env, когда в config.yaml пусто**), metrics-enabled true, instance-title dedinit(), instance-description «Нода для обычных людей», instance-contact-email kpa39l@yandex.ru - .env: GTS_SMTP_PASSWORD='fF@4guOf9spE2#8$' - backup.sh: VACUUM INTO → tar.gz (sqlite+storage) + отдельный .env-архив; копия /mnt/yandex-disk/backup/gotosocial-backups/; ротация локально 7д, ЯД 30д; mountpoint-проверка ЯД, exit 1 при ошибке - README.md, .gitignore (.env, data/, backups/, refs/, openspec/changes/archive/) ### Git ```bash cd /opt/gotosocial git init -b main && git add -A git -c user.name=estorozhenko -c user.email=kpa39l@yandex.ru commit -m "openspec: change deploy-gotosocial — развертывание GoToSocial (compose+config+backup+docs)" # d385d8b ``` ### Создание репозитория gitverse (ВАЖНО — питфолы) - SSH-ключ gitverse работает: `ssh -i /mnt/yandex-disk/.ssh_box/gitverse git@gitverse.ru` → «Hi kpa39l!» - push-to-create НЕ включён для пользователей: «Push to create is not enabled» - Токен из obsidian vault (Gitverse mirror token.md, 40 hex) НЕ работает для API gitverse (400 на всё) — это токен gitea-зеркала - **Правильный способ — скилл git-forge-management + reference gitverse-api.md:** - Токен: `source /opt/hermes/.hermes/secrets/git-tokens.env` → GITVERSE_PAT, GITVERSE_API, GITVERSE_LOGIN=kpa39l - Accept header ОБЯЗАТЕЛЕН: `application/vnd.gitverse.object+json;version=1` (без него 400) ```bash curl -s -X POST "${GITVERSE_API}/user/repos" \ -H "Authorization: Bearer ${GITVERSE_PAT}" \ -H "Accept: application/vnd.gitverse.object+json;version=1" \ -H "Content-Type: application/json" \ -d '{"name":"gotosocial","description":"...","private":false,"auto_init":false}' # HTTP 201, id 327796, full_name kpa39l/gotosocial ``` ### Push - Логин аккаунта gitverse = **kpa39l** (не estorozhenko!) ```bash git remote add origin "https://kpa39l:${GITVERSE_PAT}@gitverse.ru/kpa39l/gotosocial.git" git push -u origin main ``` - **Питфол:** токен остался зашит в .git/config — убрано: `git remote set-url origin https://kpa39l@gitverse.ru/kpa39l/gotosocial.git` (creds из git-tokens.env/credential helper) ### Gitea pull-mirror ```bash source /opt/hermes/.hermes/secrets/git-tokens.env curl -s -X POST "${GITEA_API}/repos/migrate" \ -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" \ -d "{\"clone_addr\":\"https://oauth2:${GITVERSE_PAT}@gitverse.ru/kpa39l/gotosocial.git\",\"repo_name\":\"gotosocial\",\"repo_owner\":\"estorozhenko\",\"service\":\"git\",\"mirror\":true,\"mirror_interval\":\"8h\"}" # HTTP 201, mirror=true; затем POST /repos/estorozhenko/gotosocial/mirror-sync → 200 ``` - **Питфол:** migrate с ssh:// НЕ работает (422 protocol not allowed) — только HTTPS + oauth2:PAT (проверено ранее, см. reference gitea-pull-mirror-gitverse.md) ### Команды развёртывания (следующий шаг) ```bash cd /opt/gotosocial && docker compose up -d docker compose exec gotosocial gotosocial admin account create \ --username estorozhenko --email kpa39l@yandex.ru \ --password '<пароль>' --confirmation docker compose exec gotosocial gotosocial admin account promote --username estorozhenko ``` Caddy vps02: блок `social.dedinit.ru { reverse_proxy 10.8.0.2:8080 }`, `docker exec caddy caddy reload --config /etc/caddy/Caddyfile` ## Открытые вопросы / риски - Как GtS читает SMTP-пароль: config.yaml `smtp-password: ""` + .env `GTS_SMTP_PASSWORD` — проверить при первом запуске, что письма уходят - Пароль админа estorozhenko — нужен от пользователя - Доступ к vps02 для правки Caddyfile — нужен (SSH estorozhenko@87.242.100.206 + cloudruVPS ключ) - .well-known редиректы на apex (Jino) — подготовить правила