Установка Outline WiKi на Debian/Ubuntu с KeyCloak

от автора

Очередная статья про настройку Outline + KeyCloak. С одной стороны, статьи в сети есть. С другой стороны — начинаешь по ним делать и выплывают подводные камни, которые в статьях почему то не приведены. После определенного периодического мучения с установкой данного продукта решил собрать в кучу все мысли и действия.

Первоисточник: Основной алгоритм был взят из статьи.

Первичная подготовка системы

Выбираем, что нам по душе — Debian 12 или Ubuntu Server. Алгоритм в этих вариантах один и тотже.

Устанавливаем Docker согласно документации: Docker_on_Debian или Docker_on_Ubuntu.

Придумываем и регистрируем во внешних DNS-серверах три DNS-записи для трех решений:

  • wiki.<наш домен>

  • kk.<наш домен>

  • minio.<наш домен>

ВАЖНО: Если на Linux машине IP-адрес серый (но в нас есть DNAT портов 80/443 либо Reverse Proxy), обязательно нужно в файле /etc/hosts прописать соответствие серого IP-адреса и созданным трем DNS-записям. Вообще в любом варианте (белый IP на интерфейсе) можно это сделать, лишним не будет. Если этот шаг упустить — KeyCloak аутентификация у меня не работает с Outline.

Установка KeyCloak

Создаем каталог для размещения сценария для Docker:

mkdir -pv /opt/keycloak nano /opt/keycloak/docker-compose.yml

Заполняем файл, меняем WEB-имя сервера и пароль доступа к админской части:

version: '3'   volumes:   keycloak-db:   services:   keycloak:       image: quay.io/keycloak/keycloak:latest       environment:         KC_PROXY: edge         KEYCLOAK_ADMIN: admin         KEYCLOAK_ADMIN_PASSWORD: XXXXXXXXXX         KC_HOSTNAME: kk.vdsina.vershininegor.site         KC_HOSTNAME_STRICT_HTTPS: true         KC_HOSTNAME_STRICT: true       volumes:         - keycloak-db:/opt/keycloak/data/h2       ports:         - 7214:8080       command: "start --optimized"

Сохраняем, далее, переходим в каталог /opt/keycloak/ и запускаем установку контейнера:

cd /opt/keycloak/ docker compose up -d

Ожидаемый вывод, если у нас есть Интернет, и мы правильно установили Docker:

root@ubuntu:/opt/keycloak# docker compose up -d [+] Running 5/5  ✔ keycloak 4 layers [⣿⣿⣿⣿]      0B/0B      Pulled                       15.3s    ✔ da5b6ed7dedb Pull complete                                            2.2s    ✔ 235cc15c2bca Pull complete                                            6.5s    ✔ 33a5d0f592f8 Pull complete                                            8.5s    ✔ 881ee45db5ad Pull complete                                            8.5s [+] Running 3/3  ✔ Network keycloak_default       Created                                  0.1s  ✔ Volume "keycloak_keycloak-db"  Created                                  0.0s  ✔ Container keycloak-keycloak-1  Started 

После запуска смотрим статус контейнера командой:

docker compose ps -a

Через некоторое время видим, что контейнер не запущен, статус остановки Exited:

NAME                  IMAGE                              COMMAND                  SERVICE             CREATED             STATUS                      PORTS keycloak-keycloak-1   quay.io/keycloak/keycloak:latest   "/opt/keycloak/bin/k…"   keycloak            17 minutes ago      Exited (1) 17 minutes ago

Смотрим журнал контейнера (docker logs <имя контейнера>):

2023-08-15 09:14:58,626 WARN  [io.agroal.pool] (agroal-11) Datasource '<default>': Error opening database: "Could not save properties /opt/keycloak/data/h2/keycloakdb.lock.db" [8000-220] 2023-08-15 09:14:58,653 INFO  [org.infinispan.CLUSTER] (main) ISPN000080: Disconnecting JGroups channel `ISPN` 2023-08-15 09:14:58,695 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (production) mode 2023-08-15 09:14:58,696 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to obtain JDBC connection 2023-08-15 09:14:58,696 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Error opening database: "Could not save properties /opt/keycloak/data/h2/keycloakdb.lock.db" [8000-220] 2023-08-15 09:14:58,696 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: /opt/keycloak/data/h2/keycloakdb.lock.db 2023-08-15 09:14:58,698 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) For more details run the same command passing the '--verbose' option. Also you can use '--help' to see the details about the usage of the particular command.

