С российского рынка уже ушли многие ИТ-продукты, которыми мы привыкли пользоваться в рабочих целях. Сложно сказать, какой софт станет недоступен следующим — хочется найти замену заранее, чтобы не остаться без необходимых инструментов. Мы решили потестировать разные продукты и в первую очередь найти альтернативу Confluence или Notion: нужна была удобная база знаний, которая не зависит от внешнего мира и не скажет тебе в один момент «пока». В итоге мы определили интересный вариант, и в этом материале хотим поделиться пошаговой инструкцией по развертыванию стека на собственном сервере.
Всем привет! Меня зовут Игорь, я DevOps в Malov.Tech[ссылка удалена мод.]. Недавно я нашел и развернул open-source wiki-систему для нашей команды, которую мы теперь используем как базу знаний. В статье я расскажу, на что стоит обратить внимание, когда запускаешь решение на собственном сервере. Также записал подробную видео-инструкцию — она доступна выше. Рекомендую и прочитать статью, и посмотреть инструкцию, тогда все точно получится повторить :)
Предыстория
Мы в команде искали сервис, который сможет заменить Confluence и в процессе наткнулись на Outline. Протестировали его какое-то время и поняли, что нас он абсолютно устраивает по функциональности.
Итак, Outline — это open-source база знаний, основанная на markdown-подобном языке, для коллективного пользования. Редактор поддерживает маркдаун и позволяет структурировать информацию с учетом разделения доступов. Мы храним здесь бизнес-требования заказчика, технические задания, ссылки на различные материалы и данные по коллегам (дни рождения и т.д).
Принцип ведения записей
Если TTL (срок годности) информации больше чем несколько дней, то эту инфу стоит структурно занести в Outline.
Все могут в любой момент дополнить и структурировать чужой текст.
Outline ведем все вместе.
Недостатки тоже есть, поскольку решение свежее и, по сути, MVP: нет возможности посмотреть, кто именно редактировал текст, нет баз данных как в Notion, но ребята взяли высокий темп разработки и, уверен, скоро наверстают функционал.
Мы развернули стек на виртуальном сервере с Ubuntu 20.04, 2 ГБ RAM и 2 CPU + на сервере активны еще 2-3 сервиса, необходимых для полноценной работы.
Инструкция
Предполагается, что вы уже установили:
1. Docker — https://docs.docker.com/engine/
2. Portainer — https://docs.portainer.io/start/install/server/docker/linux
Поэтому, начнем сразу из Portainer:
3. Создаем новую сеть докера, которая будет использоваться во всех необходимых сервисах.
- Networks > Add network > называем её: reverseproxy
4. Устанавливаем Nginx-Proxy-Manager (далее NPM, но не путаем его условную аббревиатуру с консольной командой "npm" — менеджера пакетов, входящего в Node.js). Наш NPM - это фактически тот же Nginx, только с интуитивно понятным веб-интерфейсом.
В рамках этого гайда с помощью NPM мы добавим конфигурацию Nginx. В нем мы настроим обратный прокси для подключенных к сети reverseproxy сервисов и получим для наших доменов SSL-сертификаты Let's Encrypt.
- Stacks > Add stack
Пример готового стека:
version: "3" services: app: image: 'jc21/nginx-proxy-manager:latest' restart: unless-stopped ports: # В формате <host-port>:<container-port> - '80:80' # Public HTTP Port - '443:443' # Public HTTPS Port - '81:81' # Admin Web Port environment: DB_MYSQL_HOST: "db" DB_MYSQL_PORT: 3306 DB_MYSQL_USER: "npm" DB_MYSQL_PASSWORD: ${MYSQL_PASSWORD} DB_MYSQL_NAME: "npm" # true, если IPv6 не включен на вашем хосте DISABLE_IPV6: 'true' volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt depends_on: - db networks: - nginx-proxy-manager - reverseproxy db: image: 'jc21/mariadb-aria:latest' restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: 'npm' MYSQL_USER: 'npm' MYSQL_PASSWORD: ${MYSQL_PASSWORD} volumes: - ./data/mysql:/var/lib/mysql networks: - nginx-proxy-manager networks: nginx-proxy-manager: reverseproxy: external: true
Ниже нажимаем "Advanced mode", либо два раза "Add an environment variable" >
MYSQL_ROOT_PASSWORD=<сгенерированный пароль, например, через openssl rand -hex 20> MYSQL_PASSWORD=<сгенерированный пароль, например, через openssl rand -hex 20>
Если установка прошла корректно, вы сможете зайти в веб-панель NPM по адресу http://{ip-адрес-сервера}:81 через стандартный аккаунт админа:
- Логин: admin@example.com
- Пароль: changeme
5. Установим Outline.
Обратите внимание, стандартные порты Outline и MinIO (о MinIO ниже) мы сразу делаем закрытыми (закомментировав), и включаем эти сервисы в сеть "reverseproxy". Немного позже настроим обращение к этим портам через NPM с помощью обратного прокси.
- Stacks > Add stack
Пример готового стека:
version: "2" services: outline_redis: image: redis restart: always container_name: outline_redis networks: - outline-internal outline_postgres: image: postgres:13 restart: always container_name: outline_postgres environment: - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_USER=outline - POSTGRES_DB=outline networks: - outline-internal volumes: - /mnt/containers/outline/container-data/db:/var/lib/postgresql/data:Z # ports: # - 5432:5432 outline_minio: image: minio/minio restart: always container_name: outline_minio volumes: - /mnt/containers/outline/container-data/data:/data:Z environment: - MINIO_ROOT_USER=minio - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD} - MINIO_BROWSER_REDIRECT_URL=${MINIO_BROWSER_REDIRECT_URL} # ports: # - 9000:9000 # - 9001:9001 networks: - reverseproxy command: "server /data --console-address :9001" outline: image: outlinewiki/outline user: root restart: always container_name: outline command: sh -c "yarn sequelize:migrate --env=production-ssl-disabled && yarn start --env=production-ssl-disabled" depends_on: - outline_postgres - outline_redis - outline_minio environment: - PGSSLMODE=disable - SECRET_KEY=${SECRET_KEY} - UTILS_SECRET=${UTILS_SECRET} - DATABASE_URL=postgres://outline:${POSTGRES_PASSWORD}@outline_postgres:5432/outline - REDIS_URL=redis://outline_redis:6379 - URL=${WIKI_URL} - PORT=443 - AWS_ACCESS_KEY_ID=minio - AWS_REGION=us-east-1 - AWS_SECRET_ACCESS_KEY=${MINIO_ROOT_PASSWORD} - AWS_S3_UPLOAD_BUCKET_URL=${WIKIDATA_URL} - AWS_S3_UPLOAD_BUCKET_NAME=outline - AWS_S3_UPLOAD_MAX_SIZE=26214400 - AWS_S3_FORCE_PATH_STYLE=true - AWS_S3_ACL=private # При необходимости, можно сразу добавить авторизацию с помощью Slack: #- SLACK_CLIENT_ID=${SLACK_CLIENT_ID} #- SLACK_CLIENT_SECRET=${SLACK_CLIENT_SECRET} - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET} # ports: # 443:443 networks: - outline-internal - reverseproxy networks: outline-internal: reverseproxy: external: true
5.1 Добавим environment variables в наш Outline Stack
Disclaimer: для первичной авторизации в Outline мы будем использовать Google OAuth 2.0. Вы можете выбрать, например, Slack. Больше сведений о конфигурации Outline можно посмотреть в файле https://github.com/outline/outline/blob/main/.env.sample
- Environment variables > Advanced mode
❗ Обратите внимание, SECRET_KEY и UTILS_SECRET обязательно должны быть 32-битными паролями.
SECRET_KEY={сгенеруйте пароль, например, командой: openssl rand -hex 32} UTILS_SECRET={сгенеруйте пароль, например, командой: openssl rand -hex 32} POSTGRES_PASSWORD={сгенеруйте пароль, например, командой: openssl rand -hex 20} MINIO_ROOT_PASSWORD={сгенеруйте пароль, например, командой: openssl rand -hex 20} MINIO_BROWSER_REDIRECT_URL=https://wikidata-admin.{Ваш-домен} WIKI_URL=https://wiki.{Ваш-домен} WIKIDATA_URL=https://wikidata.{Ваш-домен} GOOGLE_CLIENT_ID={Поменять на ваш id из https://console.cloud.google.com/} GOOGLE_CLIENT_SECRET={Поменять на ваш Client secret из https://console.cloud.google.com/}
5.2 Ваши GOOGLE_CLIENT_ID и GOOGLE_CLIENT_SECRET необходимо получить в личном кабинете Google Cloud https://console.cloud.google.com/
- Создаем проект (если еще не создан) > APIs & Services > Credentials > Create credentials > OAuth Client ID

