bolt Valebyte VPS от $4/мес — NVMe, запуск за 60 секунд.

Получить VPS arrow_forward
eco Начальный Туториал

Установка OpenProject на VPS: Docker, PostgreSQL, SSL, SMTP и резервные копии

calendar_month Oct 21, 2026 schedule 18 мин. чтения visibility 16 просмотров
Установка OpenProject на VPS: Docker, PostgreSQL, SSL, SMTP и резервные копии
info

Нужен сервер для этого гайда? Мы предлагаем выделенные серверы и VPS в 50+ странах с мгновенной настройкой.

Нужен сервер для этого гайда?

Разверните VPS или выделенный сервер за минуты.

Установка OpenProject на VPS: Docker, PostgreSQL, SSL, SMTP и резервные копии

TL;DR

В этом руководстве вы развернёте OpenProject на VPS через Docker Compose: отдельные контейнеры приложения, PostgreSQL, Redis, обратный прокси Caddy с автоматическим SSL, SMTP для уведомлений и автоматические резервные копии базы и файлов.

  • Для небольшой команды достаточно VPS с 2 vCPU, 4 ГБ RAM и 50–80 ГБ NVMe-диска.
  • OpenProject запускается в Docker Compose с PostgreSQL 16 и Redis 7.
  • Caddy автоматически выпускает и продлевает сертификаты Let's Encrypt.
  • SMTP нужен для приглашений пользователей, уведомлений о задачах и сброса паролей.
  • Бэкап должен включать PostgreSQL, каталог вложений OpenProject и конфигурацию.
  • Перед обновлением контейнеров обязательно делайте проверяемую резервную копию.

Что мы настраиваем и зачем

Схема: Что мы настраиваем и зачем
Схема: Что мы настраиваем и зачем

OpenProject — self-hosted система управления проектами с задачами, Kanban-досками, Gantt-диаграммами, wiki, контролем времени, ролями, рабочими пакетами и интеграциями. Это подходящий вариант, если команда хочет хранить проекты, обсуждения и вложения на собственной инфраструктуре, контролировать резервные копии и не зависеть от тарифов SaaS-платформ.

В результате будет доступен защищённый веб-интерфейс по адресу вида https://projects.example.com. Пользователи смогут получать письма о назначении задач, изменении статусов, комментариях и приглашениях. Все компоненты будут изолированы в Docker-контейнерах, поэтому перенос на другой сервер, обновление и восстановление будут заметно проще, чем при ручной установке Ruby-приложения в систему.

Архитектура развертывания

Компонент Назначение Доступ извне
OpenProject web Веб-интерфейс, API, обработка запросов Только через Caddy
OpenProject worker Фоновые задания, почта, уведомления Нет
PostgreSQL 16 Основная база данных проектов, пользователей и задач Нет
Redis 7 Очереди и кэш фоновых задач Нет
Caddy 2 HTTPS, reverse proxy, автоматические сертификаты Порты 80 и 443

Почему Docker Compose

Docker Compose позволяет хранить инфраструктуру рядом с конфигурацией в одном каталоге. Все зависимости описываются декларативно: версии образов, тома, сети, переменные окружения и порядок запуска. Если VPS нужно заменить, достаточно установить Docker, скопировать каталог проекта, восстановить данные и запустить docker compose up -d.

Не публикуйте порт PostgreSQL наружу. В этой схеме база данных доступна только контейнерам внутренней Docker-сети. Это уменьшает поверхность атаки и избавляет от необходимости поддерживать отдельные правила firewall для базы.

Self-hosted и облачный сервис

Критерий Облачный сервис OpenProject на VPS
Обслуживание Провайдер обновляет платформу Вы управляете обновлениями и бэкапами
Контроль данных Данные находятся у оператора сервиса Данные и ключи доступа находятся под вашим контролем
Гибкость Ограничена планом и политикой сервиса Можно менять SMTP, домен, сеть, бэкапы и интеграции
Стоимость Обычно зависит от количества пользователей Зависит преимущественно от ресурсов сервера и хранения бэкапов

