Compare commits

..

181 Commits

Author SHA1 Message Date
98004bcb67 docs: create DevOps/PostgreSQL/instruments 2025-06-17 09:33:17 +00:00
f7e0663d3e docs: upload DevOps/attachments/photo_2025-05-21_20-48-32.jpg 2025-06-17 09:32:50 +00:00
756607fbb9 docs: upload DevOps/attachments/photo_2025-05-21_20-48-32_(2).jpg 2025-06-17 09:32:50 +00:00
ce9454d518 docs: delete attachments/photo_2025-05-21_20-48-32_(2).jpg 2025-06-17 09:32:33 +00:00
038d71be6e docs: delete attachments/photo_2025-05-21_20-48-32.jpg 2025-06-17 09:32:29 +00:00
039eeb40e5 docs: upload attachments/photo_2025-05-21_20-48-32.jpg 2025-06-17 09:32:06 +00:00
cd480c69a9 docs: upload attachments/photo_2025-05-21_20-48-32_(2).jpg 2025-06-17 09:32:06 +00:00
34d17c9c9b docs: update DevOps/Docker/converter 2025-06-17 09:21:01 +00:00
351d80d3ff docs: create DevOps/Docker/converter 2025-06-17 09:20:18 +00:00
5a017ac47a docs: upload DevOps/attachments/photo_2025-05-16_16-20-54.jpg 2025-06-17 09:19:31 +00:00
f438203912 docs: upload DevOps/attachments/photo_2025-05-16_16-20-53.jpg 2025-06-17 09:19:29 +00:00
ce0d02d0b0 docs: upload DevOps/attachments/photo_2025-05-16_16-20-54_(2).jpg 2025-06-17 09:19:29 +00:00
caf80d3c20 docs: update Hypervisors/Proxmox/Cluster/DestroyCluster 2025-05-22 09:28:32 +00:00
17f6f8ac98 docs: update Hypervisors/Proxmox/Cluster/DestroyCluster 2025-05-21 11:38:58 +00:00
902ee9d5fb docs: update Hypervisors/Proxmox/Cluster/DestroyCluster 2025-05-21 11:32:20 +00:00
3905acf5b1 docs: create Hypervisors/Proxmox/Cluster/DestroyCluster 2025-05-21 11:32:12 +00:00
92a2df6b73 docs: update sysadmin/supermicro/fan 2025-05-19 09:26:40 +00:00
5118268045 docs: create sysadmin/supermicro/fan 2025-05-19 08:49:28 +00:00
a9c1d87b38 docs: update DevOps/Clickhouse/Cluster/1-Install-Clickhouse-cluster 2025-05-15 20:11:18 +00:00
3310c3143e docs: update DevOps/Clickhouse/Cluster/1-Install-Clickhouse-cluster 2025-05-15 20:10:46 +00:00
91e73ffbef docs: update DevOps/Clickhouse/Cluster/1-Install-Clickhouse-cluster 2025-05-15 20:09:24 +00:00
3f10edf636 docs: create DevOps/Clickhouse/Cluster/3-Create-manual 2025-05-15 20:07:43 +00:00
5d7f0eb094 docs: update DevOps/Clickhouse/Cluster/0-Bases-and-query 2025-05-15 20:02:43 +00:00
6864921ba2 docs: create DevOps/Clickhouse/Cluster/0-Bases-and-query 2025-05-15 20:01:53 +00:00
695d095133 docs: create DevOps/Clickhouse/Cluster/1-Install-Clickhouse-cluster 2025-05-15 18:05:05 +00:00
f8c68fc017 docs: rename Monitoring/VictoriaLogs/VictoriaLogs-setup to Monitoring/VictoriaLogs-setup 2025-04-28 07:28:04 +00:00
24027d9d7c docs: update Monitoring/VictoriaLogs/VictoriaLogs-setup 2025-04-28 07:27:35 +00:00
ca2c0ecb0d docs: rename sysadmin/Monitoring/Gatus to Monitoring/Gatus 2025-04-28 07:26:53 +00:00
3c01fb220c docs: create Monitoring/VictoriaLogs/VictoriaLogs-setup 2025-04-28 07:26:05 +00:00
7813c906b6 docs: rename monitoring/victorialogs.png to monitoring/victorialogs-3.png 2025-04-28 07:25:29 +00:00
54e0280d36 docs: rename monitoring/image.png to monitoring/victorialogs.png 2025-04-28 07:25:14 +00:00
8291eabd96 docs: upload monitoring/image.png 2025-04-28 07:25:07 +00:00
5f53344c8d docs: rename monitoring/image.png to monitoring/victorialogs-2.png 2025-04-28 07:25:00 +00:00
fffbc19277 docs: upload monitoring/image.png 2025-04-28 07:24:46 +00:00
5eab9c24f8 docs: rename monitoring/image.png to monitoring/victorialogs-1.png 2025-04-28 07:24:36 +00:00
82f1fe3ebe docs: upload monitoring/image.png 2025-04-28 07:24:22 +00:00
8b96c3784f docs: create NAS/Synology/Disable-check-hdd 2025-04-21 09:52:04 +00:00
ad86c1410a docs: update Hypervisors/Proxmox/Disable-ProxMox-Subscription-Notice 2025-04-11 07:57:43 +00:00
52ea4eb4c8 docs: create Hypervisors/Proxmox/Disable-ProxMox-Subscription-Notice 2025-04-11 07:53:57 +00:00
d56d13dfa4 docs: create NAS/Synology/synology_app_mover 2025-04-05 12:08:53 +00:00
ec880e8d5d docs: rename NAS/scrutiny to NAS/Synology/scrutiny 2025-04-05 10:11:30 +00:00
49c3a582f1 docs: rename NAS/install-xpenology to NAS/Synology/install-xpenology 2025-04-05 10:11:06 +00:00
a400048ef3 docs: rename NAS/cupsd to NAS/Synology/cupsd 2025-04-05 10:10:53 +00:00
672a33d6f9 docs: rename NAS/syn-console-command to NAS/Synology/syn-console-command 2025-04-05 10:10:31 +00:00
e5977484af docs: update NAS/syn-console-command 2025-04-05 10:10:04 +00:00
62fe0e0ca1 docs: rename NAS/Synology-support-HEVC to NAS/Synology/Synology-support-HEVC 2025-04-05 10:09:15 +00:00
1ea6770013 docs: rename NAS/Qemu-for-Synology to NAS/Synology/Qemu-for-Synology 2025-04-05 10:08:43 +00:00
8047021a44 docs: rename NAS/brtfs-or-ext-for-synology to NAS/Synology/brtfs-or-ext-for-synology 2025-04-05 10:08:28 +00:00
198d6d22a7 docs: create NAS/brtfs-or-ext-for-synology 2025-04-05 10:07:57 +00:00
17f4d4caf2 docs: update DevOps/Gitlab/Minimal-install 2025-03-25 18:40:58 +00:00
3cee2b82ac docs: create DevOps/Gitlab/Minimal-install 2025-03-25 18:40:07 +00:00
e9e886bd5d docs: create DevOps/ELK/EFK-rotate 2025-03-13 16:02:32 +00:00
3e4620a388 docs: create DevOps/ELK/Rotation-logs-ILM 2025-03-13 08:17:08 +00:00
f1bfc53bb5 docs: create NAS/scrutiny 2025-03-12 10:21:38 +00:00
83d57cfc36 docs: rename Hackintosh/Soft to Apple/Hackintosh/Opencore 2025-02-14 16:49:38 +00:00
5351b235dc docs: create Apple/MacOS/Create-flash-on-m3 2025-02-14 16:48:04 +00:00
ddace8434d docs: update NAS/syn-console-command 2024-11-27 20:02:26 +00:00
e771369149 docs: update NAS/syn-console-command 2024-11-27 18:26:34 +00:00
05c40b0ee6 docs: update NAS/syn-console-command 2024-11-27 17:23:05 +00:00
92fac48655 docs: update NAS/syn-console-command 2024-11-27 15:21:27 +00:00
a5726a2d72 docs: update NAS/syn-console-command 2024-11-27 14:47:21 +00:00
0b2f00cbb4 docs: create NAS/syn-console-command 2024-11-27 08:35:42 +00:00
7c8dd413c3 docs: rename NAS/NAS/cupsd to NAS/cupsd 2024-10-29 09:05:33 +00:00
bae611e68d docs: create NAS/NAS/cupsd 2024-10-29 09:05:08 +00:00
5fd2d3ae93 docs: rename nas/{265af3fe-c0fe-4400-bc1b-f4e4cc6acebe}.png to nas/cups4.png 2024-10-29 08:58:51 +00:00
f9bbb41e70 docs: upload nas/{265af3fe-c0fe-4400-bc1b-f4e4cc6acebe}.png 2024-10-29 08:58:39 +00:00
2871dc4b22 docs: rename nas/{bb5ebb2d-1a92-4ad1-b9b0-64f8b0ec6254}.png to nas/cups3.png 2024-10-29 08:58:07 +00:00
1831e7f03a docs: upload nas/{bb5ebb2d-1a92-4ad1-b9b0-64f8b0ec6254}.png 2024-10-29 08:57:56 +00:00
12fca342c5 docs: rename nas/{e0b22c78-2b8e-4ec3-97ee-0c4174bc2f9c}.png to nas/cups2.png 2024-10-29 08:57:27 +00:00
1551ebccaa docs: upload nas/{e0b22c78-2b8e-4ec3-97ee-0c4174bc2f9c}.png 2024-10-29 08:57:18 +00:00
70ca44f15d docs: rename nas/{9bec395a-dddb-40a3-8858-4f6fd738b022}.png to nas/cups1.png 2024-10-29 08:55:07 +00:00
6af90cffb7 docs: upload nas/{9bec395a-dddb-40a3-8858-4f6fd738b022}.png 2024-10-29 08:54:54 +00:00
43a4d24f27 docs: update Funny/Jaecoo/Jcartools 2024-10-24 18:34:40 +00:00
073a7ca4b8 docs: update Funny/Jaecoo/Jcartools 2024-10-24 18:31:27 +00:00
2976e88ea5 docs: update Funny/Jaecoo/Jcartools 2024-10-24 17:05:12 +00:00
96eb57c703 docs: update Funny/Jaecoo/Jcartools 2024-10-24 17:00:40 +00:00
4b103f90c3 docs: update Funny/Jaecoo/Jcartools 2024-10-24 16:59:13 +00:00
1fae23d524 docs: upload jaecoo/{26c4849a-5094-4662-ac6b-205e2d230e66}.png 2024-10-24 14:14:33 +00:00
63761558b2 docs: upload jaecoo/{30a2bdf4-b137-4cf1-bf8e-94721aa1c8c0}.png 2024-10-24 14:14:13 +00:00
ca97ec782f docs: update Funny/Jaecoo/Jcartools 2024-10-24 13:50:11 +00:00
e5d791d144 docs: update Funny/Jaecoo/Jcartools 2024-10-24 12:21:43 +00:00
11edd56fc8 docs: update Funny/Jaecoo/Jcartools 2024-10-24 07:31:51 +00:00
aab0e2fd4d docs: update Funny/Jaecoo/Jcartools 2024-10-24 06:54:22 +00:00
2b95597c26 docs: create Funny/Jaecoo/Jcartools 2024-10-24 06:25:52 +00:00
1b8965971a docs: update NAS/Synology-support-HEVC 2024-09-26 22:26:39 +00:00
f9c37af160 docs: create NAS/Qemu-for-Synology 2024-09-26 22:10:41 +00:00
c872d859e6 docs: rename nas/742975669_.png.d83d167412b7b674ce4d81f3cf139b0a.png to nas/qemu-3.png 2024-09-26 22:02:46 +00:00
17b384693d docs: upload nas/742975669_.png.d83d167412b7b674ce4d81f3cf139b0a.png 2024-09-26 22:02:37 +00:00
25fdf07e26 docs: rename nas/1808378820_.png.dba65d70a8982838205ffabea4674615.png to nas/qemu-2.png 2024-09-26 22:02:13 +00:00
2376c96197 docs: upload nas/1808378820_.png.dba65d70a8982838205ffabea4674615.png 2024-09-26 22:02:04 +00:00
29d72e9c76 docs: rename nas/527088589_.png.2be957d047929d2b90a17456b773966a.png to nas/qemu-1.png 2024-09-26 22:01:41 +00:00
2a65169168 docs: upload nas/527088589_.png.2be957d047929d2b90a17456b773966a.png 2024-09-26 22:01:29 +00:00
ce500cc31b docs: update NAS/Synology-support-HEVC 2024-09-26 21:42:02 +00:00
fed2a92b79 docs: update NAS/install-xpenology 2024-09-24 14:13:12 +00:00
c00a2e2460 docs: update NAS/install-xpenology 2024-09-24 12:41:05 +00:00
8cb35e0009 docs: update NAS/install-xpenology 2024-09-24 12:40:23 +00:00
6eddf40b7c docs: create sysadmin/Linux/Base-znaniy/Disk-limit2 2024-08-09 07:42:56 +00:00
8aa65149df docs: rename sysadmin/img/image.png to sysadmin/img/disk-limit.png 2024-08-09 07:42:44 +00:00
fade8ecdcf docs: upload sysadmin/img/image.png 2024-08-09 07:42:33 +00:00
3cc9e28b3a docs: create sysadmin/Linux/Base-znaniy/Disk-limit 2024-08-09 07:39:34 +00:00
76e7277186 docs: create sysadmin/Linux/Base-znaniy/Memory-limit 2024-08-09 07:34:42 +00:00
83bebf1836 docs: rename sysadmin/img/image.png to sysadmin/img/memory-limit.png 2024-08-09 07:34:28 +00:00
42e74764b3 docs: upload sysadmin/img/image.png 2024-08-09 07:34:17 +00:00
7dd332b9ed docs: update sysadmin/Monitoring/Gatus 2024-08-08 14:54:27 +00:00
561c277646 docs: update sysadmin/Monitoring/Gatus 2024-08-08 14:53:49 +00:00
15e2783cb3 docs: update sysadmin/Monitoring/Gatus 2024-08-08 14:53:37 +00:00
8730ac5fba docs: update sysadmin/Monitoring/Gatus 2024-08-08 14:51:51 +00:00
481404b050 docs: rename sysadmin/img/image.png to sysadmin/img/gatus.png 2024-08-08 14:51:40 +00:00
59389a9d4f docs: upload sysadmin/img/image.png 2024-08-08 14:51:32 +00:00
b6f3925b2e docs: update sysadmin/Monitoring/Gatus 2024-08-08 14:48:14 +00:00
716014a704 docs: create sysadmin/Monitoring/Gatus 2024-08-08 14:48:04 +00:00
5899a62772 docs: update sysadmin/MikroTik/Youtube 2024-08-06 17:07:20 +00:00
0279c2067b docs: create sysadmin/MikroTik/Youtube 2024-08-06 17:02:28 +00:00
c4a124f043 docs: rename sysadmin/img/image.png to sysadmin/img/mkrt3.png 2024-08-06 17:01:42 +00:00
c3a61631d6 docs: upload sysadmin/img/image.png 2024-08-06 17:01:34 +00:00
d813f4a043 docs: rename sysadmin/img/image.png to sysadmin/img/mkrt2.png 2024-08-06 17:01:02 +00:00
299937d418 docs: upload sysadmin/img/image.png 2024-08-06 17:00:55 +00:00
233cb48188 docs: rename sysadmin/img/image.png to sysadmin/img/mkrt1.png 2024-08-06 17:00:29 +00:00
d83565202c docs: upload sysadmin/img/image.png 2024-08-06 17:00:20 +00:00
c3f5a1ebc1 docs: update DevOps/Hashicorp-Vault/vault-postgresql-users 2024-08-01 15:52:20 +00:00
f87057d69a docs: update DevOps/Hashicorp-Vault/vault-postgresql-users 2024-08-01 15:34:49 +00:00
d2faf0c62f docs: update DevOps/Hashicorp-Vault/vault-postgresql-users 2024-08-01 15:24:59 +00:00
1005f589eb docs: create DevOps/Hashicorp-Vault/vault-postgresql-users 2024-08-01 14:55:40 +00:00
ac5ebaa626 docs: update DevOps/Hashicorp-Vault/Gitlab-with-vault 2024-08-01 14:49:04 +00:00
27a7baa660 docs: create DevOps/Hashicorp-Vault/Gitlab-with-vault 2024-07-31 12:59:44 +00:00
3cc2b962b0 docs: rename DevOps/img/yirfyaz-d3pfaevjtbz7jksz9m8.png to DevOps/img/vault-gitlab2.png 2024-07-30 15:51:46 +00:00
706cd6dcae docs: upload DevOps/img/yirfyaz-d3pfaevjtbz7jksz9m8.png 2024-07-30 15:51:35 +00:00
5434303ab1 docs: rename DevOps/img/image.png to DevOps/img/vault-gitlab.png 2024-07-30 15:50:06 +00:00
50285ff6a9 docs: upload DevOps/img/image.png 2024-07-30 15:49:52 +00:00
19e7e7bb3b docs: update DevOps/Cheat-Sheets/Regular-String-cheat-sheet 2024-07-27 09:17:30 +00:00
bfa5a90985 docs: create DevOps/Cheat-Sheets/Regular-String-cheat-sheet 2024-07-27 09:16:23 +00:00
38192a4bff docs: rename DevOps/img/image.png to DevOps/img/regular-sheet.png 2024-07-27 09:16:11 +00:00
8cc7996604 docs: upload DevOps/img/image.png 2024-07-27 09:16:00 +00:00
af2afdd1a5 docs: create DevOps/Cheat-Sheets 2024-07-27 09:12:55 +00:00
9ebfd24a41 docs: create DevOps/Cheat-Sheets/Git-Cheat-Sheet 2024-07-27 09:10:54 +00:00
3665ef64b4 docs: rename DevOps/img/image.png to DevOps/img/git-sheet.png 2024-07-27 09:10:43 +00:00
3c3097cce4 docs: upload DevOps/img/image.png 2024-07-27 09:10:27 +00:00
2c0ceba6a9 docs: create DevOps/Cheat-Sheets/Docker-cheat-sheet 2024-07-27 09:08:54 +00:00
369bb22819 docs: rename DevOps/img/image.png to DevOps/img/docker-sheet.png 2024-07-27 09:08:41 +00:00
b2101df83b docs: upload DevOps/img/image.png 2024-07-27 09:08:27 +00:00
e57cd345c7 docs: update DevOps/Hashicorp-Vault/secure-use-vault 2024-07-17 10:15:05 +00:00
0f28863f6b docs: update DevOps/Hashicorp-Vault/vault-with-ldap 2024-07-17 10:14:16 +00:00
88dacf7218 docs: update DevOps/Hashicorp-Vault/vault-policy 2024-07-17 10:13:22 +00:00
1cf32f92dd docs: update DevOps/Hashicorp-Vault/Use-vault 2024-07-17 10:12:49 +00:00
1e9213e4ca docs: update DevOps/Hashicorp-Vault/Vault-cheat-sheet 2024-07-17 10:11:16 +00:00
7e0f09b97a docs: update DevOps/Hashicorp-Vault/Vault-cheat-sheet 2024-07-17 10:08:36 +00:00
d831a84d5e docs: update DevOps/Hashicorp-Vault/Vault-cheat-sheet 2024-07-17 10:02:27 +00:00
33e2792d32 docs: create DevOps/Hashicorp-Vault/Vault-cheat-sheet 2024-07-17 09:48:12 +00:00
ba69cd7559 fix 2024-07-09 18:37:45 +03:00
c501ddc032 add pv 2024-07-09 18:35:10 +03:00
a1f2ea1201 add new vault 2024-07-09 18:20:11 +03:00
598ffb7a50 add newvault 2024-07-09 17:08:44 +03:00
7e5bf28182 ready ldap 2024-07-09 15:46:09 +03:00
bcb9dec04c add vault 2024-07-09 14:24:33 +03:00
8cd08756a2 fix 2024-07-09 13:36:23 +03:00
38e03809a4 full blog 2024-07-09 13:33:45 +03:00
4e4117b121 add new 2024-07-09 13:19:29 +03:00
fdaec73179 add new 2024-07-09 13:09:27 +03:00
ebf7fb7f04 fix 2024-07-09 12:59:52 +03:00
72f1885bbb docs: add all untracked content 2024-07-09 09:55:56 +00:00
2e39f00e20 Merge branch 'main' of https://prodik.ddns.net:4433/prodik/wiki-js 2024-07-09 12:47:49 +03:00
cd3760685e systemd 2024-07-09 12:08:09 +03:00
b726f0997d docs: rename sysadmin/Linux/vpn-server-ipsec to sysadmin/Linux/VPN/vpn-server-ipsec 2024-04-24 09:55:25 +00:00
32433545fc docs: create sysadmin/Linux/VPN/Privoxy 2024-04-24 09:54:46 +00:00
587ee1468d docs: upload photo_2024-04-18_01-11-10.jpg 2024-04-24 09:51:40 +00:00
45ab71cceb docs: create sysadmin/Linux/SSL/make-ssl-cert 2024-04-24 09:45:50 +00:00
13d3381fae docs: rename photo_2024-04-23_00-16-21.jpg to ssl-zabbix.jpg 2024-04-24 09:44:09 +00:00
06edef55d7 docs: upload photo_2024-04-23_00-16-21.jpg 2024-04-24 09:43:54 +00:00
f357571bbf docs: create sysadmin/Linux/python/venv 2024-04-12 10:15:21 +00:00
290f0c8da5 docs: rename image.png to venv.png 2024-04-12 10:14:14 +00:00
9b4c9c9feb docs: upload image.png 2024-04-12 10:14:04 +00:00
d49f4e54c5 docs: create NAS/Synology-support-HEVC 2024-04-01 15:16:02 +00:00
2c697be36a docs: update sysadmin/ssh/zsh 2024-03-26 08:52:53 +00:00
16488d93eb docs: update sysadmin/ssh/zsh 2024-03-26 08:51:19 +00:00
01a859ad6b docs: create sysadmin/ssh/zsh 2024-03-26 08:48:29 +00:00
5e91fc51b4 docs: rename sysadmin/screenshot_1.png to sysadmin/zsh.png 2024-03-26 08:48:13 +00:00
3e66c9d102 docs: upload sysadmin/screenshot_1.png 2024-03-26 08:48:02 +00:00
63a0994182 docs: update sysadmin/Databases/Clickhouse/Query-size-tables 2024-03-13 10:13:44 +00:00
407671efbe docs: rename sysadmin/image.png to sysadmin/query-db.png 2024-03-13 10:13:34 +00:00
0845684d9f docs: upload sysadmin/image.png 2024-03-13 10:13:20 +00:00
47dff00dad docs: create sysadmin/Databases/Clickhouse/Query-size-tables 2024-03-13 10:11:59 +00:00
154 changed files with 6079 additions and 48 deletions

