Home » Devops » Установка Elastic Enterprise Search

Установка Elastic Enterprise Search

Появилась необходимость настроить на собственном сервере Elastic Enterprise Search для работы App Search. Насколько я понял, раньше это была часть платного функционала, но в какой-то момент можно стало использовать бесплатно. Каких-то особых сложностей с настройкой этого продукта нет, но есть много мелких нюансов и неочевидных вещей. Когда делаешь первый раз, приходится долго разбираться.

Углубленный онлайн-курс по MikroTik.

Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном онлайн-курcе по администрированию MikroTik. Автор курcа – сертифицированный тренер MikroTik Дмитрий Скоромнов. Более 40 лабораторных работ по которым дается обратная связь. В три раза больше информации, чем в MTCNA.

Введение

Я буду настраивать Elastic Enterprise Search на Centos 8. Инструкция будет актуальна на уровне copy-paste для любого форка RHEL - Rocky Linux, Oracle Linux и т.д. Для всех остальных дистрибутивов могут отличаться пути, но конфиги самих сервисов будут такие же.

Начну настройку на базе системы ELK Stack, настроенной примерно так же, как описано у меня в статье - Установка Elasticsearch, Logstash, Kibana (ELK Stack) на Ubuntu/Debian/Centos. То есть имеем базовую систему, готовую к принятию логов. Авторизация не настроена, TLS на самих сервисах Elasticsearch и Kibana не настроен. Прямой доступ для всех и отовсюду. Я подобные конфигурации обычно защищаю на уровне firewall или списков allow, deny в nginx, который выступает в качестве proxy.

Важное замечание. Я написал эту статью, после того, как получилось все настроить и запустить в работу. То есть это не инструкция на тему того, как лучше и оптимально настраивать указанные системы. Я всё сделал без своего накопленного опыта, опираясь только на документацию продуктов.

Настройка базовой безопасности в Elasticsearch

Начнём настройку с того, что выполним базовые рекомендации по безопасности в кластере elasticsearch. Для этого активируем настройку xpack.security. Добавляем в конфиг elasticsearch:

xpack.security.enabled: true

После этого перезапустите службу elasticsearch:

# systemctl restart elasticsearch

Теперь сгенерируем пароли к встроенным учётным записям (built-in users) elastic. Для этого запускаем утилиту elasticsearch-setup-passwords. По умолчанию она находится в папке /usr/share/elasticsearch/bin.

# /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto

Настройка безопасности в Elasticsearch

Сохраните где-то эти учетные данные. Они нам понадобятся далее, а больше вы их нигде не увидите. Более подробно о работе этой утилиты читайте в документации - elasticsearch-setup-passwords.

В настоящий момент Kibana не будет иметь доступ к кластеру. Чтобы это исправить, добавьте в её конфигурационный файл параметры:

xpack.security.enabled: true
elasticsearch.username: "kibana_system"
elasticsearch.password: "fDhdXdVfpGc9iAWKcu0w"

Перезапустите Kibana:

# systemctl restart kibana

Доступ через web интерфейс снова будет доступен, только теперь необходимо пройти встроенную в Kibana авторизацию. Для этого используйте созданный ранее пароль для учётной записи elastic.

Авторизация по пользователю в Kibana

Если используете Logstash, то для него тоже необходим доступ с использованием учетной записи, которую надо создать. Как это сделать, подробно описано в инструкции - Configuring Security in Logstash. Необходимо в Kibana перейти в раздел Stack Management -> Roles и добавить роль logstash_writer. Права сделать следующие:

  • cluster - manage_index_templates и monitor
  • indices - выбрать индексы, которые создает logstash и назначить им права all.

Создание роли доступа в Elasticsearch

Затем переходите в раздел Users, добавляете пользователя logstash_writer, указываете пароль и назначаете ему ранее добавленную роль. После этого в конфигурации logstash, отвечающей за правила output, добавьте информацию об этой учетной записи:

output {
        elasticsearch {
            user     => logstash_internal
            password => OMOFYuIOFcHLDyCBnzGU
            hosts    => "localhost:9200"
            index    => "nginx-%{+YYYY.MM.dd}"
        }
}

Перезапустите logstash:

# systemctl restart logstash

Если всё в порядке, то переходите к следующему разделу. Если что-то не работает, то разбирайтесь для начала с этой настройкой.