Self-hosted OpenProject оправдан для команд, которым нужны контроль над данными, внутренний домен, собственный SMTP-шлюз, интеграция с VPN или локальными системами. Но этот вариант требует дисциплины: мониторинга свободного места, тестирования восстановления и регулярных обновлений безопасности.

Какой VPS-конфиг нужен под эту задачу

Схема: Какой VPS-конфиг нужен под эту задачу
Схема: Какой VPS-конфиг нужен под эту задачу

OpenProject потребляет заметно больше ресурсов, чем простой сайт: работают Ruby-приложение, фоновые воркеры, PostgreSQL, Redis и reverse proxy. Основные факторы роста — количество активных пользователей, объём вложений, интенсивность уведомлений, число интеграций и история проектов.

Сценарий vCPU RAM NVMe-диск Подходящее число пользователей
Тестовый стенд 2 4 ГБ 50 ГБ 1–10
Небольшая команда 2–4 8 ГБ 80–160 ГБ 10–50
Активная команда 4–6 16 ГБ 200 ГБ и больше 50–150
Высокая нагрузка 8+ 32 ГБ+ От 500 ГБ 150+ или много вложений

Для первого production-развертывания на 10–30 сотрудников практичен конфиг 4 vCPU, 8 ГБ RAM, 100 ГБ NVMe и канал от 100 Мбит/с. Такой запас позволит PostgreSQL держать рабочий кэш в памяти, а OpenProject — одновременно обслуживать пользователей и фоновые задания. Можно взять VPS с указанными характеристиками, но главное — выбирать быстрый SSD/NVMe-диск и возможность увеличить ресурсы без миграции.

Сколько диска резервировать

Планируйте место не только под приложение. PostgreSQL растёт вместе с историей задач, комментариями и аудитом, а каталог вложений часто занимает больше самой базы. Для оценки используйте правило: текущий объём данных × 3. Одна часть нужна рабочему сервису, вторая — локальному временному бэкапу, третья — запас на обновления, журналы и рост.

Например, если пользователи загрузили 25 ГБ файлов, а база занимает 5 ГБ, диск на 50 ГБ уже рискован: один полный локальный архив почти заполнит сервер. В таком случае выбирайте минимум 100–160 ГБ и отправляйте резервные копии во внешнее S3-совместимое хранилище или на отдельный сервер.

Когда нужен dedicated, а не VPS

VPS подходит большинству команд до нескольких десятков активных сотрудников. Dedicated-сервер имеет смысл, когда нужна гарантированная производительность диска и CPU, база стала большой, число одновременных пользователей выросло до сотен, либо на этой же машине работают GitLab, CI-раннеры, Nextcloud и другие тяжёлые сервисы.

Переходите на выделенный сервер также при требованиях комплаенса, когда необходима физическая изоляция, или когда PostgreSQL испытывает постоянные задержки ввода-вывода. Не пытайтесь компенсировать недостаток RAM бесконечным swap: при нагрузке это приводит к медленной работе интерфейса и задержкам фоновых задач.

Выбор локации

Локация влияет на задержку для сотрудников, требования к хранению персональных данных и скорость передачи вложений. Если команда находится в Европе, выбирайте дата-центр ближе к основным пользователям. Если OpenProject используется только через корпоративный VPN, разместите VPS в той же географической зоне, что и VPN-шлюз.

Для SSL-сертификата и публичного доступа потребуется доменное имя с A-записью на IPv4-адрес VPS. До запуска Caddy создайте DNS-запись, например projects.example.com, и дождитесь её распространения.

Подготовка сервера

Схема: Подготовка сервера
Схема: Подготовка сервера

Ниже используется Ubuntu Server 24.04 LTS — стабильная версия с долгим сроком поддержки, актуальная для развёртываний в 2026 году. Команды выполняйте от пользователя с правами sudo. Не запускайте Docker Compose от root без необходимости: это усложняет аудит и повышает риск случайно изменить системные файлы.

Обновление системы и базовые утилиты

Сначала подключитесь к серверу по SSH, обновите пакеты и установите утилиты для диагностики, firewall и автоматической блокировки перебора паролей.

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl ca-certificates gnupg ufw fail2ban jq unzip vim htop ncdu
sudo reboot