Далее,
- Application type: Web application
- Name: подходящее название вашего client ID
- Authorized JavaScript origins: https://wiki.<Ваш-домен>
- Authorized redirect URIs: https://wiki.<Ваш-домен>/auth/google.callback

6. Настроим обратный прокси через Nginx-Proxy-Manager:
В NPM http://{ip-адрес-сервера}:81 > Hosts > Add host
Для Outline мы будем использовать 3 поддомена, в нашем случае это будут:
wiki.malov.tech - основной адрес
wikidata-admin.malov.tech - для админского веб-интерфейса MinIO
wikidata.malov.tech - технический домен для системы объектного хранения MinIO
6.1 - wiki.malov.tech


6.2 wikidata-admin.malov.tech


6.3 wikidata.malov.tech


7. Дополнительно можно настроить SMTP для email оповещений из Outline, а также настроить обратный прокси для NPM и Portainer, закрыв прямой доступ к ним по айпи без SSL.
Вместо заключения
На этом все! Вы развернули базу знаний Outline на собственном сервере, и она не покинет вас по личным взглядам инвестора или собственника. Вы сможете складывать сюда все артефакты, которые касаются вашего бизнеса: документы, ссылки, вырезки, скриншоты, алгоритмы — все, что раньше хранилось в Confluence, Notion и Google Docs. Самый большой плюс — исходники всегда у вас под рукой, его можно развернуть и пользоваться. Надеюсь, что у вас тоже сложится положительный опыт использования данной вики-системы.