Настройка TLS в Elasticsearch

Далее нам нужно настроить возможность соединения с elasticsearch по tls. Без этого не заработает авторизация через api_key, которую будет использовать служба Enterprise Search. Для этого сгенерируем самоподписанные сертификаты, используя утилиту elasticsearch-certutil. Сгенерируем с её помощью CA сертификат, которым будем подписывать все остальные.

# /usr/share/elasticsearch/bin/elasticsearch-certutil ca

Настройка tls в elasticsearch

Созданный сертификат будет положен в директорию /usr/share/elasticsearch. Теперь сгенерируем клиентский сертификат с использованием CA, выпущенного ранее.

# /usr/share/elasticsearch/bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12

На выходе получим файл elastic-certificates.p12, который включает в себя сам сертификат, приватный ключ и CA. В общем, полный набор, который нам необходим. Копируем оба сертификата в /etc/elasticsearch. И обязательно назначьте права доступа к этим сертификатам пользователю elasticsearch.

# cd /etc/elasticsearch
# chown root:elasticsearch elastic-stack-ca.p12 elastic-certificates.p12
# chmod 0660 elastic-stack-ca.p12 elastic-certificates.p12

Редактируем конфигурационный файл elasticsearch, добавляя туда следующие параметры:

xpack.security.authc.api_key.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.client_authentication: required
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-certificates.p12

Перезапустите elasticsearch и проверьте, что всё в порядке. Этих минимальных настроек будет достаточно для работы Elastic Enterprise Search. При желании, можно и все http запросы к кластеру настроить на https, но у меня не получилось это сделать с самоподписанным сертификатом, только с настоящим. В Kibana можно было настроить доверие к самоподписанному сертификату, а в Elastic Enterprise Search не получилось. Я не стал сильно разбираться и просто взял валидный сертификат.

Если вы хотите все, чтобы все запросы к кластеру были по https, то добавьте дополнительно следующие параметры:

xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.key: /etc/elasticsearch/private.key
xpack.security.http.ssl.certificate: /etc/elasticsearch/cert.pem
xpack.security.http.ssl.certificate_authorities: /etc/elasticsearch/ca-bundle.pem

В данном случае используется действующий сертификат, купленный на год. Можно использовать и бесплатные сертификаты от Let's Encrypt, но придётся рассмотреть отдельно вопрос перезапуска всех служб, которые будут зависеть от этих сертификатов. Также во всех службах, которые будут обращаться к elasticsearch, надо не забывать указывать подключение через https, а не http и обязательно по имени домена, на который выпущен этот сертификат. Так что не забудьте с dns отдельно разобраться, чтобы все запросы были только по доменному имени, иначе службы будут ругаться на несоответствие адреса и записи домена в сертификате. Ну и сами сертификаты надо будет указать (key, crt, bundle), по аналогии с настройками elasticsearch. Вообще, это отдельная тема, так что не хочется её сейчас рассматривать в рамках статьи по установке именно Elastic Enterprise Search. Я показываю минимально необходимые настройки, чтобы его запустить.

Установка Elastic Enterprise Search

Переходим к тому, зачем мы тут сегодня собрались, к установке Elastic Enterprise Search. Перед этим надо установить версию Java 8 или 11. На этом моменте я сильно завис, когда первый раз настраивал Elastic Enterprise Search. Дело в том, что в комплекте с elasticsearch уже идёт jdk. Она находится в директории - /usr/share/elasticsearch/jdk. Я пытался её подсунуть EES, чтобы не ставить еще раз java. Делал этот через объявление PATH с нужным путём в юните systemd - /usr/lib/systemd/system/enterprise-search.service. Добавлял туда:

Environment=PATH=/usr/share/elasticsearch/jdk:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

Если не добавлять вручную путь к java, то Enterprise Search ругается во время запуска:

enterprise-search[86191]: Could not find java in PATH

После добавления PATH служба запускалась и даже начинала работать, но сыпала различные ошибки и по факту не работала, только делала вид. В логе было предупреждение на несоответствие версии java, но я изначально не придавал ему значения, думая, что это формальность. И только когда установил 8 или 11 версию, все заработало.

Так что ставим openjdk 11 в систему:

# dnf install java-11-openjdk-devel