Первая команда устанавливает обновления безопасности, вторая добавляет необходимые инструменты, а перезагрузка применяет новое ядро и системные библиотеки, если они были обновлены.

Создание отдельного пользователя

Если провайдер выдал только root-доступ, создайте отдельного пользователя deploy. В дальнейшем именно он будет управлять каталогом OpenProject и Docker Compose.

sudo adduser deploy
sudo usermod -aG sudo deploy
sudo mkdir -p /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh

Добавьте публичный ключ в файл /home/deploy/.ssh/authorized_keys. Права на файл должны быть строго ограничены, иначе SSH может проигнорировать ключ.

sudo nano /home/deploy/.ssh/authorized_keys
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys

Перед отключением root-входа обязательно откройте второе SSH-подключение и убедитесь, что вход под deploy по ключу работает. Только после проверки меняйте настройки SSH.

sudo nano /etc/ssh/sshd_config.d/99-hardening.conf
sudo systemctl reload ssh

В созданный файл добавьте следующие параметры:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
X11Forwarding no
AllowUsers deploy

Firewall и fail2ban

Откройте только SSH, HTTP и HTTPS. Если SSH работает не на стандартном порту, замените правило OpenSSH на конкретный номер порта.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Fail2ban будет отслеживать неудачные попытки входа через SSH и временно блокировать IP-адреса. В Ubuntu достаточно включить службу и проверить её состояние.

sudo systemctl enable --now fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd

Проверка DNS до установки

На своём компьютере или на VPS проверьте, что домен указывает на правильный IP. Caddy не сможет получить сертификат Let's Encrypt, если DNS ещё не обновился или порт 80 заблокирован внешним firewall панели провайдера.

dig +short projects.example.com A
curl -4 ifconfig.me
sudo ss -lntp

Первый вывод должен совпасть с публичным IPv4 VPS. До запуска контейнеров отсутствие слушающих процессов на 80 и 443 — нормальная ситуация.

Установка ПО — пошагово

Схема: Установка ПО — пошагово
Схема: Установка ПО — пошагово

Для запуска используются Docker Engine 27+ и Docker Compose v2. Образы фиксируются на основной версии: OpenProject 16, PostgreSQL 16, Redis 7 и Caddy 2. Перед минорным обновлением изучайте changelog OpenProject и не используйте тег latest в production: он делает обновления непредсказуемыми.

Установка Docker Engine

Добавьте официальный репозиторий Docker для Ubuntu 24.04. Команды устанавливают движок, CLI, Buildx и плагин Docker Compose.

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Добавьте пользователя deploy в группу Docker. После этого нужно выйти из SSH-сессии и войти снова, чтобы обновились группы.

sudo usermod -aG docker deploy
sudo systemctl enable --now docker
docker --version
docker compose version

Создание рабочего каталога

Храните compose-файлы и секреты в каталоге, доступном только пользователю deploy. Создайте структуру для Caddy, резервных копий и переменных окружения.

sudo -iu deploy
mkdir -p ~/openproject/{caddy,data,backups}
cd ~/openproject
umask 077
touch .env
chmod 600 .env

Выполняйте дальнейшие команды уже из пользователя deploy. Каталог ~/openproject/data будет использоваться для постоянных файлов Caddy; данные OpenProject и PostgreSQL будут храниться в Docker volumes.

Генерация секретов

Нужны отдельные случайные значения для базы данных, Rails и Redis. Не используйте короткие пароли, слова из словаря или один секрет во всех полях.

openssl rand -hex 32
openssl rand -base64 48
openssl rand -base64 32

Скопируйте результаты в файл .env. В примере ниже замените домен и SMTP-реквизиты на реальные значения.

nano ~/openproject/.env
OPENPROJECT_HOST=projects.example.com
POSTGRES_DB=openproject
POSTGRES_USER=openproject
POSTGRES_PASSWORD=REPLACE_WITH_LONG_DATABASE_PASSWORD
OPENPROJECT_SECRET_KEY_BASE=REPLACE_WITH_LONG_RAILS_SECRET
REDIS_PASSWORD=REPLACE_WITH_LONG_REDIS_PASSWORD

SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_DOMAIN=example.com
[email protected]
SMTP_PASSWORD=REPLACE_WITH_SMTP_PASSWORD
SMTP_FROM=OpenProject <[email protected]>

Создание Docker Compose файла

Следующий файл создаёт внутреннюю сеть для приложения, базы и Redis. Снаружи публикуются только порты Caddy. Контейнеры OpenProject используют одинаковый образ, но выполняют разные роли: веб-сервер и обработчик очереди.

nano ~/openproject/compose.yml
services:
  db:
    image: postgres:16-alpine
    container_name: openproject-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 10
    networks:
      - backend

  redis:
    image: redis:7-alpine
    container_name: openproject-redis
    restart: unless-stopped
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redisdata:/data
    healthcheck:
      test: ["CMD-SHELL", "redis-cli -a \"$${REDIS_PASSWORD}\" ping | grep PONG"]
      interval: 10s
      timeout: 5s
      retries: 10
    environment:
      REDIS_PASSWORD: ${REDIS_PASSWORD}
    networks:
      - backend

  web:
    image: openproject/openproject:16
    container_name: openproject-web
    restart: unless-stopped
    command: "./docker/prod/web"
    env_file: .env
    environment:
      DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
      OPENPROJECT_HOST__NAME: ${OPENPROJECT_HOST}
      OPENPROJECT_HTTPS: "true"
      OPENPROJECT_HSTS: "true"
      OPENPROJECT_SECRET_KEY_BASE: ${OPENPROJECT_SECRET_KEY_BASE}
      OPENPROJECT_CACHE__MEMCACHE__SERVER: redis:6379
      OPENPROJECT_EMAIL__DELIVERY__METHOD: smtp
      OPENPROJECT_SMTP__ADDRESS: ${SMTP_ADDRESS}
      OPENPROJECT_SMTP__PORT: ${SMTP_PORT}
      OPENPROJECT_SMTP__DOMAIN: ${SMTP_DOMAIN}
      OPENPROJECT_SMTP__AUTHENTICATION: login
      OPENPROJECT_SMTP__USER_NAME: ${SMTP_USERNAME}
      OPENPROJECT_SMTP__PASSWORD: ${SMTP_PASSWORD}
      OPENPROJECT_SMTP__ENABLE_STARTTLS_AUTO: "true"
      OPENPROJECT_EMAIL__FROM: ${SMTP_FROM}
    volumes:
      - opdata:/var/openproject/assets
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - backend
      - proxy

  worker:
    image: openproject/openproject:16
    container_name: openproject-worker
    restart: unless-stopped
    command: "./docker/prod/worker"
    env_file: .env
    environment:
      DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
      OPENPROJECT_HOST__NAME: ${OPENPROJECT_HOST}
      OPENPROJECT_HTTPS: "true"
      OPENPROJECT_SECRET_KEY_BASE: ${OPENPROJECT_SECRET_KEY_BASE}
      OPENPROJECT_CACHE__MEMCACHE__SERVER: redis:6379
      OPENPROJECT_EMAIL__DELIVERY__METHOD: smtp
      OPENPROJECT_SMTP__ADDRESS: ${SMTP_ADDRESS}
      OPENPROJECT_SMTP__PORT: ${SMTP_PORT}
      OPENPROJECT_SMTP__DOMAIN: ${SMTP_DOMAIN}
      OPENPROJECT_SMTP__AUTHENTICATION: login
      OPENPROJECT_SMTP__USER_NAME: ${SMTP_USERNAME}
      OPENPROJECT_SMTP__PASSWORD: ${SMTP_PASSWORD}
      OPENPROJECT_SMTP__ENABLE_STARTTLS_AUTO: "true"
      OPENPROJECT_EMAIL__FROM: ${SMTP_FROM}
    volumes:
      - opdata:/var/openproject/assets
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - backend

  caddy:
    image: caddy:2-alpine
    container_name: openproject-caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    environment:
      OPENPROJECT_HOST: ${OPENPROJECT_HOST}
    volumes:
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
      - caddydata:/data
      - caddyconfig:/config
    depends_on:
      - web
    networks:
      - proxy

