Эксплуатация
Как держать сервер TSMC в работе: где лежат данные, резервные копии и восстановление, обновление, HTTPS, остановка, мониторинг.
Всё состояние сервера — в одной папке (в Docker — том /data):
| Что | Где | Переменная |
|---|---|---|
| база SQLite | tsmc.db (и tsmc.db-wal, tsmc.db-shm, пока сервер работает) |
TSMC_DB |
| вложения | files/ рядом с базой — файлы по SHA-256, один раз на одинаковое содержимое |
TSMC_FILES |
| ключ токенов трекеров | secret.key рядом с базой |
TSMC_SECRET_KEY вместо файла |
| резервные копии | backups/ рядом с базой (по умолчанию) |
--out |
Резервная копия
Заголовок раздела «Резервная копия»# на сервереpnpm tsmc-server backup # → data/backups/tsmc-backup-20261025-103000/# в Dockerdocker exec tsmc tsmc-server backup # → /data/backups/… (в томе)Копия делается на ходу: сервер не останавливается и продолжает принимать запросы. База копируется
командой SQLite VACUUM INTO — это снимок одной транзакции, целостный, даже если в этот момент идёт запись.
Затем копируются файлы вложений, на которые ссылается снимок (они не меняются после записи), и ключ
secret.key. В папке копии — manifest.json: время, версия, схема базы, размеры, контрольная сумма базы,
сколько чего в ней. Недописанная копия называется ….partial и при ошибке удаляется.
Копию стоит увозить с сервера. Пример ежедневной копии с хранением 14 дней (cron, Docker):
30 3 * * * docker exec tsmc tsmc-server backup && docker run --rm -v tsmc-data:/data alpine sh -c 'cd /data/backups && ls -dt tsmc-backup-* | tail -n +15 | xargs -r rm -rf'Если ключ задан переменной TSMC_SECRET_KEY, в копию он не попадает (так сказано и в manifest.json):
храните его рядом с копией сами, иначе токены трекеров после восстановления придётся ввести заново.
Проверка
Заголовок раздела «Проверка»pnpm tsmc-server check # данные сервераTSMC_DB=backups/tsmc-backup-…/tsmc.db TSMC_FILES=backups/tsmc-backup-…/files pnpm tsmc-server check # копияПроверяет целостность SQLite (integrity_check), ссылочную целостность (foreign_key_check) и что файл
каждого вложения на месте. Код выхода 2 — что-то не так. Неиспользуемые файлы (остаток прерванной
загрузки) не ошибка: они удаляются при следующем удалении вложения.
Восстановление
Заголовок раздела «Восстановление»- Остановите сервер (
docker compose stop tsmc,systemctl stop tsmc): работающий сервер держит базу открытой, и восстановление поверх него потеряет данные. - Восстановите:
Перед заменой команда сверяет контрольную сумму и целостность копии. Прежняя база сохраняется рядом как
Окно терминала pnpm tsmc-server restore data/backups/tsmc-backup-20261025-103000 --force# в Docker, пока контейнер остановлен:docker run --rm -v tsmc-data:/data tsmc tsmc-server restore /data/backups/tsmc-backup-20261025-103000 --forcetsmc.db.before-restore-<время>, прежний ключ — так же. Без--forceсуществующая база не заменяется. - Запустите сервер. Если копия старше версии сервера, он сам применит недостающие миграции; копию более новой версии восстановить нельзя — нужен сервер той версии.
Обновление
Заголовок раздела «Обновление»- Сделайте копию (
tsmc-server backup). - Обновите образ или код и перезапустите. Миграции схемы применяются при старте, каждая — одной транзакцией: прерванная миграция не оставляет базу наполовину изменённой. Большие миграции (например, перестройка таблицы результатов на этапе 20) на базе с сотней тысяч результатов идут секунды.
- Если что-то не так — остановите сервер и восстановите копию с прежней версией.
HTTPS и обратный прокси
Заголовок раздела «HTTPS и обратный прокси»Сервер не занимается сертификатами: снаружи его закрывает обратный прокси. Готовые примеры:
- docs/deploy/Caddyfile — Caddy сам получает и продлевает сертификаты Let’s Encrypt; docs/deploy/compose.caddy.yml поднимает TSMC и Caddy вместе.
- docs/deploy/nginx.conf — nginx с сертификатом certbot.
За прокси серверу нужны TSMC_SECURE_COOKIES=1 (cookie только по HTTPS), TSMC_TRUST_PROXY=1 (адрес клиента
из X-Forwarded-For — для ограничения попыток входа и журнала) и TSMC_PUBLIC_URL (адрес в ссылках из
заведённых багов). Лимит тела запроса в прокси — не меньше TSMC_MAX_UPLOAD_MB (вложения) и с запасом для
импорта CSV.
Остановка
Заголовок раздела «Остановка»На SIGTERM (docker stop, systemctl stop) и SIGINT (Ctrl+C) сервер перестаёт принимать соединения,
дожидается текущих запросов (до 10 с), переносит журнал SQLite в основной файл и выходит с кодом 0. После
остановки данные — это tsmc.db без -wal, вложения и ключ. В Docker дайте на это время:
stop_grace_period: 20s в compose (по умолчанию Docker ждёт 10 с).
Мониторинг
Заголовок раздела «Мониторинг»-
GET /api/health— живость, версия сервера и API; на него смотрит HEALTHCHECK образа. -
Метрики Prometheus (
TSMC_METRICS=1):GET /metrics, вне/apiи без входа; сTSMC_METRICS_TOKENтребуетсяAuthorization: Bearer <токен>. Наружу их лучше не отдавать (в примерах прокси/metricsзакрыт). Что есть:tsmc_http_requests_total{method,route,status}иtsmc_http_request_duration_seconds(гистограмма) — по шаблонам маршрутов (/api/runs/:id), а не адресам;tsmc_projects,tsmc_cases{status},tsmc_runs{status},tsmc_results,tsmc_users;tsmc_attachments_bytes,tsmc_database_bytes{file="main|wal"},tsmc_process_memory_bytes,tsmc_uptime_seconds.
Пример для Prometheus:
scrape_configs:- job_name: tsmcauthorization: { credentials: change-me } # TSMC_METRICS_TOKENstatic_configs: [{ targets: ['tsmc:3000'] }] -
Журнал — JSON в stdout (Fastify/pino):
docker logs tsmc,journalctl -u tsmc.