- docker-compose.yml: профили docs (Nextcloud), office (ONLYOFFICE Document Server), ai (Ollama + скачивание модели) - автонастройка: адреса Nextcloud, ONLYOFFICE, портала и модели подставляются из .env или по именам сервисов во внутренней сети Docker; значения из интерфейса важнее - локальная модель в своей сети (имя сервиса, частный IP) подключается без ключа API - .env.example, docs/DEPLOY.md (раздел 7а), README
16 KiB
Установка на свой сервер (Docker Compose, без Coolify)
Портал поставляется как обычный проект Docker Compose: приложение (Python, FastAPI) + PostgreSQL 16. Никаких внешних сервисов не нужно — Coolify, Kubernetes и т. п. необязательны. Ниже — полная установка с нуля, обновление, резервные копии, откат и перенос на другой сервер.
1. Что нужно
- Сервер Linux (Debian 12/13, Ubuntu 22.04/24.04 и т. п.), 2 ядра, 2 ГБ ОЗУ, от 10 ГБ диска (+ место под фото).
- Docker Engine 24+ с плагином Compose v2:
docker --version,docker compose version. Установка: https://docs.docker.com/engine/install/ (на Debian и Ubuntu —curl -fsSL https://get.docker.com | sh). - Git (или архив с исходниками).
- Доменное имя и обратный прокси с HTTPS (nginx, Nginx Proxy Manager, Caddy, Traefik — любой). Без HTTPS не работают уведомления в браузере и установка мобильной версии на iPhone; приложение для Android в релизной сборке ходит только по HTTPS.
2. Получить проект
sudo mkdir -p /opt/portal && sudo chown $USER /opt/portal
git clone <адрес репозитория> /opt/portal
cd /opt/portal
git checkout main
3. Настроить переменные
cp .env.example .env
nano .env
| Переменная | Что указать |
|---|---|
DB_PASSWORD |
Пароль базы (случайный: openssl rand -hex 24). После первого запуска не меняйте — он записан в базу. |
SECRET_KEY |
Ключ подписи токенов, не короче 32 символов: openssl rand -hex 32. Смена завершит все сессии. |
ADMIN_PASSWORD |
Пароль пользователя admin, создаётся при первом запуске, не короче 10 символов. |
APP_TZ |
Часовой пояс предприятия (Europe/Moscow, Asia/Yekaterinburg …): смены, расписание нарядов, отчёты. |
APP_PORT |
Порт на хосте, куда смотрит прокси (по умолчанию 8080). |
FORWARDED_ALLOW_IPS |
Адрес обратного прокси, как его видит приложение (см. п. 6). |
В боевом режиме (APP_ENV=production прописан в docker-compose.yml) приложение не запустится со слабыми SECRET_KEY
или ADMIN_PASSWORD — это защита, а не ошибка: задайте значения по таблице.
4. Запустить
docker compose up -d --build
docker compose ps # app и db — running (healthy)
curl -s http://127.0.0.1:8080/api/v1/health
Первая сборка занимает несколько минут. Логи: docker compose logs -f app.
Данные хранятся в томах Docker: pgdata (база), photos (фото нарядов и задач), appdata (резервные копии, демо-база,
загруженный APK). Они переживают пересборку и перезапуск контейнеров. Удаляет их только docker compose down -v — не делайте так
на рабочем сервере.
5. Первый вход
Откройте http://<сервер>:8080 (до настройки прокси) или ваш домен, войдите как admin с паролем из ADMIN_PASSWORD
и сразу смените пароль: «Администрирование → Пользователи» → admin → «Изменить» → новый пароль. Пустая система предложит мастер первичной настройки:
графики, должности, отделы, места, оборудование, сотрудники, карта, склады, чек-листы, резервные копии.
6. Обратный прокси и HTTPS
Приложение слушает обычный HTTP на APP_PORT; HTTPS даёт прокси. Пример для nginx на том же сервере
(сертификат — certbot: sudo certbot --nginx -d portal.example.ru):
server {
listen 443 ssl http2;
server_name portal.example.ru;
# ssl_certificate / ssl_certificate_key — пропишет certbot
client_max_body_size 20m; # фото и картинки карт; иначе ошибка 413
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 120s; # PDF-отчёты и AI-помощник могут отвечать долго
}
}
server { listen 80; server_name portal.example.ru; return 301 https://$host$request_uri; }
- Nginx Proxy Manager: Proxy Host → Forward
http://<IP сервера>:8080, SSL (Let's Encrypt), Force SSL; во вкладке Advanced —client_max_body_size 20m;. - Caddy:
portal.example.ru { reverse_proxy 127.0.0.1:8080 }иrequest_body { max_size 20MB }.
Адрес прокси (FORWARDED_ALLOW_IPS). Приложение верит заголовку X-Forwarded-For только от этого адреса — иначе любой мог бы
подделать свой IP и обойти ограничение попыток входа. Как настроить: зайдите на портал через прокси администратором →
«Администрирование → Настройки сервера», блок «Состояние», строка «Адрес клиента, каким его видит сервер». Пока прокси не указан,
там виден адрес самого прокси (если прокси на том же хосте — обычно шлюз сети Docker вида 172.18.0.1, если на другой машине —
её IP). Впишите его в FORWARDED_ALLOW_IPS и примените: docker compose up -d. После этого в той же строке должен появиться
ваш собственный адрес — значит, всё настроено.
Файрвол. Порт APP_PORT должен быть доступен только прокси. Docker публикует порты в обход ufw, поэтому либо привяжите
порт к localhost (в docker-compose.yml: "127.0.0.1:${APP_PORT:-8080}:8000" — если прокси на этом же сервере), либо закройте
его правилом в цепочке DOCKER-USER (iptables) или на внешнем файрволе.
7. Приложение для Android
Готовый подписанный APK лежит в release/ и входит в образ: ссылка «Скачать приложение для Android» на странице входа и адрес
/app.apk работают сразу. Новую версию можно выложить без пересборки — положить файл в том appdata:
docker compose cp checklists-1.7.0.apk app:/srv/data/apk/
Версия берётся из имени файла (checklists-<версия>.apk); приложения сами предложат обновиться. В приложении на телефоне
указывается адрес вашего сервера (https://portal.example.ru).
7а. Дополнительные сервисы: документация, просмотр Office, локальный ИИ
docker-compose.yml умеет поднять рядом с порталом ещё три сервиса. Они включаются профилями — строкой в .env:
COMPOSE_PROFILES=docs,office,ai
| Профиль | Что запускается | Зачем | Ресурсы сверх портала |
|---|---|---|---|
docs |
Nextcloud + своя PostgreSQL | хранилище документации оборудования: паспорта, схемы, руководства | 1 ГБ памяти, место под документы |
office |
ONLYOFFICE Document Server | Word, Excel, PowerPoint открываются прямо в портале (переводятся в PDF) | 2–4 ГБ памяти |
ai |
Ollama + скачивание модели | локальная модель для AI-помощника: вопросы и документы не уходят в интернет | 6–8 ГБ памяти для 7B-модели, лучше видеокарта |
Профили независимы: можно взять только ai или подключить свой Nextcloud и ONLYOFFICE, указав их адреса в .env
(NC_URL, ONLYOFFICE_URL, PORTAL_INTERNAL_URL).
Настройки заполняются сами. Портал ищет сервисы во внутренней сети Docker по именам nextcloud, onlyoffice, ollama
и подставляет адреса в «Настройки сервера»: Nextcloud — http://nextcloud, ONLYOFFICE — http://onlyoffice (документы
он забирает у портала по http://app:8000), модель — http://ollama:11434/v1 с моделью из OLLAMA_MODEL. Учётная запись
Nextcloud и секрет ONLYOFFICE берутся из .env. Всё, что администратор поменяет в интерфейсе, важнее автоматических значений.
Что сделать после запуска:
- Nextcloud откройте на порту
NEXTCLOUD_PORT(по умолчанию 8081), войдите администратором из.env, создайте папку документации (например, «Документация») с подпапками по машинам и укажите её вNC_ROOTили в настройках портала. Для безопасности заведите отдельного пользователя с доступом только на чтение к этой папке и пароль приложения для него — и впишите их вNC_USER/NC_PASSWORD. - ONLYOFFICE наружу не публикуется: портал общается с ним внутри сети Docker. Задайте свой
ONLYOFFICE_JWT. - ИИ: дождитесь, пока
ollama-pullскачает модель (docker compose logs -f ollama-pull), затем в «Настройках сервера → AI-помощник» нажмите «Проверить» и включите помощника. Опция «Работа с документацией» включается там же.
8. Обновление
cd /opt/portal
git pull
docker compose up -d --build
Перед обновлением сделайте резервную копию (п. 9). Структура базы обновляется сама при запуске (только добавление новых полей),
поэтому откат на предыдущую версию кода возможен: git checkout <прежний коммит> && docker compose up -d --build.
9. Резервные копии
- Встроенные (рекомендуется): «Администрирование → Резервные копии». Копия — zip с базой в переносимом формате и настройками
(по желанию — с фото); есть автокопии по расписанию (по умолчанию раз в сутки, хранится 14). Копии лежат в томе
appdata(/srv/data/backups) — регулярно забирайте их на другой носитель:docker compose cp app:/srv/data/backups ./backups-$(date +%F) - Средствами PostgreSQL:
Имя тома —
docker compose exec -T db pg_dump -U checklists -Fc checklists > portal-$(date +%F).dump docker run --rm -v portal_photos:/p -v "$PWD":/b alpine tar czf /b/photos-$(date +%F).tgz -C /p .<имя проекта>_photos(имя проекта по умолчанию — имя каталога, здесьportal):docker volume ls. Восстановление дампа:docker compose exec -T db pg_restore -U checklists -d checklists --clean --if-exists < portal-ДАТА.dump.
10. Перенос на другой сервер
- На старом сервере: «Резервные копии» → «Создать копию» с фото → скачать zip.
- На новом: установка по пп. 1–6 (новые
DB_PASSWORD/SECRET_KEYдопустимы), входadmin. - «Резервные копии» → «Загрузить копию» → «Восстановить». Все данные, пользователи и пароли станут как на старом сервере; после восстановления все входят заново.
11. Обслуживание
| Задача | Команда |
|---|---|
| Состояние | docker compose ps |
| Логи приложения | docker compose logs -f --tail 200 app |
| Перезапуск | docker compose restart app |
| Остановить / запустить | docker compose stop / docker compose start |
| Место на диске | docker system df, «Настройки сервера» → свободно на диске |
| Забыт пароль admin | другой администратор задаёт новый в «Пользователях»; если администратор один — восстановите из копии или обратитесь к разработчику |
Важно: приложение работает одним процессом (так настроено в образе) — планировщик нарядов и демо-режим живут внутри него.
Не масштабируйте сервис app на несколько копий.
12. Если что-то не так
- Контейнер app перезапускается, в логах
SECRET_KEY не задан или слишком короткий/ADMIN_PASSWORD слабый— задайте значения по п. 3. - Фото не загружаются (413) — не задан
client_max_body_size 20mв прокси. - Все входы «блокируются на 5 минут» — прокси не указан в
FORWARDED_ALLOW_IPS, и все клиенты видны с одного адреса (п. 6). - Неверное время нарядов и смен — проверьте
APP_TZи время сервера («Настройки сервера» → время сервера). - Нет уведомлений на телефоне — нужен HTTPS; для Android-push через Firebase — ключ в «Настройках сервера».