volumes:
  pgdata:
  redisdata:
  opdata:
  caddydata:
  caddyconfig:

networks:
  backend:
    internal: true
  proxy:

Параметр internal: true запрещает контейнерам из сети backend прямое внешнее соединение. Caddy находится одновременно в proxy-сети и может передавать запросы в контейнер web.

Проверка синтаксиса и запуск

Docker Compose подставит значения из файла .env, но не выводите итоговую конфигурацию в публичные логи: там будут пароли. Сначала скачайте образы, затем запустите стек в фоновом режиме.

cd ~/openproject
docker compose config --quiet
docker compose pull
docker compose up -d
docker compose ps

Первый старт может занять несколько минут: OpenProject выполняет подготовку базы и миграции. Наблюдайте за логами, пока веб-приложение не сообщит о готовности принимать запросы.

docker compose logs -f web
docker compose logs -f worker
docker compose ps

Конфигурация OpenProject, SSL и SMTP

Схема: Конфигурация OpenProject, SSL и SMTP
Схема: Конфигурация OpenProject, SSL и SMTP

Настройка Caddy и HTTPS

Caddy автоматически запрашивает сертификат Let's Encrypt, перенаправляет HTTP на HTTPS и продлевает сертификат. Для этого DNS-запись домена должна вести на сервер, а порты 80 и 443 должны быть открыты как в UFW, так и в сетевом firewall панели VPS.

nano ~/openproject/caddy/Caddyfile
{$OPENPROJECT_HOST} {
    encode zstd gzip

    reverse_proxy web:8080 {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
    }

    log {
        output stdout
        format console
    }
}

После сохранения перезапустите только Caddy. В первые минуты он получит сертификат и сохранит его в постоянном Docker volume caddydata.

cd ~/openproject
docker compose up -d caddy
docker compose logs -f caddy

Если сертификат не выпускается, не отключайте HTTPS в OpenProject. Сначала проверьте DNS, открытые порты и отсутствие другого процесса, который уже занял 80 или 443.

Проверка веб-интерфейса

После успешного запуска откройте в браузере адрес https://projects.example.com. На первом экране OpenProject предложит создать администратора. Используйте уникальный длинный пароль и сохраните его в менеджере паролей.

С сервера проверьте HTTP-ответ, TLS и состояние контейнеров. Код 200, 302 или страница входа означают, что proxy работает. Ошибки 502 обычно указывают на проблему с контейнером web.

curl -I http://projects.example.com
curl -Ik https://projects.example.com
docker compose ps
docker stats --no-stream

Проверка PostgreSQL и Redis

Не нужно открывать PostgreSQL наружу для проверки. Используйте команды внутри Docker-сети. Они покажут, что база принимает соединения, а Redis отвечает на запросы.

docker compose exec db pg_isready -U openproject -d openproject
docker compose exec db psql -U openproject -d openproject -c "SELECT version();"
docker compose exec redis redis-cli -a "$REDIS_PASSWORD" ping

Последняя команда выполняется из shell, где доступна переменная из .env. Если вы открыли новую сессию, сначала перейдите в каталог проекта и загрузите переменные командой set -a; . ./.env; set +a.

SMTP для уведомлений

OpenProject использует SMTP для приглашений, напоминаний, уведомлений о задачах и восстановления доступа. Без правильно настроенной исходящей почты пользователи смогут работать в интерфейсе, но не будут получать важные события по email.

В файле .env используйте SMTP-пользователя, которому разрешена отправка с адреса из SMTP_FROM. Для большинства внешних провайдеров подходит порт 587 и STARTTLS. Порт 465 обычно требует SSL с начала соединения и может потребовать отдельной настройки, поэтому для первого запуска выбирайте 587, если это возможно.

После изменения SMTP-переменных примените конфигурацию перезапуском web и worker. Затем в веб-интерфейсе откройте административные настройки почты и отправьте тестовое сообщение на личный адрес.

cd ~/openproject
docker compose up -d --force-recreate web worker
docker compose logs --tail=100 worker
docker compose logs --tail=100 web