После установки java сама пропишет себя в /usr/bin/java, так что отдельно настраивать PATH для enterprise-search не придётся.

Теперь идём на страницу загрузки, скачиваем пакет под свою систему. В случае с rpm это будет следующая последовательность действий:

# wget https://artifacts.elastic.co/downloads/enterprise-search/enterprise-search-7.15.0.rpm
# rpm -ivh enterprise-search-7.15.0.rpm

Перед этим пробовал установить из стандартного репозитория elastic, но оттуда почему-то предлагается к установке пакет неподходящей архитектуры.

Установка Elastic Enterprise Search

Так что пришлось устанавливать вручную. После установки, нам надо отредактировать конфигурационный файл /usr/share/enterprise-search/config/enterprise-search.yml. Добавляем туда:

elasticsearch.username: elastic
elasticsearch.password: m97KOnUDTBVAaNetJdEG
allow_es_settings_modification: true
kibana.external_url: http://10.30.52.6:5601

Учётетную запись elastic мы настроили в самом начале. Это она же, встроенная (built-in). И не забудьте ip для web интерфейса kibana поменять на свой. Если настроили https, то доступ должен быть по доменному имени. Запускайте и добавляйте сразу в автозагрузку службу.

# systemctl enable --now enterprise-search

Смотрим лог /var/log/enterprise-search/app-server.log. Там будет ошибка:

Invalid config file (/usr/share/enterprise-search/config/enterprise-search.yml):
The setting '#/secret_management/encryption_keys' is not valid
No secret management encryption keys were provided.
Your secrets cannot be stored unencrypted.
You can use the following generated encryption key in your config file to store new encrypted secrets:

secret_management.encryption_keys: [f37a2e899b47e4749cc6c1ba01e8cfc27da9f367f0795caaed0c98e52f9dff83]

Сохраните нужную настройку и добавьте её в в конфиг enterprise-search.yml:

secret_management.encryption_keys: [f37a2e899b47e4749cc6c1ba01e8cfc27da9f367f0795caaed0c98e52f9dff83]

Снова запускайте enterprise-search:

# systemctl start enterprise-search

Теперь ошибок быть не должно. Проверьте системный лог /var/log/messages. Там будет информация о встроенной учетной записи enterprise_search. Её надо сохранить. Пригодится, если будете напрямую заходить в веб интерфейс enterprise-search, минуя Kibana.

Default user Elastic Enterprise Search

Дождитесь, когда Elastic Enterprise Search закончит создание всех необходимых сущностей в кластере:

