diff --git a/.env b/.env new file mode 100644 index 0000000..3b9f03b --- /dev/null +++ b/.env @@ -0,0 +1,146 @@ +########## Обязательные переменные ########## + +# Система Yonote поставляется с несколькими дополнительными сервисами: +# - PostgreSQL - основная БД для хранения данных +# - Keycloak - сервер авторизации +# - Minio - S3 файловое хранилище +# - Redis - key-value хранилище +# - Nginx - используется как reverse-proxy для всех сервисов +# +# Мы рекомендуем для каждого сервиса (кроме nginx) создать поддомены: +# Если мы хотим, чтобы Yonote был доступен по адресу domain.ru -> 80.11.121.12 (пример), +# то необходимо также создать следующие DNS записи для корректной работы системы: +# - domain.ru -> 80.11.121.12 +# - auth.domain.ru -> domain.ru +# - s3.domain.ru -> domain.ru +# +# Если вы запускаете сервис с HTTPS, +# необходимо соответсвенно поменять на https:// и wss:// + +### Keycloak +AUTH_VERSION=latest + +# Адрес сервера авторизации (с http/https) +KC_YNT_HOST=auth.example.ru +KC_YNT_HOST_PROTOCOL=http:// +KC_YNT_PORT=9080 +KC_YNT_URL=${KC_YNT_HOST_PROTOCOL}${KC_YNT_HOST}:${KC_YNT_PORT} +KC_YNT_INTERNAL_URL=${KC_YNT_HOST_PROTOCOL}${KC_YNT_HOST} + +# Подключение к базе данных (база создается автоматически) +KC_DB=keycloak +KC_DB_USERNAME=keycloak +KC_DB_PASSWORD=keycloak + +# Настройка клиента авторизации (ключ от OIDC провайдера) +KC_CLIENT_SECRET=MY-BRAND-NEW-SECRET-KEY + +# Адрес сервера S3/Minio (с http/https) +MINIO_YNT_INTERNAL_HOST=s3.example.ru +MINIO_YNT_HOST=s3.example.ru:9080 +MINIO_ADMIN_YNT_HOST=s3-admin.example.ru +MINIO_YNT_HOST_PROTOCOL=http:// +MINIO_YNT_URL=${MINIO_YNT_HOST_PROTOCOL}${MINIO_YNT_HOST} +# Логин и пароль для администратора S3 (пользователь создается автоматически) +MINIO_ADMIN_USERNAME=admin +MINIO_ADMIN_PASSWORD=adminadmin + +# Адрес для Yonote (укажите домен или адрес сервера) +BASENAME_FOR_SUBDOMAIN=app.example.ru:9080 +YNT_HTTP_PROTOCOL=http:// +YNT_WEBSOCKET_PROTOCOL=ws:// +YNT_INTERNAL_URL=app.example.ru + +### OAuth/OIDC (Keycloak) - сервер авторизации +KC_USERNAME=admin +KC_PASSWORD=adminadmin + +### S3 совместимое хранилище (Minio) +MINIO_ACCESS_KEY_ID=yonote +MINIO_SECRET_ACCESS_KEY=service-account-pass + +### Yonote +APP_VERSION=latest + +# Данные для подключения к БД (БД и пользователь будут созданны автоматически) +YNT_DB_NAME=yonote +YNT_DB_USER=postgres +YNT_DB_PASSWORD=azsxdc + +# Максимальный размер одно файла для загрузки в хранилище (в байтах) +AWS_S3_UPLOAD_MAX_SIZE=226214400 + +# Ключ шыфрования (32 байта). Рекомендуем использовать команду ниже для генерации ключа: +# `openssl rand -hex 32` +# храните данный ключ в надежном месте +SECRET_KEY= + +# Уникальный random ключ. Используется для различных крипто-функций, +# рекомендуем так же использовать команду ниже для генерации ключа: +# `openssl rand -hex 32` +UTILS_SECRET= + +# SMTP сервер +SMTP_HOST=smtp.example-mail.ru +SMTP_PORT=587 +SMTP_USERNAME=noreply@example-mail.ru +SMTP_PASSWORD= +SMTP_FROM_EMAIL=noreply@example-mail.ru +SMTP_REPLY_EMAIL=support@example-mail.ru +SMTP_TLS_CIPHERS= +SMTP_SECURE=false + +# Лицензионный ключ +# Для получения, обратитесь в отдел продаж hello@yonote.ru +LICENSE_KEY= + +############ OPTIONAL ################ + +# Производить редирект на HTTPS если запрос пришел на HTTP +FORCE_HTTPS=false + +# Отслеживать появление новых версий +ENABLE_UPDATES=false + +# Как много подпроцессов множно запускать. +# Самый простой вариант подсчета: разделить доступный объем памяти сервера на 512Мб +WEB_CONCURRENCY=1 + +# Максимальный размер файла импорта (Для импорта из Notion, Confluence и тд) +MAXIMUM_IMPORT_SIZE=5120000 + +# Логировать HTTP запросы. +# DEBUG=http + +# Список почтовых доменов с которых разрешена регистрация. Домены разделяются запятыми. +# По умолчанию разрешены любые домены +# ALLOWED_DOMAINS= + +# Отправка отчетов об ошибках разработчикам. +# Закомментируйте, если не хотите делиться отчетами об ошибках +SENTRY_DSN=https://5bdaaba1cf8043ba9cc43933b65f3b46@sentry.wilix.dev/7 + +# Логотип команды, который будет отображаться при входе в систему. +# Будет уменьшен до height: 60px +# TEAM_LOGO=https://example.com/images/logo.png + +# Язык по умолчанию +DEFAULT_LANGUAGE=ru_RU + +# Ключи для отправки WEB Push уведомлений +# Инструкция по получению ключей https://yo.yonote.ru/share/onprem/doc/ustanovka-i-nastrojka-KbTxPbAUoo#h-generaciya-klyuchej-web-push-service-worker +SERVICE_WORKER_PUBLIC_KEY= +SERVICE_WORKER_PRIVATE_KEY= + +# Интеграция с Telegram. Если TELEGRAM_BOT_TOKEN не указан, то интеграция отключена +# Инструкция по настройке https://yo.yonote.ru/share/onprem/doc/integraciya-s-telegram-9d2l0erXGN +# TELEGRAM_BOT_TOKEN= +# TELEGRAM_BOT_URL= + +# Интеграция с Loop https://loop.ru/. Если LOOP_KEY не указан, то интеграция отключена +# LOOP_KEY= +# LOOP_SECRET= +# LOOP_VERIFICATION_TOKEN= +# LOOP_MESSAGE_ACTIONS=true + +OPENAI_API_KEY=123 \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 2d87ab1..0000000 --- a/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 94ce5b2..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# onprem-deploy - diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2c25be0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,174 @@ +version: "3" +services: + yonote: + container_name: yonote + image: images.updates.yonote.ru/yonote:${APP_VERSION} + env_file: + - .env + ports: + - "3000" + depends_on: + - postgres + - redis + - keycloak + - s3-client + command: yarn start:selfhosted + environment: + BIND_HOST: 0.0.0.0 + PORT: 3000 + URL: ${YNT_HTTP_PROTOCOL}${BASENAME_FOR_SUBDOMAIN} + COLLABORATION_URL: ${YNT_WEBSOCKET_PROTOCOL}${BASENAME_FOR_SUBDOMAIN} + DATABASE_URL: postgres://${YNT_DB_USER}:${YNT_DB_PASSWORD}@postgres:5432/${YNT_DB_NAME} + OIDC_CLIENT_ID: yonote + OIDC_CLIENT_SECRET: ${KC_CLIENT_SECRET} + OIDC_AUTH_URI: ${KC_YNT_URL}/realms/yonote/protocol/openid-connect/auth + OIDC_TOKEN_URI: ${KC_YNT_URL}/realms/yonote/protocol/openid-connect/token + OIDC_USERINFO_URI: ${KC_YNT_URL}/realms/yonote/protocol/openid-connect/userinfo + OIDC_LOGOUT_URI: ${KC_YNT_URL}/realms/yonote/protocol/openid-connect/logout + AWS_S3_UPLOAD_BUCKET_URL: ${MINIO_YNT_URL} + AWS_ACCESS_KEY_ID: ${MINIO_ACCESS_KEY_ID} + AWS_SECRET_ACCESS_KEY: ${MINIO_SECRET_ACCESS_KEY} + AWS_S3_UPLOAD_BUCKET_NAME: yonote-bucket + AWS_REGION: xx-xxxx-x + TELEGRAM_API_URL: https://api.telegram.org + OIDC_DISPLAY_NAME: email + OIDC_SCOPES: openid email + REDIS_URL: redis://redis:6379 + PGSSLMODE: disable + USE_LEGACY_LOGOUT: true + AWS_S3_FORCE_PATH_STYLE: true + AWS_S3_ACL: private + volumes: + - ./License.key:/opt/yonote/License.key + networks: + - yonote-network + external_links: + - "nginx:${KC_YNT_HOST}" + - "nginx:${MINIO_YNT_HOST}" + + redis: + container_name: redis + image: redis:7-alpine + restart: unless-stopped + user: "redis:redis" + networks: + - yonote-network + + postgres: + container_name: postgres + image: postgres:14 + restart: unless-stopped + environment: + POSTGRES_DB: ${YNT_DB_NAME} + POSTGRES_USER: ${YNT_DB_USER} + POSTGRES_PASSWORD: ${YNT_DB_PASSWORD} + KC_DB_USERNAME: ${KC_DB_USERNAME} + KC_DB_PASSWORD: ${KC_DB_PASSWORD} + user: "postgres:postgres" + volumes: + - db:/var/lib/postgresql/data + - ./postgres/init-keycloak-db.sh:/docker-entrypoint-initdb.d/init-keycloak-db.sh + networks: + - yonote-network + + s3: + container_name: minio + image: minio/minio:RELEASE.2024-03-03T17-50-39Z + restart: unless-stopped + environment: + - MINIO_ROOT_USER=${MINIO_ADMIN_USERNAME} + - MINIO_ROOT_PASSWORD=${MINIO_ADMIN_PASSWORD} + command: server --address :9000 --console-address :9001 /data + ports: + - "9000" + - "9001" + volumes: + - minio:/data + networks: + - yonote-network + + s3-client: + container_name: minio-client + image: minio/mc:RELEASE.2022-08-28T20-08-11Z + volumes: + - ./minio:/tmp/policies + environment: + MINIO_ACCESS_KEY_ID: ${MINIO_ACCESS_KEY_ID} + MINIO_SECRET_ACCESS_KEY: ${MINIO_SECRET_ACCESS_KEY} + MINIO_ADMIN_USERNAME: ${MINIO_ADMIN_USERNAME} + MINIO_ADMIN_PASSWORD: ${MINIO_ADMIN_PASSWORD} + entrypoint: > + /bin/sh -c " + /usr/bin/mc config host add myminio http://minio:9000 ${MINIO_ADMIN_USERNAME} ${MINIO_ADMIN_PASSWORD}; + /usr/bin/mc mb myminio/yonote-bucket; + /usr/bin/mc policy set-json /tmp/policies/minio-bucket-policy.json myminio/yonote-bucket; + /usr/bin/mc admin user add myminio ${MINIO_ACCESS_KEY_ID} ${MINIO_SECRET_ACCESS_KEY}; + /usr/bin/mc admin policy add myminio yonote-policy /tmp/policies/minio-user-policy.json; + /usr/bin/mc admin policy set myminio yonote-policy user=${MINIO_ACCESS_KEY_ID}; + exit 0; + " + networks: + - yonote-network + depends_on: + - s3 + + keycloak: + container_name: keycloak + image: images.updates.yonote.ru/yonote-keycloak:${AUTH_VERSION} + ports: + - "8080" + environment: + KC_HOSTNAME: ${KC_YNT_HOST} + OIDC_CLIENT_SECRET: ${KC_CLIENT_SECRET} + YNT_HTTP_PROTOCOL: ${YNT_HTTP_PROTOCOL} + BASENAME_FOR_SUBDOMAIN: ${BASENAME_FOR_SUBDOMAIN} + KEYCLOAK_ADMIN: ${KC_USERNAME} + KEYCLOAK_ADMIN_PASSWORD: ${KC_PASSWORD} + KC_DB: postgres + KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak + KC_DB_USERNAME: ${KC_DB_USERNAME} + KC_DB_PASSWORD: ${KC_DB_PASSWORD} + PROXY_ADDRESS_FORWARDING: true + KC_PROXY_ADDRESS_FORWARDING: true + KC_PROXY: edge + KC_HOSTNAME_STRICT: false + KC_HOSTNAME_STRICT_HTTPS: false + KC_HTTP_ENABLED: true + # KC_HTTPS_ENABLED: false + # KC_HOSTNAME_DEBUG: true + command: start-dev --spi-login-protocol-openid-connect-legacy-logout-redirect-uri=true --import-realm + networks: + - yonote-network + depends_on: + - postgres + + nginx: + container_name: nginx + image: nginx + ports: + - 80:80 + environment: + BASENAME_FOR_SUBDOMAIN: ${BASENAME_FOR_SUBDOMAIN} + MINIO_YNT_HOST: ${MINIO_YNT_HOST} + MINIO_ADMIN_YNT_HOST: ${MINIO_ADMIN_YNT_HOST} + KC_YNT_HOST: ${KC_YNT_HOST} + DOLLAR: "$" + volumes: + - ./nginx/default.conf.tmpl:/etc/nginx/conf.d/default.conf.tmpl + networks: + yonote-network: + depends_on: + - postgres + - redis + - keycloak + - s3-client + - yonote + command: /bin/bash -c "envsubst < /etc/nginx/conf.d/default.conf.tmpl > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" + +networks: + yonote-network: + name: yonote-internal-network + +volumes: + db: + minio: \ No newline at end of file diff --git a/minio/minio-bucket-policy.json b/minio/minio-bucket-policy.json new file mode 100644 index 0000000..2c90ee0 --- /dev/null +++ b/minio/minio-bucket-policy.json @@ -0,0 +1,33 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": [ + "*" + ] + }, + "Action": [ + "s3:GetBucketLocation" + ], + "Resource": [ + "arn:aws:s3:::yonote-bucket" + ] + }, + { + "Effect": "Allow", + "Principal": { + "AWS": [ + "*" + ] + }, + "Action": [ + "s3:GetObject" + ], + "Resource": [ + "arn:aws:s3:::yonote-bucket/*" + ] + } + ] +} \ No newline at end of file diff --git a/minio/minio-user-policy.json b/minio/minio-user-policy.json new file mode 100644 index 0000000..c16709f --- /dev/null +++ b/minio/minio-user-policy.json @@ -0,0 +1,17 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor", + "Effect": "Allow", + "Action": [ + "s3:DeleteObject", + "s3:GetObject", + "s3:PutObject" + ], + "Resource": [ + "arn:aws:s3:::yonote-bucket/*" + ] + } + ] +} \ No newline at end of file diff --git a/nginx/default.conf.tmpl b/nginx/default.conf.tmpl new file mode 100644 index 0000000..adf861a --- /dev/null +++ b/nginx/default.conf.tmpl @@ -0,0 +1,94 @@ +server { + server_name ${BASENAME_FOR_SUBDOMAIN}; + proxy_http_version 1.1; + proxy_busy_buffers_size 512k; + proxy_buffers 4 512k; + proxy_buffer_size 256k; + proxy_connect_timeout 75s; + + location / { + proxy_pass http://yonote:3000; + proxy_set_header Host ${DOLLAR}host; + proxy_set_header Connection ''; + chunked_transfer_encoding off; + proxy_cache off; + } + + location ^~/realtime { + proxy_http_version 1.1; + proxy_set_header Upgrade ${DOLLAR}http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host ${DOLLAR}host; + proxy_pass http://yonote:3000; + } + location ^~/collaboration { + proxy_http_version 1.1; + proxy_set_header Upgrade ${DOLLAR}http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host ${DOLLAR}host; + proxy_pass http://yonote:3000; + } +} + +server { + server_name ${MINIO_YNT_HOST}; + proxy_http_version 1.1; + proxy_busy_buffers_size 512k; + proxy_buffers 4 512k; + proxy_buffer_size 256k; + proxy_read_timeout 300s; + proxy_connect_timeout 75s; + + location / { + proxy_pass http://s3:9000; + proxy_set_header Connection ''; + chunked_transfer_encoding off; + proxy_set_header Host ${DOLLAR}host; + proxy_cache off; + } +} + +server { + server_name ${MINIO_ADMIN_YNT_HOST}; + proxy_http_version 1.1; + proxy_busy_buffers_size 512k; + proxy_buffers 4 512k; + proxy_buffer_size 256k; + proxy_read_timeout 300s; + proxy_connect_timeout 75s; + + location / { + proxy_pass http://s3:9001; + proxy_set_header Connection ''; + chunked_transfer_encoding off; + proxy_cache off; + + # To support websocket + proxy_http_version 1.1; + proxy_set_header Upgrade ${DOLLAR}http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Origin ''; + } +} + +server { + server_name ${KC_YNT_HOST}; + proxy_http_version 1.1; + proxy_busy_buffers_size 512k; + proxy_buffers 4 512k; + proxy_buffer_size 256k; + proxy_read_timeout 300s; + proxy_connect_timeout 75s; + + proxy_set_header X-Forwarded-Host ${DOLLAR}host; + proxy_set_header X-Forwarded-Server ${DOLLAR}host; + proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for; # To forward the original client's IP address + proxy_set_header X-Forwarded-Proto ${DOLLAR}scheme; # to forward the original protocol (HTTP or HTTPS) + proxy_set_header Host ${DOLLAR}host; # to forward the original host requested by the client + proxy_set_header X-Real-IP ${DOLLAR}remote_addr; + + location / { + proxy_pass http://keycloak:8080; + } +} + diff --git a/postgres/init-keycloak-db.sh b/postgres/init-keycloak-db.sh new file mode 100644 index 0000000..e74ed6f --- /dev/null +++ b/postgres/init-keycloak-db.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL +CREATE DATABASE keycloak; +CREATE USER ${KC_DB_USERNAME} WITH PASSWORD '${KC_DB_PASSWORD}'; +GRANT ALL PRIVILEGES ON DATABASE keycloak TO ${KC_DB_USERNAME}; +EOSQL \ No newline at end of file