Если почта не отправляется, ищите в логах ошибки аутентификации, TLS или DNS. Не вставляйте SMTP-пароль в командную строку: он останется в истории shell. Храните его только в .env с правами 600.

Базовые настройки после первого входа

  1. Создайте отдельную учётную запись администратора для повседневной работы, а аварийную admin-учётную запись храните отдельно.
  2. Проверьте правильность URL установки в административных настройках, чтобы ссылки в письмах вели на HTTPS-домен.
  3. Создайте роли: администратор, руководитель проекта, участник, наблюдатель и внешний клиент.
  4. Настройте обязательные поля задач, типы рабочих пакетов и статусы под процесс команды.
  5. Ограничьте самостоятельную регистрацию, если система предназначена только для внутренней команды.

Не храните секреты в compose.yml и не добавляйте файл .env в Git-репозиторий. Потеря OPENPROJECT_SECRET_KEY_BASE может усложнить восстановление сессий и зашифрованных данных, поэтому он должен входить в защищённый бэкап конфигурации.

Бэкапы и обслуживание

Схема: Бэкапы и обслуживание
Схема: Бэкапы и обслуживание

Рабочий OpenProject без бэкапа — временная установка. Для полного восстановления нужны не только данные PostgreSQL. Необходимо сохранить вложения пользователей, секреты из .env, compose-файл, Caddyfile и данные Caddy, содержащие сертификаты и служебную информацию.

Что именно бэкапить

Данные Где находятся Критичность
База OpenProject Docker volume pgdata Критично
Вложения и assets Docker volume opdata Критично
Секреты и конфигурация ~/openproject/.env, compose.yml, Caddyfile Критично
Сертификаты Caddy Docker volume caddydata Желательно
Redis Docker volume redisdata Необязательно, но полезно

Для PostgreSQL используйте логический дамп pg_dump, а не простое копирование файлов работающей базы. Логический дамп можно восстановить на новой версии хоста и проверить отдельно. Для Docker volumes с вложениями используйте архив через временный Alpine-контейнер.

Скрипт локального бэкапа

Создайте скрипт, который делает дамп БД, архивирует том вложений и конфигурацию. Скрипт хранит локальные копии семь дней; этого недостаточно как единственной защиты, поэтому ниже добавляется отправка во внешнее хранилище.

mkdir -p ~/openproject/scripts
nano ~/openproject/scripts/backup.sh
chmod 700 ~/openproject/scripts/backup.sh
#!/usr/bin/env bash
set -euo pipefail

BASE_DIR="$HOME/openproject"
BACKUP_DIR="$BASE_DIR/backups"
DATE="$(date +%F_%H-%M-%S)"
ARCHIVE="$BACKUP_DIR/$DATE"

mkdir -p "$ARCHIVE"
cd "$BASE_DIR"

set -a
. ./.env
set +a

docker compose exec -T db pg_dump \
  -U "$POSTGRES_USER" \
  -d "$POSTGRES_DB" \
  --format=custom \
  --file=/tmp/openproject.dump

docker cp openproject-db:/tmp/openproject.dump "$ARCHIVE/openproject.dump"
docker compose exec -T db rm -f /tmp/openproject.dump

docker run --rm \
  -v openproject_opdata:/source:ro \
  -v "$ARCHIVE":/backup \
  alpine:3.20 \
  tar czf /backup/opdata.tar.gz -C /source .

tar czf "$ARCHIVE/config.tar.gz" \
  .env compose.yml caddy/Caddyfile scripts/backup.sh

sha256sum "$ARCHIVE"/ > "$ARCHIVE/SHA256SUMS"
find "$BACKUP_DIR" -mindepth 1 -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;

echo "Backup completed: $ARCHIVE"

Перед автоматизацией запустите скрипт вручную. Проверьте размер файлов: дамп базы не должен быть пустым, а архив opdata.tar.gz должен содержать вложения, если они уже есть.

~/openproject/scripts/backup.sh
ls -lh ~/openproject/backups/$(date +%F)
cat ~/openproject/backups/$(date +%F)/SHA256SUMS