[2021-10-11T15:54:49.754+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: connectors_jobs_v5
[2021-10-11T15:54:49.767+00:00][2355404][2002][app-server][WARN]: Index .ent-search-actastic-connectors_jobs_v5 already exists!
[2021-10-11T15:54:49.800+00:00][2355404][2002][app-server][WARN]: Going to re-create the existing empty index .ent-search-actastic-connectors_jobs_v5
[2021-10-11T15:54:55.217+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: synonyms
[2021-10-11T15:54:59.473+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: document_types_v2
[2021-10-11T15:55:12.301+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: oauth_access_grants
[2021-10-11T15:55:22.925+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: oauth_access_tokens
[2021-10-11T15:55:40.138+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: oauth_applications_v2
[2021-10-11T15:55:49.517+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: engines_v15
[2021-10-11T15:56:05.271+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: workplace_search_accounts_v16
[2021-10-11T15:56:15.427+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: workplace_search_content_sources_v21
[2021-10-11T15:56:21.023+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: workplace_search_content_source_user_identities_v3
[2021-10-11T15:56:25.353+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: workplace_search_search_groups_v4
[2021-10-11T15:56:34.451+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: workplace_search_invitations_v2
[2021-10-11T15:56:44.807+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: workplace_search_organizations_v16
[2021-10-11T15:56:49.598+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: workplace_search_pre_content_sources
[2021-10-11T15:56:58.891+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: workplace_search_role_mappings_v5
[2021-10-11T15:57:04.437+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_accounts_v9
[2021-10-11T15:57:14.853+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_api_tokens_v3
[2021-10-11T15:57:24.495+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_api_token_engines
[2021-10-11T15:57:29.830+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_crawler_content_metadata
[2021-10-11T15:57:41.719+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_crawler_content_url_metadata
[2021-10-11T15:57:47.143+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_document_positions
[2021-10-11T15:57:52.198+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_document_position_queries_v3
[2021-10-11T15:57:57.403+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_invitations_v3
[2021-10-11T15:58:01.884+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_roles_v3
[2021-10-11T15:58:07.157+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_role_engines_v3
[2021-10-11T15:58:13.895+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_search_settings
[2021-10-11T15:58:19.811+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_role_mappings_v4
[2021-10-11T15:58:23.893+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: app_search_role_mapping_engines_v3
[2021-10-11T15:58:33.492+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: reindex_jobs
[2021-10-11T15:58:39.493+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: secret_keeper_secrets
[2021-10-11T15:58:44.220+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: crawler_domains_v4
[2021-10-11T15:58:53.884+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: crawler_crawl_requests_v4
[2021-10-11T15:59:01.565+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: crawler_process_crawls
[2021-10-11T15:59:07.820+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: crawler_robots_txts_v3
[2021-10-11T15:59:11.690+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: telemetry_status_v2
[2021-10-11T15:59:16.037+00:00][2355404][2002][app-server][INFO]: Creating index for Actastic::Schema: users_v6
[2021-10-11T15:59:29.050+00:00][2355404][2002][app-server][INFO]: Saving 95 Actastic migrations
[2021-10-11T15:59:29.489+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Finished] Creating indices for 36 models
[2021-10-11T15:59:29.701+00:00][2355404][2002][app-server][INFO]: Found no migrations to run
[2021-10-11T15:59:29.701+00:00][2355404][2002][app-server][INFO]: Enterprise Search indices are ready
[2021-10-11T15:59:29.797+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Starting] Creating default Elasticsearch roles
[2021-10-11T15:59:32.561+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Finished] Creating default Elasticsearch roles
[2021-10-11T15:59:33.081+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Starting] Creating a default Workplace Search organization
[2021-10-11T15:59:35.183+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Finished] Creating a default Workplace Search organization
[2021-10-11T15:59:35.437+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Starting] Creating a default App Search account
[2021-10-11T15:59:37.775+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Finished] Creating a default App Search account
[2021-10-11T15:59:38.051+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Starting] Creating a default user account
[2021-10-11T15:59:41.081+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Finished] Creating a default user account
[2021-10-11T15:59:41.441+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Starting] Creating a default OAuth application
[2021-10-11T15:59:42.809+00:00][2355404][2002][app-server][INFO]: [db_lock] [installation] Status: [Finished] Creating a default OAuth application
[2021-10-11T16:00:49.243+00:00][2355404][2002][app-server][INFO]: Starting HTTP server...
[2021-10-11T16:00:56.914+00:00][2355404][2154][app-server][INFO]: Enterprise Search version=7.15.0, JRuby version=9.2.13.0, Ruby version=2.5.7, Rails version=5.1.7
[2021-10-11T16:00:58.666+00:00][2355404][2154][app-server][INFO]: Performing pre-flight checks for Elasticsearch running on http://127.0.0.1:9200...
[2021-10-11T16:00:58.962+00:00][2355404][2154][app-server][INFO]: [pre-flight] Elasticsearch cluster is ready
[2021-10-11T16:00:58.965+00:00][2355404][2154][app-server][INFO]: [pre-flight] Successfully connected to Elasticsearch
[2021-10-11T16:00:58.986+00:00][2355404][2154][app-server][INFO]: [pre-flight] Successfully loaded Elasticsearch plugin information for all nodes
[2021-10-11T16:00:59.016+00:00][2355404][2154][app-server][INFO]: [pre-flight] Elasticsearch running with an active basic license
[2021-10-11T16:00:59.068+00:00][2355404][2154][app-server][INFO]: [pre-flight] Elasticsearch API key service is enabled
[2021-10-11T16:00:59.069+00:00][2355404][2154][app-server][INFO]: [pre-flight] ILM is enabled in Elasticsearch
[2021-10-11T16:00:59.069+00:00][2355404][2154][app-server][INFO]: [pre-flight] Elasticsearch X-Pack security is enabled and will be used for authentication
[2021-10-11T16:00:59.071+00:00][2355404][2154][app-server][INFO]: Elasticsearch looks healthy and configured correctly to run Enterprise Search
[2021-10-11T16:00:59.071+00:00][2355404][2154][app-server][INFO]: Performing pre-flight checks for Kibana running on http://10.30.52.6:5601...
[2021-10-11T16:01:00.177+00:00][2355404][2154][app-server][INFO]: [pre-flight] Successfully connected to Kibana
[2021-10-11T16:01:01.260+00:00][2355404][2154][app-server][INFO]: Kibana looks healthy and configured correctly to run Enterprise Search
[2021-10-11T16:01:03.785+00:00][2355404][2154][app-server][INFO]: Elastic APM agent is disabled
[2021-10-11T16:01:19.148+00:00][2355404][2154][app-server][INFO]: 

#########################################################

Success! Elastic Enterprise Search is starting successfully.

In a few moments, you'll be able to access Enterprise Search from Kibana at the following address:

* URL: http://10.30.52.6:5601/app/enterprise_search/overview

  * If this is your first time starting Enterprise Search, check the console output above for your user authentication credentials.
  * Visit the documentation: https://www.elastic.co/guide/en/enterprise-search/7.15/index.html

Secret session key has been generated.

Set the key in your config file to persist user sessions through process restarts:

secret_session_key: 5dd0ce292ac448979f7dc8652a610dd84e28a383f278a2b07b65154c82e460dd6917980b442e67a2f9e1dff1a80100f2e80b3d5dda5463e8e935fe8af9466af5


#########################################################

Start Enterprise Search

Проверьте, что служба запущена и слушает свой порт:

# netstat -tulnp | grep 3002
tcp6       0      0 127.0.0.1:3002          :::*                    LISTEN      2355404/java

Всё в порядке. Осталось только добавить в конфиг Kibana информацию о службе:

enterpriseSearch.host: http://localhost:3002

Перезапустите Kibana и отправляйтесь в веб интерфейс, в раздел Enterprise Search.

Welcome to Elastic Enterprise Search

На этом установка Elastic Enterprise Search закончена, можно начинать использовать. Напомню, что для Self-hosted решения ELK этот функционал бесплатен.

Заключение

Не нашёл в англоязычном интернете подробной инструкции, а тем более в русскоязычном, поэтому решил записать всю последовательность своих настроек, чтобы можно было быстро воспроизвести. Сам долго провозился из-за того, что не сразу разобрался, как всё настроить полностью на https, в том числе и все запросы между кластером и остальными. В итоге всё получилось только на валидном сертификате, но уже решил не добавлять всё это в статью, так как для работы Enterprise Search это не обязательно. Не захотелось разные темы смешивать. Возможно сделаю отдельный материал, если ещё где-то понадобится воспроизвести подобное.

Углубленный онлайн-курс по MikroTik.

Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном онлайн-курcе по администрированию MikroTik. Автор курcа – сертифицированный тренер MikroTik Дмитрий Скоромнов. Более 40 лабораторных работ по которым дается обратная связь. В три раза больше информации, чем в MTCNA.

Помогла статья? Подписывайся на telegram канал автора

Анонсы всех статей, плюс много другой полезной и интересной информации, которая не попадает на сайт.

Автор Zerox

Владимир, системный администратор, автор сайта. Люблю настраивать сервера, изучать что-то новое, делиться знаниями, писать интересные и полезные статьи. Открыт к диалогу и сотрудничеству. Если вам интересно узнать обо мне побольше, то можете послушать интервью. Запись на моем канале - https://t.me/srv_admin/425 или на сайте в контактах.

4 комментария

  1. Привет, не подскажите как называется Enterprise Search у OpenSearch? И вообще не могли бы объяснить зачем нужен Enterprise Search, можно будет без него пользоваться умным поиском и создавать индексы, синонимы, словоформы и тд?

    • С OpenSearch вообще не работал, так что не знаю. Я точно не знаю, в чём технические особенности Enterprise Search. Знаю только, что он создан конкретно под поиск с обработкой языковых особенностей, быстрым индексированием, AI, связями и т.д. В то время как сам elasticsearch это в первую очередь хранение большого количества логов и других данных. В то время, как поиск по какому-нибудь сайту это не обязательно очень большой объём данных.

  2. Статья полезная, но можно ли это установить в windows?

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

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

Нажимая кнопку "Отправить комментарий" Я даю согласие на обработку персональных данных.
Используешь Telegram? Подпишись на канал автора →
This is default text for notification bar