Пошаговая инструкция · Самостоятельная установка
Как установить Plane на Ubuntu и запустить работу команды
Пошаговая инструкция для самостоятельной установки. Развернём Plane Community Edition на отдельном сервере, настроим HTTPS и безопасные параметры, создадим первый проект и подготовим копии задач с вложениями.
Что подготовить и как читать инструкцию #
Устанавливаем открытый Plane Community Edition, а не Commercial Edition на бесплатном плане. У этих редакций разные установщики и команды обслуживания. Для Community используем setup.sh и файлы одного стабильного релиза 1.4.2. Общее устройство работы с задачами и проектами описано на странице Plane.
Начальная оценка для небольшой команды — 4 vCPU, 8 ГБ RAM и SSD от 80 ГБ. Plane состоит из нескольких сервисов: web, API, обработчиков, PostgreSQL, кеша, очереди и хранилища вложений. Поэтому свободной памяти должно хватать всей установке, а не только открытому сайту. Подберите ресурсы по руководству выбора сервера Plane и предусмотрите место для роста базы, файлов и временной копии.
Команды выполняйте в терминале сервера после подключения по SSH, если шаг не указывает другое место. sudo даёт команде права администратора. Действия в браузере выполняйте на своём компьютере. Домены, IP-адреса и значения ВАШ_ПАРОЛЬ из примеров заменяйте своими до выполнения команды.
Двигайтесь по одному шагу и проверяйте результат перед следующим. Блок с <<EOF или другим именем завершения копируйте целиком: он записывает содержимое одного файла. При работе в nano сохраняйте файл клавишами Ctrl+O, Enter и выходите Ctrl+X. Если прервали SSH-сеанс, снова перейдите в указанный каталог; переменные предыдущего сеанса потребуется задать заново.
Подготовьте Nginx и Certbot на хосте по общей инструкции. Внешний Nginx обслуживает HTTPS, внутренний контейнер Nginx распределяет запросы по сервисам Plane. Это замена штатного proxy в официальном Compose; остальные сервисы и тома сохраняются.
Дополнительные официальные источники: Поддержка Ubuntu в Docker, Теги официального образа Nginx.
Шаг 1. Создайте каталоги Plane #
Комплект установки будет в /opt/plane-selfhost, файлы приложения — в plane-app. Не путайте каталог установки с файлами самого проекта.
sudo install -d -o "$USER" -g "$(id -gn)" -m 750 /opt/plane-selfhost
cd /opt/plane-selfhost
mkdir -p plane-appВы находитесь в /opt/plane-selfhost.
Шаг 2. Скачайте управляющие скрипты #
setup.sh управляет этой установкой, restore.sh используется для восстановления. Берём оба из релиза v1.4.2. Они пока только скачиваются.
curl -fL -o setup.sh https://github.com/makeplane/plane/releases/download/v1.4.2/setup.sh
curl -fL -o restore.sh https://github.com/makeplane/plane/releases/download/v1.4.2/restore.shОба скрипта скачаны без ошибки HTTP.
Шаг 3. Скачайте Compose и переменные #
Сохраним описание сервисов и образец plane.env того же релиза. Не смешивайте файлы разных выпусков.
curl -fL -o plane-app/docker-compose.yaml https://github.com/makeplane/plane/releases/download/v1.4.2/docker-compose.yml
curl -fL -o plane-app/plane.env https://github.com/makeplane/plane/releases/download/v1.4.2/variables.envВ plane-app находятся docker-compose.yaml и plane.env.
Шаг 4. Настройте доступ к файлам #
Скриптам нужно право запуска, файлу с секретами — ограниченное чтение. Перед запуском можно посмотреть скрипт через less setup.sh; выход — q.
chmod 750 setup.sh restore.sh
chmod 600 plane-app/plane.envСкрипты доступны владельцу, plane.env защищён правами 600.
Шаг 5. Подготовьте шесть случайных значений #
Повторите openssl rand -hex 32 шесть раз: значения нужны ключам приложения, совместного редактора, базы, очереди и двум реквизитам локального S3-совместимого хранилища. Это разные секреты, не один общий пароль.
openssl rand -hex 32Шесть значений сохранены в менеджере паролей.
Шаг 6. Заполните plane.env #
Откройте nano plane-app/plane.env и измените строки по образцу. Каждый REPLACE замените своим отдельным секретом, домен — своим адресом. Публичные URL используют HTTPS внешнего Nginx. CERT_EMAIL и параметры встроенного сертификата здесь не используются: его выпускает Certbot на хосте.
plane.envAPP_DOMAIN=plane.example.com
APP_RELEASE=v1.4.2
WEB_URL=https://plane.example.com
CORS_ALLOWED_ORIGINS=https://plane.example.com
SITE_ADDRESS=:80
CERT_EMAIL=
LISTEN_HTTP_PORT=8180
SECRET_KEY=REPLACE_WITH_RANDOM_APP_SECRET
LIVE_SERVER_SECRET_KEY=REPLACE_WITH_RANDOM_LIVE_SECRET
POSTGRES_PASSWORD=REPLACE_WITH_RANDOM_DB_PASSWORD
RABBITMQ_PASSWORD=REPLACE_WITH_RANDOM_QUEUE_PASSWORD
AWS_ACCESS_KEY_ID=REPLACE_WITH_RANDOM_STORAGE_ID
AWS_SECRET_ACCESS_KEY=REPLACE_WITH_RANDOM_STORAGE_SECRET
DEBUG=0Все REPLACE заменены; PUBLIC URL и APP_DOMAIN относятся к одному домену.
Шаг 7. Замените контейнер proxy на Nginx #
Откройте nano plane-app/docker-compose.yaml. Внутри services замените только целиком блок proxy приведённым ниже: от его строки proxy до следующего раздела верхнего уровня volumes. Прежние блоки web, api, базы и остальных сервисов сохраняйте. proxy слушает локальный 8180; 80/443 остаются Nginx на хосте.
plane-app/docker-compose.yaml proxy:
image: nginx:1.30.5-alpine
restart: unless-stopped
ports:
- "127.0.0.1:8180:80"
volumes:
- ./nginx-router.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- web
- api
- space
- admin
- live
- plane-minioСохраните файл. Имена сервисов не меняются; прежние proxy_config/proxy_data можно оставить в списке volumes — они не подключены к новому Nginx.
Шаг 8. Сохраните маршруты сервисов Plane #
Откройте nano plane-app/nginx-router.conf и сохраните файл ниже. Он повторяет маршруты релиза: /spaces — публичные проекты, /god-mode — настройки установки, /live — совместная работа, /api и /auth — сервер, /uploads — вложения. Не удаляйте префиксы путей. В нашем plane.env имя бакета AWS_S3_BUCKET_NAME=uploads; если поменяли его, поменяйте и маршрут. Внутренний Nginx получает заголовки только от внешнего Nginx, который их перезаписывает.
plane-app/nginx-router.confmap $http_upgrade $plane_internal_upgrade {
default upgrade;
"" close;
}
server {
listen 80;
client_max_body_size 5m;
location = /spaces { return 301 /spaces/; }
location = /god-mode { return 301 /god-mode/; }
location /spaces/ {
proxy_pass http://space:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $plane_internal_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
location /god-mode/ {
proxy_pass http://admin:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $plane_internal_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
location /live/ {
proxy_pass http://live:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $plane_internal_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
location /api/ {
proxy_pass http://api:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $plane_internal_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
location /auth/ {
proxy_pass http://api:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $plane_internal_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
location /static/ {
proxy_pass http://api:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $plane_internal_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
location /uploads {
proxy_pass http://plane-minio:9000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $plane_internal_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_request_buffering off;
}
location / {
proxy_pass http://web:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $plane_internal_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}Файл находится рядом с docker-compose.yaml. Лимит 5 МБ соответствует FILE_SIZE_LIMIT=5242880; если увеличиваете вложения, согласуйте оба значения.
Шаг 9. Направьте домен на сервер #
Создайте A-запись plane.example.com с публичным IP сервера. Порты 80/443 обслуживает Nginx на хосте, внутренний router доступен только на 127.0.0.1:8180.
getent ahostsv4 plane.example.com
sudo ss -lntpDNS возвращает ваш IP; у провайдера разрешены 80/443. Внешний доступ к 8180 не открывайте.
Шаг 10. Проверьте конфигурацию #
Проверим именно файлы из plane-app с указанным env-file. Без этого Compose может прочитать другой набор переменных.
cd /opt/plane-selfhost
sudo docker compose -f plane-app/docker-compose.yaml --env-file plane-app/plane.env config --quietКоманда завершилась без ошибки и отсутствующих переменных.
Шаг 11. Запустите официальный комплект #
setup.sh start запускает согласованные компоненты и подготовку базы. Первый запуск может занять несколько минут.
sudo ./setup.sh startСкрипт завершился успешно; не запускайте повторную установку во время работы.
Шаг 12. Дождитесь готовности сервиса #
Посмотрим контейнеры и миграцию базы. Migrator может завершиться после успешной миграции; API и новый proxy должны работать постоянно. Пока проверяем локальный HTTP, HTTPS будет следующим шагом.
sudo docker compose -f plane-app/docker-compose.yaml --env-file plane-app/plane.env ps
sudo docker compose -f plane-app/docker-compose.yaml --env-file plane-app/plane.env logs --tail=80 migrator api proxy
curl -I http://127.0.0.1:8180/Локальный адрес возвращает HTTP 200 или перенаправление; API и proxy не перезапускаются. Ошибка Nginx host not found требует проверить имя сервиса в Compose.
Шаг 13. Сохраните сайт Nginx #
Установите Nginx и Certbot по подготовке Ubuntu, если ещё не установили. Откройте sudo nano /etc/nginx/sites-available/plane и вставьте файл ниже. Замените все домены своими. Nginx передаёт приложению домен, адрес клиента и протокол; Upgrade и Connection сохраняют WebSocket. До получения сертификата условие $scheme блокирует обычные HTTP-запросы кодом 403, чтобы вход не происходил без шифрования. WebSocket проходит через оба Nginx без удаления /live/. Внутренние маршруты уже настроены в nginx-router.conf; внешний прокси сохраняет исходный URI.
/etc/nginx/sites-available/planemap $http_upgrade $plane_connection_upgrade {
default upgrade;
"" close;
}
server {
listen 80;
server_name plane.example.com;
client_max_body_size 5m;
location / {
if ($scheme = http) { return 403; }
proxy_pass http://127.0.0.1:8180;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $plane_connection_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}
Сохраните Ctrl+O, Enter, Ctrl+X. В файле пока нет путей к сертификатам: Nginx сможет проверить его до выпуска HTTPS.
Шаг 14. Подключите сайт и проверьте HTTP #
Ссылка подключает сохранённый сайт. nginx -t проверяет все настройки сервера; && разрешает перечитать их только при успешной проверке. curl проверяет ответ для вашего домена. При ошибке остановитесь, исправьте указанную строку и повторите проверку.
sudo ln -sfn /etc/nginx/sites-available/plane /etc/nginx/sites-enabled/plane
sudo nginx -t && sudo systemctl reload nginx
curl -I http://plane.example.com/Ожидается successful от nginx -t и HTTP 403 для обычного запроса: до HTTPS это намеренная блокировка. DNS должен указывать на сервер, TCP 80/443 — быть доступен у провайдера. Ничего не вводите в форму входа по HTTP.
Шаг 15. Получите сертификат и включите HTTPS #
Каждое имя из команды должно указывать на этот сервер. Certbot проверит домены, сам добавит сертификат в сайт Nginx и включит перенаправление HTTP → HTTPS. Укажите свою почту при запросе и подтвердите условия Let’s Encrypt. Это отдельное действие после успешной проверки HTTP.
sudo /snap/bin/certbot --nginx -d plane.example.com --redirectCertbot сообщил об успешной установке. Откройте HTTPS-адрес со своего компьютера: браузер не должен предупреждать о сертификате. Для закрытой панели используйте разрешённый IP. При ошибке исправьте DNS, в том числе AAAA, либо доступ к TCP 80; не повторяйте запросы выпуска подряд.
Шаг 16. Проверьте продление сертификата #
Certbot из snap создаёт службу автоматического продления. Dry-run выполняет пробное продление: настоящие сертификаты не заменяются. Затем проверьте, что таймер планирует следующий запуск. Сохраняйте доступ к TCP 80 для следующих проверок домена.
sudo /snap/bin/certbot renew --dry-run
systemctl list-timers --all 'snap.certbot.renew*'Пробное продление успешно, у таймера есть следующий запуск. Если тест не прошёл, проверьте /var/log/letsencrypt/letsencrypt.log; сначала исправьте причину. После этого можно создавать учётную запись и приглашать пользователей.
Шаг 17. Создайте владельца #
Откройте свой HTTPS-домен и завершите первоначальную настройку владельца. Перед публичным доступом выберите правила регистрации и приглашений организации.
Вы входите в административную часть своей установки.
Шаг 18. Создайте рабочее пространство #
Создайте workspace для тестовой команды, затем проект внутри него. Workspace объединяет участников, проект — задачи конкретной работы.
Проект появляется в нужном workspace.
Шаг 19. Добавьте первую задачу #
В проекте создайте задачу с понятным названием и описанием, назначьте себя исполнителем, измените статус. Откройте задачу повторно.
Описание, исполнитель и статус сохранены.
Шаг 20. Проверьте приглашение сотрудника #
Заполните SMTP в настройках установки по данным почтового провайдера. Пригласите вторую тестовую учётную запись в workspace и выберите обычные права.
Приглашение доставлено; участник видит только доступные ему workspace и проект.
Шаг 21. Проверьте вложение #
Загрузите небольшой тестовый файл в задачу и откройте его со второй учётной записи. Это проверяет объектное хранилище и доступ, а не только базу задач.
Файл скачивается после повторного открытия задачи.
Шаг 22. Остановите приложение для штатной копии #
Предупредите пользователей о перерыве. Выполняйте управляющие команды из /opt/plane-selfhost.
cd /opt/plane-selfhost
sudo ./setup.sh stopСервисы остановлены без удаления томов.
Шаг 23. Запустите штатный backup #
setup.sh backup создаёт копию по правилам выбранного комплекта. Сохраните путь результата из вывода. Перенесите копию в закрытое внешнее хранилище; restore.sh сначала проверяйте на отдельной машине.
Штатный backup сохраняет данные контейнеров. Отдельно архивируйте setup.sh, restore.sh, plane-app/plane.env, plane-app/docker-compose.yaml, plane-app/nginx-router.conf, /etc/nginx/sites-available/plane и /etc/letsencrypt с sudo в закрытое хранилище: именно они воспроизводят выбранную схему Nginx.
backupsudo ./setup.sh backupКопия создана без ошибки и включает необходимые части установки.
Шаг 24. Возобновите работу и проверьте копию #
Снова запустите Plane. Проверьте тестовую задачу и вложение. При пробном восстановлении эти же данные должны вернуться; только наличие архива этого не подтверждает.
sudo ./setup.sh startПроект доступен после запуска и после тестового восстановления.
Если результат шага отличается #
Вернитесь к проверке того шага, на котором появилась ошибка. Первая ошибка в выводе обычно полезнее последних строк: последующие команды могли не получить нужный файл или работающую службу. Не повторяйте установку целиком поверх частично настроенного приложения.
Если страница не открывается, сначала проверьте домен и входящие порты, затем состояние приложения и его журнал. Если сайт открывается, но отдельное действие не работает, проверьте связанные компоненты — обработчик фоновых задач, почту или права пользователя. Официальные источники в конце статьи относятся к выбранному способу установки.
setup.sh upgrade скачивает новый официальный Compose и может вернуть прежний proxy. До обновления сохраните свои файлы, прочитайте изменения релиза и повторите замену proxy и маршрутов на тестовой копии. Не запускайте обновлённый комплект, пока его внешний прокси снова занимает 80/443. После восстановления подключите сайт Nginx в sites-enabled и проверьте nginx -t и продление Certbot.
После изменения nginx-router.conf либо пересоздания контейнера API или frontend перезапустите внутренний proxy: sudo docker compose -f plane-app/docker-compose.yaml --env-file plane-app/plane.env restart proxy из /opt/plane-selfhost. Nginx перечитает файл и заново разрешит адреса сервисов Docker. Затем повторите проверку проекта, вложения и совместного редактора.