View File

@@ -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

View 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
View 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>

View 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
---
Фото
![docker-sheet.png](/DevOps/img/docker-sheet.png)

View 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>

View 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
---
![regular-sheet.png](/DevOps/img/regular-sheet.png)

View 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;
```

View 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 = '/';
```

View 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
```

View 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. Не стал обращать на них внимание, так как их существует десятки. Обычно просто в гугле ищут что-то подобное, когда надо преобразовать. Посмотрите список, может вам что-то ещё приглянётся. Меня впечатлили только эти четыре штуки.
![photo_2025-05-16_16-20-53.jpg](/DevOps/attachments/photo_2025-05-16_16-20-53.jpg)
![photo_2025-05-16_16-20-54.jpg](/DevOps/attachments/photo_2025-05-16_16-20-54.jpg)
![photo_2025-05-16_16-20-54_(2).jpg](/DevOps/attachments/photo_2025-05-16_16-20-54_(2).jpg)

49
DevOps/ELK/EFK-rotate.md Normal file
View 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
}
}
}
```

View 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 будет автоматически управлять вашими индексами, и вам не придется вручную заниматься ротацией логов. 😊

View 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-е ошибки.
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.

View 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/
Этот туториал демонстрирует пример аутентификации, конфигурации и чтения секретов с HashiCorps 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”, в этом случае данные будут хранится в формате строк и * будет означать только *.)
Полный лист опций можно посмотреть в Vaults 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 .
Полный список доступных опций можно посмотреть в Vaults 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)"
```
![vault-gitlab.png](/DevOps/img/vault-gitlab.png)
Следующее задание сможет пройти аутентификацию через роль 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
```
![vault-gitlab2.png](/DevOps/img/vault-gitlab2.png)
На этом все, надеюсь данный туториал окажется вам полезен!

View 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 в среду, где запускается приложение. Рисунок, взятый из официальной документации, показывает наглядно весь происходящий процесс.
![alt text](image-6.png)
Для получения 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, как мониторить и масштабировать кластер, как выполнять резервное копирование и восстановление, то поддержите нас лайком и непременно сообщите об этом в комментарии.
У вас появились вопросы по реализации данного метода авторизации? Не стесняйтесь, оставляйте их в комментариях. Если вы считаете другой способ более оптимальным поделитесь им в комментариях, читателям будет полезно знать несколько способов работы с секретами.

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View 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 способов трансформации вашего мониторинга и реагирования на инциденты» для создания прозрачных рабочих процессов управления инцидентами с высокой степенью совместной работы.

View 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
```

View 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.

View 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
```
![alt text](image.png)
Создадим шаблон под политику:
```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
```
![alt text](image-1.png)
Создадим групповую политику с полным доступом
```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
![alt text](image-2.png)
И если вы на этом этапе подумали «Ну что ж, заведем юзера в Vault!» - то вовсе не угадали.
Надо идти в логи AD и смотреть там ошибки авторизации у какого юзера не идет авторизация. В моем случае с Source Network Address: 192.168.31.155 прошла успешная авторизация пользователя CONTOSO\VaultSAM
Может быть, проблема в пароле товарища Иванова? Проверим. Сменим Pa$$word3 на Pa!!word3 а вот и нет.
Но у нас есть товарищ Волк, без имени и фамилии. Проверим!
vault login -method=ldap username=volk
и все работает!
![alt text](image-3.png)
# Заводим 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`
![alt text](image-4.png)
Перебрать каждый
`vault token lookup -accessor EHlDQ1tFHEgA9aq0R6IptIjo`
![alt text](image-5.png)
и так по всем. Не самая удобная процедура с точки зрения CLI, ну так Vault не под CLI заточен.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View 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

View 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

View File

@@ -2,7 +2,7 @@
title: bash-completion для kubectl
description:
published: true
date: 2023-12-26T10:23:32.800Z
date: 2024-07-09T09:49:55.778Z
tags: bash, kubectl
editor: ckeditor
dateCreated: 2023-11-08T08:53:22.629Z

View 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).
![photo_2025-05-21_20-48-32.jpg](/DevOps/attachments/photo_2025-05-21_20-48-32.jpg)
![photo_2025-05-21_20-48-32_(2).jpg](/DevOps/attachments/photo_2025-05-21_20-48-32_(2).jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
DevOps/img/docker-sheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

BIN
DevOps/img/git-sheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

BIN
DevOps/img/vault-gitlab.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

View File

@@ -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
View 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 (как то так вроде бы) &nbsp;</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. Новая версия. &nbsp;<a href="https://www.youtube.com/watch?v=mVRuAvgRIEI">https://www.youtube.com/watch?v=mVRuAvgRIEI</a></p>
<p>&nbsp;</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&nbsp;</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 и в разделе проверок протыкать разрешения у которых не стоит галочка. &nbsp;</p>
<p>5. Зайти в настройках Microg в список аккаунтов, и перед добавлением своего аккаунта - поставить ползунки как на фото ниже. &nbsp;</p>
<p>6. Добавить свой гугл аккаунт. &nbsp;</p>
<p>7. Радоваться. А чтобы не пропадала История просмотров - в настройках Revanced в настройках General Layout включить Enable Tablet Layout.</p>
<p>&nbsp;</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>&nbsp;</h3>
<h1><strong>Стрелка</strong></h1>
<p>Подскажите пожалуйста, в стрелке как настроить расстояние до камеры, в плане оповещения ?)&nbsp;</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>&nbsp;</h3>
<h1><strong>Звук</strong></h1>
<p>Звук почему то только английский (2 голоса), но звук есть.&nbsp;</p>
<blockquote>
<p>У меня вначале был английский, переключил в настройках на русский. Появилась Алиса вместо джона. Но Алиса тоже болтала по английски. Еще в настройках нашел язык "как в системе", переключил его на русский и все пошло норм</p>
</blockquote>
<p>&nbsp;В последней версии говорили же, что обязательно ставить эту настройку - фиксированные подсказки</p>
<blockquote>
<p>А если в картах поставите «закрепить указатель манёвра» будет ещё лучше</p>
</blockquote>
<p>&nbsp;</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>&nbsp;</p>
<h1>Обновление</h1>
<p>А есть ссылка на пост с обновлением по воздуху тут?)</p>
<blockquote>
<p>Все просто. Три точки сверху справа "обновить приложение" и "обновить карты". При появлении новой версии приложения при его открытии будет уведомление.</p>
</blockquote>
<p>На проекцию не выводится ограничение скорости</p>
<blockquote>
<p>Ну когда навигатор работает над стрелками на проекции в бегущей строке вместе с названием улицы есть ещё что-то типа Lim 40 km/h. В настройках навистарт нужно вкл</p>
</blockquote>
<h1>Шторка-люк</h1>
<p>Ну что бы шторка срабатывала нормально а не произвольно и очень редко &nbsp;:)</p>
<blockquote>
<p>Надо поставить галку для всех водителей</p>
<p>В списке выбрать водитель один и поставить галку шторки например</p>
</blockquote>

View File

@@ -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

View File

@@ -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

View 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&nbsp;stop&nbsp;pve-cluster.service</p>
<p>systemctl&nbsp;stop&nbsp;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&nbsp;restart&nbsp;pve-cluster.service</p>
<p>cd&nbsp;/etc/pve/nodes</p>
<p>ls</p>
<p>rm -rf /etc/pve/nodes/pve-01/</p>

View 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
```

View 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
View 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: Lets 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: Lets 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:
```
Штука простая и удобная. Меня не раз просили посоветовать что-то для простого дашборда с зелёными кнопками, когда всё нормально и красными, когда нет. Вот это идеальный вариант под такую задачу.
Также с помощью этого мониторинга удобно сделать дашборд для мониторинга мониторингов, чтобы понимать, живы они или нет.
![](/sysadmin/img/gatus.png)

View 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 сервера, но с гораздо большими возможностями.
![victorialogs-1.png](/monitoring/victorialogs-1.png)
![victorialogs-2.png](/monitoring/victorialogs-2.png)
![victorialogs-3.png](/monitoring/victorialogs-3.png)

View 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

View 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>

View 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 &amp;&amp; sh ame72-3005.sh</code></pre>

View 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
View 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 с помощью которого получилось завести.
![cups1.png](/nas/cups1.png)
Так как принтер не определяется с нормальным именем, например как /dev/ttyUSB0
Поэтому пришлось делать символьную ссылку через планировщик
`ln -s /dev/usb/04e8:3413:8J66BAAY331838K /dev/ttyUSB0`
![cups2.png](/nas/cups2.png)
![cups3.png](/nas/cups3.png)
![cups4.png](/nas/cups4.png)
Создаем 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

View File

@@ -2,7 +2,7 @@
title: Установка XPEnology
description:
published: true
date: 2023-11-15T17:00:34.979Z
date: 2024-09-24T14:13:07.116Z
tags: xpenology
editor: ckeditor
dateCreated: 2023-11-15T16:50:54.856Z
@@ -63,10 +63,11 @@ sudo ./rploader.sh identifyusb now
<pre><code class="language-plaintext">sudo ./rploader.sh build bromolow-7.0.1-42218</code></pre>
<p>После завершения сборки загрузите файл&nbsp;*.pat через WinSCP по указанному пути&nbsp; и скачивайте на вашу локальную машину.</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>&nbsp;</p>
<p>Можно скачать <a href="https://archive.synology.com/download/Os/DSM">тут</a></p>
<figure class="image"><img src="/attachments/xpenology/10.png"></figure>
<p>&nbsp;</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>&nbsp;</p>

142
NAS/Synology/scrutiny.html Normal file
View 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&nbsp;</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>&nbsp;</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>&nbsp;</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>

View 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
```

View 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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -2,7 +2,7 @@
title: Менеджер паролей Passwork
description:
published: true
date: 2023-11-15T16:47:23.462Z
date: 2024-07-09T09:50:26.092Z
tags:
editor: ckeditor
dateCreated: 2023-11-15T16:36:08.780Z

View File

@@ -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

View File

@@ -2,7 +2,7 @@
title: Выделенный сервер 1С
description:
published: true
date: 2023-11-15T16:48:23.320Z
date: 2024-07-09T09:49:51.459Z
tags:
editor: ckeditor
dateCreated: 2023-11-15T16:48:23.320Z

View File

@@ -2,7 +2,7 @@
title: Home Page
description:
published: true
date: 2023-11-08T12:52:20.918Z
date: 2024-07-09T09:49:22.061Z
tags:
editor: ckeditor
dateCreated: 2023-11-03T14:27:02.804Z

BIN
image2022-8-11_11-6-39.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

View File

@@ -0,0 +1,3 @@
https://github.com/gkpln3/ConfluenceToWikiJS
Можно так же попробовать сконвертировать html в markdown

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

BIN
nas/cups1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
nas/cups2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
nas/cups3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
nas/cups4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
nas/qemu-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
nas/qemu-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

BIN
nas/qemu-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

BIN
ssl-zabbix.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

View File

@@ -0,0 +1,18 @@
<!--
title: Запрос размера таблиц Clickhouse
description:
published: true
date: 2024-03-13T10:13:44.768Z
tags: clickhouse, query
editor: ckeditor
dateCreated: 2024-03-13T10:11:53.025Z
-->
<pre><code class="language-plaintext">SELECT table,
formatReadableSize(sum(bytes)) as size,
min(min_date) as min_date,
max(max_date) as max_date
FROM system.parts
WHERE active
GROUP BY table</code></pre>
<figure class="image"><img src="/sysadmin/query-db.png"></figure>

Some files were not shown because too many files have changed in this diff Show More