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

Отримати VPS arrow_forward
eco Початковий Туторіал

Встановлення OpenProject на VPS: Docker, PostgreSQL, SSL, SMTP та резервні копії

calendar_month Oct 21, 2026 schedule 18 хв. читання visibility 57 переглядів
Установка 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 для запрошень, нагадувань, сповіщень про завдання та відновлення доступу. Без правильно налаштованої вихідної пошти користувачі зможуть працювати в інтерфейсі, але не отримуватимуть важливі події електронною поштою.

У файлі .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 для вкладень і підготуйте план оновлень без тривалого простою.

Чи був цей гайд корисним?

Ваш відгук допомагає нам покращувати гайди.

Share this post:

Надішліть гайд тому, кому він може стати в пригоді.

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.