Исправляется следующей командой:

chmod 777 /var/lib/docker/volumes/keycloak_keycloak-db/_data/

Останавливаем и снова запускаем контейнер:

cd /opt/keycloak/ docker compose down docker compose up -d

Теперь команды docker compose ps -a и lsof -i -nP должны показывать, что контейнер с KeyCloak работает и порты доступа открыты.

SSL/TLS сертификаты для Nginx

KeyCloak и Outline по умолчанию настроены на работу только по HTTPS. При этом они также не доверяют самоподписанным сертификатам и заставить их работать у меня не получилось до конца (хотя попытки были и кое какой прогресс был).

Поэтому нам необходим белый IP, публичные DNS-записи и утилита python3-certbot. Устанавливаем, запускаем (certbot certonly), получаем на 3 месяца сертификат на три публичных DNS-записи.

Установка Nginx

Во многих статьях используют Docker контейнер с Nginx Proxy Manager, который дает GUI для настройки и сам способен автоматически продлять Les’t Encrypt сертификаты. В прошлом я его использовал, в последний раз решил от него отказаться в пользу установки Nginx на базовую систему (потому что захотелось).

apt install nginx cd /etc/nginx/sites-enabled

Настройка Nginx для Outline, KeyCloak и MinIO

Создаем следующие конфигурации — /etc/nginx/sites-enabled/keycloak.conf:

server {     listen 80;     server_name kk.vdsina.vershininegor.site;     rewrite ^ https://$server_name$request_uri? permanent; }   server {     listen 443 ssl;       server_name kk.vdsina.vershininegor.site;       # Logging (optional, but probably want it for debugging)     access_log /var/log/nginx/keycloak-access.log;     error_log /var/log/nginx/keycloak-error.log info;       ## Keep alive timeout set to a greater value for SSL/TLS.     keepalive_timeout 75 75;       # Locations of certs using Certbot     ssl_certificate /etc/letsencrypt/live/wiki.vdsina.vershininegor.site/fullchain.pem;     ssl_certificate_key /etc/letsencrypt/live/wiki.vdsina.vershininegor.site/privkey.pem;     ssl_session_timeout 5m;       # Forces browsers to redirect to HTTPS themselves for 31536000 seconds (1 year).     # includeSubDomains will cause this to upgrade HTTP on all subdomains of the given domain.     # preload adds your domain to a list of domains for browsers to automatically upgrade to HTTPS, no mattter what.     # always will append the header no matter the return code.     add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;       # SSO requests tend to be very long, will fail on default settings.     proxy_buffer_size 12k;       proxy_set_header Host $host;     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;     proxy_set_header X-Forwarded-Host $host;     proxy_set_header X-Forwarded-Server $host;     proxy_set_header X-Forwarded-Proto https;       location /js/ {         proxy_pass http://127.0.0.1:7214;     }       location /realms/ {         proxy_pass http://127.0.0.1:7214;     }       location /auth/ {         proxy_pass http://127.0.0.1:7214;     }       location /resources/ {         proxy_pass http://127.0.0.1:7214;     }       location /robots.txt {         proxy_pass http://127.0.0.1:7214;     }       # We don't really care about anything else.     location / {         return 404;     }       # -------------------     # I recommend deleting the /admin/ endpoint once done for security reasons.     # -------------------       location /admin/ {         proxy_pass http://127.0.0.1:7214;     }   }

/etc/nginx/sites-enabled/minio.conf

server {     listen 80;     server_name minio.vdsina.vershininegor.site;     rewrite ^ https://$server_name$request_uri? permanent; }  server {     listen 443 ssl;      server_name minio.vdsina.vershininegor.site;      # Logging (optional, but probably want it for debugging)     access_log /var/log/nginx/minio-access.log;     error_log /var/log/nginx/minio-error.log info;      ## Keep alive timeout set to a greater value for SSL/TLS.     keepalive_timeout 75 75;      # Locations of certs using Certbot     ssl_certificate /etc/letsencrypt/live/wiki.vdsina.vershininegor.site/fullchain.pem;     ssl_certificate_key /etc/letsencrypt/live/wiki.vdsina.vershininegor.site/privkey.pem;     ssl_session_timeout 5m;      # Forces browsers to redirect to HTTPS themselves for 31536000 seconds (1 year).     # includeSubDomains will cause this to upgrade HTTP on all subdomains of the given domain.     # preload adds your domain to a list of domains for browsers to automatically upgrade to HTTPS, no mattter what.     # always will append the header no matter the return code.     add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;      # SSO requests tend to be very long, will fail on default settings.     proxy_buffer_size 12k;      proxy_set_header Host $host;     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;     proxy_set_header X-Forwarded-Host $host;     proxy_set_header X-Forwarded-Server $host;     proxy_set_header X-Forwarded-Proto https;      ignore_invalid_headers off;     client_max_body_size 0;     proxy_buffering off;     proxy_request_buffering off;      location / {         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_connect_timeout 300;         proxy_http_version 1.1;         proxy_set_header Connection "";         chunked_transfer_encoding off;          proxy_pass http://127.0.0.1:7216;     }  }

/etc/nginx/sites-enabled/outline.conf

server {     listen 80;     server_name wiki.vdsina.vershininegor.site;     rewrite ^ https://$server_name$request_uri? permanent; }  server {     listen 443 ssl;      server_name wiki.vdsina.vershininegor.site;      # Logging (optional, but probably want it for debugging)     access_log /var/log/nginx/outline-access.log;     error_log /var/log/nginx/outline-error.log info;      ## Keep alive timeout set to a greater value for SSL/TLS.     keepalive_timeout 75 75;      # Locations of certs using Certbot     ssl_certificate /etc/letsencrypt/live/wiki.vdsina.vershininegor.site/fullchain.pem;     ssl_certificate_key /etc/letsencrypt/live/wiki.vdsina.vershininegor.site/privkey.pem;     ssl_session_timeout 5m;      # Forces browsers to redirect to HTTPS themselves for 31536000 seconds (1 year).     # includeSubDomains will cause this to upgrade HTTP on all subdomains of the given domain.     # preload adds your domain to a list of domains for browsers to automatically upgrade to HTTPS, no mattter what.     # always will append the header no matter the return code.     add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;      # SSO requests tend to be very long, will fail on default settings.     proxy_buffer_size 12k;      proxy_set_header Host $host;     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;     proxy_set_header X-Forwarded-Host $host;     proxy_set_header X-Forwarded-Server $host;     proxy_set_header X-Forwarded-Proto https;       location / {         proxy_set_header Upgrade $http_upgrade;         proxy_set_header Connection "Upgrade";         proxy_set_header Host $host;          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;         proxy_set_header Host $host;         proxy_set_header Host $http_host;         proxy_set_header X-Real-IP $remote_addr;         proxy_set_header X-Scheme $scheme;         proxy_set_header X-Forwarded-Proto $scheme;         proxy_redirect off;         # Set to the correct ports for Outline         proxy_pass http://127.0.0.1:7215;     }  }

Перезапускаем Nginx:

systemctl restart nginx

Настройка KeyCloak

Входим по адресу:

Создаем новый Realm с именем outline:

Находясь уже в новом созданном Realm с именем outline, создаем нового клиента (это наш сайт с Outline):

Указываем имя, описание и ID — outline-wiki :

Включаем клиентскую аутентификацию и отключаем прямой вход:

Указываем ряд 

Настройка KeyCloak — вторая часть

Теперь нам нужно сохранить себе мастер-ключ для взаймодействия с этим клиентом. Переходим в раздел Credentials и копируем себе ключ, который сгенерировался при создании клиента KeyCloak:

Теперь необходимо создать пользователя в KeyCloak — с его помощью мы будем авторизовываться и работать в Outline Wiki.

В левом фрейме переходим в раздел: Users и добавляем нового пользователя: Add User. Логин и email должны совпадать.

После создания пользователя у него не задан пароль — необходимо это исправить в разделе Credentials через кнопку Set password:

На этом работа с KeyCloak закончена. Других пользователей Outline создавать аналогично.

Запуск контейнеров с PostgreSQL, Redis, MinIO и Outline

Создаем нужный каталог и файлы:

mkdir -pv /opt/outline touch /opt/outline/docker-compose.yml touch /opt/outline/docker.env

Содержимое файла docker-compose.yml:

version: "3" services:     outline:     image: outlinewiki/outline:latest     env_file: ./docker.env     networks:       - outline-network     ports:       - "7215:3000"     depends_on:       - postgres       - redis       - minio     command: sh -c "yarn db:migrate --env production-ssl-disabled && yarn start"     redis:     image: redis     env_file: ./docker.env     networks:       - outline-network     volumes:       - ./redis.conf:/redis.conf     command: ["redis-server", "/redis.conf"]     postgres:     image: postgres     env_file: ./docker.env     networks:       - outline-network     volumes:       - outline-postgres-data:/var/lib/postgresql/data     minio:     image: minio/minio:latest     env_file: ./docker.env     networks:       - outline-network     ports:       - "7216:9000"       - "9001:9001"     deploy:       restart_policy:         condition: on-failure     volumes:       - outline-minio-data:/data     entrypoint: sh     command: -c 'minio server --console-address ":9001" /data'   volumes:   outline-minio-data:   outline-postgres-data:   networks:   outline-network:     name: outlinewiki-network

Содержимое с настройками (будем дальше несколько раз менять) — docker.env :

# Fill these out with "pwgen 64 1" or "openssl rand -hex 32". SECRET_KEY=2787d5895f5a61235eb73e8dc1712e57bbfa4a4d7fc3a8bf10d2ed4570c0869b UTILS_SECRET=d679896a4576c0887862b72b7bee1ae3c68d050d7f40118678d089675fefd367   # Please see "Enviroment Variables" for more information. # Make sure to change "user" and "pass". POSTGRES_USER=admin POSTGRES_PASSWORD=XXXXXXXXXX POSTGRES_DB=outline   # Please see "Enviroment Variables" for more information. # Make sure to change "user" and "pass". # If you changed POSTGRES_DB, change "outline", too. DATABASE_URL=postgres://admin:XXXXXXXXXX@postgres:5432/outline   # Was in the official Docker.env. Probably not needed? DATABASE_URL_TEST=postgres://admin:XXXXXXXXXX@postgres:5432/outline-test   # This is the domain name to access Outline. Include the "https://" URL=https://wiki.vdsina.vershininegor.site   # Please see "Enviroment Variables" for more information. # Make sure to change "user" and "pass". MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=XXXXXXXXXX   # You will need to get this from the Minio admin panel. AWS_ACCESS_KEY_ID=DpzbsYrmOnAcbSGq AWS_SECRET_ACCESS_KEY=ESMxba21uVn0NXK7UzzXaJhEmfvYJT9l AWS_REGION=us-east-1   AWS_S3_UPLOAD_BUCKET_URL=https://minio.vdsina.vershininegor.site/ AWS_S3_UPLOAD_BUCKET_NAME=datawiki AWS_S3_UPLOAD_MAX_SIZE=26214400 ## Probably shouldn't change these AWS_S3_FORCE_PATH_STYLE=true AWS_S3_ACL=private   # You will need to get this from the Keycloak admin panel. Please see "Keycloak OIDC Setup". OIDC_CLIENT_ID=outline-wiki OIDC_CLIENT_SECRET=Kw4NvTB1nEB89iTSzQ91IHRk4k3smrqh OIDC_AUTH_URI=https://kk.vdsina.vershininegor.site/realms/outline/protocol/openid-connect/auth OIDC_TOKEN_URI=https://kk.vdsina.vershininegor.site/realms/outline/protocol/openid-connect/token OIDC_USERINFO_URI=https://kk.vdsina.vershininegor.site/realms/outline/protocol/openid-connect/userinfo ## Changes what shows up on the login button. OIDC_DISPLAY_NAME=Keycloak ## Probably shouldn't change OIDC_USERNAME_CLAIM=preferred_username OIDC_SCOPES=openid profile email   # Telemtry?!?!! :O # Enable if you want. ENABLE_UPDATES=false   # Check official docs for this. Has to be with processes or whatever. WEB_CONCURRENCY=1   # Limits size of documents (esp. with images) in (I think) bytes, MAXIMUM_IMPORT_SIZE=5120000   # Default langauage. Supported codes at translate.getoutline.com. DEFAULT_LANGUAGE=en_US   # ---------------------------------- # STUFF YOU PROBABLY SHOULD NOT CHANGE. # ----------------------------------   # Self-explanatory. NODE_ENV=production   # Docker will forward this specific port to the host as the one specified in the compose file. PORT=3000   # Accessing self-hosetd redis through the Docker network. REDIS_URL=redis://redis:6379   # We will be using Postgres through the Docker network. So no HTTPS. PGSSLMODE=disable   # We will terminate SSL on nginx. FORCE_HTTPS=false

В параметр OIDC_CLIENT_SECRET впишите ключ, который мы сохраняли сразу после создания клиента в KeyCloak (outline-wiki).

Параметры AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_S3_UPLOAD_BUCKET_NAME пока оставляем как есть, мы их исправим позже, когда установим, запустим и настроим параметры контейнера с MinIO (S3-хранилища).

Теперь необходимо запустить загрузку и запуск контейнеров:

cd /opt/outline/ docker compose up -d

Настройка MinIO

Подключаемся к серверу по адресу: http://<IP>:9001

Входим учеткой admin и паролем, который мы указали в docker.env файле.

ПЕРВЫЙ ШАГ — сменить регион расположения S3 хранилища и перезапустить сервис:

Далее жмем кнопку: Restart и дал должно из сервиса выкинуть (снова на страницу входа):

Снова входим и настраиваем.

Настройка MinIO — часть 2

Теперь создаем Bucket для хранения картинок и другого контента wiki:

Выбираем имя — datawiki. Тут есть тонкости — если выбирать имена, пересекающиеся с именами 

В созданном Bucket создаем Access Rule:

Создаем Access Key для параметров AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY в файле docker.env:

Записываем в блокнот данные для AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY (больше их посмотреть не удастся).

Настройка MinIO закончена.

Донастройка контейнеров

Теперь нам нужно изменить содержимое файла /opt/outline/docker.env и указать параметры:

AWS_ACCESS_KEY_ID=Zk27jPsxqE0ro9B2 AWS_SECRET_ACCESS_KEY=MmqmnkUcvONVwhm8sBtTpa6wW1n2KsCj AWS_REGION=us-east-1   AWS_S3_UPLOAD_BUCKET_URL=https://minio.vdsina.vershininegor.site/ AWS_S3_UPLOAD_BUCKET_NAME=datawiki AWS_S3_UPLOAD_MAX_SIZE=26214400 ## Probably shouldn't change these AWS_S3_FORCE_PATH_STYLE=true AWS_S3_ACL=private

Теперь перезапускаем контейнеры с этими параметрами:

cd /opt/outline/ docker compose down docker dompose up -d

Проверка работы

Входим по адресу: https://wiki.vdsina.vershininegor.site.

При входе появляется кнопка — продолжить вход с помощью KeyCloak.

Авторизуемся в нем и нас пускают в Outline Wiki.

Потребление ресурсов

На самой дешевой виртуалке за 15 рублей в день (1 ядро, 2 Гб ОЗУ) это способно жить и работать при 2-3 пользователях. На холостом ходу Active ОЗУ чуть больше 1,2 Гб.

Личное мнение автора

С 2006 года пользуюсь сам DokuWiki, накопил более 900 заметок и статей для своих нужд. С тех под много что другого настраивал и пробовал (MediaWiki, BookStack, WikiJS, etc). Но видимо я уже динозавр, так как мне Dokuwiki проще и привычнее. Однако молодежь требует более простых инструментов. Outline действительно прост в использовании, красив и удобен. Еще бы поднимался одной кнопкой и кушал 50 Мб ОЗУ — было бы вообще идеально )))

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

А какой WiKi пользуетесь Вы?

17.65% Классические Wiki на Apache/Nginx + PHP +-SQL (MediaWiki, Dokuwiki, etc)6
5.88% WikiJS2
8.82% GitLab Wiki3
0% Самописная0
32.35% Obsidian11
23.53% Notion8
14.71% Outline5
23.53% Другой вариант8

Проголосовали 34 пользователя. Воздержались 7 пользователей.

ссылка на оригинал статьи https://habr.com/ru/articles/755432/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *