Compare commits
247 Commits
721fb0b1e7
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 98004bcb67 | |||
| f7e0663d3e | |||
| 756607fbb9 | |||
| ce9454d518 | |||
| 038d71be6e | |||
| 039eeb40e5 | |||
| cd480c69a9 | |||
| 34d17c9c9b | |||
| 351d80d3ff | |||
| 5a017ac47a | |||
| f438203912 | |||
| ce0d02d0b0 | |||
| caf80d3c20 | |||
| 17f6f8ac98 | |||
| 902ee9d5fb | |||
| 3905acf5b1 | |||
| 92a2df6b73 | |||
| 5118268045 | |||
| a9c1d87b38 | |||
| 3310c3143e | |||
| 91e73ffbef | |||
| 3f10edf636 | |||
| 5d7f0eb094 | |||
| 6864921ba2 | |||
| 695d095133 | |||
| f8c68fc017 | |||
| 24027d9d7c | |||
| ca2c0ecb0d | |||
| 3c01fb220c | |||
| 7813c906b6 | |||
| 54e0280d36 | |||
| 8291eabd96 | |||
| 5f53344c8d | |||
| fffbc19277 | |||
| 5eab9c24f8 | |||
| 82f1fe3ebe | |||
| 8b96c3784f | |||
| ad86c1410a | |||
| 52ea4eb4c8 | |||
| d56d13dfa4 | |||
| ec880e8d5d | |||
| 49c3a582f1 | |||
| a400048ef3 | |||
| 672a33d6f9 | |||
| e5977484af | |||
| 62fe0e0ca1 | |||
| 1ea6770013 | |||
| 8047021a44 | |||
| 198d6d22a7 | |||
| 17f4d4caf2 | |||
| 3cee2b82ac | |||
| e9e886bd5d | |||
| 3e4620a388 | |||
| f1bfc53bb5 | |||
| 83d57cfc36 | |||
| 5351b235dc | |||
| ddace8434d | |||
| e771369149 | |||
| 05c40b0ee6 | |||
| 92fac48655 | |||
| a5726a2d72 | |||
| 0b2f00cbb4 | |||
| 7c8dd413c3 | |||
| bae611e68d | |||
| 5fd2d3ae93 | |||
| f9bbb41e70 | |||
| 2871dc4b22 | |||
| 1831e7f03a | |||
| 12fca342c5 | |||
| 1551ebccaa | |||
| 70ca44f15d | |||
| 6af90cffb7 | |||
| 43a4d24f27 | |||
| 073a7ca4b8 | |||
| 2976e88ea5 | |||
| 96eb57c703 | |||
| 4b103f90c3 | |||
| 1fae23d524 | |||
| 63761558b2 | |||
| ca97ec782f | |||
| e5d791d144 | |||
| 11edd56fc8 | |||
| aab0e2fd4d | |||
| 2b95597c26 | |||
| 1b8965971a | |||
| f9c37af160 | |||
| c872d859e6 | |||
| 17b384693d | |||
| 25fdf07e26 | |||
| 2376c96197 | |||
| 29d72e9c76 | |||
| 2a65169168 | |||
| ce500cc31b | |||
| fed2a92b79 | |||
| c00a2e2460 | |||
| 8cb35e0009 | |||
| 6eddf40b7c | |||
| 8aa65149df | |||
| fade8ecdcf | |||
| 3cc9e28b3a | |||
| 76e7277186 | |||
| 83bebf1836 | |||
| 42e74764b3 | |||
| 7dd332b9ed | |||
| 561c277646 | |||
| 15e2783cb3 | |||
| 8730ac5fba | |||
| 481404b050 | |||
| 59389a9d4f | |||
| b6f3925b2e | |||
| 716014a704 | |||
| 5899a62772 | |||
| 0279c2067b | |||
| c4a124f043 | |||
| c3a61631d6 | |||
| d813f4a043 | |||
| 299937d418 | |||
| 233cb48188 | |||
| d83565202c | |||
| c3f5a1ebc1 | |||
| f87057d69a | |||
| d2faf0c62f | |||
| 1005f589eb | |||
| ac5ebaa626 | |||
| 27a7baa660 | |||
| 3cc2b962b0 | |||
| 706cd6dcae | |||
| 5434303ab1 | |||
| 50285ff6a9 | |||
| 19e7e7bb3b | |||
| bfa5a90985 | |||
| 38192a4bff | |||
| 8cc7996604 | |||
| af2afdd1a5 | |||
| 9ebfd24a41 | |||
| 3665ef64b4 | |||
| 3c3097cce4 | |||
| 2c0ceba6a9 | |||
| 369bb22819 | |||
| b2101df83b | |||
| e57cd345c7 | |||
| 0f28863f6b | |||
| 88dacf7218 | |||
| 1cf32f92dd | |||
| 1e9213e4ca | |||
| 7e0f09b97a | |||
| d831a84d5e | |||
| 33e2792d32 | |||
| ba69cd7559 | |||
| c501ddc032 | |||
| a1f2ea1201 | |||
| 598ffb7a50 | |||
| 7e5bf28182 | |||
| bcb9dec04c | |||
| 8cd08756a2 | |||
| 38e03809a4 | |||
| 4e4117b121 | |||
| fdaec73179 | |||
| ebf7fb7f04 | |||
| 72f1885bbb | |||
| 2e39f00e20 | |||
| cd3760685e | |||
| b726f0997d | |||
| 32433545fc | |||
| 587ee1468d | |||
| 45ab71cceb | |||
| 13d3381fae | |||
| 06edef55d7 | |||
| f357571bbf | |||
| 290f0c8da5 | |||
| 9b4c9c9feb | |||
| d49f4e54c5 | |||
| 2c697be36a | |||
| 16488d93eb | |||
| 01a859ad6b | |||
| 5e91fc51b4 | |||
| 3e66c9d102 | |||
| 63a0994182 | |||
| 407671efbe | |||
| 0845684d9f | |||
| 47dff00dad | |||
| f12a5ae974 | |||
| 3358557b81 | |||
| 447f119edd | |||
| a1688029ad | |||
| 94124551c8 | |||
| 75c1ab5b40 | |||
| c9452ee5ed | |||
| 40efd4bef5 | |||
| a14f1d2ab3 | |||
| ade4f42398 | |||
| 9f68cc73aa | |||
| 36fa12fbdf | |||
| 661f00fd6b | |||
| 607a6c727d | |||
| 9bb7d889e3 | |||
| c34382d54b | |||
| 4ea297e3e9 | |||
| 4b991a2999 | |||
| b0c6f043ea | |||
| 0dc55644e8 | |||
| 7fbdb2a7ba | |||
| b6229faedc | |||
| d56ccb47ab | |||
| 74f7794e77 | |||
| af20f47aba | |||
| f392769491 | |||
| cd38768362 | |||
| e1604781f0 | |||
| 23af64780d | |||
| 4c96585ef1 | |||
| 5d105ad9f3 | |||
| 6039b0eb13 | |||
| 0d18d193f5 | |||
| b59293a9d9 | |||
| 6b08bfa2f5 | |||
| eb7cbd1f67 | |||
| d0d79bd132 | |||
| 45bb38e051 | |||
| 4b564e0224 | |||
| 0d3b97502b | |||
| 1ff695d823 | |||
| dfa432738e | |||
| 30f18a3523 | |||
| 172bd1fced | |||
| cf01231df2 | |||
| 9cf2184bcb | |||
| 1343e92f1e | |||
| 863c2529a7 | |||
| 31648ef1ed | |||
| b17c97cf0f | |||
| 34c7938d3e | |||
| ff1f9114de | |||
| c9cd3f2606 | |||
| b000b80ec7 | |||
| 40a60b3e50 | |||
| f45ae7599e | |||
| 3868710cbe | |||
| e3ed893454 | |||
| ddc200f242 | |||
| aa7dfc7887 | |||
| 35fd7fb5f7 | |||
| 827865bbbc | |||
| ef3b5a3096 | |||
| 861469eee4 | |||
| a5ee6be2ba | |||
| 13cce4a94c |
@@ -2,7 +2,7 @@
|
||||
title: ПО, которое необходимо для установки и настройки хакинтоша
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-07T18:15:26.116Z
|
||||
date: 2024-07-09T09:49:36.868Z
|
||||
tags: mac, soft, hackintosh
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-07T10:42:22.230Z
|
||||
18
Apple/MacOS/Create-flash-on-m3.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<!--
|
||||
title: Создание загрузочной флешки с macOS
|
||||
description:
|
||||
published: true
|
||||
date: 2025-02-14T16:47:57.135Z
|
||||
tags: macos, m3, flash
|
||||
editor: ckeditor
|
||||
dateCreated: 2025-02-14T16:47:57.135Z
|
||||
-->
|
||||
|
||||
<h1>Установка на ноуте с arm процессорами</h1>
|
||||
<p><code>cd /Applications/Install\ macOS\ High\ Sierra.app/Contents/Resources/</code></p>
|
||||
<p><code>codesign -s - -f createinstallmedia</code></p>
|
||||
<p>с результатом<br>createinstallmedia: replacing existing signature</p>
|
||||
<p>После этого повторяем команду для создания и все идет.</p>
|
||||
<p><code>sudo /Applications/Install\ macOS\ High\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/macos</code></p>
|
||||
<h1>Установка High Sierra</h1>
|
||||
<p>Делал на новой ОС - "Секвойя"(MacBook Air M1), там дополнительно перед командами пришлось в настройках безопаности разрешить выполнение программы:<br>Настройки - конфиденциальности и безопасность-управление приложениями. Здес нужно добавить из раздела "программы" появившуюся там программу установки "Установка MacOS High Sierra" (!Важно, для тех кто не знает(если что то я не знал - не часто вожусьс МакОС) - в раздел "Программы" "Установка MacOS High Sierra" - добавляется простым копированием из подмонтированного .dmg-файла образа установочного.<br>Только после этого сработали команды что выше и флэшка создалась.<br>Также не забывам, что потом при загрузке с нее на старом Мак-е и попытке установки, можем получить ошибку: "Экземпляр программы "установка macOS high sierra" поврежден и не может быть использован для установки". Решается просто отключением Wi-Fi и заданием даты в терминале. И только потом жмем установку ОС.</p>
|
||||
11
DevOps/Cheat-Sheets.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!--
|
||||
title: Cheat Sheets
|
||||
description:
|
||||
published: true
|
||||
date: 2024-07-27T09:12:47.778Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2024-07-27T09:12:47.778Z
|
||||
-->
|
||||
|
||||
<p>По Hashicorp Vault есть тоже sheet https://prodik.ddns.net:3000/ru/DevOps/Hashicorp-Vault/Vault-cheat-sheet</p>
|
||||
12
DevOps/Cheat-Sheets/Docker-cheat-sheet.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Docker Cheat Sheet
|
||||
description:
|
||||
published: true
|
||||
date: 2024-07-27T09:08:46.248Z
|
||||
tags: cheat, sheet, docker
|
||||
editor: markdown
|
||||
dateCreated: 2024-07-27T09:08:46.248Z
|
||||
---
|
||||
|
||||
Фото
|
||||

|
||||
11
DevOps/Cheat-Sheets/Git-Cheat-Sheet.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!--
|
||||
title: Git Cheat Sheet
|
||||
description:
|
||||
published: true
|
||||
date: 2024-07-27T09:10:47.213Z
|
||||
tags: cheat, sheet, git
|
||||
editor: ckeditor
|
||||
dateCreated: 2024-07-27T09:10:47.213Z
|
||||
-->
|
||||
|
||||
<figure class="image"><img src="/DevOps/img/git-sheet.png"></figure>
|
||||
11
DevOps/Cheat-Sheets/Regular-String-cheat-sheet.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: Регулярные - cheat sheet
|
||||
description:
|
||||
published: true
|
||||
date: 2024-07-27T09:17:25.211Z
|
||||
tags: cheat, sheet, regular
|
||||
editor: markdown
|
||||
dateCreated: 2024-07-27T09:16:15.298Z
|
||||
---
|
||||
|
||||

|
||||
164
DevOps/Clickhouse/Cluster/0-Bases-and-query.md
Normal file
@@ -0,0 +1,164 @@
|
||||
---
|
||||
title: 0. Основы и запросы
|
||||
description:
|
||||
published: true
|
||||
date: 2025-05-15T20:02:37.600Z
|
||||
tags: clickhouse
|
||||
editor: markdown
|
||||
dateCreated: 2025-05-15T20:01:45.285Z
|
||||
---
|
||||
|
||||
## Структура кластера
|
||||
|
||||
### Найдено на просторах инета:
|
||||
##### Выбор решения:
|
||||
- Если **диск загружен на запись (INSERT)** → **шардирование (Distributed)**.
|
||||
- Если **диск загружен на чтение (SELECT)** → **репликация (Replicated)**.
|
||||
- Если **один сервер, но много дисков** → **JBOD или RAID 0/10**.
|
||||
|
||||
#### Реализуем такую структуру тестового кластера:
|
||||
- сервер clickhouse-1
|
||||
- сервер clickhouse-2
|
||||
- сервер clickhouse-keeper
|
||||
Для того, чтобы это было надежно и работало быстро с записью в БД, необходимо сделать репликацию (Replicated) таблиц и распределенный (Distributed) доступ к таблицам.
|
||||
Если делать несколько шардов (shard) в настройках кластера, то это значит, что часть данных будет находится на одном сервере, другая часть на другом. При выходе из строя сервера мы потеряем всю базу.
|
||||
Поэтому настраиваем shard1 на обоих серверах, а также replica1 и replica2 для дублирования данных на серверах.
|
||||
|
||||
### Репликация поддерживается только для таблиц семейства MergeTree:
|
||||
https://clickhouse.com/docs/ru/engines/table-engines/mergetree-family/replication
|
||||
- ReplicatedMergeTree
|
||||
- ReplicatedSummingMergeTree
|
||||
- ReplicatedReplacingMergeTree
|
||||
- ReplicatedAggregatingMergeTree
|
||||
- ReplicatedCollapsingMergeTree
|
||||
- ReplicatedVersionedCollapsingMergeTree
|
||||
- ReplicatedGraphiteMergeTree
|
||||
|
||||
### Для одиночного сервера и кластера
|
||||
#### Получение списка всех баз данных на сервере
|
||||
```sql
|
||||
SHOW DATABASES;
|
||||
```
|
||||
#### Просмотр всех таблиц в конкретной базе default
|
||||
```sql
|
||||
SHOW TABLES FROM default;
|
||||
```
|
||||
#### Получить запрос на создание таблицы из существующей
|
||||
```sql
|
||||
show create table default.event;
|
||||
```
|
||||
#### Создание базы данных
|
||||
```sql
|
||||
CREATE DATABASE IF NOT EXISTS my_database ENGINE = Atomic;
|
||||
```
|
||||
Создает новую базу данных с именем `my_database`. Если такая база уже существует, ничего не произойдет благодаря условию `IF NOT EXISTS`.
|
||||
Параметр `ENGINE = Atomic` используется для новых версий ClickHouse и позволяет создавать транзакционно безопасные базы данных. В ранних версиях использовался простой синтаксис без указания движка.
|
||||
#### Создание таблицы
|
||||
```sql
|
||||
CREATE TABLE my_table (
|
||||
event_date Date,
|
||||
user_id UInt32,
|
||||
page_views Int32,
|
||||
revenue Float64
|
||||
)
|
||||
ENGINE = MergeTree()
|
||||
ORDER BY (event_date);
|
||||
```
|
||||
##### Вставка данных
|
||||
```sql
|
||||
INSERT INTO my_table VALUES ('2023-08-01', 1, 10, 100.5), ('2023-08-02', 2, 15, 150.75);
|
||||
```
|
||||
##### Выборка данных
|
||||
```sql
|
||||
SELECT * FROM my_table WHERE event_date >= '2023-08-01' AND event_date <= '2023-08-31';
|
||||
```
|
||||
#### Показ структуры таблицы
|
||||
```sql
|
||||
DESCRIBE TABLE my_database.my_table;
|
||||
```
|
||||
или подробнее:
|
||||
```sql
|
||||
SELECT * FROM system.columns WHERE table='my_table' AND database='my_database';
|
||||
```
|
||||
### Узнать сколько занимают места базы
|
||||
```sql
|
||||
SELECT
|
||||
database,
|
||||
formatReadableSize(sum(bytes_on_disk)) AS total_size
|
||||
FROM system.parts
|
||||
WHERE active
|
||||
GROUP BY database
|
||||
ORDER BY sum(bytes_on_disk) DESC;
|
||||
```
|
||||
#### Узнать сколько занимают места таблицы в базе
|
||||
default
|
||||
```sql
|
||||
SELECT
|
||||
name AS table_name,
|
||||
formatReadableSize(total_bytes) AS size_readable,
|
||||
total_rows AS rows_count
|
||||
FROM system.tables
|
||||
WHERE database = 'default'
|
||||
ORDER BY total_bytes DESC;
|
||||
```
|
||||
system
|
||||
```sql
|
||||
SELECT
|
||||
name AS table_name,
|
||||
formatReadableSize(total_bytes) AS size_readable,
|
||||
total_rows AS rows_count
|
||||
FROM system.tables
|
||||
WHERE database = 'system'
|
||||
ORDER BY total_bytes DESC;
|
||||
```
|
||||
#### Очистка базы event_replicated
|
||||
```sql
|
||||
TRUNCATE TABLE default.event_replicated;
|
||||
```
|
||||
#### Очистка старых данных от определенной даты
|
||||
```sql
|
||||
ALTER TABLE my_table DELETE WHERE event_date < '2023-08-01';
|
||||
```
|
||||
#### Безопасное удаление таблицы
|
||||
```sql
|
||||
DROP TABLE IF EXISTS my_database.my_table;
|
||||
```
|
||||
Безопасно удаляет указанную таблицу, если она существует.
|
||||
|
||||
|
||||
### Для кластера
|
||||
|
||||
#### Вывести список серверов в кластере
|
||||
```sql
|
||||
SELECT hostName() FROM clusterAllReplicas('smvu2_cluster', 'system', 'one')
|
||||
```
|
||||
#### Получение списка Replicated таблиц
|
||||
```sql
|
||||
SELECT
|
||||
database,
|
||||
name AS table,
|
||||
engine
|
||||
FROM system.tables
|
||||
WHERE engine LIKE 'Replicated%';
|
||||
```
|
||||
#### Получение списка Distributed таблиц
|
||||
```sql
|
||||
SELECT
|
||||
database,
|
||||
name AS table,
|
||||
engine
|
||||
FROM system.tables
|
||||
WHERE engine LIKE 'Distributed%';
|
||||
```
|
||||
#### Проверить распределение данных базы event на серверах кластера
|
||||
```sql
|
||||
SELECT
|
||||
hostName() AS host,
|
||||
count() AS count
|
||||
FROM clusterAllReplicas(smvu2_cluster, default.event)
|
||||
GROUP BY host;
|
||||
```
|
||||
#### Удалить таблицу в кластере
|
||||
```sql
|
||||
DROP TABLE event_replicated ON CLUSTER smvu2_cluster SYNC;
|
||||
```
|
||||
228
DevOps/Clickhouse/Cluster/1-Install-Clickhouse-cluster.md
Normal file
@@ -0,0 +1,228 @@
|
||||
---
|
||||
title: 1. Создание кластера Clickhouse
|
||||
description:
|
||||
published: true
|
||||
date: 2025-05-15T20:11:12.215Z
|
||||
tags: clickhouse, cluster
|
||||
editor: markdown
|
||||
dateCreated: 2025-05-15T18:04:57.423Z
|
||||
---
|
||||
|
||||
https://clickhouse.com/docs/guides/sre/keeper/clickhouse-keeper
|
||||
## Установка и настройка clickhouse, clickhouse-keeper
|
||||
### Установка clickhouse-keeper
|
||||
```bash
|
||||
apt-get install -y apt-transport-https ca-certificates curl gnupg
|
||||
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | sudo gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg arch=${ARCH}] https://packages.clickhouse.com/deb stable main" | sudo tee /etc/apt/sources.list.d/clickhouse.list
|
||||
apt-get update
|
||||
apt-get install -y clickhouse-keeper
|
||||
```
|
||||
|
||||
#### Готовим конфиг clickhouse-keeper
|
||||
```
|
||||
nano /etc/clickhouse-keeper/keeper_config.xml
|
||||
```
|
||||
|
||||
```xml
|
||||
<clickhouse>
|
||||
<logger>
|
||||
<level>warning</level>
|
||||
<log>/var/log/clickhouse-keeper/clickhouse-keeper.log</log>
|
||||
<errorlog>/var/log/clickhouse-keeper/clickhouse-keeper.err.log</errorlog>
|
||||
<size>1000M</size>
|
||||
<count>10</count>
|
||||
<!-- <console>1</console> --> <!-- Default behavior is autodetection (log to console if not daemon mode and is tty) -->
|
||||
</logger>
|
||||
|
||||
<max_connections>4096</max_connections>
|
||||
<listen_host>0.0.0.0</listen_host>
|
||||
<listen_host>::1</listen_host>
|
||||
|
||||
<keeper_server>
|
||||
<tcp_port>9181</tcp_port>
|
||||
<server_id>1</server_id>
|
||||
|
||||
<log_storage_path>/var/lib/clickhouse/coordination/logs</log_storage_path>
|
||||
<snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>
|
||||
|
||||
<coordination_settings>
|
||||
<operation_timeout_ms>10000</operation_timeout_ms>
|
||||
<session_timeout_ms>30000</session_timeout_ms>
|
||||
<raft_logs_level>warning</raft_logs_level>
|
||||
<compress_logs>true</compress_logs>
|
||||
</coordination_settings>
|
||||
|
||||
<!-- enable sanity hostname checks for cluster configuration (e.g. if localhost is used with remote endpoints) -->
|
||||
<hostname_checks_enabled>false</hostname_checks_enabled>
|
||||
<raft_configuration>
|
||||
<server>
|
||||
<id>1</id>
|
||||
<hostname>localhost</hostname>
|
||||
<port>9234</port>
|
||||
</server>
|
||||
</raft_configuration>
|
||||
</keeper_server>
|
||||
</clickhouse>
|
||||
```
|
||||
|
||||
#### Пароль пользователя
|
||||
```
|
||||
nano /etc/clickhouse-server/users.d/default-password.xml
|
||||
```
|
||||
|
||||
```xml
|
||||
<yandex>
|
||||
<users>
|
||||
<default>
|
||||
<password>SuperPass</password>
|
||||
<networks>
|
||||
<ip>::/0</ip>
|
||||
<ip>127.0.0.1</ip>
|
||||
<ip>172.16.212.0/24</ip>
|
||||
</networks>
|
||||
</default>
|
||||
</users>
|
||||
</yandex>
|
||||
```
|
||||
|
||||
### Готовим конфиги clickhouse на серверах SMVU2-DEV14 и SMVU2-Click-DEV
|
||||
|
||||
```bash
|
||||
nano /etc/clickhouse-server/config.d/remote_servers.xml
|
||||
```
|
||||
##### server 1
|
||||
```xml
|
||||
<yandex>
|
||||
<display_name>smvu2_cluster node 1</display_name>
|
||||
<remote_servers replace="true">
|
||||
<smvu2_cluster>
|
||||
<!--<secret>mysecretphrase</secret> -->
|
||||
<shard>
|
||||
<internal_replication>true</internal_replication>
|
||||
<replica>
|
||||
<host>172.16.212.14</host>
|
||||
<port>9000</port>
|
||||
<priority>1</priority>
|
||||
<secure>0</secure>
|
||||
<user>default</user>
|
||||
<password>SuperPass</password>
|
||||
</replica>
|
||||
<replica>
|
||||
<host>172.16.212.42</host>
|
||||
<port>9000</port>
|
||||
<priority>2</priority>
|
||||
<secure>0</secure>
|
||||
<user>default</user>
|
||||
<password>SuperPass</password>
|
||||
</replica>
|
||||
</shard>
|
||||
</smvu2_cluster>
|
||||
</remote_servers>
|
||||
</yandex>
|
||||
```
|
||||
|
||||
```
|
||||
nano /etc/clickhouse-server/config.d/shard.xml
|
||||
```
|
||||
|
||||
```xml
|
||||
<yandex>
|
||||
<macros>
|
||||
<shard>1</shard>
|
||||
<replica>replica1</replica>
|
||||
</macros>
|
||||
</yandex>
|
||||
```
|
||||
|
||||
##### server 2
|
||||
```xml
|
||||
<yandex>
|
||||
<display_name>smvu2_cluster node 2</display_name>
|
||||
<remote_servers replace="true">
|
||||
<smvu2_cluster>
|
||||
<!--<secret>mysecretphrase</secret> -->
|
||||
<shard>
|
||||
<internal_replication>true</internal_replication>
|
||||
<replica>
|
||||
<host>172.16.212.42</host>
|
||||
<port>9000</port>
|
||||
<priority>2</priority>
|
||||
<secure>0</secure>
|
||||
<user>default</user>
|
||||
<password>SuperPass</password>
|
||||
</replica>
|
||||
<replica>
|
||||
<host>172.16.212.14</host>
|
||||
<port>9000</port>
|
||||
<priority>1</priority>
|
||||
<secure>0</secure>
|
||||
<user>default</user>
|
||||
<password>SuperPass</password>
|
||||
</replica>
|
||||
</shard>
|
||||
</smvu2_cluster>
|
||||
</remote_servers>
|
||||
</yandex>
|
||||
```
|
||||
|
||||
```
|
||||
nano /etc/clickhouse-server/config.d/shard.xml
|
||||
```
|
||||
|
||||
```xml
|
||||
<yandex>
|
||||
<macros>
|
||||
<shard>1</shard>
|
||||
<replica>replica2</replica>
|
||||
</macros>
|
||||
</yandex>
|
||||
```
|
||||
|
||||
```
|
||||
nano /etc/clickhouse-server/config.d/keeper.xml
|
||||
```
|
||||
|
||||
```xml
|
||||
<yandex>
|
||||
<zookeeper>
|
||||
<node>
|
||||
<host>172.16.212.41</host>
|
||||
<port>9181</port>
|
||||
</node>
|
||||
</zookeeper>
|
||||
</yandex>
|
||||
```
|
||||
|
||||
```
|
||||
nano /etc/clickhouse-server/config.d/distributed_ddl.xml
|
||||
```
|
||||
|
||||
```xml
|
||||
<yandex>
|
||||
<distributed_ddl>
|
||||
<task_max_lifetime>86400</task_max_lifetime>
|
||||
<profile>default</profile>
|
||||
<cleanup_delay>60</cleanup_delay>
|
||||
<max_workers>16</max_workers>
|
||||
</distributed_ddl>
|
||||
</yandex>
|
||||
```
|
||||
|
||||
### Проверить сервера, что они в кластере
|
||||
|
||||
#### Показать кластер
|
||||
```sql
|
||||
SHOW clusters;
|
||||
```
|
||||
|
||||
#### Вывести список серверов в кластере
|
||||
```sql
|
||||
SELECT hostName() FROM clusterAllReplicas('smvu2_cluster', 'system', 'one')
|
||||
```
|
||||
|
||||
#### Keeper status
|
||||
```sql
|
||||
SELECT * FROM system.zookeeper WHERE path = '/';
|
||||
```
|
||||
646
DevOps/Clickhouse/Cluster/3-Create-manual.md
Normal file
@@ -0,0 +1,646 @@
|
||||
---
|
||||
title: 3. Создание таблиц вручную
|
||||
description:
|
||||
published: true
|
||||
date: 2025-05-15T20:07:34.738Z
|
||||
tags: clickhouse
|
||||
editor: markdown
|
||||
dateCreated: 2025-05-15T20:07:34.738Z
|
||||
---
|
||||
|
||||
Можно создать все таблицы для кластера вручную.
|
||||
Запрашиваем структуру каждой таблицы, создаем под другим именем и копируем данные с исходника.
|
||||
|
||||
##### Может возникнуть проблема, что таблицы содержат много данных, поэтому внизу статьи будет решение
|
||||
|
||||
## Создаем реплицированные таблицы
|
||||
|
||||
**Разберем первую таблицу подробно**
|
||||
### 1. api_request_log_replicated
|
||||
|
||||
Запрашиваем структуру
|
||||
```sql
|
||||
show create table default.api_request_log
|
||||
```
|
||||
|
||||
Выход:
|
||||
```sql
|
||||
CREATE TABLE default.api_request_log
|
||||
(
|
||||
`uuid` UUID DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`ver` UInt8,
|
||||
`request_ts` DateTime64(3) DEFAULT '0000000000.000',
|
||||
`duration` Float64,
|
||||
`endpoint` String,
|
||||
`method` FixedString(5),
|
||||
`status_code` UInt32,
|
||||
`remote_addr` String,
|
||||
`username` Nullable(String),
|
||||
`error` Nullable(String),
|
||||
`request_body` Nullable(String) TTL toDateTime(request_ts) + toIntervalMonth(1),
|
||||
`query_params` Nullable(String) TTL toDateTime(request_ts) + toIntervalMonth(1),
|
||||
`response_body` Nullable(String) TTL toDateTime(request_ts) + toIntervalMonth(1)
|
||||
)
|
||||
ENGINE = MergeTree(ver)
|
||||
PARTITION BY toYYYYMM(request_ts)
|
||||
ORDER BY uuid
|
||||
SETTINGS index_granularity = 8192;
|
||||
```
|
||||
|
||||
Дорабатываем запрос, чтобы получилась на выходе реплицируемая таблица
|
||||
```sql
|
||||
CREATE TABLE default.api_request_log_replicated ON CLUSTER smvu2_cluster
|
||||
(
|
||||
`uuid` UUID DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`ver` UInt8,
|
||||
`request_ts` DateTime64(3) DEFAULT '0000000000.000',
|
||||
`duration` Float64,
|
||||
`endpoint` String,
|
||||
`method` FixedString(5),
|
||||
`status_code` UInt32,
|
||||
`remote_addr` String,
|
||||
`username` Nullable(String),
|
||||
`error` Nullable(String),
|
||||
`request_body` Nullable(String) TTL toDateTime(request_ts) + toIntervalMonth(1),
|
||||
`query_params` Nullable(String) TTL toDateTime(request_ts) + toIntervalMonth(1),
|
||||
`response_body` Nullable(String) TTL toDateTime(request_ts) + toIntervalMonth(1)
|
||||
)
|
||||
ENGINE = ReplicatedReplacingMergeTree(
|
||||
'/clickhouse/tables/{shard}/default/api_request_log_replicated',
|
||||
'{replica}',
|
||||
ver
|
||||
)
|
||||
PARTITION BY toYYYYMM(request_ts)
|
||||
ORDER BY uuid
|
||||
SETTINGS index_granularity = 8192;
|
||||
```
|
||||
Копируем данные
|
||||
```sql
|
||||
INSERT INTO default.api_request_log_replicated
|
||||
SELECT * FROM default.api_request_log
|
||||
```
|
||||
|
||||
### 2. event_replicated
|
||||
```sql
|
||||
show create table default.event
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.event_replicated ON CLUSTER smvu2_cluster
|
||||
(
|
||||
`event_id` UUID,
|
||||
`unipoll_id` UUID,
|
||||
`sensor_id` UUID,
|
||||
`sensor_type_id` UUID,
|
||||
`sensor_type_name` String,
|
||||
`sensor_activation_status_name` String,
|
||||
`sensor_logic_status_id` UUID,
|
||||
`sensor_logic_status_name` String,
|
||||
`sensor_comment` Nullable(String),
|
||||
`command` String,
|
||||
`priority_name` String,
|
||||
`pub_ts` DateTime,
|
||||
`sub_ts` DateTime64(3, 'Europe/Moscow'),
|
||||
`state_id` UInt8,
|
||||
`state_name` String,
|
||||
`status_id` UInt8,
|
||||
`status_name` String,
|
||||
`unitype_id` UInt16,
|
||||
`unitype_name` String,
|
||||
`system_id` UInt16,
|
||||
`system_short_name` String,
|
||||
`system_name` String,
|
||||
`checked` UInt8,
|
||||
`object_id` UUID,
|
||||
`object_type_name` String,
|
||||
`data_id` UInt8,
|
||||
`value` Nullable(String),
|
||||
`raw_value` Nullable(String),
|
||||
`data` String,
|
||||
`region_id` UUID,
|
||||
`region_name` String,
|
||||
`complex_id` UUID,
|
||||
`complex_name` String,
|
||||
`collector_id` Nullable(UUID),
|
||||
`collector_name` Nullable(String),
|
||||
`control_room_id` Nullable(UUID),
|
||||
`control_room_name` Nullable(String),
|
||||
`picket_id` Nullable(UUID),
|
||||
`picket_name` Nullable(String),
|
||||
`picket_n` Nullable(UInt32),
|
||||
`cstate_id` UUID,
|
||||
`cstate_name` String,
|
||||
`cstate_color_id` UInt8,
|
||||
`sub_ms` UInt64,
|
||||
`linked_channel_state` Nullable(String),
|
||||
`on_guard` Nullable(UInt8),
|
||||
`internal_id` Nullable(String),
|
||||
`floor_number` Nullable(Int32)
|
||||
)
|
||||
ENGINE = ReplicatedMergeTree(
|
||||
'/clickhouse/tables/{shard}/default/event_replicated',
|
||||
'{replica}'
|
||||
)
|
||||
PARTITION BY toYYYYMM(pub_ts)
|
||||
ORDER BY (priority_name, sensor_type_id, cstate_id, object_id, sensor_id, pub_ts, sub_ts, event_id)
|
||||
SETTINGS index_granularity = 8192;
|
||||
```
|
||||
Копируем данные
|
||||
```sql
|
||||
INSERT INTO default.event_replicated
|
||||
SELECT * FROM default.event
|
||||
```
|
||||
|
||||
### 3. event_automation_replicated
|
||||
```sql
|
||||
show create table default.event_automation
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.event_automation_replicated ON CLUSTER smvu2_cluster
|
||||
(
|
||||
`event_id` UUID DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`unipoll_id` UUID DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`automation_id` UUID DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`automation_name` String,
|
||||
`automation_mode` UInt8,
|
||||
`pub_ts` DateTime DEFAULT '0000000000',
|
||||
`sub_ts` DateTime64(3) DEFAULT '0000000000.000',
|
||||
`sub_ms` UInt64,
|
||||
`state_id` UInt8,
|
||||
`state_name` String,
|
||||
`status_id` UInt8,
|
||||
`unitype_id` UInt8,
|
||||
`unitype_name` String,
|
||||
`group_id` UUID DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`group_name` String,
|
||||
`data` String,
|
||||
`cstate_id` UUID DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
`cstate_name` String,
|
||||
`cstate_color_id` UInt8
|
||||
)
|
||||
ENGINE = ReplicatedMergeTree(
|
||||
'/clickhouse/tables/{shard}/default/event_automation_replicated',
|
||||
'{replica}'
|
||||
)
|
||||
PARTITION BY toYYYYMMDD(pub_ts)
|
||||
ORDER BY (event_id, pub_ts, sub_ts)
|
||||
SETTINGS index_granularity = 8192;
|
||||
```
|
||||
Копируем данные
|
||||
```sql
|
||||
INSERT INTO default.event_automation_replicated
|
||||
SELECT * FROM default.event_automation
|
||||
```
|
||||
|
||||
### 4. event_confirmation_replicated
|
||||
```sql
|
||||
show create table default.event_confirmation
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.event_confirmation_replicated ON CLUSTER smvu2_cluster
|
||||
(
|
||||
`uuid` UUID,
|
||||
`event_id` UUID,
|
||||
`reason` String DEFAULT '',
|
||||
`event_checked` Int8,
|
||||
`username` String,
|
||||
`datetime` DateTime,
|
||||
`confirmation_group` String,
|
||||
`node_id` UUID
|
||||
)
|
||||
ENGINE = ReplicatedMergeTree(
|
||||
'/clickhouse/tables/{shard}/default/event_confirmation_replicated',
|
||||
'{replica}'
|
||||
)
|
||||
PARTITION BY toYYYYMM(datetime)
|
||||
ORDER BY datetime
|
||||
SETTINGS index_granularity = 8192;
|
||||
```
|
||||
Копируем данные
|
||||
```sql
|
||||
INSERT INTO default.event_confirmation_replicated
|
||||
SELECT * FROM default.event_confirmation
|
||||
```
|
||||
|
||||
### 5. event_objects_replicated
|
||||
```sql
|
||||
show create table default.event_objects
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.event_objects_replicated ON CLUSTER smvu2_cluster
|
||||
(
|
||||
`event_id` UUID,
|
||||
`node_id` UUID,
|
||||
`pub_ts` DateTime,
|
||||
`sub_ts` DateTime64(3, 'UTC'),
|
||||
`cstate_id` UUID,
|
||||
`source_id` UUID,
|
||||
`source_name` String DEFAULT '',
|
||||
`source_type_id` UUID,
|
||||
`event_data` String,
|
||||
`complex_id` UUID
|
||||
)
|
||||
ENGINE = ReplicatedMergeTree(
|
||||
'/clickhouse/tables/{shard}/default/event_objects_replicated',
|
||||
'{replica}'
|
||||
)
|
||||
PARTITION BY toYYYYMM(pub_ts)
|
||||
PRIMARY KEY event_id
|
||||
ORDER BY (event_id, pub_ts, sub_ts)
|
||||
SETTINGS index_granularity = 8192;
|
||||
```
|
||||
Копируем данные
|
||||
```sql
|
||||
INSERT INTO default.event_objects_replicated
|
||||
SELECT * FROM default.event_objects
|
||||
```
|
||||
### 6. infi_clickhouse_orm_migrations_replicated
|
||||
|
||||
```sql
|
||||
show create table default.infi_clickhouse_orm_migrations
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.infi_clickhouse_orm_migrations_replicated ON CLUSTER smvu2_cluster
|
||||
(
|
||||
`package_name` String,
|
||||
`module_name` String,
|
||||
`applied` Date DEFAULT '1970-01-01'
|
||||
)
|
||||
ENGINE = ReplicatedMergeTree(
|
||||
'/clickhouse/tables/{shard}/default/infi_clickhouse_orm_migrations_replicated',
|
||||
'{replica}'
|
||||
)
|
||||
PARTITION BY toYYYYMM(applied)
|
||||
ORDER BY (package_name, module_name)
|
||||
SETTINGS index_granularity = 8192;
|
||||
```
|
||||
Копируем данные
|
||||
```sql
|
||||
INSERT INTO default.infi_clickhouse_orm_migrations_replicated
|
||||
SELECT * FROM default.infi_clickhouse_orm_migrations
|
||||
```
|
||||
|
||||
### 7. unchecked_event_replicated
|
||||
|
||||
```sql
|
||||
show create table default.unchecked_event
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.unchecked_event_replicated ON CLUSTER smvu2_cluster
|
||||
(
|
||||
`event_id` UUID,
|
||||
`unipoll_id` Nullable(UUID),
|
||||
`sensor_id` Nullable(UUID),
|
||||
`sensor_type_id` Nullable(UUID),
|
||||
`sensor_type_name` Nullable(String),
|
||||
`sensor_activation_status_name` Nullable(String),
|
||||
`sensor_logic_status_id` Nullable(UUID),
|
||||
`sensor_logic_status_name` Nullable(String),
|
||||
`sensor_comment` Nullable(String),
|
||||
`command` Nullable(String),
|
||||
`priority_name` Nullable(String),
|
||||
`pub_ts` Nullable(DateTime),
|
||||
`sub_ts` DateTime64(3),
|
||||
`state_id` Nullable(UInt8),
|
||||
`state_name` Nullable(String),
|
||||
`status_id` Nullable(UInt8),
|
||||
`status_name` Nullable(String),
|
||||
`unitype_id` Nullable(UInt16),
|
||||
`unitype_name` Nullable(String),
|
||||
`system_id` Nullable(UInt16),
|
||||
`system_short_name` Nullable(String),
|
||||
`system_name` Nullable(String),
|
||||
`checked` Nullable(UInt8),
|
||||
`object_id` Nullable(UUID),
|
||||
`object_type_name` Nullable(String),
|
||||
`data_id` Nullable(UInt8),
|
||||
`data` Nullable(String),
|
||||
`region_id` Nullable(UUID),
|
||||
`region_name` Nullable(String),
|
||||
`complex_id` Nullable(UUID),
|
||||
`complex_name` Nullable(String),
|
||||
`collector_id` Nullable(UUID),
|
||||
`collector_name` Nullable(String),
|
||||
`control_room_id` Nullable(UUID),
|
||||
`control_room_name` Nullable(String),
|
||||
`picket_id` Nullable(UUID),
|
||||
`picket_name` Nullable(String),
|
||||
`picket_n` Nullable(UInt32),
|
||||
`cstate_id` Nullable(UUID),
|
||||
`cstate_name` Nullable(String),
|
||||
`cstate_color_id` Nullable(UInt8),
|
||||
`sub_ms` Nullable(UInt64),
|
||||
`linked_channel_state` Nullable(String),
|
||||
`on_guard` Nullable(UInt8),
|
||||
`internal_id` Nullable(String),
|
||||
`floor_number` Nullable(Int32),
|
||||
`sign` Int8,
|
||||
`value` Nullable(String),
|
||||
`raw_value` Nullable(String)
|
||||
)
|
||||
ENGINE = ReplicatedCollapsingMergeTree(
|
||||
'/clickhouse/tables/{shard}/default/unchecked_event_replicated',
|
||||
'{replica}',
|
||||
sign
|
||||
)
|
||||
PARTITION BY toYYYYMM(sub_ts)
|
||||
PRIMARY KEY event_id
|
||||
ORDER BY event_id
|
||||
SETTINGS index_granularity = 8192;
|
||||
```
|
||||
Копируем
|
||||
```sql
|
||||
INSERT INTO default.unchecked_event_replicated
|
||||
SELECT * FROM default.unchecked_event;
|
||||
```
|
||||
|
||||
### 8. unchecked_objects_event_replicated
|
||||
```sql
|
||||
show create table default.unchecked_objects_event;
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.unchecked_objects_event_replicated ON CLUSTER smvu2_cluster
|
||||
(
|
||||
`event_id` UUID,
|
||||
`node_id` Nullable(UUID),
|
||||
`complex_id` Nullable(UUID),
|
||||
`pub_ts` Nullable(DateTime),
|
||||
`sub_ts` DateTime64(3, 'UTC'),
|
||||
`cstate_id` Nullable(UUID),
|
||||
`source_id` Nullable(UUID),
|
||||
`source_name` Nullable(String),
|
||||
`source_type_id` Nullable(UUID),
|
||||
`event_data` Nullable(String),
|
||||
`sign` Int8
|
||||
)
|
||||
ENGINE = ReplicatedCollapsingMergeTree(
|
||||
'/clickhouse/tables/{shard}/default/unchecked_objects_event_replicated',
|
||||
'{replica}',
|
||||
sign
|
||||
)
|
||||
PARTITION BY toYYYYMM(sub_ts)
|
||||
PRIMARY KEY event_id
|
||||
ORDER BY event_id
|
||||
SETTINGS index_granularity = 8192;
|
||||
```
|
||||
Копируем
|
||||
```sql
|
||||
INSERT INTO default.unchecked_objects_event_replicated
|
||||
SELECT * FROM default.unchecked_objects_event;
|
||||
```
|
||||
|
||||
|
||||
### Проверка состояния репликации после создания:
|
||||
```sql
|
||||
SELECT database, table, is_leader, total_replicas, active_replicas
|
||||
FROM system.replicas
|
||||
WHERE database = 'default'
|
||||
```
|
||||
### Узнаем и сравниваем сколько занимают места таблицы в базе default
|
||||
```sql
|
||||
SELECT
|
||||
name AS table_name,
|
||||
formatReadableSize(total_bytes) AS size_readable,
|
||||
total_rows AS rows_count
|
||||
FROM system.tables
|
||||
WHERE database = 'default'
|
||||
ORDER BY total_bytes DESC;
|
||||
```
|
||||
|
||||
### Переименовываем исходные таблицы
|
||||
```sql
|
||||
rename table api_request_log to api_request_log_old;
|
||||
rename table event to event_old;
|
||||
rename table event_objects to event_objects_old;
|
||||
rename table event_confirmation to event_confirmation_old;
|
||||
rename table audit_new to audit_new_old;
|
||||
rename table event_automation to event_automation_old;
|
||||
rename table infi_clickhouse_orm_migrations to infi_clickhouse_orm_migrations_old;
|
||||
rename table unchecked_event to unchecked_event_old;
|
||||
rename table unchecked_objects_event to unchecked_objects_event_old;
|
||||
```
|
||||
|
||||
### Создаем Distributed-таблицы
|
||||
```sql
|
||||
CREATE TABLE default.event ON CLUSTER smvu2_cluster AS default.event_replicated
|
||||
ENGINE = Distributed(smvu2_cluster, default, api_request_log_replicated, rand());
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.event ON CLUSTER smvu2_cluster AS default.event_replicated
|
||||
ENGINE = Distributed(smvu2_cluster, default, event_replicated, rand());
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.audit_new ON CLUSTER smvu2_cluster AS default.audit_new_replicated
|
||||
ENGINE = Distributed(smvu2_cluster, default, audit_new_replicated, rand());
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.event_objects ON CLUSTER smvu2_cluster AS default.event_objects_replicated
|
||||
ENGINE = Distributed(smvu2_cluster, default, event_objects_replicated, rand());
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.event_automation ON CLUSTER smvu2_cluster AS default.event_automation_replicated
|
||||
ENGINE = Distributed(smvu2_cluster, default, event_automation_replicated, rand());
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.event_confirmation ON CLUSTER smvu2_cluster AS default.event_confirmation_replicated
|
||||
ENGINE = Distributed(smvu2_cluster, default, event_confirmation_replicated, rand());
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.infi_clickhouse_orm_migrations ON CLUSTER smvu2_cluster AS default.infi_clickhouse_orm_migrations_replicated
|
||||
ENGINE = Distributed(smvu2_cluster, default, infi_clickhouse_orm_migrations_replicated, rand());
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.unchecked_event ON CLUSTER smvu2_cluster AS default.unchecked_event_replicated
|
||||
ENGINE = Distributed(smvu2_cluster, default, unchecked_event_replicated, rand());
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE TABLE default.unchecked_objects_event ON CLUSTER smvu2_cluster AS default.unchecked_objects_event_replicated
|
||||
ENGINE = Distributed(smvu2_cluster, default, unchecked_objects_event_replicated, rand());
|
||||
```
|
||||
|
||||
|
||||
### Решение проблемы размера таблицы
|
||||
#### 1. Используя ограничение отправляемых строк, прикладываю скрипт, который делает в автоматическом режиме
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Список таблиц для репликации
|
||||
TABLES=(
|
||||
api_request_log
|
||||
audit_new
|
||||
event
|
||||
event_automation
|
||||
event_confirmation
|
||||
event_objects
|
||||
infi_clickhouse_orm_migrations
|
||||
)
|
||||
|
||||
PASSWORD="q1"
|
||||
BATCH_SIZE=100000 # Размер порции для вставки
|
||||
MAX_THREADS=4 # Максимальное количество потоков для вставки
|
||||
|
||||
for table in "${TABLES[@]}"; do
|
||||
replicated_table="${table}_replicated"
|
||||
echo "Processing $table to $replicated_table"
|
||||
|
||||
# 1. Получаем общее количество строк
|
||||
total_rows=$(clickhouse-client --password "$PASSWORD" --query="
|
||||
SELECT count() FROM remote('localhost', 'default', '$table')")
|
||||
|
||||
echo "Total rows to copy: $total_rows"
|
||||
|
||||
# 2. Копируем данные порциями
|
||||
for ((offset=0; offset<total_rows; offset+=BATCH_SIZE)); do
|
||||
echo "Copying rows $((offset+1))-$((offset+BATCH_SIZE))..."
|
||||
|
||||
clickhouse-client --password "$PASSWORD" --query="
|
||||
INSERT INTO default.$replicated_table
|
||||
SELECT * FROM remote('localhost', 'default', '$table')
|
||||
LIMIT $BATCH_SIZE OFFSET $offset
|
||||
SETTINGS
|
||||
max_insert_threads=$MAX_THREADS,
|
||||
max_memory_usage='10Gi'"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error copying batch $((offset/BATCH_SIZE+1))"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# 3. Проверяем количество скопированных строк
|
||||
copied_rows=$(clickhouse-client --password "$PASSWORD" --query="
|
||||
SELECT count() FROM default.$replicated_table")
|
||||
|
||||
echo "Successfully copied $copied_rows/$total_rows rows from $table to $replicated_table"
|
||||
done
|
||||
```
|
||||
|
||||
#### 2. Копирование с помощью программы clickhouse-copier
|
||||
Создается конфиг подключения к кластеру (keeper)
|
||||
config.xml
|
||||
```xml
|
||||
<yandex>
|
||||
<logger>
|
||||
<level>warning</level>
|
||||
<log>/var/log/clickhouse-server/clickhouse-copier.log</log>
|
||||
<errorlog>/var/log/clickhouse-server/clickhouse-copier.err.log</errorlog>
|
||||
</logger>
|
||||
|
||||
<zookeeper>
|
||||
<!-- Для ClickHouse Keeper (рекомендуется) -->
|
||||
<node>
|
||||
<host>172.16.212.41</host>
|
||||
<port>9181</port>
|
||||
</node>
|
||||
</zookeeper>
|
||||
|
||||
<distributed_ddl>
|
||||
<path>/clickhouse/task_queue/ddl</path>
|
||||
</distributed_ddl>
|
||||
|
||||
<http_port>9999</http_port>
|
||||
</yandex>
|
||||
```
|
||||
|
||||
Создается папка tasks и там размещаются файлы для каждой таблицы, например api_request_log.xml
|
||||
```xml
|
||||
<yandex>
|
||||
<!-- Configuration of clusters as in an ordinary server config -->
|
||||
<remote_servers>
|
||||
<source_cluster>
|
||||
<shard>
|
||||
<internal_replication>true</internal_replication>
|
||||
<replica>
|
||||
<host>172.16.212.14</host>
|
||||
<port>9000</port>
|
||||
<user>default</user>
|
||||
<password>q1</password>
|
||||
<secure>0</secure>
|
||||
</replica>
|
||||
</shard>
|
||||
</source_cluster>
|
||||
|
||||
<destination_cluster>
|
||||
<shard>
|
||||
<internal_replication>true</internal_replication>
|
||||
<replica>
|
||||
<host>172.16.212.14</host>
|
||||
<port>9000</port>
|
||||
<user>default</user>
|
||||
<password>q1</password>
|
||||
<secure>0</secure>
|
||||
</replica>
|
||||
</shard>
|
||||
</destination_cluster>
|
||||
</remote_servers>
|
||||
|
||||
<!-- How many simultaneously active workers are possible. If you run more workers superfluous workers will sleep. -->
|
||||
<max_workers>2</max_workers>
|
||||
|
||||
<!-- Setting used to fetch (pull) data from source cluster tables -->
|
||||
<settings_pull>
|
||||
<readonly>1</readonly>
|
||||
</settings_pull>
|
||||
|
||||
<!-- Setting used to insert (push) data to destination cluster tables -->
|
||||
<settings_push>
|
||||
<readonly>0</readonly>
|
||||
</settings_push>
|
||||
|
||||
<!-- Common setting for fetch (pull) and insert (push) operations. Also, copier process context uses it.
|
||||
They are overlaid by <settings_pull/> and <settings_push/> respectively. -->
|
||||
<settings>
|
||||
<connect_timeout>3</connect_timeout>
|
||||
<!-- Sync insert is set forcibly, leave it here just in case. -->
|
||||
<insert_distributed_sync>1</insert_distributed_sync>
|
||||
</settings>
|
||||
|
||||
<tables>
|
||||
<!-- A table task, copies one table. -->
|
||||
<event>
|
||||
<!-- Source cluster name (from <remote_servers/> section) and tables in it that should be copied -->
|
||||
<cluster_pull>source_cluster</cluster_pull>
|
||||
<database_pull>default</database_pull>
|
||||
<table_pull>api_request_log</table_pull>
|
||||
|
||||
<!-- Destination cluster name and tables in which the data should be inserted -->
|
||||
<cluster_push>destination_cluster</cluster_push>
|
||||
<database_push>default</database_push>
|
||||
<table_push>api_request_log_replicated</table_push>
|
||||
|
||||
<engine>
|
||||
ENGINE = ReplicatedReplacingMergeTree(
|
||||
'/clickhouse/tables/{shard}/default/api_request_log_replicated',
|
||||
'{replica}',
|
||||
ver
|
||||
)
|
||||
PARTITION BY toYYYYMM(request_ts)
|
||||
ORDER BY uuid
|
||||
SETTINGS index_granularity = 8192;
|
||||
</engine>
|
||||
<sharding_key>rand()</sharding_key>
|
||||
</event>
|
||||
</tables>
|
||||
</yandex>
|
||||
```
|
||||
|
||||
В каждом файле меняется название базы в разделе **tables**
|
||||
После этого запускается копирование, где --task-path должен быть уникальным для каждой таблицы
|
||||
```bash
|
||||
clickhouse-copier --config config.xml --task-file ./tasks/api_request_log.xml --task-path /clickhouse/copier/task1
|
||||
```
|
||||
44
DevOps/Docker/converter.md
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: Конвертация строки в compose
|
||||
description:
|
||||
published: true
|
||||
date: 2025-06-17T09:20:55.103Z
|
||||
tags: docker
|
||||
editor: markdown
|
||||
dateCreated: 2025-06-17T09:20:07.483Z
|
||||
---
|
||||
|
||||
Я попал на сайт к какому-то девопсу, где были материалы по Playwright. Я немного походил по нему и набрёл на раздел DevTools (https://ray.run/tools). Он там собрал то ли свои, то ли просто open source инструменты для решения простых прикладных задач. Вроде ничего особенного, но некоторые вещи я просто не знал, что вообще существуют. Всегда их делал вручную.
|
||||
|
||||
Покажу сразу на примерах, что мне показалось полезным:
|
||||
|
||||
- Docker Run to Docker Compose Converter (https://ray.run/tools/docker-run-to-docker-compose)
|
||||
Отправляем в форму однострочник с docker run и получаем файл для docker compose. Вроде мелочь, но я всегда это делал вручную. Не думал, что кому-то придёт в голову написать конвертер.
|
||||
|
||||
- Docker Compose to Docker Run Converter (https://ray.run/tools/docker-compose-to-docker-run)
|
||||
И соответственно в обратную сторону преобразование из docker compose в однострочник для docker run. Не припоминаю, чтобы мне приходилось такие преобразования делать, но в тему к первому упоминаю.
|
||||
|
||||
- Bash Command Formatter (https://ray.run/tools/bash-command-formatter)
|
||||
Эта штука тоже очень понравилась. Она длинный однострочник разбивает на строки с переходами через \ То есть вот такую колбасу:
|
||||
```
|
||||
curl -v --url "smtp://mail.server.ru:25" --mail-from "root@server.ru" --mail-rcpt "user@gmail.com" --user 'root@server.ru:password123' --upload-file ~/mail.txt
|
||||
```
|
||||
Нарезает на кусочки:
|
||||
```
|
||||
curl -v \
|
||||
--url "smtp://mail.server.ru:25" \
|
||||
--mail-from "root@server.ru" \
|
||||
--mail-rcpt "user@gmail.com" \
|
||||
--user 'root@server.ru:password123' \
|
||||
--upload-file ~/mail.txt
|
||||
```
|
||||
Я тоже всегда это вручную делал, особенно для публикации сюда. Можно упростить себе задачу.
|
||||
|
||||
- URL Extractor (https://ray.run/tools/url-extractor)
|
||||
Просто кидаешь сюда любой текст, а на выходе получаешь набор ссылок, если они в нём присутствуют.
|
||||
|
||||
Там много всяких конвертеров и анализаторов синтаксиса для json, yaml, toml, csv. Не стал обращать на них внимание, так как их существует десятки. Обычно просто в гугле ищут что-то подобное, когда надо преобразовать. Посмотрите список, может вам что-то ещё приглянётся. Меня впечатлили только эти четыре штуки.
|
||||
|
||||

|
||||

|
||||
.jpg)
|
||||
49
DevOps/ELK/EFK-rotate.md
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
title: EFK - ротация логов fluent-bit
|
||||
description:
|
||||
published: true
|
||||
date: 2025-03-13T16:02:22.898Z
|
||||
tags: elk, efk, fluent-bit, rotate
|
||||
editor: markdown
|
||||
dateCreated: 2025-03-13T16:02:22.898Z
|
||||
---
|
||||
|
||||
# Ротация логов fluent-bit
|
||||
Не получилось сделать ротацию логов, если индекс имеет текущую дату, получилось с помощью порядокового номера
|
||||
|
||||
> Нужно в конфиге флюента в разделе [OUTPUT] сделать такие параметры:
|
||||
Logstash_Format Off
|
||||
Index smvu2-test-stand-docker
|
||||
|
||||
## Запросы в EFK:
|
||||
После запуска контейнера лог уже отправляется в EFK и создается индекс, поэтому нужно сначала его удалить
|
||||
```json
|
||||
DELETE /smvu2-test-stand-docker
|
||||
```
|
||||
Создаем шаблон
|
||||
```json
|
||||
PUT _index_template/smvu2-test-stand-docker-template
|
||||
{
|
||||
"index_patterns": [
|
||||
"smvu2-test-stand-docker-*"
|
||||
],
|
||||
"composed_of": ["smvu2-common-settings"],
|
||||
"template": {
|
||||
"settings": {
|
||||
"index.lifecycle.name": "smvu2-policy",
|
||||
"index.lifecycle.rollover_alias": "smvu2-test-stand-docker"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Ну и создаем индекс с алиасом, куда будет прилетать лог
|
||||
```json
|
||||
PUT smvu2-test-stand-docker-000001
|
||||
{
|
||||
"aliases": {
|
||||
"smvu2-test-stand-docker": {
|
||||
"is_write_index": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
146
DevOps/ELK/Rotation-logs-ILM.md
Normal file
@@ -0,0 +1,146 @@
|
||||
---
|
||||
title: Ротация логов с помощью Lificycle
|
||||
description: ILM
|
||||
published: true
|
||||
date: 2025-03-13T08:16:59.504Z
|
||||
tags: ilm, elk, efk
|
||||
editor: markdown
|
||||
dateCreated: 2025-03-13T08:16:59.504Z
|
||||
---
|
||||
|
||||
# Ротация логов в ELK
|
||||
Конечно! Давайте разберем настройку ротации логов с помощью ILM (Index Lifecycle Management) в Elasticsearch простым языком. Это пошаговая инструкция, которая поможет вам настроить автоматическое управление жизненным циклом индексов (логов).
|
||||
|
||||
---
|
||||
|
||||
### **1. Что такое ротация логов с ILM?**
|
||||
Ротация логов — это процесс автоматического создания новых индексов (например, когда текущий индекс становится слишком большим или старым) и удаления старых индексов, чтобы освободить место. ILM помогает автоматизировать этот процесс.
|
||||
|
||||
---
|
||||
|
||||
### **2. Основные шаги настройки ILM для ротации логов:**
|
||||
|
||||
#### **Шаг 1: Создайте алиас для индексов**
|
||||
Алиас — это "псевдоним", который будет указывать на текущий активный индекс. Все новые данные будут писаться в индекс, на который указывает этот алиас.
|
||||
|
||||
Пример:
|
||||
```bash
|
||||
PUT _aliases
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"add": {
|
||||
"index": "logs-2023.10.01-000001", # текущий индекс
|
||||
"alias": "logs-alias" # алиас
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **Шаг 2: Создайте политику ILM**
|
||||
Политика ILM определяет, что делать с индексами на разных этапах их жизни (например, когда переходить на новый индекс, когда удалять старые данные).
|
||||
|
||||
Пример политики:
|
||||
```bash
|
||||
PUT _ilm/policy/logs-policy
|
||||
{
|
||||
"policy": {
|
||||
"phases": {
|
||||
"hot": { # этап "горячих" данных
|
||||
"actions": {
|
||||
"rollover": { # ротация индекса
|
||||
"max_size": "50gb", # ротация при достижении 50 ГБ
|
||||
"max_age": "7d" # или через 7 дней
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": { # этап удаления
|
||||
"min_age": "30d", # удалить через 30 дней
|
||||
"actions": {
|
||||
"delete": {} # действие — удалить индекс
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **Шаг 3: Создайте шаблон индекса**
|
||||
Шаблон индекса автоматически применяет настройки (например, политику ILM и алиас) к новым индексам, которые соответствуют определенному шаблону имени.
|
||||
|
||||
Пример шаблона:
|
||||
```bash
|
||||
PUT _index_template/logs-template
|
||||
{
|
||||
"index_patterns": ["logs-*"], # шаблон имени индекса
|
||||
"template": {
|
||||
"settings": {
|
||||
"index.lifecycle.name": "logs-policy", # применяем политику ILM
|
||||
"index.lifecycle.rollover_alias": "logs-alias" # указываем алиас
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **Шаг 4: Создайте начальный индекс**
|
||||
Создайте первый индекс, который будет использоваться для записи данных. Убедитесь, что он соответствует шаблону и имеет алиас.
|
||||
|
||||
Пример:
|
||||
```bash
|
||||
PUT logs-2023.10.01-000001
|
||||
{
|
||||
"aliases": {
|
||||
"logs-alias": {} # назначаем алиас
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **Шаг 5: Настройте сбор логов**
|
||||
Убедитесь, что ваши логи (например, из Filebeat, Logstash или другого источника) пишутся в алиас `logs-alias`. Это гарантирует, что данные будут попадать в текущий активный индекс.
|
||||
|
||||
---
|
||||
|
||||
#### **Шаг 6: Проверка работы ILM**
|
||||
- Когда текущий индекс достигнет 50 ГБ или пройдет 7 дней, ILM создаст новый индекс (например, `logs-2023.10.08-000002`) и перенаправит запись на него.
|
||||
- Старые индексы будут автоматически удаляться через 30 дней.
|
||||
|
||||
---
|
||||
|
||||
### **3. Как проверить, что все работает?**
|
||||
- Проверьте статус ILM:
|
||||
```bash
|
||||
GET _ilm/status
|
||||
```
|
||||
- Посмотрите информацию по конкретному индексу:
|
||||
```bash
|
||||
GET logs-2023.10.01-000001/_ilm/explain
|
||||
```
|
||||
- Убедитесь, что новые индексы создаются, а старые удаляются.
|
||||
|
||||
---
|
||||
|
||||
### **4. Пример полного цикла:**
|
||||
1. Создаете алиас `logs-alias` и первый индекс `logs-2023.10.01-000001`.
|
||||
2. Данные начинают писаться в `logs-2023.10.01-000001`.
|
||||
3. Через 7 дней или при достижении 50 ГБ создается новый индекс `logs-2023.10.08-000002`, и данные начинают писаться туда.
|
||||
4. Через 30 дней индекс `logs-2023.10.01-000001` автоматически удаляется.
|
||||
|
||||
---
|
||||
|
||||
### **5. Частые ошибки:**
|
||||
- **Алиас не указан:** Убедитесь, что алиас указан в шаблоне индекса и в самом индексе.
|
||||
- **Политика не применяется:** Проверьте, что политика ILM указана в шаблоне индекса.
|
||||
- **Нет данных для ротации:** Убедитесь, что данные пишутся в алиас.
|
||||
|
||||
---
|
||||
|
||||
Если все настроено правильно, ILM будет автоматически управлять вашими индексами, и вам не придется вручную заниматься ротацией логов. 😊
|
||||
103
DevOps/Gitlab/Minimal-install.md
Normal file
@@ -0,0 +1,103 @@
|
||||
---
|
||||
title: Gitlab minimal install
|
||||
description:
|
||||
published: true
|
||||
date: 2025-03-25T18:40:52.824Z
|
||||
tags: gitlab
|
||||
editor: markdown
|
||||
dateCreated: 2025-03-25T18:39:58.350Z
|
||||
---
|
||||
|
||||
Популярный open source продукт, который можно развернуть на своём оборудовании, Gitlab требует для своей работы приличное количество ресурсов. Для того, чтобы он в установке по умолчанию работал бодрячком лучше всего начать с 4 CPU и 8 GB оперативной памяти. Можно выделить 4 GB, но будет заметно тормозить, иногда 500-е ошибки выдавать.
|
||||
|
||||
Для того, чтобы иметь возможность использовать Gitlab для единоличного использования, либо очень небольшого коллектива, многие из стандартных компонентов и настроек программного комплекса можно безболезненно отключить. В документации есть отдельная статья на этот счёт:
|
||||
|
||||
⇨ Running GitLab in a memory-constrained environment (https://docs.gitlab.com/omnibus/settings/memory_constrained_envs.html) (Запуск GitLab в среде с ограниченным объемом памяти)
|
||||
|
||||
Следуя этим рекомендация, можно заставить работать систему с использованием всего 2 GB оперативной памяти. Если вы запускаете его для себя на арендованном железе, то можно получить существенную экономию ресурсов.
|
||||
|
||||
Я взял виртуальную машину с 1 CPU и 2 GB памяти и попробовал на ней запустить Gitlab. Что для этого нужно сделать?
|
||||
|
||||
1️⃣ Подключаем 1 GB свопа.
|
||||
|
||||
```
|
||||
# dd if=/dev/zero of=/swap bs=1024 count=1000000
|
||||
# mkswap /swap
|
||||
# chmod 0600 /swap
|
||||
# swapon /swap
|
||||
```
|
||||
|
||||
Добавляем в /etc/fstab:
|
||||
`/swap swap swap defaults 0 0`
|
||||
|
||||
2️⃣ Меняем параметр swappiness:
|
||||
|
||||
`# sysctl vm.swappiness=10`
|
||||
|
||||
Добавляем в /etc/sysctl.conf:
|
||||
|
||||
`vm.swappiness=10`
|
||||
|
||||
3️⃣ Устанавливаем Gitlab.
|
||||
```
|
||||
# curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | bash
|
||||
# EXTERNAL_URL="http://10.20.1.36" apt-get install gitlab-ce
|
||||
````
|
||||
|
||||
4️⃣ Отключаем службу puma, которая помогает обрабатывает конкурентные запросы. Без большой нагрузки можно обойтись без неё. В /etc/gitlab/gitlab.rb добавляем:
|
||||
|
||||
`puma['worker_processes'] = 0`
|
||||
|
||||
5️⃣ Уменьшаем число фоновых процессов Sidekiq:
|
||||
|
||||
`sidekiq['concurrency'] = 10`
|
||||
|
||||
6️⃣ Оптимизируем Gitaly. Туда же в конфиг добавляем:
|
||||
```json
|
||||
gitaly['configuration'] = {
|
||||
concurrency: [
|
||||
{
|
||||
'rpc' => "/gitaly.SmartHTTPService/PostReceivePack",
|
||||
'max_per_repo' => 3,
|
||||
}, {
|
||||
'rpc' => "/gitaly.SSHService/SSHUploadPack",
|
||||
'max_per_repo' => 3,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
gitaly['env'] = {
|
||||
'GITALY_COMMAND_SPAWN_MAX_PARALLEL' => '2'
|
||||
}
|
||||
```
|
||||
|
||||
❗️Обращаю ваше внимание, что я убрал из этого раздела настройки, касающиеся cgroups. В инструкции судя по всему какая-то ошибка. Если их оставить, то сокет gitaly не поднимается. А в интерфейсе при создании каких-либо сущностей, например, нового проекта, вылетает 502 ошибка. И это не зависит от выделенных ресурсов.
|
||||
|
||||
7️⃣ Отключаем мониторинг:
|
||||
|
||||
`prometheus_monitoring['enable'] = false`
|
||||
|
||||
8️⃣ Уменьшаем потребление памяти процессам GitLab:
|
||||
```
|
||||
gitlab_rails['env'] = {
|
||||
'MALLOC_CONF' => 'dirty_decay_ms:1000,muzzy_decay_ms:1000'
|
||||
}
|
||||
|
||||
gitaly['env'] = {
|
||||
'MALLOC_CONF' => 'dirty_decay_ms:1000,muzzy_decay_ms:1000'
|
||||
}
|
||||
```
|
||||
|
||||
9️⃣ Перезапускаем Gitlab:
|
||||
|
||||
`# gitlab-ctl reconfigure`
|
||||
|
||||
🔟 Идём в веб интерфейс и отключаем в настройках мониторинга метрики Prometheus: Admin Area ⇨ Settings ⇨ Metrics and profiling ⇨ Metrics - Prometheus ⇨ отключаем Enable Prometheus Metrics.
|
||||
|
||||
После перезапуска Gitlab будет очень долго подниматься. Но в итоге заработает. Смотрим потребление памяти и проверяем, как всё работает:
|
||||
|
||||
`# free -h`
|
||||
|
||||
Более подробно всё это описано по ссылке в статье из начала заметки. Для комфортной работы лучше всё же добавить до 2CPU и 3GB памяти. Тогда всё это будет бодро работать с предложенными параметрами. Если этого не сделать, то иногда будете видеть 500-е ошибки.
|
||||
|
||||
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
|
||||
196
DevOps/Hashicorp-Vault/Gitlab-with-vault.md
Normal file
@@ -0,0 +1,196 @@
|
||||
---
|
||||
title: Vault через GitLab CI - Аутентификация и чтение секретов
|
||||
description:
|
||||
published: true
|
||||
date: 2024-08-01T14:48:58.749Z
|
||||
tags: vault, gitlab
|
||||
editor: markdown
|
||||
dateCreated: 2024-07-31T12:59:36.391Z
|
||||
---
|
||||
|
||||
|
||||
Источник: https://habr.com/ru/companies/nixys/articles/512754/
|
||||
Этот туториал демонстрирует пример аутентификации, конфигурации и чтения секретов с HashiCorp’s Vault через GitLab CI/CD.
|
||||
|
||||
**Требования**
|
||||
|
||||
Туториал предполагает, что вы знакомы с GitLab CI/CD и Vault.
|
||||
|
||||
Чтобы ему последовать, вам понадобятся:
|
||||
|
||||
- Аккаунт в GItLab
|
||||
- Запущенный Vault сервер и доступ для настройки аутентификации и создания ролей и политик.
|
||||
Для каждой задачи (job) генерируется свой уникальный токен JSON Web Token (JWT), доступный только как значение переменной окружения CI_JOB_JWT конкретной задачи. Данный JWT может быть использован для аутентификации в Vault при помощи метода JWT Auth.
|
||||
Пример того, как выглядит JWT в дешифрованном виде:
|
||||
```json
|
||||
{
|
||||
"jti": "c82eeb0c-5c6f-4a33-abf5-4c474b92b558", # Уникальный идентификатор токена
|
||||
"iss": "gitlab.example.com", # Issuer, т.е. домен вашего инстанса GitLab
|
||||
"iat": 1585710286, # Время выдачи
|
||||
"nbf": 1585798372, # Не валиден до
|
||||
"exp": 1585713886, # Не велиден после
|
||||
"sub": "22", # Subject (project id)
|
||||
"namespace_id": "1",
|
||||
"namespace_path": "mygroup",
|
||||
"project_id": "22",
|
||||
"project_path": "mygroup/myproject",
|
||||
"user_id": "42",
|
||||
"user_login": "myuser",
|
||||
"user_email": "myuser@example.com"
|
||||
"pipeline_id": "1212",
|
||||
"job_id": "1212",
|
||||
"ref": "auto-deploy-2020-04-01", # Название Git-refs для этой задачи
|
||||
"ref_type": "branch", # Тип Git-refs, это либо(branch) либо тег(tag)
|
||||
"ref_protected": "true" # true, если это ветка protected, иначе false
|
||||
}
|
||||
```
|
||||
|
||||
Токен кодируется по стандарту RS256 и подписывается приватным ключом OpenID Connect вашего GitLab инстанса, причем этот ключ периодически изменяется без вашего ведома. И, если приватный ключ был изменен, при cледующем запуске задания новый JWT будет подписан с новым ключом. Срок валидности токена будет устанавливаться в соотвествии с таймаутом вашего задания, а если он не задан, то срок валидности будет 5 минут.
|
||||
|
||||
Вы можете использовать этот JWT-токен и URL (https://gitlab.example.com/-/jwks) как конечную точку JWKS для аутентификации на Vault сервере, если для него настроен соответствующий метод JWT-аутентификации.
|
||||
|
||||
При настройке ролей в Vault, вы можете задавать значения bound_claims для сопоставления их с полями из JWT и, таким образом, дополнительно ограничить то, к каким секретам какой процесс CI будет иметь доступ.
|
||||
|
||||
Для получения доступа к Vault можно использовать либо его CLI, либо выполнять запросы к API (через curl или другой клиент).
|
||||
|
||||
**Пример**
|
||||
Предположим, у вас есть пароли для ваших баз данных, отличающиеся для production и staging окружений и они хранятся в Vault, который доступен по адресу http://vault.example.com:8200. Ваш пароль для stage это pa$$w0rd и real-pa$$w0rd для prod:
|
||||
```
|
||||
$ vault kv get -field=password secret/myproject/staging/db
|
||||
pa$$w0rd
|
||||
|
||||
$ vault kv get -field=password secret/myproject/production/db
|
||||
real-pa$$w0rd
|
||||
```
|
||||
Разрешим для нашего Vault-сервера метод аутентификации через JWT:
|
||||
```
|
||||
$ vault auth enable jwt
|
||||
Success! Enabled jwt auth method at: jwt/
|
||||
```
|
||||
Создаем policy, которые дают доступ на чтение к нужным нам секретам:
|
||||
```bash
|
||||
$ vault policy write myproject-staging - <<EOF
|
||||
# Policy name: myproject-staging
|
||||
#
|
||||
# Read-only permission on 'secret/data/myproject/staging/*' path
|
||||
path "secret/data/myproject/staging/*" {
|
||||
capabilities = [ "read" ]
|
||||
}
|
||||
EOF
|
||||
Success! Uploaded policy: myproject-staging
|
||||
|
||||
$ vault policy write myproject-production - <<EOF
|
||||
# Policy name: myproject-production
|
||||
#
|
||||
# Read-only permission on 'secret/data/myproject/production/*' path
|
||||
path "secret/data/myproject/production/*" {
|
||||
capabilities = [ "read" ]
|
||||
}
|
||||
EOF
|
||||
Success! Uploaded policy: myproject-production
|
||||
```
|
||||
Теперь нам нужны роли, которые будут связывать созданные политики с JWT-токенами.
|
||||
|
||||
Для stage под названием myproject-staging:
|
||||
```json
|
||||
$ vault write auth/jwt/role/myproject-staging - <<EOF
|
||||
{
|
||||
"role_type": "jwt",
|
||||
"policies": ["myproject-staging"],
|
||||
"token_explicit_max_ttl": 60,
|
||||
"user_claim": "user_email",
|
||||
"bound_claims": {
|
||||
"project_id": "22",
|
||||
"ref": "master",
|
||||
"ref_type": "branch"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
````
|
||||
И для production под названием myproject-production:
|
||||
```json
|
||||
$ vault write auth/jwt/role/myproject-production - <<EOF
|
||||
{
|
||||
"role_type": "jwt",
|
||||
"policies": ["myproject-production"],
|
||||
"token_explicit_max_ttl": 60,
|
||||
"user_claim": "user_email",
|
||||
"bound_claims_type": "glob",
|
||||
"bound_claims": {
|
||||
"project_id": "22",
|
||||
"ref_protected": "true",
|
||||
"ref_type": "branch",
|
||||
"ref": "auto-deploy-*"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
```
|
||||
В этом примере использовались bound_claims указывающие, что только JWT-токены с соответствующими значениями смогут пройти аутентификацию.
|
||||
|
||||
В сочетании с GitLab protected branches, можно разграничивать тех, кто может проходить аутентификацию и читать секреты.
|
||||
|
||||
Token_explicit_max_ttl определяет, что выпущенный Vault токен, после аутентификации имеет время жизни 60 секунд.
|
||||
|
||||
User_claim определяет имя пользователя, которое будет использовать Vault при успешной авторизации. (Прим. переводчика — В нашем случае "user_claim" = "user_email", то есть имя пользователя будет иметь значение user_email из JWT-токена. То есть определяться как (известный GitLab) email пользователя, запустившего задание.)
|
||||
|
||||
Параметр bound_claims_type задает формат значений bound_claims. Если он установлен в “glob”, то значения будут интерпретироваться в формате glob и * будет означать любое количество символов. (Прим. переводчика — Также доступно значение “string”, в этом случае данные будут хранится в формате строк и * будет означать только *.)
|
||||
Полный лист опций можно посмотреть в Vault’s Create Role documentation.
|
||||
|
||||
Предупреждение: обязательно устанавливайте либо project_id либо namespace_id, иначе любой токен, сгенерированный этим инстансом GitLab, сможет использовать эту роль.
|
||||
|
||||
Теперь зададим метод аутентификации через JWT:
|
||||
```
|
||||
$ vault write auth/jwt/config \
|
||||
jwks_url="https://gitlab.example.com/-/jwks" \
|
||||
bound_issuer="gitlab.example.com"
|
||||
```
|
||||
bound_issuer определяет, что только токены, выпущенные от имени домена gitlab.example.com (iss claim) могут использовать этот метод аутентификации, и в качестве точки валидации токена JWKS должна использоваться страница https://gitlab.example.com/-/jwks .
|
||||
|
||||
Полный список доступных опций можно посмотреть в Vault’s API documentation.
|
||||
|
||||
Теперь создадим джобу для master-ветки, у которой будут права на чтение secret/myproject/staging/, но при этом не будет прав на чтение secret/myproject/production/:
|
||||
```yaml
|
||||
read_secrets:
|
||||
script:
|
||||
# Проверяем имя ref джобы
|
||||
- echo $CI_COMMIT_REF_NAME
|
||||
# и является ли она protected
|
||||
- echo $CI_COMMIT_REF_PROTECTED
|
||||
# Адрес Vault может быть передан через переменную в CI
|
||||
- export VAULT_ADDR=http://vault.example.com:8200
|
||||
# Проходим аутентификацию и получаем токен. Время истечения жизни токена и другие
|
||||
# его параметры можно задать при конфигурации
|
||||
# JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
|
||||
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=myproject-staging jwt=$CI_JOB_JWT)"
|
||||
# Теперь используем VAULT_TOKEN для чтения секретов и сохранения их в перемнных окружения
|
||||
- export PASSWORD="$(vault kv get -field=password secret/myproject/staging/db)"
|
||||
# Используем секрет
|
||||
- echo $PASSWORD
|
||||
# Здесь получить секрет не получится, потому что роль myproject-staging не может
|
||||
# читать секреты из secret/myproject/production/*
|
||||
- export PASSWORD="$(vault kv get -field=password secret/myproject/production/db)"
|
||||
```
|
||||

|
||||
Следующее задание сможет пройти аутентификацию через роль myproject-production и прочитать секрет в /secret/myproject/production/:
|
||||
```yaml
|
||||
read_secrets:
|
||||
script:
|
||||
# Проверяем имя ref джобы
|
||||
- echo $CI_COMMIT_REF_NAME
|
||||
# и является ли она protected
|
||||
- echo $CI_COMMIT_REF_PROTECTED
|
||||
# Адрес Vault может быть передан через переменную в CI
|
||||
- export VAULT_ADDR=http://vault.example.com:8200
|
||||
# Проходим аутентификацию и получаем токен. Время истечения жизни токена и другие
|
||||
# его параметры можно задать при конфигурации
|
||||
# JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
|
||||
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=myproject-production jwt=$CI_JOB_JWT)"
|
||||
# Теперь используем VAULT_TOKEN для чтения секретов и сохранения их в перемнных окружения
|
||||
- export PASSWORD="$(vault kv get -field=password secret/myproject/production/db)"
|
||||
# Используем секрет
|
||||
- echo $PASSWORD
|
||||
```
|
||||

|
||||
На этом все, надеюсь данный туториал окажется вам полезен!
|
||||
|
||||
|
||||
317
DevOps/Hashicorp-Vault/Use-vault.md
Normal file
@@ -0,0 +1,317 @@
|
||||
---
|
||||
title: Используем vault
|
||||
description:
|
||||
published: true
|
||||
date: 2024-07-17T10:12:42.002Z
|
||||
tags:
|
||||
editor: markdown
|
||||
dateCreated: 2024-07-09T14:09:18.708Z
|
||||
---
|
||||
|
||||
# Используем Hashicorp Vault для хранения секретов
|
||||
**Источник:** https://habr.com/ru/articles/653927/
|
||||
|
||||
Методы авторизации
|
||||
Чаще всего в WEB-интерфейс мы авторизуемся либо через токен доступа, либо с помощью логина и пароля, которые могут быть внутренними или храниться на Radius или LDAP-сервере.
|
||||
|
||||
Авторизуемся в хранилище с помощью логина и пароля:
|
||||
|
||||
```
|
||||
$ vault login -method=userpass username=admin password=strongPASS
|
||||
```
|
||||
То же самое, но с использованием curl:
|
||||
|
||||
```
|
||||
$ curl --request POST --data '{"password": "strongPASS"}' http://vault_addr/v1/auth/userpass/login/admin
|
||||
```
|
||||
При использовании vault cli инструмента чаще всего применяется токен для авторизации в хранилище, который сохраняем в специальную переменную среды VAULT_TOKEN.
|
||||
```bash
|
||||
$ export VAULT_ADDR='http://10.10.10.10:8200/'
|
||||
$ export VAULT_TOKEN=<token>
|
||||
$ vault login [token=<token>]
|
||||
```
|
||||
|
||||
В последней команде опция token является не обязательной при условии, что мы установили VAULT_TOKEN в переменные окружения.
|
||||
|
||||
Для выполнения запросов через API из приложения или из утилиты curl используется все тот же токен. Либо с помощью нашей учетной записи мы генерируем новый коротко живущий токен и используем его. Все подробности по работе с токенами можно найти [тут](https://www.vaultproject.io/api/auth/token)
|
||||
|
||||
И еще один способ для взаимодействия с API – это авторизация через AppRole. Для того чтобы выполнить авторизацию в хранилище, нам нужно знать наш App-ID и Secret-ID. Что гораздо безопаснее, чем логин/пароль и токен доступа.
|
||||
|
||||
## Авторизация методом AppRole
|
||||
Вольный перевод документации гласит:
|
||||
|
||||
>Метод авторизации Approle позволяет компьютерам или приложениям проходить аутентификацию с помощью ролей, определенных Vault. Этот метод аутентификации ориентирован на автоматизированные рабочие процессы (машины и сервисы) и менее полезен для людей-операторов.
|
||||
AppRole представляет собой набор политик Vault и ограничений входа в систему, которые должны быть соблюдены для получения токена с этими политиками. AppRole может быть создан для конкретной машины или даже для конкретного пользователя на этой машине, или для службы, распределенной по машинам. Учетные данные, необходимые для успешного входа в систему, зависят от ограничений, установленных для AppRole.
|
||||
|
||||
## Конфигурация Vault
|
||||
Для того чтобы начать использовать данный метод, необходимо сперва настроить наше хранилище. Для этого выполним несколько простых команд.
|
||||
|
||||
Перед началом работы с хранилищем настроим параметры подключения к нему.
|
||||
|
||||
```
|
||||
$ export VAULT_ADDR=http://10.10.10.10:8200
|
||||
$ export VAULT_TOKEN=your_token_here
|
||||
```
|
||||
**Включаем нужный метод авторизации.**
|
||||
```
|
||||
$ vault auth enable approle
|
||||
```
|
||||
Затем добавим тестовые данные, именно с ними мы будем работать в будущем.
|
||||
```bash
|
||||
$ vault kv put secrets/demo/app/service db_name="users" username="admin" password="passw0rd"
|
||||
```
|
||||
Для дальнейшего конфигурирования данного метода авторизации можно использовать root token. Что само по себе не безопасно и не рекомендуется. Хорошей практикой является создавать отдельные учетные записи для каждого инженера или, например, включить авторизацию через LDAP.
|
||||
|
||||
Чтобы пользователь смог выполнять действия по дальнейшему конфигурированию, необходимо назначить для него следующую политику:
|
||||
```json
|
||||
# Mount the AppRole auth method
|
||||
path "sys/auth/approle" {
|
||||
capabilities = [ "create", "read", "update", "delete", "sudo" ]
|
||||
}
|
||||
|
||||
# Configure the AppRole auth method
|
||||
path "sys/auth/approle/*" {
|
||||
capabilities = [ "create", "read", "update", "delete" ]
|
||||
}
|
||||
|
||||
# Create and manage roles
|
||||
path "auth/approle/*" {
|
||||
capabilities = [ "create", "read", "update", "delete", "list" ]
|
||||
}
|
||||
|
||||
# Write ACL policies
|
||||
path "sys/policies/acl/*" {
|
||||
capabilities = [ "create", "read", "update", "delete", "list" ]
|
||||
}
|
||||
|
||||
# Write test data
|
||||
# Set the path to "secrets/data/demo/*" if you are running `kv-v2`
|
||||
path "secrets/demo/*" {
|
||||
capabilities = [ "create", "read", "update", "delete", "list" ]
|
||||
}
|
||||
```
|
||||
|
||||
Сделать это можно через веб-интерфейс или командную строку, останавливаться на этом сейчас не будем. В нашем примере все действия мы будем делать с помощью root токена. Хочу отметить, что делать так на боевых средах не стоит. Этот токен стоит хранить максимально надежно от посторонних глаз.
|
||||
|
||||
Перед тем как создать саму роль нам нужно определить для нее политику доступа. А именно, что и на каком уровне доступа мы можем делать в хранилище. В нашем случае разрешим читать созданный ранее секрет.
|
||||
```json
|
||||
$ vault policy write -tls-skip-verify app_policy_name -<<EOF
|
||||
# Read-only permission on secrets stored at 'secrets/demo/app/service'
|
||||
path "secrets/data/demo/app/service" {
|
||||
capabilities = [ "read" ]
|
||||
}
|
||||
EOF
|
||||
```
|
||||
Далее нам необходимо создать роль – ту самую роль, с помощью которой мы будем читать секреты:
|
||||
```bash
|
||||
$ vault write -tls-skip-verify auth/approle/role/my-app-role \
|
||||
token_policies="app_policy_name" \
|
||||
token_ttl=1h \
|
||||
token_max_ttl=4h \
|
||||
secret_id_bound_cidrs="0.0.0.0/0","127.0.0.1/32" \
|
||||
token_bound_cidrs="0.0.0.0/0","127.0.0.1/32" \
|
||||
secret_id_ttl=60m policies="app_policy_name" \
|
||||
bind_secret_id=false
|
||||
```
|
||||
Проверяем, что роль создалась успешно следующей командой:
|
||||
```
|
||||
$ vault read -tls-skip-verify auth/approle/role/my-app-role
|
||||
```
|
||||
Затем получаем role-id. Этот параметр нам пригодится для выполнения авторизации в хранилище.
|
||||
```
|
||||
$ vault read -tls-skip-verify auth/approle/role/my-app-role/role-id
|
||||
```
|
||||
Далее приведу небольшую выдержку вольного перевода из документации.
|
||||
|
||||
>RoleID - это идентификатор, который выбирает AppRole, по которому оцениваются другие учетные данные. При аутентификации в систему RoleID всегда является обязательным аргументом (через role_id). По умолчанию RoleID - это уникальные UUID, которые позволяют им служить вторичными секретами для другой информации об учетных данных. Однако они могут быть установлены на определенные значения, чтобы соответствовать интроспективной информации клиента (например, доменному имени клиента).
|
||||
|
||||
Теперь рассмотрим параметры, которые нам необходимы для создания роли.
|
||||
|
||||
* role_id – обязательные учетные данные в конечной точке входа. Для AppRole, на который указывает role_id будут наложены ограничения.
|
||||
|
||||
* bind_secret_id – требует обязательно или нет предоставлять secret_id в точке регистрации. Если значение будет true то Vault Agent не сможет авторизоваться. Параметр задается при создании роли.
|
||||
|
||||
Дополнительно можно настроить и другие ограничения для AppRole. Например, secret_id_bound_cidrs будет разрешено входить в систему только с IP-адресов, принадлежащих настроенным блокам CIDR на AppRole.
|
||||
|
||||
Документацию по AppRole API можно прочесть [тут](https://www.vaultproject.io/api/auth/approle)
|
||||
|
||||
## Использование
|
||||
Для авторизации можно использовать 2 метода. Первый метод заключается в передаче полного набора параметров необходимых для авторизации. Затем получение токена либо временно оборачивающего токена для того, чтобы получить основной токен. Как правило, оборачивающий токен делают коротко живущим, чтобы, например, произвести выкладку приложения на сервер и получить основной токен. Затем основной токен сохранить в память и использовать, в это время оборачивающий токен будет уже не валиден. И второй вариант более хитрый и более безопасный, который мы используем в нашей компании. Рассмотрим оба варианта подробнее.
|
||||
|
||||
### Вариант 1
|
||||
RoleID эквивалентен имени пользователя, а SecretID - соответствующему паролю. Приложению необходимо и то, и другое для входа в Vault. Естественно, следующий вопрос заключается в том, как безопасно доставить эти секреты клиенту.
|
||||
|
||||
Например, Ansible может использоваться как доверенный способ доставки RoleID в среду, где запускается приложение. Рисунок, взятый из официальной документации, показывает наглядно весь происходящий процесс.
|
||||

|
||||
|
||||
Для получения wrap token, который будет использоваться при авторизации и запросе secret-id, выполните команду:
|
||||
```
|
||||
$ vault write -wrap-ttl=600s -tls-skip-verify -force auth/approle/role/my-app-role/secret-id
|
||||
```
|
||||
Затем полученный файл необходимо поместить на файловую систему виртуальной машины, где запускается наше приложение. Этот путь должен совпадать с тем, который ожидает приложение. Полученный токен может быть использован лишь один раз. После запуска токен будет прочитан и использован для получения secret-id. После получения secret-id приложение может запросить данные из секретного хранилища Vault, пока не истек TTL для secret_id. Данный способ хорошо подходит в том случае, когда мы заполняем начальную конфигурацию приложения на этапе запуска. Например, применив паттерн Singleton, заполняем значениями структуру Config.
|
||||
|
||||
Рекомендации гласят, что wrap token должен иметь время жизни равное времени деплоя приложения. В то же время secret-id могут иметь длинное время жизни, но это не рекомендуется разработчиком Vault в силу большого потребления памяти и нагрузке при очистке истекших токенов. Лучшая рекомендация гласит, что нужно использовать короткое время жизни и постоянно продлевать его. Тем самым избегать дорогих операций авторизации и выдачи новых токенов.
|
||||
|
||||
### Вариант 2
|
||||
Для получения secret-id можно использовать vault-agent, который позволяет, зная только role-id, авторизоваться и получить token доступа в хранилище. При этом агент берет на себя функции по обновлению данного токена. Агент может поставлять как wrap token, так и готовый к использованию secret-id.
|
||||
|
||||
Подготовка конфигурации агента vault-agent.hcl. В данной конфигурации для демонстрации мы включим запись полученных токенов на диск. В результате мы получим два вида токена wrapped и уже готовый к применению обычный secret-id. Хочу отметить, что записывать токены на диск не обязательно.
|
||||
```json
|
||||
pid_file = "./pidfile"
|
||||
|
||||
auto_auth {
|
||||
mount_path = "auth/approle"
|
||||
method "approle" {
|
||||
config = {
|
||||
role_id_file_path = "./roleID"
|
||||
secret_id_response_wrapping_path = "auth/approle/role/my-app-role/secret-id"
|
||||
}
|
||||
}
|
||||
|
||||
sink {
|
||||
type = "file"
|
||||
wrap_ttl = "30m"
|
||||
config = {
|
||||
path = "./token_wrapped"
|
||||
}
|
||||
}
|
||||
|
||||
sink {
|
||||
type = "file"
|
||||
config = {
|
||||
path = "./token_unwrapped"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vault {
|
||||
address = "https://10.10.10.10:8200"
|
||||
}
|
||||
```
|
||||
Запускаем Vault Agent.
|
||||
```
|
||||
$ vault agent -tls-skip-verify -config=vault-agent.hcl -log-level=debug
|
||||
```
|
||||
После запуска агента на файловой системе появятся два файла согласно нашей конфигурации. Первый файл будет в json формате и содержать данные wrap token для получения secret-id. Второй файл будет содержать secret-id готовый к применению для авторизации. Агент берет на себя функционал по обновлению данных токенов.
|
||||
|
||||
Применение такой конфигурации оправданно, когда наше приложение постоянно читает или пишет данные в хранилище Vault. Ну и когда мы хотим обезопасить наши данные максимальным способом.
|
||||
|
||||
## От теории к практике
|
||||
В качестве примера мы попробуем сконфигурировать демо-приложение и сервер nginx. Для сокращения размера статьи я опущу некоторые подробности, но предоставлю ссылку на репозиторий , где можно все [посмотреть самому](https://gitlab.com/k11s-os/k8s-lessons/-/tree/main/Vault)
|
||||
|
||||
Vault для быстроты мы развернем в Kubernetes кластере. Можно использовать Minikube или Docker Desktop для Mac, включив там опцию Kubernetes Cluster. Все необходимые манифесты расположены в репозитории по ссылке выше в папке manifests.
|
||||
|
||||
Вы также можете запустить хранилище vault на своей рабочей машине. Для этого нужно скачать бинарный файл и запустить его.
|
||||
|
||||
Пишем демонстрационные данные в хранилище.
|
||||
```
|
||||
$ vault kv put secrets/demo/app/nginx responseText="Hello from Vault"
|
||||
```
|
||||
Создаем политику.
|
||||
```bash
|
||||
$ vault policy write -tls-skip-verify nginx_conf_demo -<<EOF
|
||||
# Read-only permission on secrets stored at 'secrets/demo/app/nginx'
|
||||
path "secrets/data/demo/app/nginx" {
|
||||
capabilities = [ "read" ]
|
||||
}
|
||||
EOF
|
||||
```
|
||||
Создаем роль.
|
||||
```bash
|
||||
$ vault write -tls-skip-verify auth/approle/role/nginx-demo \
|
||||
token_policies="nginx_conf_demo" \
|
||||
token_ttl=1h \
|
||||
token_max_ttl=4h \
|
||||
secret_id_bound_cidrs="0.0.0.0/0","127.0.0.1/32" \
|
||||
token_bound_cidrs="0.0.0.0/0","127.0.0.1/32" \
|
||||
secret_id_ttl=60m policies="nginx_conf_demo" \
|
||||
bind_secret_id=false
|
||||
```
|
||||
Получаем role-id.
|
||||
```
|
||||
$ vault read -tls-skip-verify auth/approle/role/nginx-demo/role-id
|
||||
```
|
||||
Далее в папке demo расположены манифесты. В папке nginx лежит все, что нужно для работы нашего примера. Также там есть еще папка app, которая запустит демонстрационное демо приложение, написанное на go, которое прочитает наши секреты, подготовленные в первой теоретической части.
|
||||
|
||||
Я лишь остановлюсь на пояснениях к манифестам для nginx.
|
||||
|
||||
Как мы можем увидеть из deployment, у нас несколько контейнеров.
|
||||
```yaml
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-autoreload
|
||||
labels:
|
||||
role: nginx-reload-test
|
||||
...
|
||||
|
||||
initContainers:
|
||||
- name: init-nginx-config
|
||||
image: vault:1.9.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
...
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.21.4-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
...
|
||||
- name: vault-agent-rerender
|
||||
image: vault:1.9.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
...
|
||||
volumes:
|
||||
- name: vault-nginx-template
|
||||
configMap:
|
||||
name: vault-nginx-template
|
||||
- name: vault-agent-config
|
||||
configMap:
|
||||
name: vault-agent-configs
|
||||
- name: nginx-rendered-conf
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
```
|
||||
Инит контейнер для нас генерирует изначальную конфигурацию, читая секретную строку и записывая ее в файл конфигурации nginx. Рабочий контейнер с nginx читает этот файл конфигурации и выводит в браузер секретную строку. И есть еще третий контейнер с вольтом, в котором происходит вся магия.
|
||||
|
||||
Вот самая интересная часть конфига:
|
||||
```json
|
||||
template {
|
||||
source = "/etc/vault/config/template/nginx/nginx.conf.tmpl"
|
||||
destination = "/etc/vault/config/render/nginx/nginx.conf"
|
||||
command = "ps ax | grep 'nginx: maste[r]' | awk '{print $1}' | xargs kill -s HUP"
|
||||
}
|
||||
template_config {
|
||||
static_secret_render_interval = "1m"
|
||||
}
|
||||
```
|
||||
Тут мы говорим агенту отслеживать изменения в хранилище раз в 1 минуту. Можно и реже, можно и чаще, зависит от ваших задач. Затем, если происходит рендер конфига, то мы выполняем следующую команду, а именно отправляем HUP мастер процессу nginx, и тот в свою очередь завершает активные подключения и запускает новый воркер с новой конфигурацией. Таким образом мы ее мягко перечитываем.
|
||||
|
||||
Теперь, если мы изменим нашу фразу в хранилище, то мы перезапишем конфиг и заставим nginx перечитать его и отдавать уже новые данные.
|
||||
|
||||
В качестве эксперимента с доступом из определенного CIDR в момент, когда ваше приложение работает, вы можете перезаписать роль, с которой авторизуется агент. Например, вот так:
|
||||
```bash
|
||||
$ vault write -tls-skip-verify auth/approle/role/nginx-demo \
|
||||
token_policies="nginx_conf_demo" \
|
||||
token_ttl=1h \
|
||||
token_max_ttl=4h \
|
||||
secret_id_bound_cidrs="192.168.17.0/24","127.0.0.1/32" \
|
||||
token_bound_cidrs="192.168.17.0/24","127.0.0.1/32" \
|
||||
secret_id_ttl=60m policies="nginx_conf_demo" \
|
||||
bind_secret_id=false
|
||||
```
|
||||
Заменив подсеть 0.0.0.0 на 192.168.17.0/24 или любую другую, в которой не запущено ваше приложение. После изменения политики агент больше не сможет авторизоваться в хранилище и получать данные. Чтобы проверить это, измените строку в секретах еще раз и посмотрите в логи агента. Там вы увидите сообщение о том, что авторизация невозможна.
|
||||
|
||||
# Выводы
|
||||
В чем же здесь заключается секрет? А вот в чем: при создании роли мы устанавливаем параметры secret_id_bound_cidrs и token_bound_cidrs, ограничивающие подсети, с которых мы можем получать secret-id и token. Иными словами, Vault будет отклонять запросы из других сетей и получить доступ к данным не получится. Для того чтобы сделать все по максимуму, при создании роли мы установим параметр bind_secret_id=false. Это позволит авторизоваться в хранилище, не передавая secret-id. Vault его получит за нас.
|
||||
|
||||
Таким образом получается, что для авторизации нашего приложения, нам необходим всего лишь один параметр - это role-id, который сам по себе не является секретным и его утечку в сеть можно пережить и ничего не менять в своей системе при условии, что вы настроили роль правильно и ограничили подсети, откуда этой ролью можно воспользоваться.
|
||||
|
||||
Хочется добавить одну важную особенность. Для того, чтобы получить доступ к хранилищу через AppRole, указав только role-id, нужно производить авторизацию через vault agent. На момент написания статьи библиотека для доступа к хранилищу для GO не поддерживала такой способ и требовала еще secret-id.
|
||||
|
||||
Следовательно, тут возникают архитектурные особенности построения приложений, которые в данной статье не рассматриваются. Но если быть кратким, то через агента можно заполнять env переменные для приложения и уже дальше работать с ними. Или же второй вариант - приложение само получает токен доступа при деплое через wrapped token и уже самостоятельно читает секреты из vault, имея на руках secret-id, который хранится в памяти и используется столько сколько нужно раз.
|
||||
|
||||
Из всего вышесказанного следует, что самый простой безопасный метод авторизации в хранилище это правильно настроенный AppRole. Именно этот метод мы используем в нашей компании для получения данных из хранилища. А уже дальше, по обстоятельствам, мы можем сохранять или передавать в приложения токен доступа к секретам, генерировать файлы конфигураций или устанавливать переменные среды для приложений.
|
||||
|
||||
Если вам понравилась статья и вы хотите продолжения, например, о том, как создать и работать с PKI, как мониторить и масштабировать кластер, как выполнять резервное копирование и восстановление, то поддержите нас лайком и непременно сообщите об этом в комментарии.
|
||||
|
||||
У вас появились вопросы по реализации данного метода авторизации? Не стесняйтесь, оставляйте их в комментариях. Если вы считаете другой способ более оптимальным поделитесь им в комментариях, читателям будет полезно знать несколько способов работы с секретами.
|
||||
333
DevOps/Hashicorp-Vault/Vault-cheat-sheet.md
Normal file
@@ -0,0 +1,333 @@
|
||||
---
|
||||
title: Vault Cheat Sheet
|
||||
description:
|
||||
published: true
|
||||
date: 2024-07-17T10:11:10.169Z
|
||||
tags: vault, cheat, sheet
|
||||
editor: markdown
|
||||
dateCreated: 2024-07-17T09:48:03.975Z
|
||||
---
|
||||
|
||||
# Vault Cheat Sheet
|
||||
|
||||
**Оригинал:** https://github.com/devops-cheat-sheets/vault-cheat-sheet?ysclid=lypnpval70181321372
|
||||
|
||||
|
||||
<h2>Vault Commands Cheat Sheet</h2>
|
||||
<h3>Secrets Management</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>vault kv put</code></td>
|
||||
<td>Создает или обновляет пару ключ-значение в секретном бэкэнде.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv get</code></td>
|
||||
<td>Извлекает значение определенного ключа в секретном бэкэнде.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv delete</code></td>
|
||||
<td>Удаляет пару ключ-значение из секретного бэкэнда.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv list</code></td>
|
||||
<td>Список всех ключей в секретном бэкэнде.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv metadata get</code></td>
|
||||
<td>Извлекает метаданные определенного ключа в секретном бэкэнде.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv metadata delete</code></td>
|
||||
<td>Удаляет метаданные определенного ключа в секретном бэкэнде.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv metadata list</code></td>
|
||||
<td>Содержит список метаданных для всех ключей в секретном бэкэнде.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv enable-versioning</code></td>
|
||||
<td>Включает управление версиями для секретного серверного модуля.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv disable-versioning</code></td>
|
||||
<td>Отключает управление версиями для секретного серверного модуля.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv undelete</code></td>
|
||||
<td>Восстанавливает удаленную пару ключ-значение в секретном бэкэнде.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv destroy</code></td>
|
||||
<td>Безвозвратно удаляет пару ключ-значение в секретном бэкэнде.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv undelete-metadata</code></td>
|
||||
<td>Восстанавливает метаданные удаленного ключа в секретном бэкэнде.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault kv destroy-metadata</code></td>
|
||||
<td>Безвозвратно удаляет метаданные ключа в секретном бэкэнде.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Authentication</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>vault login</code></td>
|
||||
<td>Аутентифицирует пользователя в Vault.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault logout</code></td>
|
||||
<td>Текущий аутентифицированный пользователь выходит из системы.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault token create</code></td>
|
||||
<td>Создает новый токен для аутентификации.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault token revoke</code></td>
|
||||
<td>Отзывает токен, делая его недействительным.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault token lookup</code></td>
|
||||
<td>Извлекает информацию о токене.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault token renew</code></td>
|
||||
<td>Продлевает аренду токена, продлевая срок его действия.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault token revoke-prefix</code></td>
|
||||
<td>Аннулирует все токены с заданным префиксом.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault auth enable</code></td>
|
||||
<td>Включает метод аутентификации в Vault.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault auth disable</code></td>
|
||||
<td>Отключает метод аутентификации в Vault.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault auth list</code></td>
|
||||
<td>Перечислены все разрешенные методы аутентификации в Vault.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Policies</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>vault policy write</code></td>
|
||||
<td>Создает или обновляет политику с указанным именем.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault policy read</code></td>
|
||||
<td>Извлекает содержимое политики.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault policy delete</code></td>
|
||||
<td>Удаляет политику.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault policy list</code></td>
|
||||
<td>Список всех политик в Vault.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault policy capabilities</code></td>
|
||||
<td>Отображает возможности политики.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault write auth/token/roles/my-role</code></td>
|
||||
<td>Создает или обновляет роль токена.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<td></td>
|
||||
</tr>
|
||||
<h3>Secrets Engines</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>vault secrets enable</code></td>
|
||||
<td>Включает механизм секретов в Vault.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault secrets disable</code></td>
|
||||
<td>Отключает движок секретов в Vault.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault secrets list</code></td>
|
||||
<td>Список всех включенных движков secrets в Vault.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault secrets tune</code></td>
|
||||
<td>Настраивает конфигурацию движка секретов.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault secrets move</code></td>
|
||||
<td>Переносит движок секретов с одного пути на другой.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault secrets migrate</code></td>
|
||||
<td>Переносит секреты из одного движка secrets engine в другой.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault secrets upgrade</code></td>
|
||||
<td>Обновление версии движка secrets engine.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault secrets path-help</code></td>
|
||||
<td>Отображает справочную информацию о пути к движку secrets engine.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Auditing and Logging</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>vault audit enable</code></td>
|
||||
<td>Позволяет устройству аудита в Vault регистрировать события.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault audit disable</code></td>
|
||||
<td>Отключает устройство аудита в Vault.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault audit list</code></td>
|
||||
<td>Список всех включенных устройств аудита в Vault.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault audit hash</code></td>
|
||||
<td>Хэширует единый файл журнала аудита для проверки целостности.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault audit recover</code></td>
|
||||
<td>Восстанавливает и воспроизводит журнал аудита по указанному пути.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault audit migrate</code></td>
|
||||
<td>Переносит устройства аудита с одного пути на другой.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault audit purge</code></td>
|
||||
<td>Удаляет файлы журнала аудита по указанному пути.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault monitor</code></td>
|
||||
<td>Отслеживает активность движков secrets и запросы на аутентификацию в режиме реального времени.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault read sys/audit-hash</code></td>
|
||||
<td>Извлекает текущий хэш файла журнала аудита.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Key Management</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>vault operator init</code></td>
|
||||
<td>Инициализирует новый экземпляр Vault общим общим ключом.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault operator unseal</code></td>
|
||||
<td>Распечатывает хранилище, предоставляя общий доступ к мастер-ключу.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault operator seal</code></td>
|
||||
<td>Запечатывает хранилище, делая его недоступным.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault operator rekey</code></td>
|
||||
<td>Повторно запускает Vault, меняя ключи шифрования.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault operator rotate</code></td>
|
||||
<td>Изменяет базовые ключи шифрования для механизма transit secrets engine.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault operator generate-root</code></td>
|
||||
<td>Генерирует новый токен root для аварийного восстановления.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Miscellaneous</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>vault status</code></td>
|
||||
<td>Отображает текущее состояние хранилища.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault version</code></td>
|
||||
<td>Отображает информацию о версии запущенного сервера Vault.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault list sys/mounts</code></td>
|
||||
<td>Перечисление всех смонтированных секретов серверных частей.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault auth token/lookup-self</code></td>
|
||||
<td>Извлекает информацию о текущем аутентифицированном токене.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault auth token/revoke-self</code></td>
|
||||
<td>Аннулирует текущий аутентифицированный токен.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault path-help</code></td>
|
||||
<td>Отображает справочную информацию для определенного пути к хранилищу.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>vault policy validate</code></td>
|
||||
<td>Проверяет синтаксис политики без ее сохранения.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
BIN
DevOps/Hashicorp-Vault/image-1.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
DevOps/Hashicorp-Vault/image-2.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
DevOps/Hashicorp-Vault/image-3.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
DevOps/Hashicorp-Vault/image-4.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
DevOps/Hashicorp-Vault/image-5.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
DevOps/Hashicorp-Vault/image-6.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
DevOps/Hashicorp-Vault/image.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
279
DevOps/Hashicorp-Vault/secure-use-vault.md
Normal file
@@ -0,0 +1,279 @@
|
||||
---
|
||||
title: Работа в vault
|
||||
description:
|
||||
published: true
|
||||
date: 2024-07-17T10:14:58.670Z
|
||||
tags:
|
||||
editor: markdown
|
||||
dateCreated: 2024-07-09T15:20:31.453Z
|
||||
---
|
||||
|
||||
# Безопасное использование секретов: шаблон для использования HashiCorp Vault
|
||||
**Источник:** https://habr.com/ru/articles/536694/
|
||||
|
||||
HashiCorp Vault — это инструмент с открытым исходным кодом, который обеспечивает безопасный и надежный способ хранения и распространения секретов, таких как ключи API, токены доступа и пароли. Программное обеспечение, такое как Vault, может быть критически важным при развертывании приложений, требующих использования секретов или конфиденциальных данных.
|
||||
|
||||
|
||||
Согласно недавнему исследованию ученых из Университета штата Северная Каролина, более 100 000 общедоступных репозиториев GitHub содержат открытые секреты приложений непосредственно в исходном коде. Это исследование — от частных токенов API до криптографических ключей — просканировало только около 13% общедоступных репозиториев GitHub — показывает, что надлежащая защита секретов приложений является одним из наиболее часто игнорируемых методов защиты информации в программном обеспечении.
|
||||
|
||||
|
||||
Хотя масштабы воздействия удивительны, важно отметить, что эта проблема затрагивает не только проекты с открытым исходным кодом. Даже частные репозитории исходного кода могут раскрывать секреты, если они не защищены должным образом. Возьмем, к примеру, нарушение безопасности в Buffer Inc. в 2013 году. То, что начиналось как незаконный доступ к собственному исходному коду Buffer, привело к утечке учетных данных Twitter API компании, что в конечном итоге привело к рассылке спама в учетных записях Twitter бесчисленных клиентов.
|
||||
|
||||
|
||||
Я не собираюсь угнетать Buffer прямо сейчас. Компании взламывают каждый день, и Buffer дал первоклассный ответ. Их нефильтрованная прозрачность и информирование об инцидентах послужили интересным примером важности управления секретами как основного принципа информационной безопасности. Но это также поднимает вопрос о том, как лучше всего управлять секретами в растущей, масштабируемой организации.
|
||||
|
||||
|
||||
## Введение в HashiCorp Vault
|
||||
|
||||
Я большой поклонник HashiCorp. Их подход к инструментам DevOps, не зависящий от поставщика, предоставляет отличные портативные решения, которые абстрагируются от отдельных поставщиков облачных услуг и фокусируются на решении реальных проблем. Их инструмент управления секретами, Vault, не исключение.
|
||||
|
||||
|
||||
В то время как каждый отдельный поставщик облачных услуг имеет собственное решение для управления секретами, Vault является независимым от поставщика решением, которое позволяет централизованно управлять и обеспечивать доступ к секретам приложений без учета базового механизма секретов или методов аутентификации.
|
||||
|
||||
|
||||
# Установка Vault
|
||||
[Скачать Vault — Vault от HashiCorp](https://www.vaultproject.io/downloads.html)
|
||||
Прежде чем мы сможем начать работу с Vault, нам сначала нужно его установить. Как и все продукты HashiCorp, Vault кроссплатформенный, с поддержкой macOS, Windows, Linux, Solaris и даже BSD. Вы даже можете запустить его на Raspberry Pi.
|
||||
|
||||
|
||||
## Запуск сервера
|
||||
|
||||
После установки Vault нам нужно запустить наш сервер. В этой статье я буду работать только с сервером разработки Vault. Однако важно отметить, что сервер разработки невероятно небезопасен и хранит все данные в памяти, а это означает, что при его перезапуске все будет потеряно.
|
||||
|
||||
По словам самих HashiCorp:
|
||||
Сервер разработки следует использовать для экспериментов с функциями Vault, такими как: различные методы аутентификации, механизмы секретов, устройства аудита и т. д.
|
||||
|
||||
|
||||
Чтобы запустить сервер разработки, просто запустите команду vault server -dev (-dev указывает, что мы должны запускать сервер разработки, а не рабочий сервер):
|
||||
|
||||
```bash
|
||||
$ vault server -dev
|
||||
==> Vault server configuration:
|
||||
|
||||
Api Address: http://127.0.0.1:8200
|
||||
Cgo: disabled
|
||||
Cluster Address: https://127.0.0.1:8201
|
||||
Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
|
||||
Log Level: info
|
||||
Mlock: supported: false, enabled: false
|
||||
Storage: inmem
|
||||
Version: Vault v1.2.1
|
||||
|
||||
WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
|
||||
and starts unsealed with a single unseal key. The root token is already
|
||||
authenticated to the CLI, so you can immediately begin using Vault.
|
||||
|
||||
You may need to set the following environment variable:
|
||||
|
||||
$ export VAULT_ADDR='http://127.0.0.1:8200'
|
||||
|
||||
The unseal key and root token are displayed below in case you want to seal/unseal the Vault or re-authenticate.
|
||||
|
||||
Unseal Key: p8MumXfy57bh2T1FxdvZSmHhxqr7aQAByPpfE4PLujk=
|
||||
Root Token: s.aSQmpEYEi5MKelf5TDLPC6r9
|
||||
|
||||
Development mode should NOT be used in production installations!
|
||||
|
||||
==> Vault server started! Log data will stream in below:
|
||||
```
|
||||
Как видите, на экран выводится много данных, с которыми вы можете поиграть. Прежде всего следует отметить, что сервер разработки по умолчанию не запускается как демон (и в целях тестирования, никогда не должен запускаться как демон). Следовательно, если вы хотите взаимодействовать с сервером, вы должны сначала открыть второе окно терминала и экспортировать предоставленную переменную среды VAULT_ADDR, чтобы команда Vault хранилища знала, с каким сервером она должна взаимодействовать.
|
||||
|
||||
|
||||
Также важно отметить значения Unseal Key и Root Token. Хотя мы коснемся того, что делать с Root Token в следующем разделе, понимание запечатывания / распечатывания Vault имеет решающее значение для правильного развертывания Vault в производственной среде.
|
||||
|
||||
|
||||
## Расшифровка и аутентификация
|
||||
|
||||
В производственной среде сервер Vault запускается в закрытом состоянии. Это означает, что Vault знает, где находятся данные, но не знает, как их расшифровать. На сервере разработки Vault по умолчанию не запечатан (unsealed). Однако, если вы решите запечатать его, вы получите ключ распечатки (Unseal Key), чтобы распечатать (unseal) его. Незапечатанный Vault остается в этом состоянии до тех пор, пока оно не будет повторно запечатано или сам сервер не будет перезапущен.
|
||||
|
||||
При первом запуске производственного сервера Vault важно его инициализировать. Этот процесс сгенерирует ключи шифрования и начальный корневой токен, и его можно будет запустить только с новыми хранилищами без каких-либо данных:
|
||||
|
||||
```bash
|
||||
$ vault operator init
|
||||
|
||||
Unseal Key 1: 4jYbl2CBIv6SpkKj6Hos9iD32k5RfGkLzlosrrq/JgOm
|
||||
Unseal Key 2: B05G1DRtfYckFV5BbdBvXq0wkK5HFqB9g2jcDmNfTQiS
|
||||
Unseal Key 3: Arig0N9rN9ezkTRo7qTB7gsIZDaonOcc53EHo83F5chA
|
||||
Unseal Key 4: 0cZE0C/gEk3YHaKjIWxhyyfs8REhqkRW/CSXTnmTilv+
|
||||
Unseal Key 5: fYhZOseRgzxmJCmIqUdxEm9C3jB5Q27AowER9w4FC2Ck
|
||||
|
||||
Initial Root Token: s.KkNJYWF5g0pomcCLEmDdOVCW
|
||||
|
||||
Vault initialized with 5 key shares and a key threshold of 3. Please securely distribute the key shares printed above. When the Vault is re-sealed, restarted, or stopped, you must supply at least 3 of these keys to unseal it before it can start servicing requests.
|
||||
|
||||
Vault does not store the generated master key. Without at least 3 keys to reconstruct the master key, Vault will remain permanently sealed!
|
||||
|
||||
It is possible to generate new unseal keys, provided you have a quorum of existing unseal keys shares. See "vault operator rekey" for more information.
|
||||
```
|
||||
## Вход в систему
|
||||
|
||||
Когда сервер запущен, следующее, что нам нужно сделать, это войти в него. Это можно сделать с помощью команды vault login, которая запросит токен аутентификации. При первоначальной настройке вы можете пройти аутентификацию с помощью Root Token (см. Выше). Однако в производственной среде базовые методы аутентификации можно изменить, чтобы обеспечить более точный контроль над тем, кто имеет доступ и почему:
|
||||
|
||||
```bash
|
||||
$ vault login
|
||||
Token (will be hidden):
|
||||
Success! You are now authenticated. The token information displayed below is already stored in the token helper. You do NOT need to run "vault login" again. Future Vault requests will automatically use this token.
|
||||
|
||||
Key Value
|
||||
--- -----
|
||||
token s.aSQmpEYEi5MKelf5TDLPC6r9
|
||||
token_accessor MaJhao2R54EdV9fDq7sL11d4
|
||||
token_duration ∞
|
||||
token_renewable false
|
||||
token_policies ["root"]
|
||||
identity_policies []
|
||||
policies ["root"]
|
||||
```
|
||||
|
||||
## Хранение секретов
|
||||
|
||||
В то время как Vault HashiCorp можно использовать для безопасного хранения практически любых данных, наиболее распространенным вариантом использования Vault является хранилище ключей и значений для секретов приложений. После проверки подлинности хранение секретов становится невероятно простым благодаря команде vault kv put:
|
||||
|
||||
```bash
|
||||
$ vault kv put secret/foo bar=baz
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-08-09T16:43:10.604124Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
version 1
|
||||
```
|
||||
Чтобы немного разобрать приведенную выше команду и ответ, мы создали новый секрет с именем foo в пространстве имен secret со значением bar=baz, ответ дает нам некоторые базовые метаданные о нашем новом секрете. Хотя ключи created_time, deletion_time и destroyed не требуют пояснений, вам следует обратить особое внимание на ключ version, потому что это подразумевает, что секреты могут быть версированы.
|
||||
|
||||
|
||||
Например, давайте посмотрим, что произойдет, если мы введем новое значение для того же секрета:
|
||||
|
||||
```bash
|
||||
$ vault kv put secret/foo bat=ball
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-08-09T16:43:32.638788Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
version 2
|
||||
```
|
||||
Видите, как был увеличен ключ метаданных версии? Это означает, что наше исходное значение должно поддерживаться в дополнение к новым значениям, что обеспечивает отличный журнал аудита того, какие секреты были изменены и когда.
|
||||
|
||||
|
||||
## Извлечение секретов
|
||||
```bash
|
||||
$ vault kv list secret
|
||||
Keys
|
||||
----
|
||||
foo
|
||||
```
|
||||
Хранение секретов — это только половина дела. Другая половина — извлекать эти секреты. В нашем примере выше давайте сначала посмотрим, как получить весь список секретов:
|
||||
|
||||
Как видите, хотя технически мы помещаем два секрета, отслеживается только один ключ, потому что эти два секрета на самом деле являются всего лишь двумя версиями одного секрета. Чтобы получить его, выполните команду vault kv get с секретным пространством имен и ключом:
|
||||
|
||||
```bash
|
||||
$ vault kv get secret/foo
|
||||
====== Metadata ======
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-08-09T16:43:32.638788Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
version 2
|
||||
|
||||
=== Data ===
|
||||
Key Value
|
||||
--- -----
|
||||
bat ball
|
||||
```
|
||||
|
||||
По умолчанию Vault будет извлекать самую последнюю версию секрета, но если мы хотим получить предыдущую версию, можно использовать директиву -version:
|
||||
|
||||
```bash
|
||||
$ vault kv get -version=1 secret/foo
|
||||
====== Metadata ======
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-08-09T16:43:10.604124Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
version 1
|
||||
|
||||
=== Data ===
|
||||
Key Value
|
||||
--- -----
|
||||
bar baz
|
||||
```
|
||||
|
||||
Ценность секретов с управлением версиями невероятна, поскольку они позволяют внутренним службам привязаться к различным секретным версиям, что дает возможность постепенно развиваться, выпускать (release) и откатывать изменения приложений, не опасаясь потери важных данных.
|
||||
|
||||
## Удаление секретов
|
||||
|
||||
Несмотря на преимущества контроля секретами, нам может понадобится фактическое удаление секрета (или его версии). Это можно сделать двумя способами, в зависимости от того, насколько «удаленным» вы хотите, чтобы секрет был: удалить delete и уничтожить destroy. Чтобы проиллюстрировать это, давайте сначала рассмотрим удаление версии нашего секрета foo:
|
||||
|
||||
```bash
|
||||
$ vault kv delete -versions=1 secret/foo
|
||||
Success! Data deleted (if it existed) at: secret/foo
|
||||
```
|
||||
|
||||
Это помечает данные как удаленные (deleted) и предотвращает их извлечение в обычных запросах GET, но фактически не удаляет данные:
|
||||
|
||||
```bash
|
||||
$ vault kv get -version=1 secret/foo
|
||||
====== Metadata ======
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-08-09T16:43:10.604124Z
|
||||
deletion_time 2019-08-09T16:45:39.664577Z
|
||||
destroyed false
|
||||
version 1
|
||||
```
|
||||
|
||||
Чтобы данные действительно были удалены без возможности восстановления, необходимо использовать команду destroy:
|
||||
|
||||
```bash
|
||||
$ vault kv destroy -versions=1 secret/foo
|
||||
Success! Data written to: secret/destroy/foo
|
||||
```
|
||||
|
||||
Вместо того, чтобы просто пометить данные как удаленные и ограничить доступ к ним, команда destroy удалит их полностью, что сделает невозможным последующее извлечение:
|
||||
|
||||
```bash
|
||||
$ vault kv get -version=1 secret/foo
|
||||
====== Metadata ======
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-08-09T16:43:10.604124Z
|
||||
deletion_time 2019-08-09T16:45:39.664577Z
|
||||
destroyed true
|
||||
version 1
|
||||
```
|
||||
# Копаем глубже в HashiCorp Vault
|
||||
|
||||
Vault — сложный инструмент, и управление такими секретами — это лишь малая часть того, что можно с его помощью сделать. Хотя тонкости Vault выходят далеко за рамки этой статьи, давайте коснемся лишь нескольких других концепций, которые делают Vault таким мощным.
|
||||
|
||||
## Secrets engines
|
||||
```bash
|
||||
$ vault secrets enable database
|
||||
Success! Enabled the database secrets engine at: database/
|
||||
```
|
||||
|
||||
Хранилище ключей и значений по умолчанию в Vault является примером механизма секретов (в частности, механизма под названием kv). По своей сути алгоритм секретов — это абстрактный механизм хранения секретных данных. Это означает, что вместо механизма хранения на основе ключа-значения можно использовать более целевые механизмы хранения. Например, механизм секретов базы данных может использоваться для динамического генерирования учетных данных базы данных (database) на основе настроенных ролей для MySQL и MariaDB, что позволяет производить автоматическую ротацию учетных данных root или даже временные учетные данные для доступа по запросу.
|
||||
|
||||
|
||||
## Методы аутентификации
|
||||
|
||||
```bash
|
||||
$ vault auth enable github
|
||||
Success! Enabled github auth method at: github/
|
||||
```
|
||||
|
||||
В дополнение к стандартному методу аутентификации на основе токенов Vault поддерживает ряд дополнительных методов аутентификации для лучшей поддержки ваших вариантов использования. Отличным примером этого является метод проверки подлинности GitHub, который можно использовать для автоматического предоставления доступа к Vault разработчикам, принадлежащим к определенной организации GitHub — и даже к определенной группе внутри организации GitHub — с использованием только токена личного доступа. Для более крупных организаций решения единого входа на уровне предприятия, такие как LDAP или Okta, могут использоваться для аутентификации пользователей в Vault.
|
||||
|
||||
## Авторизация
|
||||
```bash
|
||||
$ vault write auth/userpass/users/test policies="dev-readonly,logs"
|
||||
```
|
||||
|
||||
Авторизация всегда идет рука об руку с аутентификацией. Хотя предоставить глобальный доступ с помощью GitHub или аутентификации на основе токенов несложно, это почти никогда не бывает полным решением. Благодаря политике Vault может быть реализован метод авторизации в стиле RBAC, предоставляющий разным пользователям и группам CRUD-подобный доступ к различным аспектам самого хранилища. В сочетании с одним из более продвинутых методов аутентификации это может стать невероятно мощным инструментом для детального контроля доступа в большой организации.
|
||||
|
||||
# За пределами Vault
|
||||
|
||||
Каким бы мощным ни было Vault, настроить его правильно довольно сложно. Хотя размер и объем различных методов проверки подлинности и механизмов секретов ясно показывают, сколько вы можете сделать с Vault, может быть сложным осмыслить основы управления секретами в контексте информационной безопасности исходного кода. Благодаря впечатляюще большому количеству как официальных, так и общественных библиотек API, получение секретов безопасным способом невероятно просто, и если вы стремитесь стать опытным пользователем Vault, собственная учебная программа Vault HashiCorp – отличный способ для начала изучения.
|
||||
|
||||
Помимо безопасности приложений и инфраструктуры, вам нужен план быстрого реагирования на инциденты. Ознакомьтесь с нашим бесплатным руководством «От реактивного к упреждающему: 6 способов трансформации вашего мониторинга и реагирования на инциденты» для создания прозрачных рабочих процессов управления инцидентами с высокой степенью совместной работы.
|
||||
93
DevOps/Hashicorp-Vault/vault-policy.md
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
title: Политики vault
|
||||
description:
|
||||
published: true
|
||||
date: 2024-07-17T10:13:17.528Z
|
||||
tags: vault, policy
|
||||
editor: markdown
|
||||
dateCreated: 2024-07-09T14:09:25.393Z
|
||||
---
|
||||
|
||||
# Vault policy
|
||||
https://www.vaultproject.io/docs/concepts/policies.html
|
||||
По-умолчанию, применяется модель «Все что не разрешено, то запрещено», то есть для доступа пользователей или группы над явно прописывать доступы к нужным SecretEngine либо на более глубокий уровень.
|
||||
|
||||
Выдача доступа к SecretEngine строится по логике
|
||||
|
||||
* Создаем политику и определяем уровни доступа
|
||||
* Подключаем пользователя или группу к политике
|
||||
|
||||
**Проверить текущие политики**
|
||||
```
|
||||
vault policy list
|
||||
```
|
||||
|
||||
**Чтение содержимого политики**
|
||||
```
|
||||
vault policy read app-policy
|
||||
```
|
||||
|
||||
**Создание политики**
|
||||
Удобнее политику создавать через GUI, чем через консоль и файл.
|
||||
Пример политики
|
||||
```json
|
||||
path "examplestorage/" {
|
||||
capabilities = ["create", "read", "list"]
|
||||
}
|
||||
path "examplestorage/hello" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
path "examplestorage/ansible/*"
|
||||
{
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
}
|
||||
```
|
||||
**Подключение политики к пользователю**
|
||||
Политику можно назначить, в момент создания пользователя — за это отвечает ключ `-policy=policy_name`
|
||||
|
||||
Либо подключить к уже созданному, например пользователю vasy, который входит по логину и паролю, мы подключаем политику «my-policy«
|
||||
|
||||
**ВАЖНО**: Tсли мы хотим назначить сразу несколько политик, надо их все перечислить через запятую, иначе my-policy перезатрет все остальные политики
|
||||
```
|
||||
vault write auth/userpass/users/vasy policies="my-policy"
|
||||
```
|
||||
**Несколько политик:**
|
||||
```
|
||||
vault write auth/userpass/users/vasy policies="my-policy","policy2"
|
||||
```
|
||||
|
||||
## Подключение политики к LDAP группе
|
||||
```
|
||||
vault write auth/ldap/groups/ldap-group-name policies="example-policy"
|
||||
```
|
||||
**Узнать какие политики назначены на пользователя**
|
||||
Например пользователю vasy, который входит по логину и паролю
|
||||
```
|
||||
vault read auth/userpass/users/vasy
|
||||
```
|
||||
|
||||
**Узнать какие политики назначены на LDAP группу**
|
||||
```
|
||||
vault read auth/ldap/groups/groupname
|
||||
```
|
||||
|
||||
**Узнать какие политики назначены на пользователя при входе**
|
||||
Видно в выводе при входе
|
||||
```bash
|
||||
vault login -method=ldap username=username
|
||||
Password (will be hidden):
|
||||
Success! You are now authenticated. The token information displayed below
|
||||
is already stored in the token helper. You do NOT need to run "vault login"
|
||||
again. Future Vault requests will automatically use this token.
|
||||
|
||||
Key Value
|
||||
--- -----
|
||||
token s.bwcvQFpodcXWrRiOYxLO80RI
|
||||
token_accessor 6Ypav42huMYvQfccWYK6CNH0
|
||||
token_duration 10h
|
||||
token_renewable true
|
||||
token_policies ["default" "example-policy"]
|
||||
identity_policies []
|
||||
policies ["default" "example-policy"]
|
||||
token_meta_username username
|
||||
```
|
||||
338
DevOps/Hashicorp-Vault/vault-postgresql-users.md
Normal file
@@ -0,0 +1,338 @@
|
||||
---
|
||||
title: PostgreSQL через Vault - управление динамическими учетными записями
|
||||
description:
|
||||
published: true
|
||||
date: 2024-08-01T15:52:14.268Z
|
||||
tags: vault, postgresql
|
||||
editor: markdown
|
||||
dateCreated: 2024-08-01T14:55:31.582Z
|
||||
---
|
||||
|
||||
# Управление динамическими учетными записями в PostgreSQL через Hashicorp Vault
|
||||
|
||||
>В инструкции мы рассмотрим процесс хранения учетной записи PostgreSQL в хранилище секретов Hashicorp Vault, используя механизм database, с возможностью автоматической смены секрета в СУБД при его смене в Vault. Также мы настроим Vault для создания временных учетных записей в PostgreSQL.
|
||||
|
||||
|
||||
## Настройка прав PostgreSQL
|
||||
|
||||
На сервере PostgreSQL нам необходимо:
|
||||
|
||||
- Задать пароль для пользователя postgres.
|
||||
- Создать пользователя, пароль для которого мы будем хранить в Vault.
|
||||
- Разрешить подключение к базе данных для postgres и созданного пользователя.
|
||||
- Открыть порт 5432 для удаленного подключения.
|
||||
- Проверить доступы.
|
||||
|
||||
Рассмотрим действия по шагам.
|
||||
|
||||
### Задаем пароль для postgres
|
||||
Данные действия необходимы, если мы не задавали пароль для пользователя postgres или мы не знаем данный пароль.
|
||||
>Стоит иметь ввиду, что данный пользователь может использоваться другими приложениями — таким образом, смена пароля приведет к потере их работоспособности. В этом случае, стоит уточнить текущий пароль и использовать его.
|
||||
|
||||
Заходим под пользователем postgres и подключаемся к СУБД:
|
||||
```
|
||||
su - postgres
|
||||
$ psql
|
||||
```
|
||||
|
||||
Вводим:
|
||||
```
|
||||
=# ALTER USER postgres PASSWORD 'qwerty123';
|
||||
```
|
||||
*в данном примере мы задаем пароль qwerty123 для пользователя postgres.*
|
||||
|
||||
### Создаем нового пользователя
|
||||
На данном шаге мы создадим пользователя, для которого и будем хранить секрет в Vault. В рамках примера мы не будем его предоставлять никаких доступов. Для нас достаточно, чтобы мы могли подключиться и удостовериться, что пароль будет меняться.
|
||||
|
||||
В той же командной оболочке postgresql вводим:
|
||||
```
|
||||
=# CREATE USER ksu WITH PASSWORD 'qwerty123';
|
||||
```
|
||||
*с помощью данной команды мы создадим пользователя ksu с паролем qwerty123.*
|
||||
|
||||
### Разрешаем подключение к СУБД
|
||||
Нам необходимо разрешить подключаться к базе данных пользователю ksu (создали на шаге 2) с локального компьютера и пользователю postgres с сервера Vault. Это делается посредством редактирования файла pg_hba.conf.
|
||||
|
||||
Но размещение этого файла может быть разным — это зависит от версии установленного PostgreSQL. Вводим команду:
|
||||
```
|
||||
=# SHOW config_file;
|
||||
```
|
||||
Данная команда нам покажет место размещения конфигурационного файла postgresql.conf — в этом же каталоге находятся и другие конфигурационные файлы. Например, если команда показала:
|
||||
```
|
||||
----------------------------------------
|
||||
/etc/postgresql/11/main/postgresql.conf
|
||||
(1 row)
|
||||
```
|
||||
... то значит нужный нам файл в каталоге /etc/postgresql/11/main/.
|
||||
|
||||
Выходим из командной оболочки psql:
|
||||
```
|
||||
=# \q
|
||||
```
|
||||
Разлогиниваемся из-под пользователя postgres:
|
||||
```
|
||||
$ exit
|
||||
```
|
||||
И вводим:
|
||||
```
|
||||
vi /etc/postgresql/11/main/pg_hba.conf
|
||||
```
|
||||
*где /etc/postgresql/11/main/ — путь, который мы получили с помощью sql-команды SHOW config_file.*
|
||||
|
||||
В данном файле мы должны добавить 2 строки:
|
||||
```
|
||||
...
|
||||
# "local" is for Unix domain socket connections only
|
||||
local all ksu md5
|
||||
...
|
||||
# IPv4 local connections:
|
||||
host all postgres 172.30.5.19/32 md5
|
||||
...
|
||||
```
|
||||
|
||||
*где 172.30.5.19 — IP-адрес предполагаемого сервера Vault, с которого мы будем подключаться под пользователем postgres.*
|
||||
|
||||
Открываем конфигурационный файл:
|
||||
```
|
||||
vi /etc/postgresql/11/main/postgresql.conf
|
||||
```
|
||||
Приводим опцию listen_addresses к виду:
|
||||
```
|
||||
listen_addresses = '*'
|
||||
```
|
||||
*в данном примере мы настроили, чтобы postgresql слушал запросы на всех сетевых интерфейсах. При необходимости. мы можем ограничить их число вводом конкретного адреса.*
|
||||
|
||||
Перезапускаем службу СУБД:
|
||||
```
|
||||
systemctl restart postgresql
|
||||
```
|
||||
*команда для перезапуска PostgreSQL может отличаться и зависит от версии СУБД.*
|
||||
|
||||
### Настраиваем межсетевой экран
|
||||
Для подключения к серверу баз данных по сети, нам необходимо открыть порт 5432.
|
||||
|
||||
Как правило, в CentOS используется firewalld, как средство управления брандмауэром. Вводим:
|
||||
```
|
||||
firewall-cmd --permanent --add-port=5432/tcp
|
||||
|
||||
firewall-cmd --reload
|
||||
```
|
||||
5. Делаем проверку
|
||||
Убедимся, что наши учетные записи имеют права для подключения к базе данных.
|
||||
|
||||
На сервере с СУБД вводим:
|
||||
```
|
||||
psql -Uksu -W template1
|
||||
```
|
||||
* в данном примере мы подключаемся к локальному хосту под пользователем ksu.
|
||||
|
||||
Система запросит пароль — вводим тот, что задали при создании нашего пользователя. Мы должны попасть в оболочку psql.
|
||||
|
||||
Теперь подключаемся по SSH на сервер Vault. Нам придется установить на него клиента postgresql.
|
||||
|
||||
На Deb (Ubuntu, Debian):
|
||||
```
|
||||
apt install postgresql
|
||||
```
|
||||
После установки можно подключаться к нашему серверу с помощью команды psql.
|
||||
|
||||
Вводим:
|
||||
```
|
||||
psql -h172.30.30.87 -Upostgres -W
|
||||
```
|
||||
*в данном примере мы подключимся к серверу 172.30.30.87 под учетной записью postgres.*
|
||||
|
||||
Консоль у нас запросит пароль — вводим тот, что задали для пользователя postgres. В итоге мы должны подключиться к серверу:
|
||||
```
|
||||
postgres=#
|
||||
```
|
||||
Выходим из SQL-оболочки:
|
||||
```
|
||||
postgres=# \q
|
||||
```
|
||||
... и переходим к настройке Vault.
|
||||
|
||||
### Настройка Vault
|
||||
На стороне хранилища паролей необходимо:
|
||||
|
||||
Включить механизм хранения database.
|
||||
Создать конфигурацию для подключения к СУБД и привязать ее к роли.
|
||||
Выполним настройки по шагам.
|
||||
|
||||
Включаем механизм database
|
||||
Для включения механизма database вводим:
|
||||
```
|
||||
vault secrets enable database
|
||||
```
|
||||
Мы должны получить ответ:
|
||||
```
|
||||
Success! Enabled the database secrets engine at: database/
|
||||
```
|
||||
... или:
|
||||
```
|
||||
Error enabling: Error making API request.
|
||||
...
|
||||
* path is already in use at database/
|
||||
```
|
||||
Второй ответ говорит нам о том, что механизм database уже работает по пути database/. Так или иначе, идем дальше.
|
||||
### Настройка подключения к postgresql
|
||||
Создаем конфигурацию с опциями подключения к базе данных:
|
||||
```
|
||||
vault write database/config/postgresql \
|
||||
plugin_name=postgresql-database-plugin \
|
||||
allowed_roles="postgresql-rotate,postgresql-create" \
|
||||
connection_url=postgresql://{{username}}:{{password}}@172.30.30.87:5432/postgres?sslmode=disable \
|
||||
username="postgres" \
|
||||
password="qwerty123"
|
||||
```
|
||||
где:
|
||||
|
||||
- **database/config/postgresql** — путь в системе Vault к секрету.
|
||||
- **plugin_name** — плагин, который будем использоваться конфигурацией.
|
||||
- **allowed_roles** — для каких ролей будет использоваться данная конфигурация. Ниже по инструкции мы создадим 2 роли — для ротации паролей и для создания временных пользователей.
|
||||
- **connection_url** — строка подключения к базе данных. В данном примере 172.30.30.87 — сервер PostgreSQL.
|
||||
- **username** — пользователь, под которым выполняется подключение к СУБД.
|
||||
- **password** — пароль для пользователя, под которым выполняем подключение.
|
||||
|
||||
Наш Vault подготовлен для работы с базой PostgreSQL.
|
||||
|
||||
## Настройка ротации паролей
|
||||
Данная настройка позволит автоматически по таймеру менять пароли в СУБД PostgreSQL для определенных учетных записей.
|
||||
|
||||
На стороне хранилища паролей необходимо:
|
||||
|
||||
- Создать роль, которая будет менять пароль в базе данных.
|
||||
- Проверить настройки, создав новый пароль и подключившись к базе данных.
|
||||
|
||||
Переходим к настройке.
|
||||
|
||||
### Создаем роль для смены пароля
|
||||
Настройка задается с помощью static-roles. В нашем Vault вводим команду:
|
||||
```
|
||||
vault write database/static-roles/postgresql-rotate \
|
||||
db_name=postgresql \
|
||||
rotation_statements="ALTER USER \"{{name}}\" WITH PASSWORD '{{password}}';" \
|
||||
username="ksu" \
|
||||
rotation_period=720h
|
||||
```
|
||||
|* обратите внимание, что запрос rotation_statements важно написать именно так — первая кавычка двойная, вторая одинарная.
|
||||
|** в данном примере:
|
||||
|
||||
- Мы создадим роль с названием **postgresql-rotate** (с тем названием, которое мы использовали в allowed_roles, когда создавали конфигурацию).
|
||||
- Опция **db_name** должна называться как настройка, которую мы создали на предыдущем шаге (database/config/postgresql).
|
||||
- Наша роль будет выполнять команду **rotation_statements** (менять пароль для пользователя).
|
||||
- Каждые 720 часов (30 дней) пароль будет меняться автоматически.
|
||||
|
||||
Мы должны увидеть что-то на подобие:
|
||||
```
|
||||
Success! Data written to: database/static-roles/postgresql-rotate
|
||||
```
|
||||
Готово.
|
||||
|
||||
### Меняем пароль и проверяем доступ
|
||||
Давайте посмотрим текущий пароль:
|
||||
```
|
||||
vault read database/static-creds/postgresql-rotate
|
||||
```
|
||||
Мы получим что-то на подобие:
|
||||
```
|
||||
Key Value
|
||||
--- -----
|
||||
last_vault_rotation 2024-08-01T17:08:42.837263316+03:00
|
||||
password O-Zl1M15Ze1FWzTtPZN1
|
||||
rotation_period 720h
|
||||
ttl 719h39m58s
|
||||
username ksu
|
||||
|
||||
```
|
||||
Где **O-Zl1M15Ze1FWzTtPZN1** — наш пароль от учетной записи ksu.
|
||||
|
||||
Перейдем на сервер с PostgreSQL и попробуем войти в СУБД с использованием этих данных:
|
||||
```
|
||||
psql -Uksu -W template1
|
||||
```
|
||||
Мы должны подключиться с использованием пароля, который получили от Vault.
|
||||
|
||||
## Создание временных пользователей в PostgreSQL
|
||||
Давайте теперь рассмотрим настройку, при которой Vault будет создавать временных пользователей.
|
||||
Для этого мы:
|
||||
|
||||
- Создадим роль в Vault, которая будет создавать учетную запись в базе PostgreSQL.
|
||||
- Настроим файл pg_hba.conf для возможности подключаться к базе пользователям по паролю.
|
||||
- Проверим настройки, создав учетную запись и подключившись к СУБД.
|
||||
|
||||
Приступим.
|
||||
|
||||
### Создаем роль для создания нового пользователя
|
||||
Настройка задается с помощью roles. На сервере Vault вводим команду:
|
||||
```
|
||||
vault write database/roles/postgresql-create \
|
||||
db_name=postgresql \
|
||||
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
|
||||
default_ttl="1h" \
|
||||
max_ttl="24h"
|
||||
```
|
||||
|* обратите внимание, что запрос creation_statements важно написать именно так — первая кавычка двойная, остальные одинарные.
|
||||
|** в данном примере:
|
||||
- Мы создадим роль с названием **postgresql-create** (с тем названием, которое мы использовали в allowed_roles, когда создавали конфигурацию).
|
||||
- Опция **db_name** должна называться как настройка, которую мы создали на шаге создания конфига (database/config/**postgresql**).
|
||||
- Наша роль будет выполнять команду **creation_statements** — создавать пользователя и задавать ему права. Нужно переписать запрос, чтобы права выдавались такими, какими нужны именно вам. Для тестовых целей можно поставить как в данном примере.
|
||||
- **default_ttl** — время, в течение которого будет действовать пароль.
|
||||
- **max_ttl** — время, в течение которого пользователю можно будет обновлять пароль.
|
||||
|
||||
Мы должны увидеть что-то на подобие:
|
||||
```
|
||||
Success! Data written to: database/roles/postgresql-create
|
||||
```
|
||||
Готово.
|
||||
|
||||
### Настраиваем файл pg_hba.conf
|
||||
Ранее в инструкции мы настраивали данный файл, чтобы обеспечить возможность подключения к базе пользователям ksu и postgresql. Но при создании динамических учетных записей, логины будут разные — необходимо разрешить парольный вход для всех пользователей.
|
||||
|
||||
Открываем файл:
|
||||
```
|
||||
vi /etc/postgresql/11/main/pg_hba.conf
|
||||
```
|
||||
* напомню, что путь до нашего файла может быть другим — это зависит от операционной системы и версии postgresql. Посмотреть расположение конфигурационных файлов можно sql-командой **SHOW config_file**;
|
||||
|
||||
В открывшемся редакторе необходимо внести изменения:
|
||||
```
|
||||
...
|
||||
# "local" is for Unix domain socket connections only
|
||||
local all ksu md5
|
||||
local all postgres peer
|
||||
local all all md5
|
||||
##local all all peer
|
||||
...
|
||||
```
|
||||
|* мы добавили строку, разрешающую пользователю postgres логин с локального хоста (local) без запроса пароля; также мы закомментировали строку, которая позволяет вход всем пользователям с локального хоста без пароля и добавили новую, почти, такую же, но требующую ввода логина и пароля.
|
||||
|** это, всего лишь, пример настройки. В вашем случае необходимо руководствоваться политикой безопасности, принятой в компании и требованиями приложения.
|
||||
|
||||
Перезапускаем сервис СУБД:
|
||||
```
|
||||
systemctl restart postgresql
|
||||
```
|
||||
* также напомню, что название сервиса может отличаться и это зависит от версии PostgreSQL.
|
||||
|
||||
### Создаем нового пользователя и проверяем доступ
|
||||
Создаем временного пользователя командой:
|
||||
```
|
||||
vault read database/creds/postgresql-create
|
||||
```
|
||||
Мы должны увидеть что-то на подобие:
|
||||
```
|
||||
Key Value
|
||||
--- -----
|
||||
lease_id database/creds/postgresql-create/dluf4Zt8DUn28jsEhAv6tqmE
|
||||
lease_duration 1h
|
||||
lease_renewable true
|
||||
password SREUIRWI2D-IyGi5npN9
|
||||
username v-ldap-dfe-postgres-73SnRsVbtmVw86CAAlPy-1722523328
|
||||
```
|
||||
Наши логин и пароль соответственно — **v-root-postgres-0VO0sWprjEuCPZkZpu62-1631008720** и **9oAhg1VIEhleeRA7EU-U**.
|
||||
|
||||
Перейдем на сервер с PostgreSQL и попробуем войти в СУБД с использованием этих данных:
|
||||
```
|
||||
psql -U'v-ldap-dfe-postgres-73SnRsVbtmVw86CAAlPy-1722523328' -W template1
|
||||
```
|
||||
Мы должны подключиться с использованием пароля, который получили от Vault.
|
||||
268
DevOps/Hashicorp-Vault/vault-with-ldap.md
Normal file
@@ -0,0 +1,268 @@
|
||||
---
|
||||
title: Vault с доменной авторизацией
|
||||
description:
|
||||
published: true
|
||||
date: 2024-07-17T10:14:10.792Z
|
||||
tags:
|
||||
editor: markdown
|
||||
dateCreated: 2024-07-09T14:09:31.262Z
|
||||
---
|
||||
|
||||
# Развертывание Hashicorp Vault на стенде с Microsoft Active Directory (LDAP)
|
||||
|
||||
## Политики и пользователи
|
||||
|
||||
Политики в Vault по сути напоминают права или access list (ACL). К юзеру или группе привязан ACL, с разного рода правами же.
|
||||
|
||||
## Настройка образца политик
|
||||
|
||||
Сначала настроим политики – потому что пользователи и группы привязаны в политике, а ввиду убогого GUI делается это не очевидно. Да и в руководстве по политикам прописано как-то странновато. https://developer.hashicorp.com/vault/tutorials/getting-started/getting-started-policies?in=vault%2Fgetting-started
|
||||
|
||||
Посмотрим, что у нас есть:
|
||||
Логинимся через токенЖ
|
||||
```
|
||||
vault login
|
||||
```
|
||||
Проверяем, что все успешно
|
||||
```
|
||||
vault status
|
||||
```
|
||||
Окей, сервер работает. Проверим сикреты.
|
||||
|
||||
```
|
||||
vault secrets list
|
||||
```
|
||||
|
||||
Проверим существующие политики:
|
||||
```
|
||||
vault policy list
|
||||
```
|
||||

|
||||
|
||||
Создадим шаблон под политику:
|
||||
```bash
|
||||
nano policyUSER1.hcl
|
||||
|
||||
# policyUSER1
|
||||
# Write and manage secrets in key/value secrets engine
|
||||
path "kv_UserAD/*" {
|
||||
capabilities = [ "create", "read", "update", "delete", "list" ]
|
||||
}
|
||||
```
|
||||
Почитаем help и применим политику
|
||||
```
|
||||
vault policy write -h
|
||||
vault policy write policyuser1 /home/vuser/policyUSER.hcl
|
||||
```
|
||||

|
||||
|
||||
Создадим групповую политику с полным доступом
|
||||
```bash
|
||||
nano policy_groupad_fullacess1.hcl
|
||||
|
||||
# policy_groupad_fullacess1
|
||||
path "kv_groupAD/*" {
|
||||
capabilities = [ "create", "read", "update", "delete", "list" ]
|
||||
}
|
||||
|
||||
# Выполним
|
||||
vault policy write policy_groupad_fullacess1 /home/vuser/policy_groupad_fullacess1.hcl
|
||||
```
|
||||
|
||||
Удостоверимся, что все записалось
|
||||
```
|
||||
vault policy list
|
||||
vault policy read policy_groupad_fullacess1
|
||||
```
|
||||
|
||||
# Привяжем LDAP к AD
|
||||
Идем и читаем *Auth Methods* https://developer.hashicorp.com/vault/docs/auth
|
||||
|
||||
Без чтения дальше продолжать бессмысленно. Особенно внимательно читаем LDAP Auth Method
|
||||
Включаем LDAP по руководству, раздел Configuration
|
||||
```
|
||||
vault auth enable ldap
|
||||
```
|
||||
Сначала настроим связку с AD – потому что сейчас в Vault пользователей нет.
|
||||
|
||||
>Учитывать: пробелы и переносы строк значимы, если не поставите пробел перед закрывающим “\”, то получите проблемы. Учтите, в тестовой конфигурации пароль прописан в исполняемом файле в открытом виде, не забудьте потом удалить файл и историю.
|
||||
|
||||
```bash
|
||||
nano ad_auth_1.sh
|
||||
|
||||
#!/bin/sh
|
||||
vault write auth/ldap/config \
|
||||
url="ldap://192.168.32.155:389" \
|
||||
groupdn="OU=N Watch,OU=Zoo MSK,DC=contoso,DC=lab" \
|
||||
groupfilter="(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))" \
|
||||
userdn="OU=N Watch,OU=Zoo MSK,DC=contoso,DC=lab " \
|
||||
userattr=sAMAccountName \
|
||||
groupattr="memberOf" \
|
||||
insecure_tls=false \
|
||||
deny_null_bind=true \
|
||||
use_token_groups=true \
|
||||
starttls=false
|
||||
```
|
||||
И выполняем
|
||||
```
|
||||
sh ad_auth_1.sh
|
||||
```
|
||||
теперь нам надо бы проверить что все работает и привязать юзеров к политикам.
|
||||
|
||||
Проверим через GUI
|
||||
|
||||
User- Ivanov, Password - Pa$$word3
|
||||
|
||||
Получаем ошибку:
|
||||
```
|
||||
Authentication failed: 1 error occurred: * error connecting to host "ldap://192.168.32.155:389": LDAP Result Code 200 "Network Error": dial tcp 192.168.32.155:389: connect: connection refused
|
||||
```
|
||||
|
||||
Посмотрим в CLI
|
||||
```
|
||||
vault login -method=ldap username=Ivanov
|
||||
```
|
||||
та же ошибка, а все почему? Потому что по невнимательности я прописал
|
||||
|
||||
url="ldap://192.168.32.155:389" \
|
||||
|
||||
а AD у нас где? 192.168.31.151
|
||||
|
||||
и заодно, insecure_tls=false – а у нас ничего для TLS нет, так что читаем руководство еще раз,
|
||||
|
||||
insecure_tls - (bool, optional) - If true, skips LDAP server SSL certificate verification - insecure, use with caution!
|
||||
|
||||
**В БОЕВОЙ СРЕДЕ НЕ ЗАБЫВАЕМ СЕРТИФИКАТЫ AD!**
|
||||
|
||||
И мы же не прописали самое главное – bindDN!
|
||||
|
||||
Исправляемся, не зря в ldapsearch проверяли. Не забываем про “\”, кроме последней строки
|
||||
|
||||
`binddn="CN=Vault connector,OU=Vault,OU=Robo base,DC=contoso,DC=lab " \`
|
||||
|
||||
`bindpass="Pa!!word2"`
|
||||
|
||||
Исправляем, выполняем
|
||||
|
||||
```
|
||||
vault auth disable ldap
|
||||
vault auth enable ldap
|
||||
sh ad_auth_1.sh
|
||||
```
|
||||
Учтите:
|
||||
|
||||
1) При выполнении vault auth disable ldap – будут удалены не только настройки ldap, но и пользователи. У нас пока пользователей нет, а когда будут – попробуйте и увидите.
|
||||
|
||||
2) При каждой удачной команде vault login(и так далее) – вы будете получать новый токен. Поэтому лучше бы держать две SSH сессии – одну с vault login и root token, а вторую для проверок. Я в тексте не пишу про переключение, потому что по лени ввожу vault login каждый раз.
|
||||
|
||||
*Проверяем*
|
||||
|
||||
`vault login -method=ldap username=Ivanov`
|
||||
Получаем годное красивое
|
||||
|
||||
Error authenticating: Error making API request.
|
||||
|
||||
URL: PUT http://192.168.31.155:8200/v1/auth/ldap/login/Ivanov
|
||||
|
||||
Code: 400. Errors:
|
||||
|
||||
* ldap operation failed: failed to bind as user
|
||||
|
||||

|
||||
|
||||
И если вы на этом этапе подумали – «Ну что ж, заведем юзера в Vault!» - то вовсе не угадали.
|
||||
|
||||
Надо идти в логи AD и смотреть там ошибки авторизации – у какого юзера не идет авторизация. В моем случае – с Source Network Address: 192.168.31.155 прошла успешная авторизация пользователя CONTOSO\VaultSAM
|
||||
|
||||
Может быть, проблема в пароле товарища Иванова? Проверим. Сменим Pa$$word3 на Pa!!word3 –а вот и нет.
|
||||
|
||||
Но у нас есть товарищ Волк, без имени и фамилии. Проверим!
|
||||
|
||||
vault login -method=ldap username=volk
|
||||
|
||||
и все работает!
|
||||
|
||||

|
||||
|
||||
|
||||
# Заводим MS AD юзеров в Vault LDAP
|
||||
Не забудем перейти в соседнюю сессию или перелогинимся
|
||||
```
|
||||
vault login
|
||||
```
|
||||
Юзер у нас ходит, а политик ему не назначили – так заведем.
|
||||
|
||||
```
|
||||
vault write auth/ldap/users/Ivanov
|
||||
```
|
||||
и получим ошибку, Must supply data or use –force
|
||||
|
||||
Заведем сразу с политикой -
|
||||
|
||||
```
|
||||
vault write auth/ldap/users/Ivanov policies=policyuser1
|
||||
vault login -method=ldap username=Ivanov
|
||||
```
|
||||
работает, отлично – политика и токен["default" "policyuser1"],а как с группой быть?
|
||||
|
||||
В конфиге я считерил и сразу прописал
|
||||
|
||||
`groupfilter="(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))`
|
||||
|
||||
В конфиге я считерил и сразу прописал
|
||||
|
||||
`groupfilter="(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))" \`
|
||||
|
||||
это известное читерство, описанное тут Поиск всех групп пользователя AD по протоколу LDAP, и случайно мне попавшееся в обсуждении на hashicorp
|
||||
|
||||
и в google groups ,да и в документации в разделе Group Membership Resolution, но как-то совсем косо, с первого второго и далее раза не очевидно.
|
||||
|
||||
**Проверим**:
|
||||
|
||||
```
|
||||
vault login -method=ldap username=Petrov
|
||||
```
|
||||
теперь логинится, и получает политику ["default"]
|
||||
|
||||
Пропишем группу AD
|
||||
|
||||
```
|
||||
vault login
|
||||
vault policy list
|
||||
vault write auth/ldap/groups/VltADM policies=policy_groupad_fullacess1
|
||||
vault login -method=ldap username=Petrov
|
||||
```
|
||||
и получим что: Верно. Индейскую народную национальную избу мы получим. Логин есть – политики нет.
|
||||
|
||||
```
|
||||
vault list auth/ldap/groups
|
||||
vault delete auth/ldap/groups/VltADM
|
||||
vault write "auth/ldap/groups/Vault login" policies=policy_groupad_fullacess1
|
||||
vault login -method=ldap username=Petrov
|
||||
["default" "policy_groupad_fullacess1"]
|
||||
```
|
||||
**Теперь про неприятное.**
|
||||
|
||||
Удалим пользователя Иванова без очистки токенов.
|
||||
|
||||
`vault delete auth/ldap/users/Ivanov`
|
||||
|
||||
зайдем им
|
||||
|
||||
`vault login -method=ldap username=Ivanov`
|
||||
|
||||
ОП – и у нас по прежнему есть старая политика. Для сброса придется в обязательном порядке отзывать токены –
|
||||
|
||||
Получить список токенов
|
||||
|
||||
`vault list auth/token/accessors`
|
||||
|
||||

|
||||
|
||||
Перебрать каждый
|
||||
|
||||
`vault token lookup -accessor EHlDQ1tFHEgA9aq0R6IptIjo`
|
||||
|
||||

|
||||
|
||||
и так по всем. Не самая удобная процедура с точки зрения CLI, ну так Vault не под CLI заточен.
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 01-base-helm
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-09T15:06:22.191Z
|
||||
date: 2023-11-09T15:06:26.646Z
|
||||
tags: helm
|
||||
editor: markdown
|
||||
dateCreated: 2023-11-08T08:24:36.599Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 02-video-app-metadata
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-09T10:02:30.373Z
|
||||
date: 2023-11-09T10:02:36.449Z
|
||||
tags:
|
||||
editor: markdown
|
||||
dateCreated: 2023-11-08T10:42:51.395Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 03-video-spec
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-09T14:12:51.136Z
|
||||
date: 2023-11-09T14:12:57.049Z
|
||||
tags: helm
|
||||
editor: markdown
|
||||
dateCreated: 2023-11-09T10:06:13.204Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 04-video-svc-ingress
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-09T14:58:52.878Z
|
||||
date: 2023-11-09T14:58:58.607Z
|
||||
tags:
|
||||
editor: markdown
|
||||
dateCreated: 2023-11-09T14:11:37.963Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 05-video-cm
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-09T15:05:32.795Z
|
||||
date: 2023-11-09T15:05:38.914Z
|
||||
tags:
|
||||
editor: markdown
|
||||
dateCreated: 2023-11-09T15:05:32.795Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 06-video-final
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-09T15:17:21.129Z
|
||||
date: 2023-11-09T15:17:27.035Z
|
||||
tags:
|
||||
editor: markdown
|
||||
dateCreated: 2023-11-09T15:17:21.129Z
|
||||
|
||||
60
DevOps/Helm/Learn-by-Krukov/manifests/deployment-test.yaml
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: openresty
|
||||
labels:
|
||||
k8s-app: openresty
|
||||
annotations:
|
||||
reloader.stakater.com/auto: "true"
|
||||
configmap.reloader.stakater.com/reload: "openresty"
|
||||
spec:
|
||||
replicas: 2
|
||||
revisionHistoryLimit: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: openresty
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: openresty
|
||||
spec:
|
||||
containers:
|
||||
- name: openresty
|
||||
image: openresty/openresty:centos-rpm
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /index.html
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 15
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /index.html
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 15
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: "0.2"
|
||||
memory: "400Mi"
|
||||
requests:
|
||||
cpu: "0.1"
|
||||
memory: "200Mi"
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/local/openresty/nginx/html/
|
||||
- name: config
|
||||
mountPath: /etc/nginx/conf.d/
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: openresty-html
|
||||
- name: config
|
||||
configMap:
|
||||
name: openresty-conf
|
||||
60
DevOps/Helm/Learn-by-Krukov/manifests/deployment.yaml
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: openresty
|
||||
labels:
|
||||
k8s-app: openresty
|
||||
annotations:
|
||||
reloader.stakater.com/auto: "true"
|
||||
configmap.reloader.stakater.com/reload: "openresty"
|
||||
spec:
|
||||
replicas: 2
|
||||
revisionHistoryLimit: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: openresty
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: openresty
|
||||
spec:
|
||||
containers:
|
||||
- name: openresty
|
||||
image: openresty/openresty:centos-rpm
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /index.html
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 15
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /index.html
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 15
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: "0.2"
|
||||
memory: "400Mi"
|
||||
requests:
|
||||
cpu: "0.1"
|
||||
memory: "200Mi"
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/local/openresty/nginx/html/
|
||||
- name: config
|
||||
mountPath: /etc/nginx/conf.d/
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: openresty-html
|
||||
- name: config
|
||||
configMap:
|
||||
name: openresty-conf
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: openresty
|
||||
labels:
|
||||
k8s-app: openresty
|
||||
annotations:
|
||||
reloader.stakater.com/auto: "true"
|
||||
configmap.reloader.stakater.com/reload: "openresty"
|
||||
spec:
|
||||
replicas: 2
|
||||
revisionHistoryLimit: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: openresty
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: openresty
|
||||
spec:
|
||||
containers:
|
||||
- name: openresty
|
||||
image: openresty/openresty:centos-rpm
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /index.html
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 15
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /index.html
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 15
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: "0.2"
|
||||
memory: "400Mi"
|
||||
requests:
|
||||
cpu: "0.1"
|
||||
memory: "200Mi"
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/local/openresty/nginx/html/
|
||||
- name: config
|
||||
mountPath: /etc/nginx/conf.d/
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: openresty-html
|
||||
- name: config
|
||||
configMap:
|
||||
name: openresty-conf
|
||||
@@ -2,10 +2,10 @@
|
||||
title: bash-completion для kubectl
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-07T18:14:58.029Z
|
||||
date: 2024-07-09T09:49:55.778Z
|
||||
tags: bash, kubectl
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-03T08:55:30.344Z
|
||||
dateCreated: 2023-11-08T08:53:22.629Z
|
||||
-->
|
||||
|
||||
<h3>Установка bash-completion</h3>
|
||||
|
||||
82
DevOps/PostgreSQL/instruments.md
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
title: Инструменты для обслуживания postgresql
|
||||
description:
|
||||
published: true
|
||||
date: 2025-06-17T09:33:07.672Z
|
||||
tags: postgresql
|
||||
editor: markdown
|
||||
dateCreated: 2025-06-17T09:33:07.672Z
|
||||
---
|
||||
|
||||
Расскажу про парочку инструментов, которые упростят обслуживание сервера PostgreSQL. Начну с наиболее простого - pgBadger (https://pgbadger.darold.net/examples/sample.html). Это анализатор лога, который на его основе генерирует отчёты в формате html. На выходе получаются одиночные html файлы, которые можно просто открыть в браузере. Сделано всё аккуратно и добротно, легко настраивается, отчёты наглядные и информационные.
|
||||
|
||||
🔹Чтобы было что анализировать, необходимо включить логирование интересующих вас событий. Для разовой отладки это всё можно включать на ходу, либо постоянно через файл конфигурации `postgresql.conf` и перезапуск сервера. Он обычно хорошо прокомментирован. Вас будут интересовать параметры, начинающие с log_*. Они собраны все в отдельном блоке. Для примера я включил почти всё:
|
||||
```
|
||||
log_min_duration_statement = 0
|
||||
log_checkpoints = on
|
||||
log_connections = on
|
||||
log_disconnections = on
|
||||
log_duration = on
|
||||
log_line_prefix = '%m [%p] %q%u@%d '
|
||||
log_lock_waits = on
|
||||
log_temp_files = 0
|
||||
log_timezone = 'Europe/Moscow'
|
||||
```
|
||||
Вся включенная статистика стала писаться в общий лог-файл `/var/log/postgresql/postgresql-17-main.log`. С ним и будем работать. Устанавливаем pgBadger:
|
||||
```
|
||||
# wget https://github.com/darold/pgbadger/archive/refs/tags/v13.1.tar.gz
|
||||
# tar xzvf v13.1.tar.gz
|
||||
# cd pgbadger-*
|
||||
# apt install make
|
||||
# make && make install
|
||||
```
|
||||
Анализируем лог файл:
|
||||
```
|
||||
# pgbadger /var/log/postgresql/postgresql-17-main.log
|
||||
```
|
||||
Тут же в директории, где его запускали, увидите файл out.html. Забирайте его к себе и смотрите. Там будет информация с общей статистикой сервера, информация по запросам и их типам, времени исполнения, подключениям, по пользователям, базам и хостам откуда подключались и много всего остального.
|
||||
|
||||
PgBadger удобен тем, что по сути это одиночный скрипт на Perl. Можно включить логирование в конфигурации, применить её через `SELECT pg_reload_conf();` без перезапуска сервера СУБД. Пособирать некоторое время данные, забрать лог и анализировать его. Логирование отключить и снова перечитать конфиг. В итоге всё будет сделано без перезапуска сервера.
|
||||
|
||||
🔹Второй инструмент - PgHero (https://github.com/ankane/pghero), он показывает примерно то же самое, только в режиме реального времени и работает в виде веб сервиса. Для него уже надо создавать пользователя, настраивать доступ, отдельную базу. Немного другой подход. Надо будет дёргать сервер с СУБД.
|
||||
|
||||
Надо перейти в консоль и создать необходимые сущности:
|
||||
```sql
|
||||
# su postgres
|
||||
# psql
|
||||
> CREATE USER pghero WITH PASSWORD 'pgheropass';
|
||||
> CREATE DATABASE pgherodb OWNER pghero;
|
||||
> \q
|
||||
```
|
||||
Разрешаем этому пользователю подключаться. Добавляем в `pg_hba.conf` строку:
|
||||
```
|
||||
host pgherodb pghero 172.17.0.0/24 md5
|
||||
```
|
||||
`172.17.0.0/24` - подсеть, из которой будет подключаться PgHero. В данном случае это Docker контейнер, запущенный на этом же хосте. PostgreSQL должен принимать запросы с локального IP адреса, к которому будет доступ из Docker сети. Можно добавить в конфиг `postgresql.conf` параметр:
|
||||
```
|
||||
listen_addresses = 'localhost,172.17.0.1'
|
||||
```
|
||||
Перезапускаем PotgreSQL:
|
||||
```
|
||||
# systemctl restart postgresql
|
||||
```
|
||||
Запускаем PgHero в Docker контейнере:
|
||||
```
|
||||
# docker run -ti -e DATABASE_URL=postgres://pghero:pgheropass@172.17.0.1:5432/pgherodb -p 8080:8080 ankane/pghero
|
||||
```
|
||||
Идём на порт севера 8080, где запущен контейнер и смотрим информацию о PostgreSQL. Если у вас не настроено расширение **pg_stat_statements**, которое использует PgHero для сбора статистики, то установите его. Для этого в конфигурацию `postgresql.conf` добавьте параметры:
|
||||
```
|
||||
shared_preload_libraries = 'pg_stat_statements'
|
||||
pg_stat_statements.track = all
|
||||
pg_stat_statements.max = 10000
|
||||
track_activity_query_size = 2048
|
||||
```
|
||||
Перезапустите Postgresql и выполните в консоли СУБД:
|
||||
```sql
|
||||
> CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
|
||||
> GRANT pg_read_all_stats TO pghero;
|
||||
```
|
||||
Теперь можно возвращаться в веб интерфейс и смотреть информацию. По умолчанию, пользователь pghero не будет видеть запросы других пользователей, если ему не дать права superuser. Это можно исправить, выдав ему набор прав и ролей из этой инструкции (https://github.com/ankane/pghero/blob/master/guides/Permissions.md).
|
||||
|
||||

|
||||
.jpg)
|
||||
BIN
DevOps/attachments/bash-comp1.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
DevOps/attachments/image2022-8-11_11-6-39.png
Normal file
|
After Width: | Height: | Size: 451 KiB |
BIN
DevOps/attachments/photo_2023-10-31_14-45-08.jpg
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
DevOps/attachments/photo_2025-05-16_16-20-53.jpg
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
DevOps/attachments/photo_2025-05-16_16-20-54.jpg
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
DevOps/attachments/photo_2025-05-16_16-20-54_(2).jpg
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
DevOps/attachments/photo_2025-05-21_20-48-32.jpg
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
DevOps/attachments/photo_2025-05-21_20-48-32_(2).jpg
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
DevOps/attachments/снимок_экрана_2023-11-07_182216.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
DevOps/img/docker-sheet.png
Normal file
|
After Width: | Height: | Size: 578 KiB |
BIN
DevOps/img/git-sheet.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
DevOps/img/regular-sheet.png
Normal file
|
After Width: | Height: | Size: 900 KiB |
BIN
DevOps/img/vault-gitlab.png
Normal file
|
After Width: | Height: | Size: 291 KiB |
BIN
DevOps/img/vault-gitlab2.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
@@ -2,7 +2,7 @@
|
||||
title: Как проходить собеседования
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:31:42.044Z
|
||||
date: 2024-07-09T09:49:26.072Z
|
||||
tags: work, find
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:31:42.044Z
|
||||
|
||||
131
Funny/Jaecoo/Jcartools.html
Normal file
@@ -0,0 +1,131 @@
|
||||
<!--
|
||||
title: Jcartools
|
||||
description:
|
||||
published: true
|
||||
date: 2024-10-24T18:34:35.072Z
|
||||
tags: jaecoo
|
||||
editor: ckeditor
|
||||
dateCreated: 2024-10-24T06:25:44.217Z
|
||||
-->
|
||||
|
||||
<h1>APK</h1>
|
||||
<p>Предоставление прав apk установленным из rustore:</p>
|
||||
<blockquote>
|
||||
<p>запись<br>adb shell pm grant название пакета android.permission.WRITE_EXTERNAL_STORAGE<br><br>чтение<br>все тоже самое, но в конце после последней точки READ_EXTERNAL_STORAGE<br><br>доступ к хранилищу(полный)<br>после последней точки MANAGE_EXTERNAL_STORAGE</p>
|
||||
</blockquote>
|
||||
<p>а как узнать название пакета?</p>
|
||||
<blockquote>
|
||||
<p>Через adb прибуду какую нибудь типа adb app control (как то так вроде бы) </p>
|
||||
<p>Или же узнать уже с машины (установленные программы) через командную строку adb shell pm list packages -3</p>
|
||||
</blockquote>
|
||||
<h1><strong>Iphone</strong></h1>
|
||||
<p>Нестабильно работает wifi на iphone</p>
|
||||
<blockquote>
|
||||
<p>На айфоне максимальную совместимость и пароль не замудреный поставить</p>
|
||||
</blockquote>
|
||||
<p>Утилита для прошивки (установка приложений) на Jaecoo j7. Новая версия. <a href="https://www.youtube.com/watch?v=mVRuAvgRIEI">https://www.youtube.com/watch?v=mVRuAvgRIEI</a></p>
|
||||
<p> </p>
|
||||
<p>Подскажите, что надо сделать что бы во время работы ЯН на ГУ или приборке, показывало стрелки на проекции?</p>
|
||||
<blockquote>
|
||||
<p>Проверить Включено ли в настройках проекционного дисплея отображение ассистентов вождения.</p>
|
||||
</blockquote>
|
||||
<p>Подскажите. Как сделать так что бы вместо ЯК включался ЯН?</p>
|
||||
<blockquote>
|
||||
<p>переписать имя пакета на ru.yandex.yandexnavi</p>
|
||||
</blockquote>
|
||||
<p>woha с версии 7.3 и продолжилось в 7.4 перестали выводиться на проекцию данные с антирадар Стрелка при проложенном маршруте як, стрелки як выводятся.</p>
|
||||
<blockquote>
|
||||
<p>Это сделано намерено, так как по практике Як, камер много и перекрывались маневры в самый неподходящий момент. Думаю сделать настройкой, но будет или то или то скорее всего. Или вариант с перекрытием маневров то же рассматривать?</p>
|
||||
</blockquote>
|
||||
<p>Прошу прощения, можно поподробнее пояснить. В настоящий момент, чтобы вместо стрелок навигации на проекцию выводились уведомления от приложения стрелка то необходимо отключить выведение навигации в HUD?</p>
|
||||
<blockquote>
|
||||
<p>Когда не выводятся стрелки от навигации, отображаются камеры со стрелки</p>
|
||||
</blockquote>
|
||||
<p>Подскажите зачем нужна стрелка дублирующая камеры из ЯН?</p>
|
||||
<blockquote>
|
||||
<p>В як нужно для этого маршрут строить, а антирадар работает постоянно</p>
|
||||
</blockquote>
|
||||
<h1>Youtube и аналоги</h1>
|
||||
<p>Для тех, кто спрашивал про Revanced Youtube</p>
|
||||
<p>1. Старые, если были, снести</p>
|
||||
<p>2. Эти два новых apk установить</p>
|
||||
<p>3. выполнить в adb shell </p>
|
||||
<pre><code class="language-plaintext">#разрешить microg поверх всех окон
|
||||
appops set app.revanced.android.gms SYSTEM_ALERT_WINDOW allow
|
||||
|
||||
#добавить в белый список (отключить оптимизацию батареи) для microg
|
||||
dumpsys deviceidle whitelist +app.revanced.android.gms </code></pre>
|
||||
<p>4. Зайти в настройки Microg и в разделе проверок протыкать разрешения у которых не стоит галочка. </p>
|
||||
<p>5. Зайти в настройках Microg в список аккаунтов, и перед добавлением своего аккаунта - поставить ползунки как на фото ниже. </p>
|
||||
<p>6. Добавить свой гугл аккаунт. </p>
|
||||
<p>7. Радоваться. А чтобы не пропадала История просмотров - в настройках Revanced в настройках General Layout включить Enable Tablet Layout.</p>
|
||||
<p> </p>
|
||||
<h1>Wifi</h1>
|
||||
<p>Всем привет! Перестал вай фай подключаться</p>
|
||||
<blockquote>
|
||||
<p>в инженерке удалите, перезагрузите ГУ и снова в инженерке подключите</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Для стабильного подключения ГУ к WiFi вашего мобильного устройства или модема необходимо отключить автоматическое включение Android Auto. Удалить все настройки подключения AA в самом ГУ и в приложении Android Auto вашего мобильного устройства. Зайдите в приложения на телефоне, найдите там приложение android auto и отключите.</p>
|
||||
<p>AA работает по принципу точки доступа. Ваше ГУ становится точкой доступа и в этот же момент отключает поиск и подключение к WiFi-сети находящейся поблизости.</p>
|
||||
</blockquote>
|
||||
<h3> </h3>
|
||||
<h1><strong>Стрелка</strong></h1>
|
||||
<p>Подскажите пожалуйста, в стрелке как настроить расстояние до камеры, в плане оповещения ?) </p>
|
||||
<blockquote>
|
||||
<p>В объектах выбираете нужную камеру, там же есть 3 раздела трасса, город, мегаполис. И 3 уровня уведомления(дистанции):</p>
|
||||
<p>1 уровень это самый дальний - от 1км до 2км.</p>
|
||||
<p>2 уровень от 300м до 1км.</p>
|
||||
<p>3 уровень от 50м до 300м.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Вот и настраиваете как вам удобно, себе всё настроил с 2мя уведомлениями</p>
|
||||
<p>1 уведомление естественно отключено.</p>
|
||||
<p>2 уведомление за 700м.</p>
|
||||
<p>3 уведомление за 300м.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Ну Вам нужно знать только о камерах или о всех событиях по пути.? Стрелка все может показывать. От лежачих , переходах , перекрёстках..... в незнакомом городе очень удобно и безопасно .</p>
|
||||
</blockquote>
|
||||
<h3> </h3>
|
||||
<h1><strong>Звук</strong></h1>
|
||||
<p>Звук почему то только английский (2 голоса), но звук есть. </p>
|
||||
<blockquote>
|
||||
<p>У меня вначале был английский, переключил в настройках на русский. Появилась Алиса вместо джона. Но Алиса тоже болтала по английски. Еще в настройках нашел язык "как в системе", переключил его на русский и все пошло норм</p>
|
||||
</blockquote>
|
||||
<p> В последней версии говорили же, что обязательно ставить эту настройку - фиксированные подсказки</p>
|
||||
<blockquote>
|
||||
<p>А если в картах поставите «закрепить указатель манёвра» будет ещё лучше</p>
|
||||
</blockquote>
|
||||
<p> </p>
|
||||
<h1>Яндекс карта</h1>
|
||||
<blockquote>
|
||||
<p>Приборку нужно перевести в режим отображения навигации. Нажать на левом джойстике руля по центру о и выбрать влево-вправо значок стрелки. Только после этого кидать на приборку.</p>
|
||||
<p>На руле "о" один раз, стрелка влево, чтобы режим карт появился, и зажать "о". Или в приложении "открыть на приборке".</p>
|
||||
</blockquote>
|
||||
<figure class="image image_resized" style="width:21.6%;"><img src="/jaecoo/{30a2bdf4-b137-4cf1-bf8e-94721aa1c8c0}.png"></figure>
|
||||
<figure class="image image_resized" style="width:21.51%;"><img src="/jaecoo/{26c4849a-5094-4662-ac6b-205e2d230e66}.png"></figure>
|
||||
<p>у всех оповещение при движении по маршруту на английском произносит или это только у меня. как это исправить. в настройках навигатора русский стоит.</p>
|
||||
<blockquote>
|
||||
<p>язык аннотаций на русский поменяйте. И даже если стоит язык "как в системе" и вы уверены, что в системе у вас русский, то все равно надо ставить русский.</p>
|
||||
</blockquote>
|
||||
<p>Приходится яндекс навигатор каждый раз открывать</p>
|
||||
<blockquote>
|
||||
<p>Включите настройку в як "переходить в навигатор при движении"</p>
|
||||
</blockquote>
|
||||
<p> </p>
|
||||
<h1>Обновление</h1>
|
||||
<p>А есть ссылка на пост с обновлением по воздуху тут?)</p>
|
||||
<blockquote>
|
||||
<p>Все просто. Три точки сверху справа "обновить приложение" и "обновить карты". При появлении новой версии приложения при его открытии будет уведомление.</p>
|
||||
</blockquote>
|
||||
<p>На проекцию не выводится ограничение скорости</p>
|
||||
<blockquote>
|
||||
<p>Ну когда навигатор работает над стрелками на проекции в бегущей строке вместе с названием улицы есть ещё что-то типа Lim 40 km/h. В настройках навистарт нужно вкл</p>
|
||||
</blockquote>
|
||||
<h1>Шторка-люк</h1>
|
||||
<p>Ну что бы шторка срабатывала нормально а не произвольно и очень редко :)</p>
|
||||
<blockquote>
|
||||
<p>Надо поставить галку для всех водителей</p>
|
||||
<p>В списке выбрать водитель один и поставить галку шторки например</p>
|
||||
</blockquote>
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Бессмысленная работа DevOps
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:28:01.117Z
|
||||
date: 2024-07-09T09:49:29.590Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:28:01.117Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Игра, обучение
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:29:10.428Z
|
||||
date: 2024-07-09T09:49:33.389Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:29:10.428Z
|
||||
|
||||
20
Hypervisors/Proxmox/Cluster/DestroyCluster.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!--
|
||||
title: Удаление кластера Proxmox
|
||||
description:
|
||||
published: true
|
||||
date: 2025-05-21T11:31:51.721Z
|
||||
tags: proxmox, cluster
|
||||
editor: ckeditor
|
||||
dateCreated: 2025-05-21T11:31:51.721Z
|
||||
-->
|
||||
|
||||
<p>systemctl stop pve-cluster.service</p>
|
||||
<p>systemctl stop corosync.service</p>
|
||||
<p>pmxcfs -l</p>
|
||||
<p>rm -rf /etc/pve/corosync.conf</p>
|
||||
<p>rm -rf /etc/corosync/</p>
|
||||
<p>killall pmxcfs</p>
|
||||
<p>systemctl restart pve-cluster.service</p>
|
||||
<p>cd /etc/pve/nodes</p>
|
||||
<p>ls</p>
|
||||
<p>rm -rf /etc/pve/nodes/pve-01/</p>
|
||||
68
Hypervisors/Proxmox/Cluster/DestroyCluster.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Как удалить ноду из кластера Proxmox?
|
||||
description:
|
||||
published: true
|
||||
date: 2025-05-22T09:28:25.522Z
|
||||
tags: proxmox, cluster
|
||||
editor: markdown
|
||||
dateCreated: 2025-05-21T11:31:51.721Z
|
||||
---
|
||||
|
||||
|
||||
Перед удалением ноды важно убедиться в том, что все виртуальные машины и данные безопасно мигрированы или созданы резервные копии, чтобы избежать потери данных и поддерживать целостность кластера.
|
||||
1. Остановите службу "pve-cluster" на изолируемой ноде
|
||||
```
|
||||
systemctl stop pve-cluster.service
|
||||
systemctl stop corosync.service
|
||||
```
|
||||
2. Запустите команду для перевода файловой системы кластера на изолируемой ноде в локальный режим
|
||||
```
|
||||
pmxcfs -l
|
||||
```
|
||||
3. Запустите команду для удаления файлов конфигурации Corosync:
|
||||
```
|
||||
rm -rf /etc/pve/corosync.conf
|
||||
rm -rf /etc/corosync/*
|
||||
```
|
||||
4. Запустите команду для перезапуска службы файловой системы кластера:
|
||||
```
|
||||
killall pmxcfs
|
||||
systemctl start pve-cluster.service
|
||||
```
|
||||
5. Удалите файлы неисправной ноды:
|
||||
```
|
||||
cd /etc/pve/nodes
|
||||
ls
|
||||
rm -rf /etc/pve/nodes/pve2 # Path corresponding to the faulty node
|
||||
```
|
||||
6. Очистите остаточную информацию о кластере:
|
||||
```
|
||||
pvecm delnode NodeName
|
||||
```
|
||||
Здесь приведена информация по устранению распространенных проблем, с которыми вы можете столкнуться.
|
||||
|
||||
Нода не отвечает: Если нода, которую вы хотите удалить, не отвечает из-за проблем с сетью или по другим причинам, вы можете использовать опцию Force для принудительного удаления ее из кластера:
|
||||
```
|
||||
pvecm delnode <NODE_NAME> --force
|
||||
```
|
||||
Застревание процесса удаления: В случае возникновения проблем с выполнением команды или застревания процесса во время удаления, вы можете диагностировать проблему, просмотрев системный журнал:
|
||||
```
|
||||
journalctl -xe
|
||||
```
|
||||
После устранения потенциальной проблемы попробуйте удалить ноду еще раз.
|
||||
|
||||
```
|
||||
systemctl stop pve-cluster.service
|
||||
systemctl stop corosync.service
|
||||
pmxcfs -l
|
||||
rm -rf /etc/pve/corosync.conf
|
||||
rm -rf /etc/corosync/
|
||||
killall pmxcfs
|
||||
systemctl restart pve-cluster.service
|
||||
cd /etc/pve/nodes
|
||||
ls
|
||||
rm -rf /etc/pve/nodes/pve-01/
|
||||
pvecm delnode pve-01
|
||||
pvecm delnode pve-01 --force
|
||||
systemctl restart corosync.service
|
||||
```
|
||||
14
Hypervisors/Proxmox/Disable-ProxMox-Subscription-Notice.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: Disable ProxMox Subscription Notice
|
||||
description:
|
||||
published: true
|
||||
date: 2025-04-11T07:57:37.999Z
|
||||
tags: proxmox
|
||||
editor: markdown
|
||||
dateCreated: 2025-04-11T07:53:49.776Z
|
||||
---
|
||||
|
||||
Proxmox 8.3
|
||||
```bash
|
||||
sed -Ezi.bak "s/(function\(orig_cmd\) \{)/\1\n\torig_cmd\(\);\n\treturn;/g" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js && systemctl restart pveproxy.service
|
||||
```
|
||||
123
Monitoring/Gatus.md
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
title: Gatus - просто мониторинг
|
||||
description:
|
||||
published: true
|
||||
date: 2024-08-08T14:54:22.568Z
|
||||
tags: мониторинг, gatus
|
||||
editor: markdown
|
||||
dateCreated: 2024-08-08T14:47:57.868Z
|
||||
---
|
||||
|
||||
У меня было очень много заметок про различные мониторинги. Кажется, что я уже про всё более-менее полезное что-то да писал. Оказалось, что нет. Расскажу про очередной небольшой и удобный мониторинг, который позволяет очень просто и быстро создать дашборд с зелёными и красными кнопками. Если зелёные, то всё ОК, если красные, то НЕ ОК.
|
||||
|
||||
Речь пойдёт про Gatus (https://github.com/TwiN/gatus). С его помощью очень удобно создавать Status Page. Сразу покажу, как это будет выглядеть:
|
||||
|
||||
⇨ [https://status.twin.sh](https://status.twin.sh)
|
||||
|
||||
И сразу же простой пример, как это настраивается. Там всё максимально просто и быстро. Мы будем проверять следующие условия:
|
||||
|
||||
◽️Подключение к сайту [zabbix.com](https://zabbix.com) проходит успешно, а его IP равен 188.114.99.224. Так как этот домен резолвится в разные IP, можно будет увидеть, как срабатывает проверка.
|
||||
|
||||
◽️Сайт [github.com](https://github.com) отдаёт код 200 при подключении и содержит заголовок страницы GitHub: Let’s build from here · GitHub.
|
||||
|
||||
◽️Сайт ya.ru отдаёт код 200 и имеет отклик менее 10 мс. На практике он будет больше, посмотрим, как срабатывает триггер. По этой проверке будет уведомление в Telegram.
|
||||
|
||||
◽️Домен [vk.com](https://vk.com) имеет сертификат со сроком истечения не менее 48 часов и делегирование домена не менее 720 часов.
|
||||
|
||||
Специально подобрал разнообразные примеры, чтобы вы оценили возможности мониторинга. Я просто открыл документацию и сходу по ней всё сделал. Всё очень просто и понятно, особо разбираться не пришлось. Создаём конфигурационный файл для этих проверок:
|
||||
|
||||
```bash
|
||||
mkdir gatus && cd gatus
|
||||
touch config.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
alerting:
|
||||
telegram:
|
||||
token: "1393668911:AAHtEAKqxUH7ZpyX28R-wxKfvH1WR6-vdNw"
|
||||
id: "210806260"
|
||||
|
||||
endpoints:
|
||||
- name: Zabbix Connection
|
||||
url: "https://zabbix.com"
|
||||
interval: 30s
|
||||
conditions:
|
||||
- "[CONNECTED] == true"
|
||||
- "[IP] == 188.114.99.224"
|
||||
|
||||
- name: Github Title
|
||||
url: "https://github.com"
|
||||
interval: 30s
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
- "[BODY] == pat(*<title>GitHub: Let’s build from here · GitHub</title>*)"
|
||||
|
||||
- name: Yandex response
|
||||
url: "https://ya.ru"
|
||||
interval: 30s
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
- "[RESPONSE_TIME] < 10"
|
||||
alerts:
|
||||
- type: telegram
|
||||
send-on-resolved: true
|
||||
|
||||
- name: VK cert & domain
|
||||
url: "https://vk.com"
|
||||
interval: 5m
|
||||
conditions:
|
||||
- "[CERTIFICATE_EXPIRATION] > 48h"
|
||||
- "[DOMAIN_EXPIRATION] > 720h"
|
||||
```
|
||||
|
||||
Запускаем Docker контейнер и цепляем к нему этот файл:
|
||||
|
||||
```bash
|
||||
docker run -p 8080:8080 -d \
|
||||
--mount type=bind,source="$(pwd)"/config.yaml,target=/config/config.yaml \
|
||||
--name gatus twinproduction/gatus
|
||||
```
|
||||
|
||||
Идём по IP адресу сервера на порт 8080 и смотрим на свой мониторинг. Данные могут храниться в оперативной памяти, sqlite или postgresql базе. Если выберите последнее, то вот готовый [docker-compose](https://github.com/TwiN/gatus/blob/master/.examples/docker-compose-postgres-storage/docker-compose.yml) для этого. По умолчанию данные хранятся в оперативной памяти и после перезапуска контейнера пропадают.
|
||||
|
||||
```yaml
|
||||
version: "3.9"
|
||||
services:
|
||||
postgres:
|
||||
image: postgres
|
||||
volumes:
|
||||
- ./data/db:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
- POSTGRES_DB=gatus
|
||||
- POSTGRES_USER=username
|
||||
- POSTGRES_PASSWORD=password
|
||||
networks:
|
||||
- web
|
||||
|
||||
gatus:
|
||||
image: twinproduction/gatus:latest
|
||||
restart: always
|
||||
ports:
|
||||
- "8080:8080"
|
||||
environment:
|
||||
- POSTGRES_USER=username
|
||||
- POSTGRES_PASSWORD=password
|
||||
- POSTGRES_DB=gatus
|
||||
volumes:
|
||||
- ./config:/config
|
||||
networks:
|
||||
- web
|
||||
depends_on:
|
||||
- postgres
|
||||
|
||||
networks:
|
||||
web:
|
||||
```
|
||||
|
||||
Штука простая и удобная. Меня не раз просили посоветовать что-то для простого дашборда с зелёными кнопками, когда всё нормально и красными, когда нет. Вот это идеальный вариант под такую задачу.
|
||||
|
||||
Также с помощью этого мониторинга удобно сделать дашборд для мониторинга мониторингов, чтобы понимать, живы они или нет.
|
||||
|
||||

|
||||
80
Monitoring/VictoriaLogs-setup.md
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: VictoriaLogs - установка и настройка
|
||||
description:
|
||||
published: true
|
||||
date: 2025-04-28T07:27:29.722Z
|
||||
tags: victorialogs
|
||||
editor: markdown
|
||||
dateCreated: 2025-04-28T07:25:56.957Z
|
||||
---
|
||||
|
||||
Пару лет назад у VictoriaMetrics вышел продукт, который является частью именного стека, – VictoriaLogs. Руки не доходили раньше на него посмотреть и вот дошли. Сразу скажу, что всё очень понравилось за простоту, функциональность и удобство. Покажу сразу с примерами.
|
||||
|
||||
Отдельно перечислю особенности VictoriaLogs:
|
||||
|
||||
▪️По своей сути это одиночный бинарник, который можно сконфигурировать ключами запуска, не нужен даже конфигурационный файл.
|
||||
▪️В бинарнике есть всё, что надо для сбора и просмотра логов: веб интерфейс, метрики для мониторинга за системой, все типы приёмников логов.
|
||||
▪️Для бэкапа достаточно скопировать директорию с данными, например, с помощью rsync. То есть вообще никаких проблем и заморочек с бэкапом.
|
||||
▪️Есть плагин для datasource в Grafana, чтобы делать оттуда запросы к логам, а также готовый дашборд для визуализации метрик хранилища.
|
||||
▪️Простая, короткая документация, где есть всё необходимое для запуска и настройки.
|
||||
|
||||
Покажу примеры сбора логов в VictoriaLogs от Journald, Syslog и Vector. Для этого подготовил небольшой docker-compose.yml с некоторыми параметрами:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
victoria-logs:
|
||||
image: victoriametrics/victoria-logs:latest
|
||||
volumes:
|
||||
- ./victoria-logs-data:/victoria-logs-data
|
||||
command:
|
||||
- --storageDataPath=/victoria-logs-data
|
||||
- --retentionPeriod=90d
|
||||
- --syslog.listenAddr.tcp=:514
|
||||
ports:
|
||||
- 9428:9428
|
||||
- 514:514
|
||||
restart: always
|
||||
```
|
||||
Запускаем проект, переходим на порт 9428, чтобы убедиться в том, что всё запустилось. По умолчанию открывается страница с некоторыми ссылками на Web UI, Метрики и ключи запуска.
|
||||
|
||||
Отправим в VictoriaLogs логи от systemd от любого сервера, локального или внешнего. Для этого понадобится служба systemd-journal-remote (https://t.me/srv_admin/3136). Ставим её:
|
||||
|
||||
`# apt install systemd-journal-remote`
|
||||
|
||||
Редактируем конфиг /etc/systemd/journal-upload.conf, добавляя один параметр:
|
||||
```
|
||||
[Upload]
|
||||
URL=http://localhost:9428/insert/journald
|
||||
```
|
||||
URL, соответственно, измените, если у вас сбор логов не с локального сервера, а удалённого. Запускаем службу и проверяем, что она успешно начала отправку логов:
|
||||
|
||||
`# systemctl start systemd-journal-upload`
|
||||
`# systemctl status systemd-journal-upload`
|
||||
|
||||
Идём в веб интерфейс VictoriaLogs - http://212.193.59.87:9428/select/vmui и смотрим там логи.
|
||||
|
||||
Переходим к Syslog. Я уже добавил параметр syslog.listenAddr.tcp=:514. Убедитесь, что указанный порт прослушивается:
|
||||
|
||||
`# ss -tulnp | grep 514`
|
||||
|
||||
Если у вас этот порт уже занят syslog сервером, то измените порт для VictoriaLogs. В общем-то настраивать больше ничего не надо. Теперь в любом софте, который умеет отправлять данные в формате syslog, укажите в качестве сервера IP вашего VictoriaLogs. Например, в том же Микротике: System ⇨ Logging ⇨ Actions ⇨ Add Type Remote.
|
||||
|
||||
Для сбора логов от всех популярных агентов, типа Filebeat, Fluentd, Vector (https://t.me/srv_admin/2388) и т.д. тоже ничего специально настраивать не надо. Делаете всё точно так же, как для отправки логов в Elasticsearch, только в качестве endpoint указываете URL от вашего сервера VictoriaLogs. Вот пример для Vector:
|
||||
|
||||
```yaml
|
||||
sinks:
|
||||
vlogs:
|
||||
inputs:
|
||||
- nginx_access_logs
|
||||
type: elasticsearch
|
||||
endpoints:
|
||||
- http://212.193.59.87:9428/insert/elasticsearch/
|
||||
api_version: v8
|
||||
compression: gzip
|
||||
```
|
||||
Решение очень понравилось своей простотой, универсальностью и скоростью настройки. Буквально за час со всем разобрался и настроил. Никаких затруднений. Отдельно нужно решать вопрос доступа к приёмнику логов и веб интерфейсу. С уровня приложения никаких решений нет. Нужно либо firewall, либо proxy использовать.
|
||||
|
||||
Отдельно отмечу, что те же логи syslog и journald сразу парсятся по основным полям, типа hostname, time, cmdline и т.д. Ничего для этого настраивать не надо. Сразу в веб интерфейсе можно поиск и группировку по ним делать. Получается очень функциональное решение по простоте и скорости настройки на уровне обычного syslog сервера, но с гораздо большими возможностями.
|
||||

|
||||

|
||||

|
||||
11
NAS/Synology/Disable-check-hdd.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: Отключение проверки совместимости дисков в Synology
|
||||
description:
|
||||
published: true
|
||||
date: 2025-04-21T09:51:56.904Z
|
||||
tags: synology, check, hdd
|
||||
editor: markdown
|
||||
dateCreated: 2025-04-21T09:51:56.903Z
|
||||
---
|
||||
|
||||
https://github.com/007revad/Synology_HDD_db?tab=readme-ov-file
|
||||
19
NAS/Synology/Qemu-for-Synology.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!--
|
||||
title: Qemu agent for Synology
|
||||
description:
|
||||
published: true
|
||||
date: 2024-09-26T22:10:34.314Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2024-09-26T22:10:34.314Z
|
||||
-->
|
||||
|
||||
<p>Для того, чтобы была возможность управлять перезагрузкой и выключение в Proxmox нужно поставить дополнение</p>
|
||||
<p>Нужно добавить репозиторий: <a href="https://spk7.imnks.com">https://spk7.imnks.com</a></p>
|
||||
<figure class="image image_resized" style="width:52.45%;"><img src="/nas/qemu-1.png"></figure>
|
||||
<p><strong>Install it and don't start at first.</strong> Then you need to ssh in your Xpeno and run this command, as described:</p>
|
||||
<p>sudo sed -i 's/package/root/g' /var/packages/qemu-ga/conf/privilege</p>
|
||||
<p>After that you need to stop Xpeno VM, turn on Qemu Guest Agent in VM options at Proxmox console:</p>
|
||||
<figure class="image image_resized" style="width:52.32%;"><img src="/nas/qemu-2.png"></figure>
|
||||
<p>В Proxmox нужно включить агента.</p>
|
||||
<figure class="image image_resized" style="width:52.59%;"><img src="/nas/qemu-3.png"></figure>
|
||||
20
NAS/Synology/Synology-support-HEVC.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!--
|
||||
title: Synology-support-HEVC
|
||||
description:
|
||||
published: true
|
||||
date: 2024-09-26T22:26:34.511Z
|
||||
tags: hevc, synology
|
||||
editor: ckeditor
|
||||
dateCreated: 2024-04-01T15:15:52.913Z
|
||||
-->
|
||||
|
||||
<p>В synology photo не показывает пиктограммы и ролики формата HEVC.</p>
|
||||
<p>Решение проблемы:</p>
|
||||
<p><a href="https://xpenology.com/forum/topic/65643-ame-30-patcher/page/3/">https://xpenology.com/forum/topic/65643-ame-30-patcher/page/3/</a></p>
|
||||
<p><a href="https://github.com/wirgen/synocodectool-patch?tab=readme-ov-file">https://github.com/wirgen/synocodectool-patch?tab=readme-ov-file</a></p>
|
||||
<p><a href="https://bafista.ru/xpenology-ustanovka-ame-3-1-patch-dlya-dsm-7-2/">https://bafista.ru/xpenology-ustanovka-ame-3-1-patch-dlya-dsm-7-2/</a></p>
|
||||
<pre><code class="language-plaintext">#DSM7.1 AMУ 3.0.1-2004
|
||||
curl http://code.imnks.com/ame3patch/ame71-2004.sh | bash
|
||||
#DSM7.2 AME 3.1.0-3005
|
||||
curl http://code.imnks.com/ame3patch/ame72-3005.sh | bash
|
||||
wget http://code.imnks.com/ame3patch/ame72-3005.sh && sh ame72-3005.sh</code></pre>
|
||||
48
NAS/Synology/brtfs-or-ext-for-synology.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: Какую файловую систему выбрать brtfs или ext4 для synology ?
|
||||
description:
|
||||
published: true
|
||||
date: 2025-04-05T10:07:48.849Z
|
||||
tags: brtfs, ext4
|
||||
editor: markdown
|
||||
dateCreated: 2025-04-05T10:07:48.849Z
|
||||
---
|
||||
|
||||
Выбор между **Btrfs** и **ext4** для Synology зависит от ваших потребностей в функциональности, надёжности и производительности.
|
||||
|
||||
### **1. Btrfs (Рекомендуется для Synology)**
|
||||
**Плюсы:**
|
||||
✅ **Снимки (snapshots)** – возможность создавать мгновенные копии файлов для защиты от случайного удаления или ransomware.
|
||||
✅ **Самовосстановление данных** – проверка целостности данных и автоматическое исправление ошибок (если используется SHR-1/SHR-2 или RAID с избыточностью).
|
||||
✅ **Эффективное сжатие** – экономия места без потери производительности (особенно полезно для текстовых файлов, логов, баз данных).
|
||||
✅ **Дедупликация** (вручную или через сторонние утилиты) – экономия места при дублировании файлов.
|
||||
✅ **Поддержка копирования при записи (CoW)** – уменьшает риск повреждения данных.
|
||||
|
||||
**Минусы:**
|
||||
❌ **Требует больше ресурсов** (CPU, RAM) – на слабых моделях (например, DS220j) может работать медленнее.
|
||||
❌ **Не поддерживается на всех моделях** (старые или бюджетные Synology могут не иметь Btrfs).
|
||||
❌ **Чувствителен к внезапному отключению питания** (но Synology использует журналирование для минимизации рисков).
|
||||
|
||||
---
|
||||
|
||||
### **2. ext4 (Классический вариант)**
|
||||
**Плюсы:**
|
||||
✅ **Высокая скорость** – особенно на слабом железе.
|
||||
✅ **Стабильность** – проверенная временем файловая система.
|
||||
✅ **Меньше накладных расходов** – не требует много оперативной памяти.
|
||||
|
||||
**Минусы:**
|
||||
❌ **Нет снимков (snapshots)** – нельзя быстро откатить изменения.
|
||||
❌ **Нет самовосстановления данных** – при повреждении файлов потребуется проверка вручную (fsck).
|
||||
❌ **Нет сжатия и дедупликации** – занимает больше места.
|
||||
|
||||
---
|
||||
|
||||
### **Вывод: что выбрать?**
|
||||
- **Btrfs** – если у вас **NAS с двухдисковой (или более) конфигурацией (SHR-1/SHR-2, RAID 1/5/6)** и вы хотите **защиту от повреждения данных, снимки и сжатие**.
|
||||
- **ext4** – если у вас **однодисковый NAS** или **очень слабое железо** (например, серия **"j"**), и вам важна **максимальная скорость без дополнительных функций**.
|
||||
|
||||
#### **Рекомендация для большинства пользователей:**
|
||||
**Btrfs** – лучший выбор для Synology, если ваша модель его поддерживает. Он даёт больше возможностей для защиты данных и экономии места.
|
||||
|
||||
Если сомневаетесь, выбирайте **Btrfs**, но убедитесь, что у вас **достаточно оперативной памяти** (минимум **1-2 ГБ** для комфортной работы).
|
||||
70
NAS/Synology/cupsd.md
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: Подключение принтера в Synology
|
||||
description:
|
||||
published: true
|
||||
date: 2024-10-29T09:04:59.553Z
|
||||
tags: synology, cups
|
||||
editor: markdown
|
||||
dateCreated: 2024-10-29T09:04:59.553Z
|
||||
---
|
||||
|
||||
# Подключение принтера по usb
|
||||
https://github.com/ziwork/synology-airprint
|
||||
|
||||
Когда подключил принтер по usb к synology, то не получилось распечатать удаленно, вполне возможно что малая поддержка устройств.
|
||||
Нашел на просторах интернета проект synology-airprint с помощью которого получилось завести.
|
||||

|
||||
|
||||
Так как принтер не определяется с нормальным именем, например как /dev/ttyUSB0
|
||||
Поэтому пришлось делать символьную ссылку через планировщик
|
||||
`ln -s /dev/usb/04e8:3413:8J66BAAY331838K /dev/ttyUSB0`
|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
Создаем docker-compose с таким содержимым
|
||||
```
|
||||
nano docker-compose.yml
|
||||
|
||||
```
|
||||
```yaml
|
||||
version: '3.5'
|
||||
|
||||
services:
|
||||
airprint:
|
||||
container_name: airprint
|
||||
image: znetwork/synology-airprint:latest
|
||||
restart: always
|
||||
# network_mode: "bridge"
|
||||
network_mode: "host"
|
||||
devices:
|
||||
# - "/dev/bus/usb/001/001:/dev/ttyUSB0"
|
||||
- "/dev/ttyUSB0:/dev/ttyUSB0"
|
||||
# ports:
|
||||
# - "9631:631"
|
||||
environment:
|
||||
CUPSADMIN: admin
|
||||
CUPSPASSWORD: admin
|
||||
```
|
||||
Нужно по странице проекта остановить и выключить службы
|
||||
```
|
||||
sudo synosystemctl stop cupsd
|
||||
sudo synosystemctl stop cups-lpd
|
||||
sudo synosystemctl stop cups-service-handler
|
||||
sudo synosystemctl disable cupsd
|
||||
sudo synosystemctl disable cups-lpd
|
||||
sudo synosystemctl disable cups-service-handler
|
||||
```
|
||||
|
||||
И поднимаем контейнер (нужно перед этим через центр пакетов поставить Container Manager)
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Заходим на страницу и там добавляем принтер
|
||||
http://192.168.88.250:631/
|
||||
|
||||
И потом добавляем принтер на компьютере:
|
||||
через ipip http://192.168.88.250:631/printers/samsung
|
||||
75
NAS/Synology/install-xpenology.html
Normal file
@@ -0,0 +1,75 @@
|
||||
<!--
|
||||
title: Установка XPEnology
|
||||
description:
|
||||
published: true
|
||||
date: 2024-09-24T14:13:07.116Z
|
||||
tags: xpenology
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:50:54.856Z
|
||||
-->
|
||||
|
||||
<p>Источник: <a href="https://xpenology.club/install-dsm-7-on-baremetal-or-vm/">https://xpenology.club/install-dsm-7-on-baremetal-or-vm/</a></p>
|
||||
<p>На Proxmox <a href="https://www.wundertech.net/how-to-install-xpenology-on-proxmox-dsm-7/">https://www.wundertech.net/how-to-install-xpenology-on-proxmox-dsm-7/</a></p>
|
||||
<p><a href="https://www.wundertech.net/how-to-install-xpenology-on-proxmox-dsm-7/">https://www.wundertech.net/how-to-install-xpenology-on-proxmox-dsm-7/</a></p>
|
||||
<p>В новых материнских платах возможно потребуется отключить безопасную загрузку Windows в биосе.</p>
|
||||
<figure class="image"><img src="/attachments/xpenology/1.jpg"></figure>
|
||||
<p><strong>Тестовая версия, может что то не работать!</strong></p>
|
||||
<p>Идем по ссылке <a href="https://github.com/pocopico/tinycore-redpill">https://github.com/pocopico/tinycore-redpill</a> и качаем образ.</p>
|
||||
<figure class="image image_resized" style="width:62.59%;"><img src="/attachments/xpenology/2.jpg"></figure>
|
||||
<p>Разархивируем образ , должен появиться файл img.</p>
|
||||
<p>Вставляем флешку и записываем образ с помощью win32DiskImager или Rufus и делаем загрузку с USB.</p>
|
||||
<p> </p>
|
||||
<p>Удобнее работать удаленно через putty, поэтому нажимаем иконку терминала и смотрим ip адрес, который был получен.</p>
|
||||
<pre><code class="language-plaintext">ifconfig</code></pre>
|
||||
<p> </p>
|
||||
<figure class="image"><img src="/attachments/xpenology/3.jpg"></figure>
|
||||
<figure class="image"><img src="/attachments/xpenology/4.jpg"></figure>
|
||||
<p>Так же необходима программа WinSCP для того, чтобы скачать сформированный файл прошивки.</p>
|
||||
<figure class="image"><img src="/attachments/xpenology/5.png"></figure>
|
||||
<p><strong>Для входа используются логины и пароли:</strong></p>
|
||||
<blockquote>
|
||||
<p><strong>User: tc</strong><br><strong>Password: P@ssw0rd</strong></p>
|
||||
</blockquote>
|
||||
<p> </p>
|
||||
<p>Здесь вы можете найти нужные вам конфигурации. Вы можете заполнить их вручную (vid/pid/mac/disks) или попробовать использовать функции в скрипте.</p>
|
||||
<p>Вы можете редактировать файлы с помощью winscp. Но сначала нам нужно обновить скрипт до последней версии.</p>
|
||||
<p>Сначала проверьте, есть ли обновление скрипта.</p>
|
||||
<pre><code class="language-plaintext">sudo ./rploader.sh update now
|
||||
sudo ./rploader.sh fullupgrade now</code></pre>
|
||||
<p> </p>
|
||||
<figure class="image"><img src="/attachments/xpenology/6.jpg"></figure>
|
||||
<p> </p>
|
||||
<p>Когда это будет сделано, у вас будет последняя версия скрипта. Теперь пришло время отредактировать файл user_config.json</p>
|
||||
<figure class="image"><img src="/attachments/xpenology/7.png"></figure>
|
||||
<pre><code class="language-plaintext">user_config.json</code></pre>
|
||||
<p> </p>
|
||||
<figure class="image"><img src="/attachments/xpenology/8.png"></figure>
|
||||
<p> </p>
|
||||
<p>Вы можете вручную ввести правильные значения или попробовать использовать автоматическую функцию скрипта.</p>
|
||||
<pre><code class="language-plaintext">sudo ./rploader.sh serialgen DS3615xs realmac now
|
||||
...
|
||||
sudo ./rploader.sh satamap now
|
||||
...
|
||||
sudo ./rploader.sh identifyusb now
|
||||
...</code></pre>
|
||||
<p>Теперь пишем:</p>
|
||||
<pre><code class="language-plaintext">sudo ./rploader.sh</code></pre>
|
||||
<p>Чтобы просмотреть справку по скрипту и команды, которые вы можете использовать. Можнопоэкспериментировать с ними просто ради удовольствия.</p>
|
||||
<p>Убедитесь, что вы используете правильные настройки vid/pid/mac и диска. Если вы не используете правильный vid/pid, dsm не будет установлен.</p>
|
||||
<p>После генерации всех значений проверьте user_config.json, прежде чем запускать скрипт сборки.</p>
|
||||
<p>Есть еще команды, которые вы можете использовать, но они мне не нужны, поэтому я не буду их использовать. Вот помощь скрипта.</p>
|
||||
<p>В моем случае я использую:</p>
|
||||
<figure class="image"><img src="/attachments/xpenology/9.png"></figure>
|
||||
<pre><code class="language-plaintext">sudo ./rploader.sh build bromolow-7.0.1-42218</code></pre>
|
||||
<p>После завершения сборки загрузите файл *.pat через WinSCP по указанному пути и скачивайте на вашу локальную машину.</p>
|
||||
<pre><code class="language-plaintext">Found /home/tc/redpill-load/cache/ds3615xs_42218.pat, copying to cache directory : /mnt/sdc3/auxfiles</code></pre>
|
||||
<p>Можно скачать <a href="https://archive.synology.com/download/Os/DSM">тут</a></p>
|
||||
<figure class="image"><img src="/attachments/xpenology/10.png"></figure>
|
||||
<p> </p>
|
||||
<p>Перезагрузите свой компьютер (оставьте USB включенным), и запустится новый загрузчик, и вы сможете установить dsm или снова запустить tinycore.</p>
|
||||
<p><mark class="pen-red">Нашел инфу, что нужно </mark><a href="https://xpenology.com/forum/topic/57525-%D0%BF%D0%B5%D1%80%D0%B5%D1%85%D0%BE%D0%B4-%D0%BD%D0%B0-7xx-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-tinycore-redpill/"><mark class="pen-red">отключать </mark></a><mark class="pen-red">интернет синолоджи перед тем как устанавливать dsm.</mark></p>
|
||||
<p>Начните с <a href="http://find.synology.com">find.synology.com</a> в веб-браузере (или в программе <strong>Synology Assistant</strong>) и найдите свое хранилище dsm 7. Загрузите файл pat, который вы скачали, и будьте довольны своей версией DSM 7.</p>
|
||||
<figure class="image"><img src="/attachments/xpenology/11.png"></figure>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
142
NAS/Synology/scrutiny.html
Normal file
@@ -0,0 +1,142 @@
|
||||
<!--
|
||||
title: Просмотр атрибутов SMART в DSM 7.2.1 и новее
|
||||
description: scrutiny
|
||||
published: true
|
||||
date: 2025-03-12T10:21:29.816Z
|
||||
tags: scrutiny, smart
|
||||
editor: ckeditor
|
||||
dateCreated: 2025-03-12T10:21:29.816Z
|
||||
-->
|
||||
|
||||
<p>Источник: https://bafista.ru/prosmotr-atributov-smart-v-dsm-7-2-1-i-novee/</p>
|
||||
<h2><strong>Введение</strong></h2>
|
||||
<p>В самой лучшей на данный момент ОС DSM для NAS от компании Synology было все необходимое для работы с дисками. Но 26.09.2023 вышло <a href="https://www.synology.com/ru-ru/releaseNote/DSM"><u>обновление DSM 7.2.1</u></a> и вместе с ним обновление для <a href="https://www.synology.com/ru-ru/releaseNote/StorageManager"><u>диспетчера хранения</u></a> 1.0.0-0017. В этом обновлении произошло невероятное: <i><strong>Атрибуты S.M.A.R.T. больше не записываются и не отображаются.</strong></i></p>
|
||||
<p>При проверке опасения подтвердились. Кнопка просмотров атрибутов SMART пропала со своего места и теперь ее нигде нет. Очень печальная ситуация.</p>
|
||||
<p><a href="https://github.com/AnalogJ/scrutiny"><u>Scrutiny </u></a>– это инструмент, который собирает данные SMART с жесткого диска и отображает их через веб-интерфейс. Дополнительно ведется логирование полученных данных и есть возможность настроить уведомления.</p>
|
||||
<figure class="image image_resized" style="width:47.66%;"><img src="https://bafista.ru/wp-content/uploads/2023/09/scr-20230930-iwuw.png"></figure>
|
||||
<p> </p>
|
||||
<figure class="image image_resized" style="width:47.81%;"><img src="https://bafista.ru/wp-content/uploads/2023/09/scr-20230930-jdtv.png"></figure>
|
||||
<h2><strong>Установка Scrutiny</strong></h2>
|
||||
<p>Для установки нам понадобится Container Manager. Поэтому перед началом найдите его в центре пакетов и установите. Если в центре пакетов его нет, значит ваше устройство его не поддерживает и дальше вам можно не читать данную инструкцию.</p>
|
||||
<p>Откройте File station и перейдите в папку docker. В этой папке создайте пустой каталог с именем <strong>scrutiny</strong>, а внутри еще один пустой с именем <strong>influxdb</strong> как показано на картинке ниже.</p>
|
||||
<figure class="image image_resized" style="width:46.87%;"><img src="https://bafista.ru/wp-content/uploads/2023/09/image-180-1024x594.png"></figure>
|
||||
<p>Так тут же нужно создать файл <strong>collector.yaml</strong> следующего содержимого:</p>
|
||||
<pre><code class="language-plaintext">version: 1
|
||||
host:
|
||||
id: "NAS"
|
||||
devices:
|
||||
- device: /dev/sata1
|
||||
type: 'sat'
|
||||
# - device: /dev/sata2
|
||||
# type: 'sat'
|
||||
# - device: /dev/sata3
|
||||
# type: 'sat'
|
||||
- device: /dev/nvme0n1
|
||||
type: 'nvme'
|
||||
# - device: /dev/nvme1n1
|
||||
# type: 'nvme'</code></pre>
|
||||
<p>Разберем что в этом файле и зачем.</p>
|
||||
<ul>
|
||||
<li>ИмяСервера – замените на ваше, желательно латинскими буквами</li>
|
||||
<li>sata1 sata2 sata3 – это все ваши диски. Укажите тут точное количество ваших дисков в Synology и где они установлены. Номер 1 2 и 3 совпадает с номеров диска в слотах устройства. В некоторых случаях вместо sata1 sata2 sata3 и т.д. нужно указывать sda sdb sdc и т.д.</li>
|
||||
<li>nvme0m1 и nvme1n1 – это ssd диски установленные в M2 слоты, если у вас их нет, то просто удалите их.</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<p><i>Так же можно добавить диски подключенные по USB, подробнее в комментарии по </i><a href="https://bafista.ru/prosmotr-atributov-smart-v-dsm-7-2-1-i-novee/#comment-2692"><i><u>ссылке</u></i></a></p>
|
||||
</blockquote>
|
||||
<p>Теперь открываем Container Manager, переходим в проекты и нажимаем создать проект. В открывшемся окне придумываем имя, задаем путь, который мы ранее создали и выбираем создать docker-compose.yml как показано на картинке ниже.</p>
|
||||
<figure class="image"><img src="https://bafista.ru/wp-content/uploads/2023/09/image-181-1024x617.png"></figure>
|
||||
<p>В тактовое поле вставляем такой текст заранее его подредактировав:</p>
|
||||
<pre><code class="language-plaintext">services:
|
||||
scrutiny:
|
||||
container_name: scrutiny
|
||||
image: ghcr.io/analogj/scrutiny:master-omnibus
|
||||
cap_add:
|
||||
- SYS_RAWIO
|
||||
- SYS_ADMIN
|
||||
ports:
|
||||
- "8095:8080" # webapp
|
||||
- "8096:8086" # influxDB admin
|
||||
volumes:
|
||||
- /run/udev:/run/udev:ro
|
||||
- ./:/opt/scrutiny/config
|
||||
- ./influxdb:/opt/scrutiny/influxdb
|
||||
- ./scrutiny.yaml:/opt/scrutiny/config/scrutiny.yaml
|
||||
devices:
|
||||
- /dev/sata1:/dev/sata1
|
||||
# - /dev/sata2:/dev/sata2
|
||||
# - /dev/sata3:/dev/sata3
|
||||
- /dev/nvme0n1:/dev/nvme0n1
|
||||
# - /dev/nvme1n1:/dev/nvme1n1
|
||||
environment:
|
||||
- COLLECTOR_CRON_SCHEDULE='*/5 * * * *'
|
||||
- SCRUTINY_WEB_INFLUXDB_TOKEN=ANYLONGSTRING
|
||||
- SCRUTINY_WEB_INFLUXDB_INIT_USERNAME=sadmin
|
||||
- SCRUTINY_WEB_INFLUXDB_INIT_PASSWORD=6lise-shorter-Direct0
|
||||
- TZ=Europe/Moscow
|
||||
restart: unless-stopped</code></pre>
|
||||
<p>Разберем что в этом файле и зачем.</p>
|
||||
<ul>
|
||||
<li>Порт 8095 – это порт для web интерфейса scrutiny. Порт 8096 для web интерфейса influxDB. Порты после двоеточия 8080 и 8086 менять нельзя.</li>
|
||||
<li>sata1 sata2 sata3 – это все ваши диски. Укажите тут точное количество ваших дисков в Synology и где они установлены. Номер 1 2 и 3 совпадает с номеров диска в слотах устройства. В некоторых случаях вместо sata1 sata2 sata3 и т.д. нужно указывать sda sdb sdc и т.д.</li>
|
||||
<li>nvme0m1 и nvme1n1 – это ssd диски установленные в M2 слоты, если у вас их нет, то просто удалите их.</li>
|
||||
<li>Токен, логин и пароль устанавливайте на свое усмотрение, но не менее 8 символов иначе не будет работать.</li>
|
||||
</ul>
|
||||
<p>По умолчанию сбор данных в scrutiny выполняется раз в сутки и этого вполне достаточно почти всегда, но это можно переопределить вставив такую переменную:</p>
|
||||
<blockquote>
|
||||
<p><i>Спешу напомнить, что если вы хотите переопределить частоту запуска коллектора, то нужно заново создавать проект с контейнером.</i></p>
|
||||
<p style="text-align:center;"><i>!!! Не делайте часто, это не есть хорошо !!!</i></p>
|
||||
</blockquote>
|
||||
<pre><code class="language-plaintext">- COLLECTOR_CRON_SCHEDULE='*/1 * * * *'</code></pre>
|
||||
<p>Где:</p>
|
||||
<ul>
|
||||
<li>‘*/1 * * * *’ – запуск коллектора каждую минуту</li>
|
||||
<li>‘*/5 * * * *’ – запуск коллектора каждые 5 минут</li>
|
||||
<li>‘*/10 * * * *’ – запуск коллектора каждые 10 минут</li>
|
||||
<li>‘0 * * * *’ – запуск коллектора каждый час</li>
|
||||
</ul>
|
||||
<p>Далее нигде ничего менять не нужно, просто на заключительном этапе жмите выполнено для создания и запуска проекта scrutiny</p>
|
||||
<figure class="image"><img src="https://bafista.ru/wp-content/uploads/2023/09/image-182-1024x554.png"></figure>
|
||||
<p>Процесс этот весьма небыстрый. Будет скачен образ контейнера docker, затем распакован и создан сам контейнер. Если все сделано правильно, то увидите Exit Code 0, что означает успешное создание проекта с контейнером. Если нет, то увидите в чем проблема, ее нужно будет устранить и начать заново.</p>
|
||||
<figure class="image"><img src="https://bafista.ru/wp-content/uploads/2023/09/image-183-1024x559.png"></figure>
|
||||
<p> </p>
|
||||
<p>Теперь в браузере открываете новую вкладку и вбиваете http://IP-NAS:8095. Естественно, что IP адрес и порт вы вставляете свои.</p>
|
||||
<blockquote>
|
||||
<p><i>При создании проекта для него создается отдельная сеть bridge, которую нужно разрешить на фаерволе Synology, если он у вас включен</i></p>
|
||||
</blockquote>
|
||||
<figure class="image"><img src="https://bafista.ru/wp-content/uploads/2023/09/image-184-1024x674.png"></figure>
|
||||
<p>Для просмотра атрибутов SMART щелкните три точки у нужного диска и нажмите Detail</p>
|
||||
<figure class="image"><img src="https://bafista.ru/wp-content/uploads/2023/09/image-185-1024x674.png"></figure>
|
||||
<p>Тут нужно отметить, что данные обновляются раз в сутки в 6:00 утра или после старта контейнера scrunity.</p>
|
||||
<p><i>За образец была взята эта </i><a href="https://drfrankenstein.co.uk/2023/05/29/scrutiny-in-container-manager-on-a-synology-nas/"><i><u>инструкция</u></i></a><i>, но сделано по моему.</i></p>
|
||||
<p>Добавочные файлы config.yml</p>
|
||||
<pre><code class="language-plaintext">bolt-path: /opt/scrutiny/influxdb/influxd.bolt
|
||||
engine-path: /opt/scrutiny/influxdb/engine
|
||||
http-bind-address: ":8086"
|
||||
reporting-disabled: true
|
||||
</code></pre>
|
||||
<p>Уведомление через Gotify scrutiny.yml</p>
|
||||
<pre><code class="language-plaintext">version: 1
|
||||
|
||||
web:
|
||||
listen:
|
||||
port: 8080
|
||||
host: 0.0.0.0
|
||||
basepath: ''
|
||||
database:
|
||||
location: /opt/scrutiny/config/scrutiny.db
|
||||
src:
|
||||
frontend:
|
||||
path: /opt/scrutiny/web
|
||||
influxdb:
|
||||
host: 0.0.0.0
|
||||
port: 8086
|
||||
retention_policy: true
|
||||
log:
|
||||
file: '' #absolute or relative paths allowed, eg. web.log
|
||||
level: INFO
|
||||
notify:
|
||||
urls:
|
||||
# - "telegram://token@telegram?channels=channel-1[,channel-2,...]"
|
||||
- "gotify://prodik.ddns.net:8880/token"
|
||||
</code></pre>
|
||||
90
NAS/Synology/syn-console-command.md
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Synology - reindex photo
|
||||
description:
|
||||
published: true
|
||||
date: 2025-04-05T10:09:59.015Z
|
||||
tags: ssh, synology, reindex, photo
|
||||
editor: markdown
|
||||
dateCreated: 2024-11-27T08:35:34.807Z
|
||||
---
|
||||
|
||||
# Зависла индексация
|
||||
Попытки исправить проблему с зависшей индексацией ни к чему не привели.
|
||||
Пытался с помощью консольных команд, но ругался на битую таблицу в postgresql.
|
||||
Пробовал исправить таблицу, но не получилось.
|
||||
В итоге нашел решение, которое помогло, хотя очень кординальным методом, гроханием базы данных.
|
||||
|
||||
```
|
||||
sudo rm -rf /volume1/@database/pgsql
|
||||
reboot
|
||||
```
|
||||
После этого сделать реиндексацию фоток и видео.
|
||||
Источник https://community.synology.com/enu/forum/17/post/103120
|
||||
|
||||
## Перезапуск synology photo
|
||||
```bash
|
||||
synopkgctl stop SynologyPhotos && synopkgctl start SynologyPhotos
|
||||
```
|
||||
|
||||
## Реиндексация фото и видео
|
||||
```
|
||||
synoindex -a /volume3/photo/PhotoLibrary/2024/11/
|
||||
synoindex -R all
|
||||
```
|
||||
|
||||
Help:
|
||||
```
|
||||
bash-4.4# synoindex --help
|
||||
Usage:
|
||||
synoindex [OPTIONS]
|
||||
|
||||
Index Options:
|
||||
-h, --help
|
||||
this help text
|
||||
-A dirpath
|
||||
add a dir
|
||||
-a filepath
|
||||
add a file
|
||||
-D dirpath
|
||||
delete a dir
|
||||
-d filepath
|
||||
delete a file
|
||||
-N new_dirpath old_dirpath
|
||||
rename a dir
|
||||
-n new_filepath old_filepath
|
||||
rename a file
|
||||
-R [all|media|photo|music|video|thumb|dirpath]
|
||||
all: reindex all dirpath that registered in each package
|
||||
media: reindex dirpath that registered in MediaIndex package
|
||||
photo: reindex photo dirpath
|
||||
music: reindex music dirpath
|
||||
video: reindex video dirpath
|
||||
thumb: check converted video of each video file
|
||||
dirpath: reindex this specific dirpath
|
||||
-R user:{user_name}
|
||||
reindex personal photo dirpath
|
||||
-R share:{share_name}
|
||||
reindex share dirpath
|
||||
-R [type_music|type_video|type_photo]
|
||||
reindex dirpath that registered with specific type in MediaIndex
|
||||
|
||||
Package Index Options:
|
||||
-P [MediaIndex|{package_name}] {index_option}
|
||||
index operation only apply on this package
|
||||
-p [MediaIndex|{package_name}] {index_option}
|
||||
index operation apply all packages except for this package
|
||||
|
||||
File Index Options:
|
||||
-f {index_option}
|
||||
index operation apply on file index
|
||||
-U photo
|
||||
update photo images
|
||||
```
|
||||
|
||||
```
|
||||
/var/packages/SynologyPhotos/target/usr/bin/synofoto-bin-clear-index-task -t thumbnail
|
||||
```
|
||||
|
||||
```
|
||||
/var/packages/SynologyPhotos/target/usr/bin/synofoto-bin-index-tool -t basic -i /volume3/photo/PhotoLibrary/2024/ -t basic_reindex
|
||||
```
|
||||
11
NAS/Synology/synology_app_mover.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!--
|
||||
title: Перенос приложений на другой том
|
||||
description:
|
||||
published: true
|
||||
date: 2025-04-05T12:08:46.013Z
|
||||
tags: synology, app, move
|
||||
editor: ckeditor
|
||||
dateCreated: 2025-04-05T12:08:46.013Z
|
||||
-->
|
||||
|
||||
<p>https://github.com/007revad/Synology_app_mover</p>
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Lampa
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:16:40.380Z
|
||||
date: 2024-07-09T09:49:47.593Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:16:40.380Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Jacket
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:16:16.404Z
|
||||
date: 2024-07-09T09:49:59.258Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:16:16.404Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Torrserver
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:17:38.636Z
|
||||
date: 2024-07-09T09:50:02.697Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:17:38.636Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Сервис документации Gitbook
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:25:24.896Z
|
||||
date: 2024-07-09T09:50:06.265Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:25:24.896Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Joplin аля Evernote
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:20:19.477Z
|
||||
date: 2024-07-09T09:50:10.752Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:20:19.477Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Автоматизации написания документации
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:23:59.264Z
|
||||
date: 2024-07-09T09:50:14.462Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:22:07.682Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Zammad
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:13:37.364Z
|
||||
date: 2024-07-09T09:50:18.059Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:12:51.621Z
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: FreeScout Help Desk
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:12:07.708Z
|
||||
date: 2024-07-09T09:50:21.851Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:12:07.708Z
|
||||
|
||||
@@ -2,225 +2,262 @@
|
||||
title: Менеджер паролей Passwork
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:43:00.037Z
|
||||
date: 2024-07-09T09:50:26.092Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:36:08.780Z
|
||||
-->
|
||||
|
||||
<h1>Описание</h1>
|
||||
<p> </p>
|
||||
<blockquote>
|
||||
<p>Пассворк упрощает совместную работу с корпоративными паролями. Все данные безопасно хранятся на вашем сервере, а сотрудники быстро находят нужные пароли. Администратор управляет правами пользователей, отслеживает все действия и изменения.</p>
|
||||
<p> </p>
|
||||
</blockquote>
|
||||
<figure class="image"><img src="/attachments/image2022-12-12_11-39-19.png"></figure>
|
||||
<figure class="image"><img src="/attachments/image2022-12-12_11-39-59.png"></figure>
|
||||
<figure class="image"><img src="/attachments/image2022-12-12_11-41-52.png"></figure>
|
||||
<p>Рекомендации по установке</p>
|
||||
<h3><strong>Минимальные системные требования</strong></h3>
|
||||
<p>Пассворк не требователен к ресурсам сервера(-ов). Объемы необходимых ресурсов (RAM, CPU, HDD) и количество серверов зависят от количества активных пользователей, объема хранимых данных, а также требований к отказоустойчивости системы.</p>
|
||||
<blockquote>
|
||||
<p>Показатель IOPS имеет большое значения для скорости работы базы данных, поэтому желательно использовать SSD диски.</p>
|
||||
</blockquote>
|
||||
<p><strong>Варианты установки Пассворк на выделенных или виртуальных серверах</strong></p>
|
||||
<h3>1. Все на одном сервере</h3>
|
||||
<p>Обычно подходит для редакций до 500 пользователей, без специальных требований по хранению данных:</p>
|
||||
<figure class="table">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Кол-во пользователей</th>
|
||||
<th>RAM</th>
|
||||
<th>CPU</th>
|
||||
<th>HDD</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 50</th>
|
||||
<th>2-4 ГБ</th>
|
||||
<th>4</th>
|
||||
<th>100 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 100</th>
|
||||
<th>4-8 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>150 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 500</th>
|
||||
<th>8-16 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>200 ГБ</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</figure>
|
||||
<p><strong>2. Сервер приложения и база данных на разных серверах</strong></p>
|
||||
<p>База данных и сервер приложения разносятся по разным серверам. </p>
|
||||
<p>RAM-1, CPU-1, HDD-1 — сервер приложения.</p>
|
||||
<p>RAM-2, CPU-2, HDD-2 — база данных.</p>
|
||||
<figure class="table">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Кол-во пользователей</th>
|
||||
<th>RAM-1</th>
|
||||
<th>CPU-1</th>
|
||||
<th>HDD-1</th>
|
||||
<th>RAM-2</th>
|
||||
<th>CPU-2</th>
|
||||
<th>HDD-2</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 50</th>
|
||||
<th>2-4 ГБ</th>
|
||||
<th>4</th>
|
||||
<th>100 ГБ</th>
|
||||
<th>2-4 ГБ</th>
|
||||
<th>4</th>
|
||||
<th>100 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 100</th>
|
||||
<th>4 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>100 ГБ</th>
|
||||
<th>4 ГБ</th>
|
||||
<th>4</th>
|
||||
<th>150 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 500</th>
|
||||
<th>8-16 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>100 ГБ</th>
|
||||
<th>8 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>200 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 1000</th>
|
||||
<th>8-16 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>100 ГБ</th>
|
||||
<th>16 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>200 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 10000</th>
|
||||
<th>16-32 ГБ</th>
|
||||
<th>16</th>
|
||||
<th>100 ГБ</th>
|
||||
<th>16-32 ГБ</th>
|
||||
<th>16</th>
|
||||
<th>200 ГБ</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</figure>
|
||||
<p> </p>
|
||||
<h1>Установка</h1>
|
||||
<h2>Установка Docker</h2>
|
||||
<p>Скачайте и установите Docker CE (<a href="https://docs.docker.com/engine/installation/">https://docs.docker.com/engine/installation/</a>).</p>
|
||||
<p>Cкачайте и установите Docker-сompose (<a href="https://docs.docker.com/compose/install/">https://docs.docker.com/compose/install/</a>)</p>
|
||||
<p><strong>Обновите систему:</strong></p>
|
||||
<pre><code class="language-plaintext">sudo –i
|
||||
apt-get update
|
||||
apt-get upgrade</code></pre>
|
||||
<p><strong>Установите Git:</strong></p>
|
||||
<pre><code class="language-plaintext">apt-get install git</code></pre>
|
||||
<p><strong>Скачайте файлы управления и шаблонные конфиг-файлы</strong></p>
|
||||
<p>Создайте директорию /server и склонируйте файлы:</p>
|
||||
<pre><code class="language-plaintext">rm /server/sites/prod/.gitkeep</code></pre>
|
||||
<p>Склонируйте репозиторий. Укажите логин и пароль, которые вам сообщили менеджеры Пассворк.</p>
|
||||
<pre><code class="language-plaintext">git clone http://passwork.download/passwork/passwork.git /server/sites/prod</code></pre>
|
||||
<pre><code class="language-plaintext">cd /server/sites/prod/
|
||||
git checkout v5</code></pre>
|
||||
<blockquote>
|
||||
<p>Где взять логин и пароль</p>
|
||||
<p>Мы отправляем логин и пароль к нашему репозиторию после покупки Пассворк.</p>
|
||||
</blockquote>
|
||||
<p><strong>Перейдите в каталог для Docker Compose</strong></p>
|
||||
<pre><code class="language-plaintext">cd /server/docker-compose/</code></pre>
|
||||
<p>В каталоге есть файл docker-compose.override.yml , в котором можно указать назначение портов, на случай если порты могут быть заняты.</p>
|
||||
<p><strong>Запустите Docker Compose</strong></p>
|
||||
<pre><code class="language-plaintext">docker-compose up -d</code></pre>
|
||||
<p><strong>Проверьте, что контейнеры запустились и работают:</strong></p>
|
||||
<pre><code class="language-plaintext">docker ps</code></pre>
|
||||
<h3><strong>Инсталляция</strong></h3>
|
||||
<p>При первом открытии Пассворк вы увидите диалог инсталляции, который проверит корректность настройки сервера и позволит ввести базовые параметры.</p>
|
||||
<figure class="image"><img src="/attachments/снимок_экрана_2023-11-15_193934.png"></figure>
|
||||
<p>Тут нужно подправить сервер и указать строчку: <a href="mongodb://db:27017">mongodb://db:27017</a></p>
|
||||
<p>Нужно будет сохранить ключ шифрования для восстановления, если появится такая необходимость.</p>
|
||||
<p><strong>Зарегистрируйте администратора Пассворк</strong></p>
|
||||
<p>Введите логин и пароль для первого пользователя. Пользователь автоматически станет администратором и владельцем организации.</p>
|
||||
<p> </p>
|
||||
<h1>Обслуживание</h1>
|
||||
<h2>Настройка фоновых задач</h2>
|
||||
<p>Фоновые задачи — это задачи, которые выполняются по планировщику в фоновом режиме. Например, синхронизация LDAP, загрузка фавиконов и другие задачи, которые требует много времени, постоянного выполнения или распределения ресурсов.</p>
|
||||
<p>Проверить список запланированных задач и корректность всех настроек можно на странице «Фоновые задачи».</p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p>Для настройки фоновых задач необходимо настроить планировщик вашей операционной системы Cron (для Линукс) или Windows Scheduler. Планировщик должен запускать скрипт <code><u><папка с Пассворк>/app/tools/run-scheduled-tasks.php</u></code> каждую минуту.</p>
|
||||
<p>Скрипт проанализирует какие задачи необходимо запустить и для каждой задачи создаст отдельный поток. При выполнении каждая задача записывает лог в папку <code><u><папка Пассворк>/app/logs/</u></code><u> в файлы вида </u><code><u>task-*.log</u></code>, например, <code><u>task-62f8e9624e0446fba40bbb12.log</u></code>. После завершения задачи вы можете посмотреть и скачать лог со страницы Фоновые задачи → История задач.</p>
|
||||
<p>Системные логи планировщика (с ошибками) находятся в <code><u><папка Пассворк>/app/logs/run-command.log</u></code>.</p>
|
||||
<h2>О Docker-образах</h2>
|
||||
<p>Docker-образы устроены таким способом, что все важные данные вынесены в общие с хостовой машиной папки. Поэтому вы можете смело останавливать, удалять и создавать новые контейнеры. Конфигурационные файлы так же хранятся в общих папках (т.е. не в контейнере), поэтому вы можете провести любую настройку Nginx, PHP и MongoDB без внесения изменений непосредственно в образы или контейнеры. Просто внесите изменения в конфиг файлы и перезапустите контейнер или сервисы.</p>
|
||||
<p>Если вам необходимо внести изменения в образ, то войдите в контейнер, внесите изменения и затем сделайте коммит в ваш образ командой</p>
|
||||
<pre><code class="language-plaintext">docker commit <container id> you-name/image-name</code></pre>
|
||||
<p>Более подробно описано в официальной документации Docker.</p>
|
||||
<h2>Полезные команды</h2>
|
||||
<p>Скопируйте утилиту <i>dexec</i> в /usr/bin/:</p>
|
||||
<p><code>cp</code> <code>/server/dexec</code> <code>/usr/bin/dexec</code></p>
|
||||
<p>Вход в контейнер:</p>
|
||||
<p>bash]]></p>
|
||||
<p>Восстановление прав для файлов сайта (требуется после обновления):</p>
|
||||
<p>Перезагрузка Nginx без остановки:</p>
|
||||
<p>Контейнеры запущены с опцией autostart. Это означает, что Docker автоматически перезапустит контейнер, если он по каким-либо причинам остановится. Поэтому, если вам необходимо остановить контейнер, сперва отключите autostart:</p>
|
||||
<p>]]></p>
|
||||
<p>Включить autostart обратно:</p>
|
||||
<p>]]></p>
|
||||
<p>Без опции autostart вы можете остановить контейнеры принудительно:</p>
|
||||
<p>]]></p>
|
||||
<p>Обратите внимание, что если опция <i>autostart</i> включена, то эти команды перезапустят Nginx и MongoDB, Используйте ее в крайних случаях, так как это может повлечь порчу данных.</p>
|
||||
<h2>Структура файлов</h2>
|
||||
<p>Файлы конфигураций:</p>
|
||||
<p>Данные (база данных):</p>
|
||||
<p>Логи:</p>
|
||||
<p>Сайты:</p>
|
||||
<h2>Пример: Как изменить конфигурацию Nginx или PHP</h2>
|
||||
<p>Отредактируйте файлы:</p>
|
||||
<p>Перезапустите nginx и php-fpm:</p>
|
||||
<h2>Настройка почты</h2>
|
||||
<p>Nginx контейнер использует Postfix для отправки почты. Все конфигурационные файлы вы можете найти здесь:</p>
|
||||
<p>Отредактируйте их под свои нужды. Перезапустите Postfix, чтобы изменения вступили в силу.</p>
|
||||
<h2>Пример настройки Postfix</h2>
|
||||
<p>Откройте конфигурационный файл <code>/server/conf/postfix/</code><a href="http://main.cf"><code>main.cf</code></a>.</p>
|
||||
<p>Убедитесь в том, что параметр myhostname совпадает с полным доменным именем вашего сервера:</p>
|
||||
<h3>Настройка имен и паролей SMTP</h3>
|
||||
<p>Откройте или создайте файл <code>/server/conf/postfix/sasl_passwd</code>.</p>
|
||||
<p>Добавьте SMTP хост, имя пользователя и пароль должны быть записаны в следующем формате:</p>
|
||||
<p>Если вы хотите использовать нестандартный TCP-порт (например, 587), используйте следующий формат:</p>
|
||||
<p>для Gmail запись будет выглядеть следующим образом:</p>
|
||||
<p>Создайте хэшированную базу данных для Postfix, выполните команду postmap:</p>
|
||||
<p>После успешного выполнения команды в директории /server/conf/postfix должен появиться новый файл sasl_passwd.db.</p>
|
||||
<h3>Защита файла с паролями и хэш-файла.</h3>
|
||||
<p>Файлы /server/conf/postfix/sasl_passwd и /server/conf/postfix/sasl_passwd.db, созданные в предыдущих шагах, содержат ваши учетные данные SMTP в виде простого текста. По соображениям безопасности вы должны изменить права доступа к ним, так чтобы только пользователь root мог читать и записывать в файл.</p>
|
||||
<p>Выполните следующие команды, чтобы изменить владельца файлов на root и обновить права доступа для файлов:</p>
|
||||
<h3><strong>Конфигурация релей сервера</strong></h3>
|
||||
<p>Откройте файл <code>/server/conf/postfix/</code><a href="http://main.cf"><code>main.cf</code></a>.</p>
|
||||
<p>Измените параметр relayhost, на свой внешний SMTP релей. Если в файле sasl_passwd был указан нестандартный TCP-порт, то вы должны использовать тот же порт при настройке параметра relayhost.</p>
|
||||
<p>Укажите SMTP релей:</p>
|
||||
<p>для Gmail запись будет выглядеть следующим образом:</p>
|
||||
<p>В конце файла добавьте следующие параметры для включения аутентификации:</p>
|
||||
<p>Сохраните изменения.</p>
|
||||
<p>Перезапустите Postfix:</p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<h1>Описание</h1>
|
||||
<p> </p>
|
||||
<blockquote>
|
||||
<p>Пассворк упрощает совместную работу с корпоративными паролями. Все данные безопасно хранятся на вашем сервере, а сотрудники быстро находят нужные пароли. Администратор управляет правами пользователей, отслеживает все действия и изменения.</p>
|
||||
<p> </p>
|
||||
</blockquote>
|
||||
<figure class="image"><img src="/attachments/image2022-12-12_11-39-19.png"></figure>
|
||||
<figure class="image"><img src="/attachments/image2022-12-12_11-39-59.png"></figure>
|
||||
<figure class="image"><img src="/attachments/image2022-12-12_11-41-52.png"></figure>
|
||||
<p>Рекомендации по установке</p>
|
||||
<h3><strong>Минимальные системные требования</strong></h3>
|
||||
<p>Пассворк не требователен к ресурсам сервера(-ов). Объемы необходимых ресурсов (RAM, CPU, HDD) и количество серверов зависят от количества активных пользователей, объема хранимых данных, а также требований к отказоустойчивости системы.</p>
|
||||
<blockquote>
|
||||
<p>Показатель IOPS имеет большое значения для скорости работы базы данных, поэтому желательно использовать SSD диски.</p>
|
||||
</blockquote>
|
||||
<p><strong>Варианты установки Пассворк на выделенных или виртуальных серверах</strong></p>
|
||||
<h3>1. Все на одном сервере</h3>
|
||||
<p>Обычно подходит для редакций до 500 пользователей, без специальных требований по хранению данных:</p>
|
||||
<figure class="table">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Кол-во пользователей</th>
|
||||
<th>RAM</th>
|
||||
<th>CPU</th>
|
||||
<th>HDD</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 50</th>
|
||||
<th>2-4 ГБ</th>
|
||||
<th>4</th>
|
||||
<th>100 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 100</th>
|
||||
<th>4-8 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>150 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 500</th>
|
||||
<th>8-16 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>200 ГБ</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</figure>
|
||||
<p><strong>2. Сервер приложения и база данных на разных серверах</strong></p>
|
||||
<p>База данных и сервер приложения разносятся по разным серверам. </p>
|
||||
<p>RAM-1, CPU-1, HDD-1 — сервер приложения.</p>
|
||||
<p>RAM-2, CPU-2, HDD-2 — база данных.</p>
|
||||
<figure class="table">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Кол-во пользователей</th>
|
||||
<th>RAM-1</th>
|
||||
<th>CPU-1</th>
|
||||
<th>HDD-1</th>
|
||||
<th>RAM-2</th>
|
||||
<th>CPU-2</th>
|
||||
<th>HDD-2</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 50</th>
|
||||
<th>2-4 ГБ</th>
|
||||
<th>4</th>
|
||||
<th>100 ГБ</th>
|
||||
<th>2-4 ГБ</th>
|
||||
<th>4</th>
|
||||
<th>100 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 100</th>
|
||||
<th>4 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>100 ГБ</th>
|
||||
<th>4 ГБ</th>
|
||||
<th>4</th>
|
||||
<th>150 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 500</th>
|
||||
<th>8-16 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>100 ГБ</th>
|
||||
<th>8 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>200 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 1000</th>
|
||||
<th>8-16 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>100 ГБ</th>
|
||||
<th>16 ГБ</th>
|
||||
<th>8</th>
|
||||
<th>200 ГБ</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>до 10000</th>
|
||||
<th>16-32 ГБ</th>
|
||||
<th>16</th>
|
||||
<th>100 ГБ</th>
|
||||
<th>16-32 ГБ</th>
|
||||
<th>16</th>
|
||||
<th>200 ГБ</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</figure>
|
||||
<p> </p>
|
||||
<h1>Установка</h1>
|
||||
<h2>Установка Docker</h2>
|
||||
<p>Скачайте и установите Docker CE (<a href="https://docs.docker.com/engine/installation/">https://docs.docker.com/engine/installation/</a>).</p>
|
||||
<p>Cкачайте и установите Docker-сompose (<a href="https://docs.docker.com/compose/install/">https://docs.docker.com/compose/install/</a>)</p>
|
||||
<p><strong>Обновите систему:</strong></p>
|
||||
<pre><code class="language-plaintext">sudo –i
|
||||
apt-get update
|
||||
apt-get upgrade</code></pre>
|
||||
<p><strong>Установите Git:</strong></p>
|
||||
<pre><code class="language-plaintext">apt-get install git</code></pre>
|
||||
<p><strong>Скачайте файлы управления и шаблонные конфиг-файлы</strong></p>
|
||||
<p>Создайте директорию /server и склонируйте файлы:</p>
|
||||
<pre><code class="language-plaintext">rm /server/sites/prod/.gitkeep</code></pre>
|
||||
<p>Склонируйте репозиторий. Укажите логин и пароль, которые вам сообщили менеджеры Пассворк.</p>
|
||||
<pre><code class="language-plaintext">git clone http://passwork.download/passwork/passwork.git /server/sites/prod</code></pre>
|
||||
<p> </p>
|
||||
<pre><code class="language-plaintext">cd /server/sites/prod/
|
||||
git checkout v5</code></pre>
|
||||
<p> </p>
|
||||
<blockquote>
|
||||
<p>Где взять логин и пароль</p>
|
||||
<p>Мы отправляем логин и пароль к нашему репозиторию после покупки Пассворк.</p>
|
||||
</blockquote>
|
||||
<p><strong>Перейдите в каталог для Docker Compose</strong></p>
|
||||
<pre><code class="language-plaintext">cd /server/docker-compose/</code></pre>
|
||||
<p>В каталоге есть файл docker-compose.override.yml , в котором можно указать назначение портов, на случай если порты могут быть заняты.</p>
|
||||
<p><strong>Запустите Docker Compose</strong></p>
|
||||
<pre><code class="language-plaintext">docker-compose up -d</code></pre>
|
||||
<p><strong>Проверьте, что контейнеры запустились и работают:</strong></p>
|
||||
<pre><code class="language-plaintext">docker ps</code></pre>
|
||||
<h3><strong>Инсталляция</strong></h3>
|
||||
<p>При первом открытии Пассворк вы увидите диалог инсталляции, который проверит корректность настройки сервера и позволит ввести базовые параметры.</p>
|
||||
<figure class="image"><img src="/attachments/снимок_экрана_2023-11-15_193934.png"></figure>
|
||||
<p>Тут нужно подправить сервер и указать строчку: <a href="mongodb://db:27017">mongodb://db:27017</a></p>
|
||||
<p>Нужно будет сохранить ключ шифрования для восстановления, если появится такая необходимость.</p>
|
||||
<p><strong>Зарегистрируйте администратора Пассворк</strong></p>
|
||||
<p>Введите логин и пароль для первого пользователя. Пользователь автоматически станет администратором и владельцем организации.</p>
|
||||
<p> </p>
|
||||
<h1>Обслуживание</h1>
|
||||
<h2>Настройка фоновых задач</h2>
|
||||
<p>Фоновые задачи — это задачи, которые выполняются по планировщику в фоновом режиме. Например, синхронизация LDAP, загрузка фавиконов и другие задачи, которые требует много времени, постоянного выполнения или распределения ресурсов.</p>
|
||||
<p>Проверить список запланированных задач и корректность всех настроек можно на странице «Фоновые задачи».</p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p>Для настройки фоновых задач необходимо настроить планировщик вашей операционной системы Cron (для Линукс) или Windows Scheduler. Планировщик должен запускать скрипт <code><u><папка с Пассворк>/app/tools/run-scheduled-tasks.php</u></code> каждую минуту.</p>
|
||||
<p>Скрипт проанализирует какие задачи необходимо запустить и для каждой задачи создаст отдельный поток. При выполнении каждая задача записывает лог в папку <code><u><папка Пассворк>/app/logs/</u></code><u> в файлы вида </u><code><u>task-*.log</u></code>, например, <code><u>task-62f8e9624e0446fba40bbb12.log</u></code>. После завершения задачи вы можете посмотреть и скачать лог со страницы Фоновые задачи → История задач.</p>
|
||||
<p>Системные логи планировщика (с ошибками) находятся в <code><u><папка Пассворк>/app/logs/run-command.log</u></code>.</p>
|
||||
<h2>О Docker-образах</h2>
|
||||
<p>Docker-образы устроены таким способом, что все важные данные вынесены в общие с хостовой машиной папки. Поэтому вы можете смело останавливать, удалять и создавать новые контейнеры. Конфигурационные файлы так же хранятся в общих папках (т.е. не в контейнере), поэтому вы можете провести любую настройку Nginx, PHP и MongoDB без внесения изменений непосредственно в образы или контейнеры. Просто внесите изменения в конфиг файлы и перезапустите контейнер или сервисы.</p>
|
||||
<p>Если вам необходимо внести изменения в образ, то войдите в контейнер, внесите изменения и затем сделайте коммит в ваш образ командой</p>
|
||||
<pre><code class="language-plaintext">docker commit <container id> you-name/image-name</code></pre>
|
||||
<p>Более подробно описано в официальной документации Docker.</p>
|
||||
<h2>Полезные команды</h2>
|
||||
<p>Скопируйте утилиту <i>dexec</i> в /usr/bin/:</p>
|
||||
<pre><code class="language-plaintext">cp /server/dexec /usr/bin/dexec</code></pre>
|
||||
<p>Вход в контейнер:</p>
|
||||
<pre><code class="language-plaintext">docker exec -it <container> bash</code></pre>
|
||||
<p>Восстановление прав для файлов сайта (требуется после обновления):</p>
|
||||
<pre><code class="language-plaintext">/server/docker-nginx-permissions nginx</code></pre>
|
||||
<p>Перезагрузка Nginx без остановки:</p>
|
||||
<pre><code class="language-plaintext">/server/docker-nginx-reload nginx</code></pre>
|
||||
<p>Контейнеры запущены с опцией autostart. Это означает, что Docker автоматически перезапустит контейнер, если он по каким-либо причинам остановится. Поэтому, если вам необходимо остановить контейнер, сперва отключите autostart:</p>
|
||||
<pre><code class="language-plaintext">/server/docker-norestart <container></code></pre>
|
||||
<p>Включить autostart обратно:</p>
|
||||
<pre><code class="language-plaintext">/server/docker-autorestart <container></code></pre>
|
||||
<p>Без опции autostart вы можете остановить контейнеры принудительно:</p>
|
||||
<pre><code class="language-plaintext">docker stop <container></code></pre>
|
||||
<p>Обратите внимание, что если опция <i>autostart</i> включена, то эти команды перезапустят Nginx и MongoDB, Используйте ее в крайних случаях, так как это может повлечь порчу данных.</p>
|
||||
<h2>Структура файлов</h2>
|
||||
<p>Файлы конфигураций:</p>
|
||||
<pre><code class="language-plaintext">/server/conf/</code></pre>
|
||||
<p>Данные (база данных):</p>
|
||||
<pre><code class="language-plaintext">/server/data/</code></pre>
|
||||
<p>Логи:</p>
|
||||
<pre><code class="language-plaintext">/server/log/</code></pre>
|
||||
<p>Сайты:</p>
|
||||
<pre><code class="language-plaintext">/server/sites/</code></pre>
|
||||
<h2>Пример: Как изменить конфигурацию Nginx или PHP</h2>
|
||||
<p>Отредактируйте файлы:</p>
|
||||
<pre><code class="language-plaintext">mcedit /server/conf/nginx/prod.site
|
||||
mcedit /server/conf/nginx/nginx.conf
|
||||
mcedit /server/conf/php8/php.ini</code></pre>
|
||||
<p>Перезапустите nginx и php-fpm:</p>
|
||||
<pre><code class="language-plaintext">/server/docker-nginx-reload nginx
|
||||
docker restart php8</code></pre>
|
||||
<h2>Настройка почты</h2>
|
||||
<p>Nginx контейнер использует Postfix для отправки почты. Все конфигурационные файлы вы можете найти здесь:</p>
|
||||
<pre><code class="language-plaintext">/server/conf/postfix/</code></pre>
|
||||
<p>Отредактируйте их под свои нужды. Перезапустите Postfix, чтобы изменения вступили в силу.</p>
|
||||
<h2>Пример настройки Postfix</h2>
|
||||
<p>Откройте конфигурационный файл <code>/server/conf/postfix/</code><a href="http://main.cf"><code>main.cf</code></a>.</p>
|
||||
<pre><code class="language-plaintext">mcedit /server/conf/postfix/main.cf</code></pre>
|
||||
<p>Убедитесь в том, что параметр myhostname совпадает с полным доменным именем вашего сервера:</p>
|
||||
<pre><code class="language-plaintext">myhostname = passwork</code></pre>
|
||||
<h3>Настройка имен и паролей SMTP</h3>
|
||||
<p>Откройте или создайте файл <code>/server/conf/postfix/sasl_passwd</code>.</p>
|
||||
<pre><code class="language-plaintext">mcedit /server/conf/postfix/sasl_passwd</code></pre>
|
||||
<p>Добавьте SMTP хост, имя пользователя и пароль должны быть записаны в следующем формате:</p>
|
||||
<pre><code class="language-plaintext">[mail.isp.example] username:password</code></pre>
|
||||
<p>Если вы хотите использовать нестандартный TCP-порт (например, 587), используйте следующий формат:</p>
|
||||
<pre><code class="language-plaintext">[mail.isp.example]:587 username:password</code></pre>
|
||||
<p>для Gmail запись будет выглядеть следующим образом:</p>
|
||||
<pre><code class="language-plaintext">[smtp.gmail.com]:587 username:password</code></pre>
|
||||
<p>Создайте хэшированную базу данных для Postfix, выполните команду postmap:</p>
|
||||
<pre><code class="language-plaintext">docker exec -it postfix postmap /etc/postfix/sasl_passwd</code></pre>
|
||||
<p>После успешного выполнения команды в директории /server/conf/postfix должен появиться новый файл sasl_passwd.db.</p>
|
||||
<h3>Защита файла с паролями и хэш-файла.</h3>
|
||||
<p>Файлы /server/conf/postfix/sasl_passwd и /server/conf/postfix/sasl_passwd.db, созданные в предыдущих шагах, содержат ваши учетные данные SMTP в виде простого текста. По соображениям безопасности вы должны изменить права доступа к ним, так чтобы только пользователь root мог читать и записывать в файл.</p>
|
||||
<p>Выполните следующие команды, чтобы изменить владельца файлов на root и обновить права доступа для файлов:</p>
|
||||
<pre><code class="language-plaintext">chown root:root /server/conf/postfix/sasl_passwd /server/conf/postfix/sasl_passwd.db
|
||||
chmod 0600 /server/conf/postfix/sasl_passwd /server/conf/postfix/sasl_passwd.db</code></pre>
|
||||
<h3><strong>Конфигурация релей сервера</strong></h3>
|
||||
<p>Откройте файл <code>/server/conf/postfix/</code><a href="http://main.cf"><code>main.cf</code></a></p>
|
||||
<pre><code class="language-plaintext">mcedit /server/conf/postfix/main.cf</code></pre>
|
||||
<p>Измените параметр relayhost, на свой внешний SMTP релей. Если в файле sasl_passwd был указан нестандартный TCP-порт, то вы должны использовать тот же порт при настройке параметра relayhost.</p>
|
||||
<p>Укажите SMTP релей:</p>
|
||||
<pre><code class="language-plaintext">relayhost = [mail.isp.example]:587</code></pre>
|
||||
<p>для Gmail запись будет выглядеть следующим образом:</p>
|
||||
<pre><code class="language-plaintext">relayhost = [smtp.gmail.com]:587</code></pre>
|
||||
<p>В конце файла добавьте следующие параметры для включения аутентификации:</p>
|
||||
<pre><code class="language-plaintext"># enable SASL authentication
|
||||
smtp_sasl_auth_enable = yes
|
||||
# disallow methods that allow anonymous authentication.
|
||||
smtp_sasl_security_options = noanonymous
|
||||
# where to find sasl_passwd
|
||||
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
|
||||
# Enable STARTTLS encryption
|
||||
smtp_use_tls = yes
|
||||
# where to find CA certificates
|
||||
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt</code></pre>
|
||||
<p>Сохраните изменения.</p>
|
||||
<p>Перезапустите Postfix:</p>
|
||||
<pre><code class="language-plaintext">docker exec -i postfix service postfix reload</code></pre>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Менеджер паролей Bitwarden
|
||||
description:
|
||||
published: true
|
||||
date: 2023-11-15T16:34:29.896Z
|
||||
date: 2024-07-09T09:50:29.679Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:34:29.896Z
|
||||
|
||||
19
Soft/server1c.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!--
|
||||
title: Выделенный сервер 1С
|
||||
description:
|
||||
published: true
|
||||
date: 2024-07-09T09:49:51.459Z
|
||||
tags:
|
||||
editor: ckeditor
|
||||
dateCreated: 2023-11-15T16:48:23.320Z
|
||||
-->
|
||||
|
||||
<p>Я время от времени настраиваю сервера 1С для небольших организаций на основе файловых баз с публикацией в веб. Получается удобное, безопасное и законченное решение, которое почти не требует обслуживания и участия со стороны IT специалиста. Расскажу, как это всё выглядит на практике.</p>
|
||||
<p>Арендуется выделенный сервер в Selectel (<a href="https://serveradmin.ru/lklTref4">https://serveradmin.ru/lklTref4</a>). Последний из заказанных серверов стоил 5200р. и имел конфигурацию i7, 64 гига оперативы и 2 SSD диска по 480Гб. На таком сервере файловая 1С работает очень шустро. Для двух-трех человек в базе нормальный вариант. Баз может быть много.</p>
|
||||
<p>Далее на сервер ставится гипервизор Proxmox на софтовый RAID1 mdadm. На нём настраиваются 3 виртуальные машины:<br>1. Windows, где будет работать 1С.<br>2. Debian 11 для Nginx и Apache Guacamole.<br>3. Debian 11 для локальных бэкапов.</p>
|
||||
<p>Первым делом настраивается сам гипервизор и фаервол на нём. Максимально закрывается доступ, настраиваются пробросы к виртуальным машинам. Весь доступ к инфраструктуре будет через Apache Guacamole (<a href="https://t.me/srv_admin/1447">https://t.me/srv_admin/1447</a>), так что пробрасываем порты к нему и открываем 80 и 443 порты к виртуалке с Nginx. Всё остальное закрываем.</p>
|
||||
<p>Следующим этапом настраивается Nginx, который будет проксировать запросы на 1С. Я закрываю туда доступ через Basic Auth. И тут же настраиваем Apache Guacamole для доступа к виртуальным машинам через браузер. Особенно это актуально для доступа к Windows машине, так как проброс RDP порта с полным доступом из интернета делать нельзя. Дополнительно при желании через Nginx можно закрыть паролем доступ к самому Guacamole и веб интерфейсу Proxmox. В данном случае Apache Guacamole заменяет нам VPN, обеспечивая дополнительную безопасность и возможность получить прямой доступ к серверам напрямую через интернет. Пользователям ничего у себя настраивать не надо.</p>
|
||||
<p>На Windows сервере устанавливается как обычно платформа 1С и веб сервер Apache. Делается публикация баз. Тут никакой экзотики, всё стандартно.</p>
|
||||
<p>На третьем сервере настраивается Samba, создаётся сетевой диск с доступом только на чтение. Этот диск подключается к Windows машине. В этот сетевой диск ежедневно делаются бэкапы файловых баз, старые удаляются. Работает скрипт на самом сервере с бэкапами. Монтирует папку с Windows сервера и забирает файлы к себе, а отдаёт их уже только в режиме чтения. Это сделано, чтобы был оперативный доступ к бэкапам с Windows машины, но при этом их нельзя было удалить с неё. С самого бэкап сервера базы копируются куда-то во вне в зависимости от имеющихся ресурсов для хранения. Это может быть и обычный Яндекс.Диск.</p>
|
||||
<p>Схема получается гибкая. Вместо файловых баз можно настроить и клиент-серверную архитектуру на базе MSSQL или PostgreSQL. А сам внешний доступ будет такой же.</p>
|
||||
<p>Если хотите настроить что-то подобное, можете заказать настройку у меня. Готовых инструкций с подобной настройкой в сети нет.</p>
|
||||
BIN
attachments/base/1.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
attachments/base/2.png
Normal file
|
After Width: | Height: | Size: 210 KiB |
BIN
attachments/base/3.png
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
attachments/base/4.png
Normal file
|
After Width: | Height: | Size: 472 KiB |
BIN
attachments/base/5.png
Normal file
|
After Width: | Height: | Size: 489 KiB |
BIN
attachments/base/6.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
attachments/base/7.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
attachments/sysadmin/image2022-12-13_18-54-41.png
Normal file
|
After Width: | Height: | Size: 359 KiB |
BIN
attachments/sysadmin/image2022-8-16_9-13-53.png
Normal file
|
After Width: | Height: | Size: 448 KiB |
BIN
attachments/xpenology/1.jpg
Normal file
|
After Width: | Height: | Size: 223 KiB |
BIN
attachments/xpenology/10.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
attachments/xpenology/11.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
attachments/xpenology/2.jpg
Normal file
|
After Width: | Height: | Size: 176 KiB |
BIN
attachments/xpenology/3.jpg
Normal file
|
After Width: | Height: | Size: 200 KiB |
BIN
attachments/xpenology/4.jpg
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
attachments/xpenology/5.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
attachments/xpenology/6.jpg
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
attachments/xpenology/7.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
attachments/xpenology/8.png
Normal file
|
After Width: | Height: | Size: 23 KiB |