Управление задачами в команде превратилось в отдельную дисциплину со своими гуру, методологиями и облачными сервисами на любой кошелёк. Trello, Asana, Notion, Monday - список можно продолжать долго, и каждый из этих игроков предлагает что-то своё за ежемесячную абонентскую плату. Но есть категория пользователей, которая хочет иметь kanban-доски и трекинг задач, не отдавая чувствительные данные в чужие облака. Для них существует Focalboard - открытая самохостящаяся альтернатива коммерческим монстрам, разработанная командой Mattermost.
Focalboard написан на Go и работает практически на любой платформе. На бэкенде это компактный сервер, способный жить как с SQLite для домашних экспериментов, так и с полноценной PostgreSQL для командных инсталляций. На фронтенде - React-приложение с привычным kanban-интерфейсом, картами задач, метками, чек-листами и кастомными свойствами. По функционалу инструмент покрывает потребности большинства небольших и средних команд, а наличие исходников на GitHub даёт ту самую свободу, которой не хватает в проприетарных аналогах.
В материале разбирается полный сценарий развёртывания Focalboard на сервере под Ubuntu 22.04. Установка PostgreSQL и создание базы под нужды приложения, выкачивание свежей версии Focalboard с GitHub, настройка systemd-юнита для автозапуска, проксирование через Nginx с поддержкой WebSocket для realtime-обновлений досок и подключение бесплатного SSL-сертификата от Let's Encrypt. Шаги выстроены так, чтобы каждый следующий логично вытекал из предыдущего.
Установка СУБД PostgreSQL и подготовка базы данных под хранение содержимого досок Focalboard
Focalboard поддерживает несколько движков для хранения данных, но PostgreSQL остаётся предпочтительным выбором для серьёзных инсталляций. Эта реляционная база данных давно зарекомендовала себя как одна из самых надёжных в мире open source - умеет работать с JSON, держит транзакции с гарантиями ACID, прощает многое и масштабируется до огромных нагрузок. Для kanban-досок с десятками тысяч карточек её возможностей хватит с большим запасом.
Сначала ставятся вспомогательные утилиты, которые понадобятся на следующих шагах для скачивания файлов и работы с ключами.
apt-get install curl wget gnupg2 -y
После этого устанавливается сама СУБД и пакет с дополнительными модулями contrib.
apt-get install postgresql postgresql-contrib -y
Пакет postgresql-contrib содержит набор расширений и утилит, которые формально не входят в ядро системы, но регулярно нужны на практике. Среди них есть, например, расширение для работы с криптографическими функциями pgcrypto или генератор UUID. Без них Focalboard стартанёт, но иметь их под рукой - правильная привычка.
После установки подключение к базе выполняется через стандартного системного пользователя postgres, который создаётся автоматически.
su - postgres
psql
Первая команда переключает контекст оболочки на пользователя postgres, у которого есть права на доступ к серверу БД через сокет без пароля. Вторая запускает интерактивную консоль psql - это основной клиент для работы с PostgreSQL из командной строки.
Внутри psql создаётся отдельная база данных и пользователь, который будет ходить в неё от имени Focalboard.
CREATE DATABASE focaldb;
CREATE USER focaluser WITH PASSWORD 'password';
Принцип минимальных привилегий тут проявляется в полную силу. Приложение получает доступ только к своей базе под отдельной учётной записью, а не использует суперпользовательские полномочия. Если завтра в Focalboard найдут уязвимость, остальные базы на этом же сервере останутся недоступными для атакующего. Пароль 'password' оставлен в туториале для наглядности, но в реальной установке его нужно заменить на длинную случайную последовательность.
Выход из консоли и пользовательской сессии postgres делается двумя командами.
\q
exit
Обратный слеш с буквой q - это специальная команда psql для выхода из клиента. Команда exit завершает сессию пользователя postgres и возвращает обратно к root-оболочке. База готова, можно переходить к самому приложению.
Скачивание актуальной версии Focalboard с GitHub и настройка подключения к базе данных
Focalboard распространяется в виде готовых бинарных сборок для разных платформ. Никакой компиляции из исходников не требуется - достаточно скачать архив для нужной архитектуры и распаковать его в подходящий каталог. Чтобы каждый раз не лазить на страницу релизов и не копировать ссылки руками, удобно автоматизировать получение свежей версии через API GitHub.
VER=$(curl -s https://api.github.com/repos/mattermost/focalboard/releases/latest|grep tag_name | cut -d '"' -f 4)
wget https://github.com/mattermost/focalboard/releases/download/${VER}/focalboard-server-linux-amd64.tar.gz
Первая строка делает запрос к API GitHub за информацией о последнем релизе, вытаскивает строку с тегом версии через grep и обрезает её через cut по разделителю - двойной кавычке. Получается переменная VER со значением вроде v7.10.4 или какой там окажется актуальная цифра на момент установки. Вторая команда подставляет эту переменную в URL и качает архив с сервером для Linux на архитектуре amd64.
Распаковка делается обычным tar-ом.
tar -xvzf focalboard-server-linux-amd64.tar.gz
Флаги расшифровываются как extract (-x), verbose (-v), gzip (-z) и file (-f). Verbose покажет, какие именно файлы вынимаются из архива - полезно для понимания структуры дистрибутива.
Распакованный каталог переносится в /opt - стандартное место для установки сторонних приложений в Linux.
mv focalboard /opt
Каталог /opt существует именно для таких случаев. Туда складывают софт, который не вписывается в иерархию /usr - не системные утилиты, не стандартные пакеты, а отдельные продукты со своей структурой каталогов. Focalboard со своими bin, templates, files идеально подходит под этот сценарий.
Дальше настраивается соединение с базой данных. Конфигурационный файл лежит в корне установки.
nano /opt/focalboard/config.json
В нём нужно найти и поправить две строки, описывающие тип СУБД и параметры подключения.
"dbtype": "postgres",
"dbconfig": "postgres://focaluser:password@localhost/focaldb?sslmode=disable&connect_timeout=10",
Первая строка переключает Focalboard с дефолтного SQLite на PostgreSQL. Вторая - это строка подключения в формате DSN. Структура её довольно прозрачна - протокол postgres, далее пользователь и пароль через двоеточие, после собачки имя хоста, после слеша имя базы. В query-параметрах указано отключение SSL для локального соединения и таймаут подключения в десять секунд. Для удалённого PostgreSQL-сервера sslmode стоит включить, но в нашем сценарии база лежит на той же машине и шифрование локальных сокетов избыточно.
После сохранения файла приложение готово стартовать, но запускать его руками каждый раз неправильно - надо оформить как системный сервис.
Создание systemd-юнита для управления процессом Focalboard и его автозапуска при загрузке системы
Любое серьёзное приложение в Linux должно работать как сервис под управлением systemd. Это даёт автозапуск при загрузке, автоматический перезапуск при сбоях, централизованное логирование через journalctl и удобное управление через стандартные команды systemctl. Без юнита приложение - просто процесс, который умрёт при ближайшем выходе из SSH-сессии.
nano /lib/systemd/system/focalboard.service
В файл добавляется минимальный, но достаточный набор директив.
[Unit]
Description=Focalboard server
[Service]
Type=simple
Restart=always
RestartSec=5s
ExecStart=/opt/focalboard/bin/focalboard-server
WorkingDirectory=/opt/focalboard
[Install]
WantedBy=multi-user.target
Разберём содержимое последовательно. Секция Unit содержит человекочитаемое описание - оно появится в выводе systemctl list-units и в логах. Параметр Description короткий, но осмысленный, чего вполне достаточно.
Секция Service - сердце юнита. Type simple означает простой запуск без форков и демонизации. Главный процесс - тот, что в ExecStart. Параметр Restart со значением always заставляет systemd возрождать сервис при любом завершении, штатном или аварийном. RestartSec задаёт паузу в пять секунд перед перезапуском - это страховка от бесконечного цикла перезапусков, если приложение падает сразу при старте по какой-то фундаментальной причине.
Директива ExecStart содержит полный путь к бинарнику. Никаких аргументов не нужно - все настройки Focalboard берёт из config.json в рабочем каталоге. Параметр WorkingDirectory как раз задаёт этот рабочий каталог. Без него приложение запустилось бы из корня системы и не нашло бы свои конфиги, шаблоны и статические файлы.
Секция Install с записью WantedBy=multi-user.target отвечает за автозапуск. Когда сервер выйдет в многопользовательский режим (а это происходит при каждой нормальной загрузке), systemd подцепит и наш сервис вместе с прочими.
После сохранения файла систему демонов нужно уведомить о появлении нового юнита.
systemctl daemon-reload
Без этой команды systemd не узнает о свежесозданном файле и попытка запустить focalboard завершится ошибкой. Перезагрузка демона перечитывает все юнит-файлы и обновляет внутреннюю базу. Затем сервис стартует и одновременно прописывается в автозапуск.
systemctl start focalboard
systemctl enable focalboard
Эти две команды можно было бы объединить в одну - systemctl enable focalboard --now - но в туториале они разнесены для наглядности. Результат одинаковый.
Проверка статуса подтверждает успешный старт.
systemctl status focalboard
В нормальной ситуации вывод выглядит примерно так.
? focalboard.service - Focalboard server
Loaded: loaded (/lib/systemd/system/focalboard.service; disabled; vendor preset: enabled)
Active: active (running) since Sun 2022-08-21 11:22:22 UTC; 8s ago
Main PID: 4347 (focalboard-serv)
Tasks: 4 (limit: 2242)
Memory: 18.1M
CPU: 1.977s
CGroup: /system.slice/focalboard.service
??4347 /opt/focalboard/bin/focalboard-server
Aug 21 11:22:23 ubuntu2204 focalboard-server[4347]: debug [2022-08-21 11:22:23.507 Z] listener(s) for blockID caller="ws/ser>
Aug 21 11:22:23 ubuntu2204 focalboard-server[4347]: debug [2022-08-21 11:22:23.507 Z] listener(s) for blockID caller="ws/ser>
Aug 21 11:22:23 ubuntu2204 focalboard-server[4347]: debug [2022-08-21 11:22:23.510 Z] listener(s) for workspaceID caller="ws/ser>
Aug 21 11:22:23 ubuntu2204 focalboard-server[4347]: debug [2022-08-21 11:22:23.510 Z] listener(s) for blockID caller="ws/ser>
Aug 21 11:22:23 ubuntu2204 focalboard-server[4347]: debug [2022-08-21 11:22:23.510 Z] listener(s) for blockID caller="ws/ser>
Aug 21 11:22:24 ubuntu2204 focalboard-server[4347]: debug [2022-08-21 11:22:24.928 Z] import archive - done caller="app/im>
Aug 21 11:22:24 ubuntu2204 focalboard-server[4347]: info [2022-08-21 11:22:24.937 Z] initialized workspace caller="app/wo>
Aug 21 11:22:24 ubuntu2204 focalboard-server[4347]: info [2022-08-21 11:22:24.941 Z] Server.Start caller="server>
Aug 21 11:22:24 ubuntu2204 focalboard-server[4347]: info [2022-08-21 11:22:24.941 Z] http server started caller="web/we>
Aug 21 11:22:24 ubuntu2204 focalboard-server[4347]: info [2022-08-21 11:22:24.947 Z] Starting unix socket server caller="server>
Зелёный active (running) и низкое потребление памяти около 18 мегабайт - картина здорового приложения. По умолчанию Focalboard слушает порт 8000 для HTTP и порт 9092 для метрик. Проверить занятые порты можно через ss.
ss -antpl | grep focalboard
Вывод подтверждает, что приложение принимает соединения на обоих портах.
LISTEN 0 4096 *:8000 *:* users:(("focalboard-serv",pid=4347,fd=9))
LISTEN 0 4096 *:9092 *:* users:(("focalboard-serv",pid=4347,fd=8))
Первый порт - основной веб-интерфейс, второй пригодится для интеграции с системами мониторинга вроде Prometheus.
Конфигурация Nginx как обратного прокси с поддержкой WebSocket для работы realtime-обновлений досок
Открывать восьмой тысячный порт наружу - решение неэлегантное и небезопасное. Куда правильнее поставить перед Focalboard полноценный веб-сервер, который будет принимать соединения на стандартных портах 80 и 443, шифровать трафик и проксировать запросы на бэкенд. Nginx подходит для этой роли идеально благодаря своей лёгкости и зрелой поддержке проксирования.
apt-get install nginx -y
После установки создаётся отдельный конфиг-файл для нашего приложения.
nano /etc/nginx/conf.d/focalboard.conf
Содержимое конфига получается объёмным, но каждая директива в нём оправдана.
upstream focalboard {
server localhost:8000;
keepalive 32;
}
server {
listen 80;
server_name focalboard.example.com;
location ~ /ws/* {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 50M;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_buffers 256 16k;
proxy_buffer_size 16k;
client_body_timeout 60;
send_timeout 300;
lingering_timeout 5;
proxy_connect_timeout 1d;
proxy_send_timeout 1d;
proxy_read_timeout 1d;
proxy_pass http://focalboard;
}
location / {
client_max_body_size 50M;
proxy_set_header Connection "";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_buffers 256 16k;
proxy_buffer_size 16k;
proxy_read_timeout 600s;
proxy_cache_revalidate on;
proxy_cache_min_uses 2;
proxy_cache_use_stale timeout;
proxy_cache_lock on;
proxy_http_version 1.1;
proxy_pass http://focalboard;
}
}
Разберём ключевые моменты. Блок upstream объявляет именованный пул бэкендов с одним сервером на локальном порту 8000. Параметр keepalive 32 заставляет Nginx держать в кеше до 32 готовых TCP-соединений с бэкендом, экономя время на установлении новых сессий при каждом запросе. Для приложения с активным интерфейсом это даёт заметный прирост отзывчивости.
Server-блок слушает 80-й порт и обрабатывает запросы для конкретного домена focalboard.example.com. Внутри объявлены две локации с разной логикой обработки.
Первая локация с регулярным выражением /ws/* ловит все запросы к WebSocket-эндпоинтам. Focalboard использует WebSocket для синхронизации досок в реальном времени - когда один пользователь двигает карточку, все остальные видят изменение мгновенно без перезагрузки страницы. Чтобы Nginx корректно проксировал такие соединения, нужны заголовки Upgrade и Connection со значением upgrade. Без них браузерный WebSocket попытается установиться, получит обычный HTTP-ответ и сломается.
Параметры таймаутов в WebSocket-блоке выставлены в один день (1d). Это сделано намеренно - реалтайм-соединение должно жить долго, иначе клиент будет постоянно его переустанавливать, теряя обновления. Для обычного HTTP такие таймауты были бы безумием, но для long-polling и постоянных коннектов - в самый раз.
Вторая локация с одинарным слешем ловит весь остальной трафик - HTML-страницы, JavaScript, CSS, картинки, API-вызовы. Здесь набор заголовков попроще, но появляются интересные директивы proxy_cache_*. Они включают кеширование ответов от бэкенда с возможностью проверки актуальности, использования устаревших данных при недоступности backend и блокировкой одновременных запросов на одну и ту же страницу. Параметр proxy_cache_min_uses 2 означает, что в кеш попадёт только то, что запрошено хотя бы дважды - это отсекает разовые обращения и не засоряет кеш.
Размер тела запроса ограничен 50 мегабайтами через client_max_body_size. Этого достаточно для прикрепления к карточкам Focalboard картинок, документов и большинства других файлов. Если планируется загружать что-то крупнее, цифру нужно увеличить.
Заголовки X-Real-IP, X-Forwarded-For и X-Forwarded-Proto передают бэкенду информацию об оригинальном клиенте. Без них Focalboard будет видеть все запросы как идущие с 127.0.0.1, что сломает любую логику ограничения доступа по IP, аналитику и логирование. X-Frame-Options SAMEORIGIN запрещает показывать страницы Focalboard внутри iframe на сторонних сайтах - простая защита от clickjacking-атак.
Перед перезапуском Nginx обязательна проверка синтаксиса.
nginx -t
Корректный конфиг даёт два радостных подтверждения.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Если же где-то закралась опечатка, Nginx честно покажет проблемную строку и не даст применить битый конфиг. Эта проверка спасла больше серверов от падения, чем все системы мониторинга вместе взятые.
systemctl restart nginx
После перезапуска прокси готов к работе. Проверка статуса не помешает.
systemctl status nginx
? nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2022-08-21 11:24:08 UTC; 7s ago
Docs: man:nginx(8)
Process: 5017 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 5018 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 5019 (nginx)
Tasks: 2 (limit: 2242)
Memory: 2.6M
CPU: 35ms
CGroup: /system.slice/nginx.service
??5019 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
??5020 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
Aug 21 11:24:08 ubuntu2204 systemd[1]: Starting A high performance web server and a reverse proxy server...
Aug 21 11:24:08 ubuntu2204 systemd[1]: Started A high performance web server and a reverse proxy server.
Nginx запущен, потребляет смешные пару мегабайт памяти и готов принимать соединения на 80-м порту.
Первый вход в веб-интерфейс Focalboard и регистрация администраторской учётной записи
Открыв в браузере адрес http://focalboard.example.com/login, посетитель попадает на страницу входа. Поскольку учётных записей пока нет, нужно нажать кнопку create an account и пройти регистрацию первого пользователя.
В форме регистрации запрашивается email-адрес, имя пользователя и пароль. Первый зарегистрированный получает права администратора - это типовой паттерн для самохостящихся приложений, когда первый пользователь становится владельцем системы по умолчанию. Все последующие учётные записи будут обычными, без особых привилегий, если их явно не повысить через интерфейс.
После нажатия кнопки Register происходит автоматическая авторизация и переход на главную страницу - dashboard со списком рабочих пространств. Пользователь сразу попадает в готовое к работе приложение с шаблонами kanban-досок, готовыми категориями карточек и базовыми настройками. Можно создавать свои доски с нуля или начинать с одного из шаблонов - управление личными задачами, отслеживание спринтов в команде разработки, ведение редакционного календаря и так далее.
Подключение бесплатного SSL-сертификата от Let's Encrypt через Certbot для шифрования соединений
Работающий сайт по HTTP - решение времён начала двухтысячных. Современные браузеры активно ругают незащищённые соединения, поисковики понижают такие сайты в выдаче, а пользователи справедливо насторожены. Бесплатный сертификат от Let's Encrypt снимает все эти проблемы за пять минут.
Для автоматизации процесса используется Certbot - официальный клиент проекта Let's Encrypt с плагином для интеграции с Nginx.
apt-get install python3-certbot-nginx -y
Плагин python3-certbot-nginx умеет сам править конфиги Nginx, добавляя нужные директивы для SSL и редиректы с HTTP на HTTPS. Это удобно, когда не хочется лезть в конфиг руками.
Сам запрос сертификата выполняется командой.
certbot --nginx -d focalboard.example.com
Параметр --nginx активирует упомянутый плагин, флаг -d указывает доменное имя, для которого нужен сертификат. Certbot запросит email для уведомлений и согласие с пользовательским соглашением.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for focalboard.example.com
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/conf.d/focalboard.conf
Email используется для уведомлений о скором истечении сертификата и других важных событиях. Подписка на рассылку EFF опциональна и никак не влияет на работу сертификата. После согласия Certbot проводит http-01 challenge - размещает специальный файл в корне сайта и просит сервера Let's Encrypt проверить его наличие. Так подтверждается владение доменом.
В завершение процесса задаётся вопрос о редиректе с HTTP на HTTPS.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Выбор второго варианта добавит в конфиг Nginx перенаправление всех HTTP-запросов на HTTPS. Это правильная практика для современных сайтов - незачем оставлять возможность подключаться по незашифрованному протоколу, если шифрование уже настроено.
Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/focalboard.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://focalboard.example.com
You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=focalboard.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/focalboard.example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/focalboard.example.com/privkey.pem
Your cert will expire on 2022-11-21. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
- We were unable to subscribe you the EFF mailing list because your
e-mail address appears to be invalid. You can try again later by
visiting https://act.eff.org.
Сертификаты Let's Encrypt действуют 90 дней, но Certbot автоматически устанавливает systemd-таймер для их продления. Каждые двенадцать часов запускается фоновая задача, которая проверяет, не пора ли обновить сертификаты, и при необходимости делает это без вмешательства человека. Ручной прогон обновления через certbot renew тоже работает - полезно для проверки, что всё настроено корректно.
Сразу после получения сертификата по адресу https://focalboard.example.com открывается то же самое приложение, но уже с зелёным замочком в адресной строке и полноценным TLS-шифрованием.
Практическая ценность самохостящегося трекера задач и сценарии его применения в небольших командах
Получившаяся установка Focalboard - это полноценный инструмент управления задачами, развёрнутый на собственной инфраструктуре с настоящей базой данных, надёжным веб-сервером и шифрованием трафика. Для команды из пяти - двадцати человек такая конфигурация переваривает нагрузку без малейших усилий. На скромном VPS с двумя гигабайтами памяти и одним ядром процессора Focalboard живёт уютно, оставляя ресурсы для других сервисов.
Основная ценность самохостящегося решения раскрывается в нескольких плоскостях. Первая - контроль над данными. Информация о проектах, рабочих процессах и приоритетах команды никуда не уходит за пределы корпоративной инфраструктуры. Это особенно ценно для проектов, связанных с интеллектуальной собственностью, конкурентной разведкой или просто чувствительной коммерческой информацией.
Вторая плоскость - стоимость. Облачные альтернативы вроде Asana или Notion берут плату за каждого пользователя в месяц, и при росте команды счёт может перевалить за неприличные цифры. Focalboard на собственном сервере обходится в стоимость самого сервера - двадцать долларов в месяц на VPS покрывают потребности команды любого разумного размера.
Третья плоскость - кастомизация. Открытый исходный код позволяет править функционал под свои процессы, добавлять интеграции с внутренними системами компании, настраивать внешний вид. Команды разработчиков могут включить Focalboard в свой CI/CD-конвейер, автоматически создавая карточки из issue в трекере или закрывая задачи при мерже pull request.
Освоение схемы развёртывания, разобранной в материале, открывает дорогу к другим самохостящимся решениям. Принципы те же самые - PostgreSQL для данных, systemd для управления процессом, Nginx для проксирования, Let's Encrypt для шифрования. Поменяй приложение - и получится готовый Mattermost, или Gitea, или Nextcloud, или десяток других продуктов с похожей архитектурой. Один раз потраченное время на освоение этой схемы окупается многократно при каждом следующем сервисе.