С российского рынка уже ушли многие ИТ-продукты, которыми мы привыкли пользоваться в рабочих целях. Сложно сказать, какой софт станет недоступен следующим — хочется найти замену заранее, чтобы не остаться без необходимых инструментов. Мы решили потестировать разные продукты и в первую очередь найти альтернативу 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. Самый большой плюс — исходники всегда у вас под рукой, его можно развернуть и пользоваться. Надеюсь, что у вас тоже сложится положительный опыт использования данной вики-системы.

Комментарии (12)


  1. AndreyYu
    20.10.2022 14:22
    -3

    Недавно у HOSTKEY была статья как за 270р в месяц развернуть свой Outline сервер буквально в пару кликов


    1. sarbarco
      20.10.2022 17:58
      +1

      AndreyYu - по-моему, здесь речь идет о другом Outline:

      https://www.getoutline.com/ vs https://getoutline.org/

      Hidden text

      Вы, вероятно, имели ввиду ...outline.org - https://hostkey.com/blog/24-your-own-outline-vpn-server-for-3-euro-per-month/ (не реклама).

      Hidden text


      1. Devopsik Автор
        20.10.2022 18:10
        +1

        Так и есть.. в моем скромном туториале речь идет про "Outline" wiki-систему, а у упомянутого хостера - про "Outline VPN", VPN не плохой, но к топику отношения не имеет)


  1. kpmy
    20.10.2022 19:17

    Если бы вам было не трудно оформить это дело в виде гит-репозитория, было бы очень спасибо!

    И отдельное спасибо на NPM. ????


    1. Devopsik Автор
      20.10.2022 19:45

      Если есть референс, в каком виде это привычно/удобно, - оперативно решу, и возьму на заметку, спасибо



  1. PlatonDig
    21.10.2022 04:10
    +1

    Было бы хорошо увидеть интеграцию с ldap


    1. aborouhin
      21.10.2022 09:38

      +1. Я именно на этом споткнулся в попытке внедрить Outline. Напрямую не работает, а поднимать свой OIDC - ну очень уж нетривиально.


  1. polyvinyl
    21.10.2022 10:53

    Игорь, добрый день!
    Скажите, а как Outline в плане производительности? Notion многие ругают за его тормознутость, которая растёт по мере заполнения базы знаний, а у Outline с этим как?


    1. Devopsik Автор
      21.10.2022 14:22

      Добрый день! Тут есть нюансы: во-первых, у нас пока всего около 20 постоянных пользователей в Outline, во-вторых- объем документов не дотягивает пока и до 300 штук, в третьих, функционал разработчиками пока довольно заметно расширяется - будем надеяться, что продолжат в том же духе, и сервис не станет перегруженным)

      С тем, что было и есть у нас - все летает, при том, что сервис работает пока на одном сервере с активно используемыми Keycloak / MinIO, никаких проблем с нагрузками за полгода не наблюдалось


      1. polyvinyl
        22.10.2022 08:59

        Класс, спасибо за ответ!
        Будем пробовать c:


  1. sap058
    21.10.2022 20:20

    Notion он же не про wiki

    Его прелесть совсем в этом!