Отправка резервных копий в S3 через restic

Локальная копия не спасёт при удалении VPS, сбое диска или компрометации сервера. Храните вторую копию в отдельном S3-совместимом хранилище, другом дата-центре или на отдельном сервере. Restic шифрует данные на стороне клиента до загрузки.

sudo apt install -y restic
mkdir -p ~/.config/restic
chmod 700 ~/.config/restic
nano ~/.config/restic/openproject.env
chmod 600 ~/.config/restic/openproject.env
RESTIC_REPOSITORY=s3:https://s3.example.com/openproject-backups
RESTIC_PASSWORD=REPLACE_WITH_LONG_RESTIC_REPOSITORY_PASSWORD
AWS_ACCESS_KEY_ID=REPLACE_WITH_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=REPLACE_WITH_SECRET_KEY

Инициализируйте репозиторий один раз, затем добавьте отправку в конец скрипта после создания контрольных сумм.

set -a
. ~/.config/restic/openproject.env
set +a
restic init

Добавьте в backup.sh перед строкой echo следующие команды:

set -a
. "$HOME/.config/restic/openproject.env"
set +a
restic backup "$ARCHIVE"
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

Автоматический запуск через cron

Запускайте бэкап ночью, например в 03:30. Cron перенаправляет вывод в лог, чтобы можно было быстро увидеть ошибку загрузки или недостаток места.

crontab -e
30 3    /home/deploy/openproject/scripts/backup.sh >> /home/deploy/openproject/backups/backup.log 2>&1

Раз в месяц проверяйте репозиторий и выполняйте тестовое восстановление на отдельной машине или в отдельном каталоге. Бэкап считается рабочим только после успешного восстановления.

set -a
. ~/.config/restic/openproject.env
set +a
restic snapshots
restic check
restic restore latest --target /tmp/openproject-restore-test

Обновления OpenProject и инфраструктуры

Для небольшой команды обновления лучше проводить в maintenance window. OpenProject может применять миграции базы, поэтому не обновляйте контейнеры в разгар рабочего дня. Сначала прочитайте заметки к релизу, сделайте бэкап, затем скачайте образ и перезапустите сервисы.

cd ~/openproject
./scripts/backup.sh
docker compose pull
docker compose up -d
docker compose logs --tail=100 web
docker compose ps

Rolling-обновление с несколькими web-контейнерами имеет смысл только при отдельном балансировщике, внешнем PostgreSQL и проверенной схеме миграций. Для одного VPS корректнее короткое окно обслуживания: включить уведомление для команды, обновить стек, проверить вход, создание задачи, вложение и тестовую отправку письма.

Еженедельно проверяйте состояние диска, потребление памяти и размеры Docker-объектов. Не запускайте бездумно docker system prune -a: команда может удалить образы, нужные для быстрого отката. Удаляйте только неиспользуемые образы после проверки списка.

df -h
free -h
docker system df
docker compose logs --since=24h --tail=200 web
sudo journalctl -u docker --since "24 hours ago"

Troubleshooting + FAQ

Почему Caddy выдаёт ошибку получения SSL-сертификата?

Сначала проверьте, что A-запись домена указывает на публичный IPv4 VPS: dig +short projects.example.com. Затем убедитесь, что порты 80 и 443 разрешены в UFW и в панели сетевой защиты. Ошибка также возникает, если другой процесс уже слушает порт 80: проверьте это командой sudo ss -lntp '( sport = :80 or sport = :443 )'. После исправления перезапустите Caddy через docker compose restart caddy.

Почему сайт отвечает 502 Bad Gateway?

Код 502 означает, что Caddy доступен, но не может подключиться к контейнеру OpenProject. Выполните docker compose ps и убедитесь, что контейнер openproject-web имеет статус Up. Затем посмотрите последние логи: docker compose logs --tail=150 web. Частые причины — неуспешная миграция базы, ошибка переменной DATABASE_URL, недостаток памяти или нездоровый PostgreSQL. Исправьте первичную ошибку и выполните docker compose up -d.

OpenProject постоянно перезапускается после запуска. Что делать?

Сначала посмотрите причину через docker compose logs --tail=200 web и docker compose logs --tail=200 worker. Если в логах есть OOMKilled, VPS не хватает памяти: для production используйте не менее 4 ГБ RAM, а лучше 8 ГБ. Если ошибка связана с базой, проверьте docker compose logs db и статус pg_isready. Также убедитесь, что OPENPROJECT_SECRET_KEY_BASE не пустой и не меняется между перезапусками.

Почему не отправляются письма через SMTP?

Проверьте логи web и worker: ошибки аутентификации обычно содержат 535, а TLS-ошибки — упоминание сертификата или handshake. Для большинства SMTP-провайдеров используйте порт 587, OPENPROJECT_SMTP__ENABLE_STARTTLS_AUTO=true и пароль приложения вместо основного пароля аккаунта. Убедитесь, что адрес SMTP_FROM разрешён провайдером. После правки .env пересоздайте контейнеры web и worker с флагом --force-recreate.

Какой VPS-конфиг минимально подойдёт?

Для теста или команды до десяти человек минимален VPS с 2 vCPU, 4 ГБ RAM и 50 ГБ SSD/NVMe. Он подходит при небольшом количестве вложений и умеренной активности. Для реальной рабочей команды лучше сразу выбрать 4 vCPU, 8 ГБ RAM и 80–100 ГБ NVMe: PostgreSQL получает больше кэша, фоновые задания не мешают веб-интерфейсу, а на диске остаётся место для временных бэкапов. Не экономьте на скорости диска.

Что выбрать — VPS или dedicated для этой задачи?

Для большинства установок OpenProject достаточно VPS: он дешевле, быстрее масштабируется и хорошо подходит командам до нескольких десятков пользователей. Dedicated нужен при сотнях активных пользователей, больших объёмах файлов, высокой нагрузке на PostgreSQL, строгих требованиях к физической изоляции или если на той же машине запускаются тяжёлые сервисы. Практичный путь — начать с VPS с запасом по RAM и диску, измерить нагрузку и переноситься только при реальной необходимости.

Как восстановить OpenProject из резервной копии?

На новом сервере разверните Docker и тот же каталог compose-конфигурации, но не запускайте OpenProject до восстановления данных. Создайте тома командой docker compose up -d db redis, импортируйте дамп через pg_restore в контейнер PostgreSQL и распакуйте opdata.tar.gz в Docker volume openproject_opdata. Верните исходный файл .env, особенно Rails secret, затем запустите весь стек и проверьте вход, проекты и вложения.

Диск быстро заполняется. Какие данные можно удалять?

Сначала определите источник роста: df -h, docker system df, du -sh ~/openproject/backups и docker volume ls. Чаще всего место занимают локальные бэкапы, вложения пользователей или журналы контейнеров. Уменьшите срок хранения локальных архивов только после успешной отправки во внешнее хранилище. Не удаляйте Docker volumes PostgreSQL или OpenProject вручную: это уничтожит рабочие данные. Для логов настройте ротацию Docker и контролируйте размеры.

Выводы и следующие шаги

Схема: Выводы и следующие шаги
Схема: Выводы и следующие шаги

Теперь OpenProject работает на VPS в Docker Compose, использует PostgreSQL и Redis, доступен по HTTPS через Caddy, отправляет уведомления через SMTP и имеет автоматизированные резервные копии. Такая схема подходит для небольшой и средней команды и позволяет контролировать данные, обновления и восстановление.

  1. Протестируйте восстановление последнего бэкапа на отдельном сервере или в изолированном Docker-окружении.
  2. Настройте мониторинг CPU, RAM, свободного места, доступности HTTPS и статуса резервного копирования.
  3. При росте команды вынесите PostgreSQL на отдельный сервер, добавьте внешний S3 для вложений и подготовьте план обновлений без длительного простоя.

Был ли этот гайд полезен?

Ваш отзыв помогает нам улучшать гайды.

Поделиться записью:

Отправьте гайд тому, кому он может пригодиться.

Telegram VKVK WhatsApp Facebook LinkedIn XX

установка openproject на vps: docker, postgresql, ssl, smtp и резервные копии
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.