<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DevOps Notes</title><link>https://vlasov.pro/ru/</link><description>Recent content on DevOps Notes</description><generator>Hugo -- gohugo.io</generator><language>ru-RU</language><lastBuildDate>Sun, 25 Jan 2026 14:55:27 +0200</lastBuildDate><atom:link href="https://vlasov.pro/ru/index.xml" rel="self" type="application/rss+xml"/><item><title>Хитрое шифрование диска dm-crypt nuke</title><link>https://vlasov.pro/ru/p/dm-crypt-nuke/</link><pubDate>Thu, 16 Jan 2025 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/dm-crypt-nuke/</guid><description>&lt;img src="https://vlasov.pro/ru/p/dm-crypt-nuke/logo.webp" alt="Featured image of post Хитрое шифрование диска dm-crypt nuke" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Шифрование диска с использованием &lt;code>dm-crypt&lt;/code> — это надёжный способ защиты данных. Однако в экстремальных ситуациях может потребоваться мгновенное и необратимое уничтожение ключей шифрования, чтобы данные стали недоступными. Для этого можно использовать механизм &lt;strong>nuke&lt;/strong>, который активируется при вводе специального пароля.&lt;/p>
&lt;p>В этой статье рассмотрим, как реализовать &lt;strong>nuke&lt;/strong> в &lt;code>dm-crypt&lt;/code>, используя &lt;strong>initramfs&lt;/strong>, &lt;code>cryptsetup&lt;/code> и &lt;code>mkpasswd&lt;/code>.&lt;/p>
&lt;p>Разработанный хук умеет:&lt;/p>
&lt;ol>
&lt;li>Расшифровывать диск используя данные с файла&lt;/li>
&lt;li>Если файл не найден, спрашивает пароль&lt;/li>
&lt;li>Если пароль это nuke пароль - удаляет все ключи&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Важно!&lt;/strong> У меня это работает на Ubuntu 22.04.5, есть большая вероятность, что на других дистрибутивах нужно будет сделать что-то по другому. В любом случае, вот статья по &lt;a class="link" href="../gpt-btrfs-gnome/#grub-recovery-script" >восcтановлению Grub&lt;/a>.&lt;/p>
&lt;h2 id="установка">Установка &lt;a href="#%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0">¶&lt;/a>&lt;/h2>
&lt;p>Я подготовил &lt;a class="link" href="deb/dm-nuke-1.0.0.deb" >&lt;em>DEB пакет&lt;/em>&lt;/a> для простой установки. Качаем и ставим вот такой командой.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">sudo apt-get install -f dm-nuke.deb
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="настройка-загрузки">Настройка загрузки &lt;a href="#%d0%bd%d0%b0%d1%81%d1%82%d1%80%d0%be%d0%b9%d0%ba%d0%b0-%d0%b7%d0%b0%d0%b3%d1%80%d1%83%d0%b7%d0%ba%d0%b8">¶&lt;/a>&lt;/h2>
&lt;p>В моём случае, у меня зашифрован / и не зашифрован /boot.
Прежде всего, нужно добавить &lt;code>cryptdevice&lt;/code> аргумент в &lt;code>/etc/default/grub&lt;/code>. UUID можно получить из вывода &lt;code>blkid&lt;/code> (берём UUID зашифрованного раздела).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">GRUB_CMDLINE_LINUX_DEFAULT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;... cryptdevice=UUID=bb85fe0a-4ef7-49c4-b15c-fb613d51e9ef:cryptroot&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь, нужно добавить в &lt;code>/etc/crypttab&lt;/code> указание использовать таш скрипт.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">cryptroot &lt;span class="nv">UUID&lt;/span>&lt;span class="o">=&lt;/span>bb85fe0a-4ef7-49c4-b15c-fb613d51e9ef keyfile-path&lt;span class="o">=&lt;/span>/dev/mmcblk0,keyfile-offset&lt;span class="o">=&lt;/span>8932578598,keyfile-size&lt;span class="o">=&lt;/span>11045,nuke&lt;span class="o">=&lt;/span>HASH luks,discard,keyscript&lt;span class="o">=&lt;/span>decrypt_smart_nuke
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Описание аргументов:&lt;/p>
&lt;ol>
&lt;li>&lt;code>cryptroot&lt;/code> - имя раздела после расшифровки. В данном случае он появится в системе как &lt;em>/dev/mapper/cryptroot&lt;/em>. Должно совпадать с тем, что мы написали в &lt;em>/etc/default/grub&lt;/em>.&lt;/li>
&lt;li>&lt;code>UUID=bb85fe0a-4ef7-49c4-b15c-fb613d51e9ef&lt;/code> - то же, что мы прописали в &lt;em>/etc/default/grub&lt;/em>.&lt;/li>
&lt;li>Всё третье поле это аргумент к скрипту:
&lt;ol>
&lt;li>&lt;code>keyfile-path=/dev/mmcblk0&lt;/code> - путь к файлу или устройству откуда читать пароль, в моём случае это SD карта&lt;/li>
&lt;li>&lt;code>keyfile-offset=4194836274&lt;/code> - отступ в байтах от начала файла, если не указано - читать с начала.&lt;/li>
&lt;li>&lt;code>keyfile-size=7333&lt;/code> - длинна последовательности для чтения, если не указано - читать до конца.&lt;/li>
&lt;li>&lt;code>nuke=HASH&lt;/code> - хеш пароля самоуничтожения.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;code>luks,discard,keyscript=decrypt_smart_nuke&lt;/code> - опции для cryptsetup, где мы, среди всего прочего, указываем имя скрипта для получения пароля.&lt;/li>
&lt;/ol>
&lt;p>Замените &lt;code>HASH&lt;/code> на хэш пароля, который можно получить вот так.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">mkpasswd -m sha512crypt --rounds&lt;span class="o">=&lt;/span>&lt;span class="m">5000&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>И keyfile, и nuke опциональны, можно не указывать их и скрипт отработает только на интерактивный ввод.&lt;/p>
&lt;h2 id="файле-для-считывания-ключа">Файле для считывания ключа &lt;a href="#%d1%84%d0%b0%d0%b9%d0%bb%d0%b5-%d0%b4%d0%bb%d1%8f-%d1%81%d1%87%d0%b8%d1%82%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%ba%d0%bb%d1%8e%d1%87%d0%b0">¶&lt;/a>&lt;/h2>
&lt;p>Тут идея в следующем. У меня на ноутбуке есть SD Card Reader, так вот он всегда живёт с заглушкой. Почему бы, подумал я, его не использовать для хранения ключа? Есть два интересных варианта:&lt;/p>
&lt;ol>
&lt;li>Сделать раздел на флешке, но оставить буквально один мегабайт до или после него. Забить случайными данными и использовать этот кусок как ключ - незаметно. Сам раздел использовать с пользой.&lt;/li>
&lt;li>Забить всю флешку случайными данными и использовать случайный адрес и длину последовательности.&lt;/li>
&lt;/ol>
&lt;p>Вот второй вариант я и выбрал. Да, сторонний наблюдатель поймёт, что тут что-то не чисто, да, флешку нельзя использовать по прямому назначению, но поди угадай тот адрес начала и длину последовательности.&lt;/p>
&lt;p>И ещё, можно использовать другие, более безопасные варианты указаний пути к разделу:&lt;/p>
&lt;ol>
&lt;li>/dev/disk/by-id/&amp;hellip;&lt;/li>
&lt;li>/dev/disk/by-uuid/&amp;hellip;&lt;/li>
&lt;li>/dev/disk/by-label/&amp;hellip;&lt;/li>
&lt;/ol>
&lt;p>У меня просто SD Card Reader один физически и больше не планируется.&lt;/p>
&lt;h2 id="обновление-initramfs">Обновление &lt;code>initramfs&lt;/code> &lt;a href="#%d0%be%d0%b1%d0%bd%d0%be%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-initramfs">¶&lt;/a>&lt;/h2>
&lt;p>После внесения всех изменений обновите initramfs и grub.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">sudo update-initramfs -u
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo update-grub2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="итог">Итог &lt;a href="#%d0%b8%d1%82%d0%be%d0%b3">¶&lt;/a>&lt;/h2>
&lt;p>Теперь, если при загрузке системы ввести &lt;strong>nuke-пароль&lt;/strong>, скрипт уничтожит ключи шифрования и сделает данные недоступными. Этот метод подходит для критических ситуаций, требующих быстрой и необратимой защиты информации.&lt;/p>
&lt;p>Кроме того, система будет расшифровываться сама, а если нужно куда-то поехать с ноутбуком, то флешку можно вытащить и он будет спрашивать пароль.&lt;/p>
&lt;p>Будьте осторожны при использовании данного механизма и имейте бекап.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo cryptsetup luksHeaderBackup /dev/sda1 --header-backup-file ./backup.luks
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Подписываем Git коммиты</title><link>https://vlasov.pro/ru/p/git-sign/</link><pubDate>Tue, 10 Dec 2024 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/git-sign/</guid><description>&lt;img src="https://vlasov.pro/ru/p/git-sign/logo.webp" alt="Featured image of post Подписываем Git коммиты" />&lt;h1 id="как-настроить-подпись-коммитов-и-тегов-в-git-с-помощью-gpg-и-ssh">Как настроить подпись коммитов и тегов в Git с помощью GPG и SSH &lt;a href="#%d0%ba%d0%b0%d0%ba-%d0%bd%d0%b0%d1%81%d1%82%d1%80%d0%be%d0%b8%d1%82%d1%8c-%d0%bf%d0%be%d0%b4%d0%bf%d0%b8%d1%81%d1%8c-%d0%ba%d0%be%d0%bc%d0%bc%d0%b8%d1%82%d0%be%d0%b2-%d0%b8-%d1%82%d0%b5%d0%b3%d0%be%d0%b2-%d0%b2-git-%d1%81-%d0%bf%d0%be%d0%bc%d0%be%d1%89%d1%8c%d1%8e-gpg-%d0%b8-ssh">¶&lt;/a>&lt;/h1>
&lt;p>Подпись коммитов и тегов позволяет подтвердить, что изменения действительно внесены Вами. Это важный шаг для защиты проекта и обеспечения прозрачности работы. В этой статье я расскажу, как настроить автоматическую подпись коммитов и тегов в Git, а также как разделить конфигурации для личных и рабочих проектов.&lt;/p>
&lt;hr>
&lt;h2 id="основной-файл-конфигурации-git">Основной файл конфигурации Git &lt;a href="#%d0%be%d1%81%d0%bd%d0%be%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d0%b0%d0%b9%d0%bb-%d0%ba%d0%be%d0%bd%d1%84%d0%b8%d0%b3%d1%83%d1%80%d0%b0%d1%86%d0%b8%d0%b8-git">¶&lt;/a>&lt;/h2>
&lt;p>Основной файл конфигурации &lt;code>~/.gitconfig&lt;/code> задаёт общие параметры для всех репозиториев. В нём можно указать имя пользователя, включить обязательную подпись коммитов и тегов, а также подключить дополнительные конфигурационные файлы для отдельных групп проектов.&lt;/p>
&lt;p>Пример базового файла конфигурации:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ~/.gitconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[user]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">John Smith&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[commit]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">gpgsign&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[tag]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">gpgSign&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[includeIf &amp;#34;gitdir:~/Personal/&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">~/Personal/.gitconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[includeIf &amp;#34;gitdir:~/Work/&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">~/Work/.gitconfig&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>С помощью директив &lt;code>[includeIf]&lt;/code> Git будет подключать нужные конфигурации в зависимости от расположения репозитория.&lt;/p>
&lt;hr>
&lt;h2 id="конфигурация-для-личных-проектов">Конфигурация для личных проектов &lt;a href="#%d0%ba%d0%be%d0%bd%d1%84%d0%b8%d0%b3%d1%83%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%b4%d0%bb%d1%8f-%d0%bb%d0%b8%d1%87%d0%bd%d1%8b%d1%85-%d0%bf%d1%80%d0%be%d0%b5%d0%ba%d1%82%d0%be%d0%b2">¶&lt;/a>&lt;/h2>
&lt;p>Если Вы используете SSH для подписи в личных проектах, настройка будет выглядеть следующим образом. В конфигурационном файле &lt;code>~/Personal/.gitconfig&lt;/code> задаётся личный email, а формат подписи указывается как &lt;code>ssh&lt;/code>. Команда, прописанная в настройках, позволяет Git автоматически находить нужный ключ в &lt;code>ssh-agent&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ~/Personal/.gitconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[user]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">email&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">personal@a.com&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[gpg]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">format&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">ssh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[gpg &amp;#34;ssh&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">defaultKeyCommand&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">sh -c &amp;#34;ssh-add -L | awk &amp;#39;$3~/^personal@a\\.com$/{print \&amp;#34;key::\&amp;#34;$0}&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Эта настройка позволяет использовать ключ, уже добавленный в &lt;code>ssh-agent&lt;/code>, что упрощает процесс подписи.&lt;/p>
&lt;hr>
&lt;h2 id="конфигурация-для-рабочих-проектов">Конфигурация для рабочих проектов &lt;a href="#%d0%ba%d0%be%d0%bd%d1%84%d0%b8%d0%b3%d1%83%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%b4%d0%bb%d1%8f-%d1%80%d0%b0%d0%b1%d0%be%d1%87%d0%b8%d1%85-%d0%bf%d1%80%d0%be%d0%b5%d0%ba%d1%82%d0%be%d0%b2">¶&lt;/a>&lt;/h2>
&lt;p>Для рабочих проектов часто используется GPG. В конфигурации &lt;code>~/Work/.gitconfig&lt;/code> указывается рабочий email и идентификатор GPG-ключа, который будет использоваться для подписи.&lt;/p>
&lt;p>Если у Вас ещё нет GPG-ключа, его можно создать с помощью команды:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">gpg --full-gen-key
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Для получения идентификатора ключа выполните:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">gpg --list-keys
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Пример файла конфигурации для рабочих проектов:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ~/Work/.gitconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[user]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">email&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">company@b.com
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> signingKey = 35C1A64CD7FC0AB6EB66756B2445463C3234ECE1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[gpg]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">format&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">openpgp&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>С помощью этого файла рабочие коммиты и теги будут подписаны с использованием указанного GPG-ключа.&lt;/p>
&lt;hr>
&lt;p>Теперь Ваш Git настроен на автоматическое использование нужного ключа в зависимости от репозитория. Это поможет Вам поддерживать порядок и прозрачность при работе с коммитами и тегами.&lt;/p></description></item><item><title>Kubernetes Node role labeler</title><link>https://vlasov.pro/ru/p/node-role-labeler/</link><pubDate>Tue, 08 Oct 2024 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/node-role-labeler/</guid><description>&lt;img src="https://vlasov.pro/ru/p/node-role-labeler/logo.webp" alt="Featured image of post Kubernetes Node role labeler" />&lt;h2 id="описание">Описание &lt;a href="#%d0%be%d0%bf%d0%b8%d1%81%d0%b0%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://github.com/vlasov-y/node-role-labeler" target="_blank" rel="noopener"
>Node Role Labeler&lt;/a> давно руки чесались написать, примитивнейший оператор, но задачу выполняет. Проблема в том, что Kubernetes, а именно kubelet, не может назначить себе самому при создании узла label &lt;code>node-role.kubernetes.io/ROLE_NAME&lt;/code>, потому что kubernetes.io защищённый префикс. Очень не удобно.&lt;/p>
&lt;p>Вот у меня &lt;a class="link" href="https://karpenter.sh" target="_blank" rel="noopener"
>Karpenter&lt;/a>, или &lt;a class="link" href="https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler" target="_blank" rel="noopener"
>Cluster Autoscaler&lt;/a>, да не важно, я хочу чтобы узлы сразу были с красивыми ролями, а из коробки так не получается, только руками. Теперь можно навесить &lt;code>node-role.cluster.local/NAME&lt;/code> и оператор создаст копию с доменом kubernetes.io автоматически. В обратную сторону тоже работает. Подробнее - читайте на GitHub.&lt;/p>
&lt;h2 id="демо">Демо &lt;a href="#%d0%b4%d0%b5%d0%bc%d0%be">¶&lt;/a>&lt;/h2>
&lt;script src="https://asciinema.org/a/679600.js" id="asciicast-679600" async="true">&lt;/script>
&lt;h2 id="karpenter-конфигурация">Karpenter конфигурация &lt;a href="#karpenter-%d0%ba%d0%be%d0%bd%d1%84%d0%b8%d0%b3%d1%83%d1%80%d0%b0%d1%86%d0%b8%d1%8f">¶&lt;/a>&lt;/h2>
&lt;p>Вот таким образом можно сразу навешивать labels на узлы Karpenter-a.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;span class="lnt">88
&lt;/span>&lt;span class="lnt">89
&lt;/span>&lt;span class="lnt">90
&lt;/span>&lt;span class="lnt">91
&lt;/span>&lt;span class="lnt">92
&lt;/span>&lt;span class="lnt">93
&lt;/span>&lt;span class="lnt">94
&lt;/span>&lt;span class="lnt">95
&lt;/span>&lt;span class="lnt">96
&lt;/span>&lt;span class="lnt">97
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">karpenter.k8s.aws/v1beta1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">EC2NodeClass&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">private&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">amiFamily&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">AL2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">metadataOptions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">httpEndpoint&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">enabled&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">httpProtocolIPv6&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">disabled&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">httpPutResponseHopLimit&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">httpTokens&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">required&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">role&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Karpenter-development-role&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">securityGroupSelectorTerms&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">tags&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">karpenter.sh/discovery&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">development&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">subnetSelectorTerms&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">tags&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">karpenter.sh/discovery/development/subnet&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">private&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">tags&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">karpenter.sh/discovery&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">development&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">karpenter.sh/v1beta1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">NodePool&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">on&lt;/span>-&lt;span class="l">demand-amd64&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">disruption&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">budgets&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">nodes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">20&lt;/span>&lt;span class="l">%&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">nodes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;5&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">duration&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">20h&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">nodes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;0&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">schedule&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">5&lt;/span>&lt;span class="w"> &lt;/span>*&lt;span class="w"> &lt;/span>*&lt;span class="w"> &lt;/span>*&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">consolidationPolicy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">WhenUnderutilized&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">expireAfter&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">720h&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">limits&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;200&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">400Gi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">template&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">node-role.cluster.local/on-demand-amd64&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">nodeClassRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">private&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">requirements&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">key&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">kubernetes.io/arch&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">In&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">amd64&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">key&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">node.kubernetes.io/instance-type&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">In&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5a.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5a.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5a.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5a.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5a.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m6i.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m6i.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m6i.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m6i.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m6i.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5a.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5a.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5a.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5a.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5a.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6a.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6a.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6a.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6a.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6a.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">t3a.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">t3a.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">t3a.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">t3a.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">t3a.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">key&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">karpenter.sh/capacity-type&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">In&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="kc">on&lt;/span>-&lt;span class="l">demand&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>BTRFS checksum benchmark</title><link>https://vlasov.pro/ru/p/btrfs-checksum/</link><pubDate>Sun, 30 Jul 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/btrfs-checksum/</guid><description>&lt;img src="https://vlasov.pro/ru/p/btrfs-checksum/logo.webp" alt="Featured image of post BTRFS checksum benchmark" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Переезжаю на новое железо и на чистый SSD. Встал перед выбором алгоритма хеширования для свежей файловой системы BTRFS. Здесь представлен скрипт, которым я определил что на моём конкретном процессоре бытсрее.&lt;/p>
&lt;h2 id="тело">Тело &lt;a href="#%d1%82%d0%b5%d0%bb%d0%be">¶&lt;/a>&lt;/h2>
&lt;p>Искал в начале утилиту для проведения замеров производительности разных алгоритмов хеширования. Зачем? Дело в том, что, каким бы быстрым не был алгоритм на бумаге, если у меня нет аппаратной его поддержки на процессоре - он будет медленным. А как понять что у меня есть на процессоре? В спецификации в сети не нашёл информацию.&lt;/p>
&lt;p>Попал на утилиту &lt;a class="link" href="https://github.com/rhash/RHash" target="_blank" rel="noopener"
>rhash&lt;/a>, у которой есть ключ &lt;code>--speed&lt;/code> ним то я и попробовал замерять производительность, но результаты у blake2b и crc32c были практически идентичны, что показалось странным. В итоге пришёл к вот такому скрипту.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env bash
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -eo pipefail
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">TMPFS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mktemp -d&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SIZE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;5G&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount -t tmpfs -o &lt;span class="nv">size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SIZE&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> tmpfs &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">TMPFS&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">TMPFS&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">fallocate -l 4GiB btrfs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> CSUM in crc32c xxhash sha256 blake2&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mkfs.btrfs -f -d single -m single --csum &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CSUM&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> btrfs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mount btrfs /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> cd /mnt
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> echo &amp;#34;&lt;/span>info: &lt;span class="si">${&lt;/span>&lt;span class="nv">CSUM&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> dd if=/dev/urandom of=test bs=4M count=1024 2&amp;gt;/dev/null
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> rm -f test
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> for i in {1..1000}; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> dd if=/dev/urandom of=&amp;#34;&lt;/span>&lt;span class="se">\$&lt;/span>i&lt;span class="s2">&amp;#34; bs=4M count=1 2&amp;gt;/dev/null
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> done
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> rm -f /mnt/*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> /usr/bin/time bash
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> umount /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">TMPFS&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rm -rf &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">TMPFS&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Что здесь происходит?&lt;/p>
&lt;ol>
&lt;li>Создаётся tmpfs временная точка монтирования на 5 ГБ (прямо в оперативной памяти, чтобы не зависет от SSD/HDD)&lt;/li>
&lt;li>Создаётся внутри файл на 4 ГБ и по очереди форматируется в BTRFS с разными алгоритмами хеширования&lt;/li>
&lt;li>Для каждого алгоритма выполняется запись файлов в двух режимах
&lt;ol>
&lt;li>Один большой файл на 4 ГБ&lt;/li>
&lt;li>1000 файлов по 4 МБ&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>По итогу команда time выводит время выполнения скрипта&lt;/li>
&lt;/ol>
&lt;p>Так вот на моём &lt;em>11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz&lt;/em> лучший результат показал старый, добрый &lt;strong>crc32c&lt;/strong> (~35 секунд), а остальные были по ~52 секунды.&lt;/p></description></item><item><title>Redis Migration Script</title><link>https://vlasov.pro/ru/p/redis-migration/</link><pubDate>Sun, 25 Jun 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/redis-migration/</guid><description>&lt;img src="https://vlasov.pro/ru/p/redis-migration/logo.webp" alt="Featured image of post Redis Migration Script" />&lt;h2 id="старый-способ">Старый способ &lt;a href="#%d1%81%d1%82%d0%b0%d1%80%d1%8b%d0%b9-%d1%81%d0%bf%d0%be%d1%81%d0%be%d0%b1">¶&lt;/a>&lt;/h2>
&lt;p>Иногда нужно мигрировать данные из одного Redis в другой, или между базами другого. Ранее, я мог перенести данные с сервера на сервер только через полный бекап, но это не позволяет мигрировать данные между базами. Всё равно, приведу здесь этот алгоритм.&lt;/p>
&lt;ol>
&lt;li>Зайти в исходный Redis и сделать Save&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">REDISCLI_AUTH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;password&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">redis-cli CONFIG GET DIR
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">redis-cli SAVE
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Первая команда выведет путь к папке, где будет лежать дамп.&lt;/p>
&lt;ol start="2">
&lt;li>Добавить к целевому Redis аргументы для отключения AppendOnly и перезапустить его&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">--dbfilename dump.rdb
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">--appendonly no
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>Скопировать дамп в целевой Redis и выполнить его загрузку&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">REDISCLI_AUTH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;password&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">redis-cli BGREWRITEAOF
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="4">
&lt;li>Перевести целевой Redis в AppendOnly режим убрав ранее добавленные ключи&lt;/li>
&lt;/ol>
&lt;blockquote>
&lt;p>Зачем мигрировать данные между базами?&lt;/p>
&lt;/blockquote>
&lt;p>В старом кластере у меня два сервиса, у каждого свой Redis. В любом Redis есть по умолчанию 16 баз, почему бы не использовать №0 для сервиса А и №2 - для сервиса Б? Вот тут то ты и сталкиваешься с задачей миграции из базы в базу.&lt;/p>
&lt;h2 id="новый-способ">Новый способ &lt;a href="#%d0%bd%d0%be%d0%b2%d1%8b%d0%b9-%d1%81%d0%bf%d0%be%d1%81%d0%be%d0%b1">¶&lt;/a>&lt;/h2>
&lt;p>Основан на &lt;a class="link" href="https://redis.io/commands/migrate/" target="_blank" rel="noopener"
>MIGRATE&lt;/a>. Скрипт представлен ниже. Преимущества этого способа - тоже.&lt;/p>
&lt;ol>
&lt;li>Можно мигрировать между базами&lt;/li>
&lt;li>Не нужно перезапускать Redis-ы&lt;/li>
&lt;li>Не нужно копировать бекапы&lt;/li>
&lt;li>Есть проверка после переноса путём вычисления хеш суммы учитывая так же и содержимое ключей&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SRC_HOSTNAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;source-redis-hostname&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SRC_PORT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;6379&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SRC_PASSWORD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;password&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SRC_DATABASE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;0&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEST_HOSTNAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;destination-redis-hostname&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEST_PORT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;6379&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEST_PASSWORD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;password&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEST_DATABASE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;1&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">main&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> migrate &lt;span class="p">|&lt;/span> xargs -0 &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;migration status: %s&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">CHECKSUM&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mktemp&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">hash&lt;/span> --no-auth-warning -h &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_HOSTNAME&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -p &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_PORT&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -a &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_PASSWORD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -n &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_DATABASE&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> tee &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CHECKSUM&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> xargs -0 &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;source checksum: %s&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">CHECKSUM_VERIFY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CHECKSUM&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="nb">hash&lt;/span> --no-auth-warning -h &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_HOSTNAME&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -p &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_PORT&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -a &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_PASSWORD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -n &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_DATABASE&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> xargs -0 &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;target checksum validation: %s&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CHECKSUM&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">hash&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">EXTRA_ARGS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="p">@&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> redis-cli &lt;span class="si">${&lt;/span>&lt;span class="nv">EXTRA_ARGS&lt;/span>&lt;span class="si">}&lt;/span> --raw --scan &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> sed -r &lt;span class="s1">&amp;#39;s/&amp;#34;/\\&amp;#34;/g; s/^(.+)$/GET &amp;#34;\1&amp;#34;/g;&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> redis-cli &lt;span class="si">${&lt;/span>&lt;span class="nv">EXTRA_ARGS&lt;/span>&lt;span class="si">}&lt;/span> &lt;span class="p">|&lt;/span> sort &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CHECKSUM_VERIFY&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sha256sum -c &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CHECKSUM_VERIFY&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sha256sum -
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">migrate&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">AUTH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;--no-auth-warning -h &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_HOSTNAME&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -p &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_PORT&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -a &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_PASSWORD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -n &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_DATABASE&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> redis-cli &lt;span class="si">${&lt;/span>&lt;span class="nv">AUTH&lt;/span>&lt;span class="si">}&lt;/span> --raw --scan &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> tr &lt;span class="s1">&amp;#39;\n&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;\0&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> xargs -0 redis-cli &lt;span class="si">${&lt;/span>&lt;span class="nv">AUTH&lt;/span>&lt;span class="si">}&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> MIGRATE &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_HOSTNAME&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_PORT&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_DATABASE&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="m">5000&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> COPY REPLACE AUTH &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_PASSWORD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> KEYS
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">main
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Мой опыт с Git</title><link>https://vlasov.pro/ru/p/git-hacks/</link><pubDate>Sun, 18 Jun 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/git-hacks/</guid><description>&lt;img src="https://vlasov.pro/ru/p/git-hacks/logo.webp" alt="Featured image of post Мой опыт с Git" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Часто используемые мною команды и пояснения к ним. Надеюсь будет кому-то так же полезно как и мне.&lt;/p>
&lt;h2 id="основное">Основное &lt;a href="#%d0%be%d1%81%d0%bd%d0%be%d0%b2%d0%bd%d0%be%d0%b5">¶&lt;/a>&lt;/h2>
&lt;h3 id="в-git-есть-встроенный-графический-интерфейс">В Git есть встроенный графический интерфейс &lt;a href="#%d0%b2-git-%d0%b5%d1%81%d1%82%d1%8c-%d0%b2%d1%81%d1%82%d1%80%d0%be%d0%b5%d0%bd%d0%bd%d1%8b%d0%b9-%d0%b3%d1%80%d0%b0%d1%84%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b9-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d1%84%d0%b5%d0%b9%d1%81">¶&lt;/a>&lt;/h3>
&lt;p>&lt;a class="link" href="https://git-scm.com/docs/gitk" target="_blank" rel="noopener"
>Gitk&lt;/a> - простой встроенный графический интерфейс. Мне очень нравится из-за своей точности и наглядности. Я стараюсь не пользоваться какими-либо Git UI и всё делаю командами, а эта и так работает только в режиме просмотра.&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/git-hacks/gitk-interface.png"
width="1570"
height="868"
srcset="https://vlasov.pro/ru/p/git-hacks/gitk-interface_hu9045001261438640488.png 480w, https://vlasov.pro/ru/p/git-hacks/gitk-interface_hu9426254138151857176.png 1024w"
loading="lazy"
alt="Интерфейс Gitk"
class="gallery-image"
data-flex-grow="180"
data-flex-basis="434px"
>&lt;/p>
&lt;ol>
&lt;li>Дерево коммитов с тегами и ветками&lt;/li>
&lt;li>Хеш выбранного коммита из дерева&lt;/li>
&lt;li>Список изменённых файлов в этом коммите&lt;/li>
&lt;li>Переключатель режима diff&lt;/li>
&lt;li>Сам diff из коммита с его описанием в начале&lt;/li>
&lt;/ol>
&lt;p>На Manjaro кроме самого Git, нужно поставить ещё и tk, тогда заработает. Как на других дистрибутивах - не знаю.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">pacman -Sy git tk
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="как-обновлять-настройки-окружений-основываясь-на-diff-е-нового-окружения">Как обновлять настройки окружений основываясь на diff-е нового окружения &lt;a href="#%d0%ba%d0%b0%d0%ba-%d0%be%d0%b1%d0%bd%d0%be%d0%b2%d0%bb%d1%8f%d1%82%d1%8c-%d0%bd%d0%b0%d1%81%d1%82%d1%80%d0%be%d0%b9%d0%ba%d0%b8-%d0%be%d0%ba%d1%80%d1%83%d0%b6%d0%b5%d0%bd%d0%b8%d0%b9-%d0%be%d1%81%d0%bd%d0%be%d0%b2%d1%8b%d0%b2%d0%b0%d1%8f%d1%81%d1%8c-%d0%bd%d0%b0-diff-%d0%b5-%d0%bd%d0%be%d0%b2%d0%be%d0%b3%d0%be-%d0%be%d0%ba%d1%80%d1%83%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f">¶&lt;/a>&lt;/h3>
&lt;p>Тут вот какой момент. У меня в инфраструктурном репозитории есть, к примеру, values для Helmfile окружений &lt;strong>Development&lt;/strong> и &lt;strong>Production&lt;/strong>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ruby" data-lang="ruby">&lt;span class="line">&lt;span class="cl">&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">├──&lt;/span> &lt;span class="n">development&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">main&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">└──&lt;/span> &lt;span class="n">values&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">cert&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">manager&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">external&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">secrets&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">fluentbit&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">kube&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">prometheus&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">stack&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">loki&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">└──&lt;/span> &lt;span class="n">promtail&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">└──&lt;/span> &lt;span class="n">production&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">main&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">└──&lt;/span> &lt;span class="n">values&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">cert&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">manager&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">external&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">secrets&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">fluentbit&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">kube&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">prometheus&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">stack&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">loki&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">└──&lt;/span> &lt;span class="n">promtail&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mi">5&lt;/span> &lt;span class="n">directories&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">14&lt;/span> &lt;span class="n">files&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>И вот разрабатывал я разрабатывал новые приложения, менял настройки в development и теперь мне нужно всё то же самое перенести в production. Чтобы не вспоминать все мелочи где что нужно поменять делаю следующее.&lt;/p>
&lt;ol>
&lt;li>Переходим на ветку с актуальным development&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git checkout development
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>Смотрим когда последний раз менялся production&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git log -n &lt;span class="m">1&lt;/span> --oneline -- ./production
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Здесь &lt;code>./production&lt;/code> это путь к папке, изменения по файлам которой нас интересует. Можно конкретный файл указать или несколько источников. В данном случае мы получим хеш самого последнего коммита, в котором что-либо менялось в production.&lt;/p>
&lt;ol start="3">
&lt;li>Смотрим изменения с этого момента и по сей день&lt;/li>
&lt;/ol>
&lt;p>Теперь нам нужно отследить все изменения с момента последней версии production по текущий момент, который является актуальным development.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git diff 493d3aa..HEAD -- ./development
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Хеш &lt;strong>493d3aa&lt;/strong> это тот самый, который я получил в прошлом пункте для production.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl">&lt;span class="gh">diff --git a/development/values/cert-manager.yaml.gotmpl b/development/values/cert-manager.yaml.gotmpl
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gh">index 493d3aa..cb34bd2 100644
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gh">&lt;/span>&lt;span class="gd">--- a/development/values/cert-manager.yaml.gotmpl
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+++ b/development/values/cert-manager.yaml.gotmpl
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>&lt;span class="gu">@@ -34,7 +34,8 @@ asdf:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gu">&lt;/span> alpha: cert-manager-a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> contextKey:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> beta: something-else
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">- key: json
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+ someSetting:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ subkey: cert-manager-example
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> urls:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> api: {{ quote .Values.apiURL }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> web: {{ quote .Values.webURL }}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Таким образом, мы теперь можем в ручном режиме перенести все интересующие нас изменения в production и ничего не потерять.&lt;/p>
&lt;h3 id="как-искать-пароли-и-чувствительные-данные-используя-поиск-по-коммитам">Как искать пароли и чувствительные данные используя поиск по коммитам &lt;a href="#%d0%ba%d0%b0%d0%ba-%d0%b8%d1%81%d0%ba%d0%b0%d1%82%d1%8c-%d0%bf%d0%b0%d1%80%d0%be%d0%bb%d0%b8-%d0%b8-%d1%87%d1%83%d0%b2%d1%81%d1%82%d0%b2%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d0%b5-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-%d0%bf%d0%be%d0%b8%d1%81%d0%ba-%d0%bf%d0%be-%d0%ba%d0%be%d0%bc%d0%bc%d0%b8%d1%82%d0%b0%d0%bc">¶&lt;/a>&lt;/h3>
&lt;p>У Git есть встроенный поиск по файлам в коммитах. Можно использовать регулярные выражения для поиска секретный данных. Это применимо в отдельных ручных операциях, но намного правильнее будет настроить и постоянно иметь &lt;a class="link" href="https://gitleaks.io" target="_blank" rel="noopener"
>Gitleaks&lt;/a> или &lt;a class="link" href="https://aquasecurity.github.io/trivy/v0.42/docs/target/git-repository/" target="_blank" rel="noopener"
>Trivy&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git rev-list --all &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>xargs git grep -irnE &lt;span class="s1">&amp;#39;&amp;#34;type&amp;#34;:\s*&amp;#34;service_account&amp;#34;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://vlasov.pro/ru/p/git-hacks/git-grep-result.png.png"
width="1436"
height="400"
srcset="https://vlasov.pro/ru/p/git-hacks/git-grep-result.png_hu17935566524260525823.png 480w, https://vlasov.pro/ru/p/git-hacks/git-grep-result.png_hu16809239544126765716.png 1024w"
loading="lazy"
alt="Результаты поиска подстроки &amp;ldquo;val&amp;rdquo;"
class="gallery-image"
data-flex-grow="359"
data-flex-basis="861px"
>&lt;/p>
&lt;p>Таким образом, можно найти все файлы в истории, которые содержат секреты и выполнять ротацию. Вырезать их из истории не имеет смысла, лучше просто поменять секреты.&lt;/p>
&lt;h3 id="rebase-стратегии">Rebase стратегии &lt;a href="#rebase-%d1%81%d1%82%d1%80%d0%b0%d1%82%d0%b5%d0%b3%d0%b8%d0%b8">¶&lt;/a>&lt;/h3>
&lt;p>Когда нужно выполнить rebase кучей конфликтов и ты точно знаешь, что тебе просто нужно оставить всё как есть в текущей\целевой ветке, то можно сделать так.&lt;/p>
&lt;ol>
&lt;li>Убеждаемся, что наша локальная ветка (которую мы будем rebase-ить) запушена и такая же как в облаке&lt;/li>
&lt;/ol>
&lt;p>Для чего это нужно? Для самоконтроля. К примеру, у меня задача сделать rebase &lt;em>development&lt;/em> ветки на &lt;em>main&lt;/em> да так, чтобы она не поменялась, просто перенести. Если на момент начала переноса я проверил, что diff-a &lt;em>origin/development&lt;/em> у меня нет, то после переноса, я смогу сравнить &lt;code>git diff origin/development..development&lt;/code> и там так же должно быть пусто.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git pull
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git push
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>Выполняем одну из операций ниже&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git rebase -i --strategy&lt;span class="o">=&lt;/span>ort -Xtheirs main --empty&lt;span class="o">=&lt;/span>keep
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git rebase -i --strategy&lt;span class="o">=&lt;/span>ort -Xours main --empty&lt;span class="o">=&lt;/span>keep
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Git разрешит все конфликты в пользу одной из веток, в зависимости от &lt;code>ours&lt;/code> или &lt;code>theirs&lt;/code>.&lt;/p>
&lt;h3 id="как-сбросить-локальную-ветку-до-состояния-облачной-если-кто-то-пушил-с-форсом">Как сбросить локальную ветку до состояния облачной, если кто-то пушил с форсом &lt;a href="#%d0%ba%d0%b0%d0%ba-%d1%81%d0%b1%d1%80%d0%be%d1%81%d0%b8%d1%82%d1%8c-%d0%bb%d0%be%d0%ba%d0%b0%d0%bb%d1%8c%d0%bd%d1%83%d1%8e-%d0%b2%d0%b5%d1%82%d0%ba%d1%83-%d0%b4%d0%be-%d1%81%d0%be%d1%81%d1%82%d0%be%d1%8f%d0%bd%d0%b8%d1%8f-%d0%be%d0%b1%d0%bb%d0%b0%d1%87%d0%bd%d0%be%d0%b9-%d0%b5%d1%81%d0%bb%d0%b8-%d0%ba%d1%82%d0%be-%d1%82%d0%be-%d0%bf%d1%83%d1%88%d0%b8%d0%bb-%d1%81-%d1%84%d0%be%d1%80%d1%81%d0%be%d0%bc">¶&lt;/a>&lt;/h3>
&lt;p>Тут всё довольно просто. К примеру, мы работаем на &lt;em>development&lt;/em>.&lt;/p>
&lt;ol>
&lt;li>Переходим на ветку&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git checkout development
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>Делаем git fetch&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git fetch --all
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>Делаем reset&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git reset --hard origin/development
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Всё, наша ветка точно такая как облаке.&lt;/p></description></item><item><title>Kubernetes in Docker</title><link>https://vlasov.pro/ru/p/kind/</link><pubDate>Mon, 12 Jun 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/kind/</guid><description>&lt;img src="https://vlasov.pro/ru/p/kind/logo.webp" alt="Featured image of post Kubernetes in Docker" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Частенько бывает, что нужен Kubernetes под рукой для быстрого запуска чего-то.&lt;/p>
&lt;ol>
&lt;li>Отладить самописный Helm чарт&lt;/li>
&lt;li>Спросить что-то у &lt;code>kubectl explain&lt;/code>&lt;/li>
&lt;li>Проверить какие-то настройки&lt;/li>
&lt;/ol>
&lt;p>Начинаешь искать какой-нибудь кластер на первом попавшемся проекте, что не есть хорошо, потому что можно сломать что-то ненароком. Неудобно, нужно что-то делать. Оказывается, есть много разных легковесных и быстрых установщиков Kubernetes. Это может и не все, но те которые я либо пробовал, либо мимо проходил. Все они работают немного по-разному.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Minikube&lt;/strong> - один из старейших, так сказать. Столкнулись с тем, что стандартная инсталяция kube-prometheus-stack на нём просто не завелась, а на следующем - с ходу.&lt;/li>
&lt;li>&lt;strong>k3s&lt;/strong> - один из трёх движков от &lt;a class="link" href="https://www.rancher.com" target="_blank" rel="noopener"
>Rancher&lt;/a>. Отличная вещь, использовал и использую на проде небольших проектов. Так же, у меня два личных кластера именно на k3s, но он тоже не ванильный, всё собрано в один бинарь. Это и хорошо, и плохо. Очень легковесный и легко устанавливается, но нарвался на то, что он ломал мне Wireguard VPN своими правилами IPTables. Пришлось поменять Wireguard FwMark на &lt;code>0x8000&lt;/code> и всё заработало.&lt;/li>
&lt;li>&lt;strong>rke&lt;/strong> - ещё один из трёх движков. Первый из движков от Rancher. Очень классный, а особенно тем, что под него есть &lt;a class="link" href="https://registry.terraform.io/providers/rancher/rke/latest" target="_blank" rel="noopener"
>Terraform Module&lt;/a> - кайф. Уже более похож на ванильную инсталяцию.&lt;/li>
&lt;li>&lt;strong>rke2&lt;/strong> - rke + k3s. Тут всё собрано в один бинарь, но apiserver, scheduler etc. всё ещё видны как отдельные поды. Пробовал его, жаль, что нет поддержки из Terraform как у rke. Не понравился, на практике оказался менее стабильным чем k3s, или у меня просто руки кривые.&lt;/li>
&lt;li>&lt;strong>Microk8s&lt;/strong> - от Canonical, не пробовал.&lt;/li>
&lt;li>&lt;strong>k0s&lt;/strong> - то же самое, как по мне, что &lt;em>k3s&lt;/em>, только сообщество меньше и документация хуже, а так - хорош.&lt;/li>
&lt;li>&lt;strong>kind&lt;/strong> - гвоздь программы сегодня. Про него поподробнее.&lt;/li>
&lt;/ol>
&lt;h2 id="kind">kind &lt;a href="#kind">¶&lt;/a>&lt;/h2>
&lt;p>Почему хочу рассказать о нём. Это самый &lt;strong>ванильный&lt;/strong> из всех способ для получения Kubernetes локально. У него масса плюсов.&lt;/p>
&lt;ol>
&lt;li>Есть возможность подкинуть конфиг&lt;/li>
&lt;li>Создаёт Kubernetes в Docker&lt;/li>
&lt;li>&lt;strong>Можно создать больше одного узла!&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Под коробкой использует ванильный kubeadm!&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Все конфиги, пути и форматы - стандартный kubeadm!&lt;/strong>&lt;/li>
&lt;li>Он не лезет в iptables на хосте&lt;/li>
&lt;/ol>
&lt;p>Из минусов.&lt;/p>
&lt;ol>
&lt;li>Control-plane ест в состоянии простоя 900 MiB RAM с ходу&lt;/li>
&lt;li>Нужно выбрасывать порты с узлов на хост&lt;/li>
&lt;/ol>
&lt;p>Вот пример конфига kind&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Cluster&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">kind.x-k8s.io/v1alpha4&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">nodes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">role&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">control-plane&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extraMounts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">hostPath&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">/home/bzm/projects/kind/&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">containerPath&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">/host&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kubeadmConfigPatches&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> kind: InitConfiguration
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> nodeRegistration:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> kubeletExtraArgs:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> seccomp-default: &amp;#34;true&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> apiServer:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> extraArgs:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> enable-admission-plugins: NodeRestriction&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">role&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">worker&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extraPortMappings&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">containerPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">hostPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">listenAddress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;127.0.0.1&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">containerPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">443&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">hostPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">443&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">listenAddress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;127.0.0.1&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>То есть, можно на одном компьютере, поднять кучу узлов и всё в контейнерах. Конфиги и настройки все - как в официальной документации. Нужно попробовать какие-то ключи к api-server - пожалуйста, нужно отточить что-то по безопасности - легко. Мне очень понравился.&lt;/p></description></item><item><title>Redis Sentinel Watchdog</title><link>https://vlasov.pro/ru/p/redis-watchdog/</link><pubDate>Fri, 09 Jun 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/redis-watchdog/</guid><description>&lt;img src="https://vlasov.pro/ru/p/redis-watchdog/logo.webp" alt="Featured image of post Redis Sentinel Watchdog" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Очень люблю чарты от &lt;a class="link" href="https://artifacthub.io/packages/search?org=bitnami&amp;amp;sort=relevance&amp;amp;page=1" target="_blank" rel="noopener"
>Bitnami&lt;/a>, хорошо написаны и довольно стабильны. Среди прочего, всегда ставлю &lt;a class="link" href="https://artifacthub.io/packages/helm/bitnami/redis" target="_blank" rel="noopener"
>Redis из их чарта&lt;/a>. Всё бы хорошо, когда тебе нужен просто Redis без всякого там High Availability, но так бывает не всегда.&lt;/p>
&lt;blockquote>
&lt;p>В чём сложность поднять Redis HA?&lt;/p>
&lt;/blockquote>
&lt;p>Тут дело в том, что драйверы подключения к Redis в сервисах-клиентах должны поддерживать Redis Sentinel. Когда мы поднимаем кластер с Redis, так же поднимается по контейнеру с Sentinel - это своего рода контроллер для кластера, который сделает замену мастера если текущий пропадёт. Очень похоже на &lt;a class="link" href="https://www.mongodb.com/docs/manual/core/replica-set-arbiter/" target="_blank" rel="noopener"
>Mongo Arbiter&lt;/a>. Так вот механизм подключения из-за этого самого Sentinel меняется.&lt;/p>
&lt;ol>
&lt;li>Подключаемся к Sentinel&lt;/li>
&lt;li>Запрашиваем адрес мастера&lt;/li>
&lt;li>Подключаемся к мастеру&lt;/li>
&lt;li>Если мастер недоступен - опять идём к Sentinel&lt;/li>
&lt;/ol>
&lt;p>Очень часто приложения такое не поддерживают. Что же делать в таком случае? Я решил что мне поможет, как всегда, &lt;strong>инкостыляция&lt;/strong>.&lt;/p>
&lt;p>Ниже представлен фрагмент &lt;em>values.yaml&lt;/em>, с которыми я запускаю &lt;em>bitnami/redis&lt;/em> используя &lt;a class="link" href="https://helmfile.readthedocs.io/en/latest/" target="_blank" rel="noopener"
>Helmfile&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>Что там происходит?&lt;/p>
&lt;/blockquote>
&lt;p>Среди прочего, я создаю дополнительный sidecar контейнер, который каждые N секунд запрашивает у Sentinel адрес мастера и если он отличается от такового в созданном Service типа ExternalName - обновляет сервис. Таким образом, мы можем просто направить приложения, которые с Sentinel не умеют общаться, на этот сервис и всё будет работать, так как сервис всегда будет указывать на правильный под.&lt;/p>
&lt;p>Потребляет такой sidecar контейнер &lt;em>~65 mCPU&lt;/em> и &lt;em>1 MiB&lt;/em>. Можно конечно собрать образ и включить туда redis-cli чтобы подключаться напрямую, но неохота поддерживать и хранить этот образ, обновлять его.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;span class="lnt">107
&lt;/span>&lt;span class="lnt">108
&lt;/span>&lt;span class="lnt">109
&lt;/span>&lt;span class="lnt">110
&lt;/span>&lt;span class="lnt">111
&lt;/span>&lt;span class="lnt">112
&lt;/span>&lt;span class="lnt">113
&lt;/span>&lt;span class="lnt">114
&lt;/span>&lt;span class="lnt">115
&lt;/span>&lt;span class="lnt">116
&lt;/span>&lt;span class="lnt">117
&lt;/span>&lt;span class="lnt">118
&lt;/span>&lt;span class="lnt">119
&lt;/span>&lt;span class="lnt">120
&lt;/span>&lt;span class="lnt">121
&lt;/span>&lt;span class="lnt">122
&lt;/span>&lt;span class="lnt">123
&lt;/span>&lt;span class="lnt">124
&lt;/span>&lt;span class="lnt">125
&lt;/span>&lt;span class="lnt">126
&lt;/span>&lt;span class="lnt">127
&lt;/span>&lt;span class="lnt">128
&lt;/span>&lt;span class="lnt">129
&lt;/span>&lt;span class="lnt">130
&lt;/span>&lt;span class="lnt">131
&lt;/span>&lt;span class="lnt">132
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># ┬─┐┬─┐┬─┐o┐─┐&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># │┬┘├─ │ ││└─┐&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># ┘└┘┴─┘┘─┘┘──┘&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>{{- &lt;span class="l">$name := &amp;#34;redis&amp;#34; }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>{{- &lt;span class="l">$masterServiceName := printf &amp;#34;%s-master&amp;#34; $name }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">nameOverride&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">$name }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">fullnameOverride&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">$name }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">architecture&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">replication&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">auth&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">password&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">quote .Values.secrets.redisPassword }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">replica&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">replicaCount&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">limits&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">75Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">requests&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">25Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">persistence&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">storageClass&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">standard&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">size&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">1Gi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">podAntiAffinityPreset&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">hard&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">sidecars&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">master-service-watchdog&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;{{`{{ printf &amp;#34;bitnami/kubectl:%s.%s&amp;#34; .Capabilities.KubeVersion.Major .Capabilities.KubeVersion.Minor }}`}}&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">imagePullPolicy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">IfNotPresent&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;/bin/sh&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;-ec&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> while sleep 5; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> MASTER_ADDRESS=&amp;#34;$(kubectl exec -c sentinel &amp;#34;${POD_NAME}&amp;#34; -- sh -c &amp;#34;REDISCLI_AUTH=&amp;#39;$REDISCLI_AUTH&amp;#39; redis-cli -p &amp;#39;${REDIS_SENTINEL_PORT}&amp;#39; SENTINEL get-master-addr-by-name this&amp;#34; | head -1)&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> if ! kubectl get svc &amp;#34;${MASTER_SERVICE}&amp;#34; -o jsonpath=&amp;#39;{.spec.externalName}&amp;#39; | grep -qF &amp;#34;${MASTER_ADDRESS}&amp;#34;; then
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> echo &amp;#34;info: master address has changed to ${MASTER_ADDRESS}&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> jq -Mnr --arg address &amp;#34;${MASTER_ADDRESS}&amp;#34; &amp;#39;[{op:&amp;#34;replace&amp;#34;,path:&amp;#34;/spec/externalName&amp;#34;,value:$address}]&amp;#39; | \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> xargs -0 kubectl patch svc &amp;#34;${MASTER_SERVICE}&amp;#34; --type=json --patch
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> fi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> done&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">env&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MASTER_SERVICE&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">quote $masterServiceName }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">POD_NAME&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">valueFrom&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">fieldRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">fieldPath&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">metadata.name&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">REDISCLI_AUTH&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">valueFrom&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">secretKeyRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;{{`{{ template &amp;#34;common.names.fullname&amp;#34; . }}`}}&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">key&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">redis-password&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">REDIS_SENTINEL_PORT&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;{{`{{ .Values.sentinel.containerPorts.sentinel }}`}}&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">limits&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">100m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">requests&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">100m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">securityContext&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">readOnlyRootFilesystem&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runAsNonRoot&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runAsUser&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">privileged&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">allowPrivilegeEscalation&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">capabilities&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">drop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="l">ALL]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">seccompProfile&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">RuntimeDefault&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">serviceAccount&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">create&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">sentinel&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">masterSet&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">this&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">automateClusterRecovery&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">downAfterMilliseconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">limits&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">requests&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">networkPolicy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extraIngress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">6379&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">namespaceSelector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kubernetes.io/metadata.name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">.Release.Namespace }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">rbac&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">create&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">rules&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># Allow watchdog update our service&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">apiGroups&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;services&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">verbs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;get&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;update&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;patch&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resourceNames&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">quote $masterServiceName }}]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># Allow exec into Redis pods&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">apiGroups&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;pods/exec&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">verbs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;create&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">apiGroups&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;pods&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">verbs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;get&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;list&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">pdb&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">create&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">raw&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">Service&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Service&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">$masterServiceName }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ExternalName&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 1.1.1.1 is just a stub value that is used for initial deployment&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># It will be overridden as soon as first watchdog will be ready&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">externalName&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1.1.1.1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">6379&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">protocol&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TCP&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">targetPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">6379&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">redis&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Timeshift BTRFS бекапы на Manjaro</title><link>https://vlasov.pro/ru/p/timeshift/</link><pubDate>Sun, 01 Jan 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/timeshift/</guid><description>&lt;img src="https://vlasov.pro/ru/p/timeshift/logo.webp" alt="Featured image of post Timeshift BTRFS бекапы на Manjaro" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://github.com/linuxmint/timeshift" target="_blank" rel="noopener"
>Timeshift&lt;/a> инструмент просто обалденный! Помогает делать автоматические бекапы системы. Можно и вручную делать, если очень хочется. Поддерживает он работу в двух режимах.&lt;/p>
&lt;ol>
&lt;li>Копирование куда-то &lt;a class="link" href="https://linux.die.net/man/1/rsync" target="_blank" rel="noopener"
>rsync-ом&lt;/a>, с хитрым линкованием, чтобы место экономить по максимуму&lt;/li>
&lt;li>Использование BTRFS snapshot&lt;/li>
&lt;/ol>
&lt;p>Первый вариант вообще не интересует. Это долго и не забавно, а вот BTRFS это то, что нужно! Делается мгновенно и где дубликаты, как можно сэкономить, решает сама файловая система напрямую. Кроме того, можно с них грузиться прямо при загрузке системы.&lt;/p>
&lt;h2 id="требования-к-системе">Требования к системе &lt;a href="#%d1%82%d1%80%d0%b5%d0%b1%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%ba-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Часть, описана на главной странице репозитория, но есть ещё и то, что я нашёл сам.&lt;/p>
&lt;ol>
&lt;li>Подраздел по умолчанию для файловой системы BTRFS должен быть /&lt;/li>
&lt;/ol>
&lt;p>Когда монтируешь раздел с BTRFS куда либо без указания опции монтирования &lt;em>subvol=&amp;hellip;&lt;/em> должен монтироваться именно корень, иначе программа падает. Вот скрипт, который это проверяет и ставит правильно.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">MP&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mktemp -d&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;/on \/ type btrfs/{print $1}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> sudo xargs -I&lt;span class="o">{}&lt;/span> mount &lt;span class="o">{}&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>sudo btrfs subvolume set-default &lt;span class="m">5&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>sudo umount &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>В &lt;code>/etc/fstab&lt;/code> корневой раздел системы должен быть прописан корректно&lt;/li>
&lt;/ol>
&lt;p>Та самая опция &lt;em>subvol=&amp;hellip;&lt;/em> должна быть установлена в &lt;em>@&lt;/em> или &lt;em>/@&lt;/em>, не важно. Вот этот скрипт подскажет прописано ли у Вас всё верно.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">grep -E &lt;span class="s1">&amp;#39;^[^#].+/\s+btrfs&amp;#39;&lt;/span> /etc/fstab &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>grep -oE &lt;span class="s1">&amp;#39;subvol=[^,]+&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>cut -d&lt;span class="o">=&lt;/span> -f2 &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>grep -qE &lt;span class="s1">&amp;#39;^/?@$&amp;#39;&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;OK&amp;#39;&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;Not OK&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="как-работает">Как работает &lt;a href="#%d0%ba%d0%b0%d0%ba-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d0%b5%d1%82">¶&lt;/a>&lt;/h2>
&lt;p>При установке любого пакета через &lt;em>pamac&lt;/em> или &lt;em>yay&lt;/em>, в моём случае, timeshift срабатывает автоматически, если в &lt;em>/etc/timeshift-autosnap.conf&lt;/em> не прописано его пропускать.&lt;/p>
&lt;script id="asciicast-547865" src="https://asciinema.org/a/547865.js" async>&lt;/script>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/timeshift/timeshift-after-install.webp"
width="820"
height="655"
srcset="https://vlasov.pro/ru/p/timeshift/timeshift-after-install_hu11808219343456374573.webp 480w, https://vlasov.pro/ru/p/timeshift/timeshift-after-install_hu1277256472034217943.webp 1024w"
loading="lazy"
alt="И вот, у меня даже два бекапа теперь"
class="gallery-image"
data-flex-grow="125"
data-flex-basis="300px"
>&lt;/p></description></item><item><title>Удобный и красочный ZSH с p10k</title><link>https://vlasov.pro/ru/p/zsh-p10k/</link><pubDate>Sun, 25 Dec 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/zsh-p10k/</guid><description>&lt;img src="https://vlasov.pro/ru/p/zsh-p10k/logo.webp" alt="Featured image of post Удобный и красочный ZSH с p10k" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Ранее, я уже описывал мой опыт с ZSH &lt;a class="link" href="../shells" >здесь&lt;/a>. Сейчас всё немного иначе, я полностью перешёл на &lt;a class="link" href="https://github.com/romkatv/powerlevel10k" target="_blank" rel="noopener"
>Powerlevel10k&lt;/a>.&lt;/p>
&lt;p>Это очень красивый и удобный обвес, который просто ставится и настраивается на ходу.&lt;/p>
&lt;h2 id="настройка-p10k">Настройка p10k &lt;a href="#%d0%bd%d0%b0%d1%81%d1%82%d1%80%d0%be%d0%b9%d0%ba%d0%b0-p10k">¶&lt;/a>&lt;/h2>
&lt;p>Настроить p10k можно очень просто, прямо на ходу, хоть по 10 раз на дню.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">p10k configure
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Установку самого p10k я зашил прямо в .zshrc, по этому, можно даже не следовать официальным инструкциям на сайте. Ну почти. Есть ещё рекомендованные шрифты, чтобы всё точно было красиво, описано вот &lt;a class="link" href="https://github.com/romkatv/powerlevel10k#fonts" target="_blank" rel="noopener"
>здесь&lt;/a>. Ниже, я записал и показал как выглядит настройка самого p10k. Вот только, в записи asciinema всё красивости квадратиками, не поддерживаются эти символы в записи, к сожалению. По этому, вот скриншот терминального окна.&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/zsh-p10k/tilix-screenshot.webp"
width="872"
height="658"
srcset="https://vlasov.pro/ru/p/zsh-p10k/tilix-screenshot_hu9219161931832726404.webp 480w, https://vlasov.pro/ru/p/zsh-p10k/tilix-screenshot_hu10273949202985261343.webp 1024w"
loading="lazy"
alt="(Нажми на изображение для увеличения)"
class="gallery-image"
data-flex-grow="132"
data-flex-basis="318px"
>&lt;/p>
&lt;p>В то время, как в записи, получилось не очень. Ну да ладно, хоть сами меню покажу.&lt;/p>
&lt;script id="asciicast-547818" src="https://asciinema.org/a/547818.js" async>&lt;/script>
&lt;h2 id="объяснение-моего-zshrc">Объяснение моего .zshrc &lt;a href="#%d0%be%d0%b1%d1%8a%d1%8f%d1%81%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bc%d0%be%d0%b5%d0%b3%d0%be-zshrc">¶&lt;/a>&lt;/h2>
&lt;p>Всё написанное далее это куски самого .zshrc, которые можно скачать в конце статьи. Для вашего удобства, продублирую ссылку ещё и &lt;a class="link" href="files/dot.zshrc" >здесь&lt;/a>.&lt;/p>
&lt;h3 id="установка-p10k">Установка p10k &lt;a href="#%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-p10k">¶&lt;/a>&lt;/h3>
&lt;p>Выполнено это простым условием и прямым стягиванием из GitHub. Если у нас есть Git и ещё не стоит p10k - можем склонировать.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="nb">command&lt;/span> -v git &amp;gt;/dev/null &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="o">[&lt;/span> ! -d ~/powerlevel10k &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;info: installing p10k&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> git clone --depth &lt;span class="m">1&lt;/span> --single-branch https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="плагины">Плагины &lt;a href="#%d0%bf%d0%bb%d0%b0%d0%b3%d0%b8%d0%bd%d1%8b">¶&lt;/a>&lt;/h3>
&lt;p>Плагины ставлю просто, тоже клонированием из GitHub. Добавил комментарии прямо в код для пояснения происходящего.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># if we have git installed&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="nb">command&lt;/span> -v git &amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># and folder with plugins is absent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -d /usr/share/zsh/plugins &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># let&amp;#39;s create it with sudo&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sudo mkdir -p /usr/share/zsh/plugins
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># and jump in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">cd&lt;/span> /usr/share/zsh/plugins
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># now, let&amp;#39;s read every line between &amp;lt;&amp;lt;EOF and EOF lines below&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="nv">IFS&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="nb">read&lt;/span> -r REPO&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># and for every line, which will be available in variable named REPO&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># let&amp;#39;s cut only last part of the url (ex: zsh-autosuggestions.git) and save to BASENAME var&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">BASENAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>basename &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$REPO&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># now, we will remove .git from the end of BASENAME and check either such folder exists&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -d &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">BASENAME&lt;/span>&lt;span class="p">%.git&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># if not, let&amp;#39;s print an info message&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">REPO&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: Cloning to &lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">pwd&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">/&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">BASENAME&lt;/span>&lt;span class="p">%.git&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># and finally clone that plugin&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sudo git clone --depth &lt;span class="m">1&lt;/span> --single-branch &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$REPO&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">done&lt;/span> &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">https://github.com/zsh-users/zsh-history-substring-search.git
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">https://github.com/zsh-users/zsh-syntax-highlighting.git
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">https://github.com/zsh-users/zsh-autosuggestions.git
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># after all plugins cloned, we cd back to the location we were&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">cd&lt;/span> - &amp;gt;/dev/null
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># okay, now we assume that all plugins are cloned and we have to include them&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># once again, for every hardcoded path to .zsh file&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">while&lt;/span> &lt;span class="nv">IFS&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="nb">read&lt;/span> -r SOURCE&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># we skip the plugin if it starts with &amp;#39;#&amp;#39; (commented out)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SOURCE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> grep -qE &lt;span class="s1">&amp;#39;^#&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="o">[&lt;/span> -s &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SOURCE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># if it is enabled, we just include it in current shell session with source command&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">source&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>realpath &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SOURCE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span> &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/usr/share/zsh/plugins/zsh-history-substring-search/zsh-history-substring-search.zsh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="добавление-путей-в-path">Добавление путей в PATH &lt;a href="#%d0%b4%d0%be%d0%b1%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bf%d1%83%d1%82%d0%b5%d0%b9-%d0%b2-path">¶&lt;/a>&lt;/h3>
&lt;p>Часто бывает, что дополнительные бинарники мы ставим в нестандартные папки. У меня, к примеру, &lt;em>~/.local/bin&lt;/em> используется для всяких kubectl, helm, k9s и другого. Вот тут мы для каждой папочки, если она конечно есть, выполняем проверку и включаем её в переменную &lt;em>PATH&lt;/em>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="k">while&lt;/span> &lt;span class="nv">IFS&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="nb">read&lt;/span> -r P&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -d &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$P&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">export&lt;/span> &lt;span class="nv">PATH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">P&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">PATH&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span> &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">${HOME}/.local/share/gem/ruby/3.0.0/bin
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">${HOME}/projects/stm32/gcc-arm-none-eabi-10.3-2021.10/bin
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">${HOME}/.local/bin
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="алиасы">Алиасы &lt;a href="#%d0%b0%d0%bb%d0%b8%d0%b0%d1%81%d1%8b">¶&lt;/a>&lt;/h3>
&lt;p>Ну тут всё понятно, много всяких алиасов.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> ..&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;cd .. &amp;amp;&amp;amp; ls -lhA --color=auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">d&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;sudo -E docker&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">dc&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;docker-compose&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">e&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;exit&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">j&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo journalctl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">l&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ls -lh --color=always&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">la&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ls -lhA --color=always&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">p&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ping 8.8.8.8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">please&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;sudo&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">reborn&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo shutdown -r now&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;sudo&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">sctl&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo systemctl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">svi&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo vim&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">svim&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo vim&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">t&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;terraform&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubectl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">kd&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubectl describe&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">kg&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubectl get&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">ky&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubectl get -o yaml&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">ke&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;kubectl exec -it&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">vi&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;vim&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">g&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;git&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">b&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo btrfs&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">c&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;code .&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> ansible-time&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;time ansible-playbook&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="git-config">Git config &lt;a href="#git-config">¶&lt;/a>&lt;/h3>
&lt;p>К слову, у меня ж ещё есть и Git config. Ссылка &lt;a class="link" href="files/dot.gitconfig" >тут&lt;/a> или то же самое в конце страницы. Из интересного тут две команды.&lt;/p>
&lt;ol>
&lt;li>&lt;code>git ps&lt;/code> - пушит ветку, а если её ещё нет, ловит сообщение из лога ошибки git-а и пушит с &amp;ndash;set-upstream&lt;/li>
&lt;li>&lt;code>git dpush&lt;/code> (dummy push) - добавляет в коммит все файлы и папки, пишет стандартное сообщение к комиту и пушит&lt;/li>
&lt;li>&lt;code>git cc&lt;/code> - просто делает коммит со стандартным сообщением&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ruby" data-lang="ruby">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>&lt;span class="k">alias&lt;/span>&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">co&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">checkout&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">add&lt;/span> &lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ci&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">commit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">cc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">commit&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">m&lt;/span> &lt;span class="s1">&amp;#39;Nothing special. Just regular commit.&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ps&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">!&lt;/span> &lt;span class="n">sh&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">c&lt;/span> &lt;span class="s1">&amp;#39;git push &amp;gt;/tmp/git-ps 2&amp;gt;&amp;amp;1 || grep -- \&amp;#34;git push --set-upstream\&amp;#34; /tmp/git-ps | sh&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">pt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">push&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">tags&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">pts&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">!&lt;/span> &lt;span class="n">sh&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">c&lt;/span> &lt;span class="s1">&amp;#39;git push &amp;amp;&amp;amp; git push --tags&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">pl&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pull&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">st&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">status&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">br&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">branch&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">hist&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">log&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">pretty&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">format&lt;/span>&lt;span class="ss">:&amp;#39;%h %ad | %s%d [%an]&amp;#39;&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">graph&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">date&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">short&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">type&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">cat&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">file&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">dump&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">cat&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">file&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="nb">p&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">dpush&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">!&lt;/span> &lt;span class="n">sh&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">c&lt;/span> &lt;span class="s1">&amp;#39;git add . &amp;amp;&amp;amp; git commit -m \&amp;#34;Nothing special. Just regular commit.\&amp;#34;&amp;#39;&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">git&lt;/span> &lt;span class="n">push&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="kubeconfig">KUBECONFIG &lt;a href="#kubeconfig">¶&lt;/a>&lt;/h3>
&lt;p>Тут ищется стандартный kubeconfig для &lt;a class="link" href="https://k3s.io" target="_blank" rel="noopener"
>k3s&lt;/a> или &lt;a class="link" href="https://docs.rke2.io" target="_blank" rel="noopener"
>rke2&lt;/a> и прописывается в KUBECONFIG.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># if there is no file at the path that is already being set in KUBECONFIG var&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -z &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$KUBECONFIG&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># for every filepath from the list below&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="nv">IFS&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="nb">read&lt;/span> -r K&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># check if file exists and it is not empty&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -s &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$K&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># change owner and group to current user&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> ! stat -c &lt;span class="s1">&amp;#39;%u:%g&amp;#39;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$K&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> grep -qF &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>id -u&lt;span class="k">)&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="k">$(&lt;/span>id -g&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sudo chown &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">USER&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">USER&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$K&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;info: chown &lt;/span>&lt;span class="nv">$K&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;info: selecting &lt;/span>&lt;span class="nv">$K&lt;/span>&lt;span class="s2"> as kubeconfig&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># and select as default KUBECONFIG&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">export&lt;/span> &lt;span class="nv">KUBECONFIG&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$K&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">done&lt;/span> &lt;span class="s">&amp;lt;&amp;lt; EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/etc/rancher/rke2/rke2.yaml
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/etc/rancher/k3s/k3s.yaml
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># last listed path wins&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="автоматическая-загрузка-утилит">Автоматическая загрузка утилит &lt;a href="#%d0%b0%d0%b2%d1%82%d0%be%d0%bc%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%b7%d0%b0%d0%b3%d1%80%d1%83%d0%b7%d0%ba%d0%b0-%d1%83%d1%82%d0%b8%d0%bb%d0%b8%d1%82">¶&lt;/a>&lt;/h3>
&lt;p>Тут, значится, происходит следующее: .zshrc сам следит за тем, чтобы у нас были установлены бинарники утилит, которые мы используем. Если утилиты нет вообще, он её качает, если нет - ничего не делает, но я вручную могу обновить k9s выполнив _update_k9s. Здесь ставятся такие вещи.&lt;/p>
&lt;ol>
&lt;li>&lt;a class="link" href="https://k9scli.io" target="_blank" rel="noopener"
>k9s&lt;/a> - подробнее &lt;a class="link" href="../k9s" >в моей статье&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/rikatz/kubepug" target="_blank" rel="noopener"
>kubepug&lt;/a> - утилита для проверки устаревших API в кластере перед обновлением версии самого Kubernetes&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/hidetatz/kubecolor" target="_blank" rel="noopener"
>kubecolor&lt;/a> - обёртка над kubectl для разноцветного вывода&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">_update_kubepug&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mkdir -p ~/.local/bin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LOCATION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>curl --connect-timeout &lt;span class="m">1&lt;/span> -sS https://github.com/rikatz/kubepug/releases/latest -D- &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;/^location:/{print $2}&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LATEST_VERSION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LOCATION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> awk -F/ &lt;span class="s1">&amp;#39;{print $NF}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;[0-9a-zA-Z_.-]+&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> ! k9s version --short &lt;span class="p">|&lt;/span> grep -qF &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s2">&amp;#34;Updating kubepug to %s\n&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;https://github.com/rikatz/kubepug/releases/download/%s/kubepug_linux_%s.tar.gz&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>uname -p &lt;span class="p">|&lt;/span> sed &lt;span class="s1">&amp;#39;s/unknown/amd64/g&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> tr -d &lt;span class="s1">&amp;#39;[[:space:]]&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> xargs curl -sSL &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> tar -xpzf - kubepug
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> install kubepug ~/.local/bin/kubepug -m &lt;span class="m">0755&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f kubepug
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! &lt;span class="nb">command&lt;/span> -v kubepug &lt;span class="p">&amp;amp;&lt;/span>&amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> _update_kubepug
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">_update_k9s&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mkdir -p ~/.local/bin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LOCATION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>curl --connect-timeout &lt;span class="m">1&lt;/span> -sS https://github.com/derailed/k9s/releases/latest -D- &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;/^location:/{print $2}&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LATEST_VERSION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LOCATION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> awk -F/ &lt;span class="s1">&amp;#39;{print $NF}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;[0-9a-zA-Z_.-]+&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> ! k9s version --short &lt;span class="p">|&lt;/span> grep -qF &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s2">&amp;#34;Updating k9s to %s\n&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;https://github.com/derailed/k9s/releases/download/%s/k9s_Linux_%s.tar.gz&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>uname -p &lt;span class="p">|&lt;/span> sed &lt;span class="s1">&amp;#39;s/unknown/x86_64/g&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> tr -d &lt;span class="s1">&amp;#39;[[:space:]]&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> xargs curl -sSL &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> tar -xpzf - k9s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> install k9s ~/.local/bin/k9s -m &lt;span class="m">0755&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f k9s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! &lt;span class="nb">command&lt;/span> -v k9s &lt;span class="p">&amp;amp;&lt;/span>&amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> _update_k9s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">_update_kubecolor&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mkdir -p ~/.local/bin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LOCATION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>curl --connect-timeout &lt;span class="m">1&lt;/span> -sS https://github.com/hidetatz/kubecolor/releases/latest -D- &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;/^location:/{print $2}&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LATEST_VERSION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LOCATION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> awk -F/ &lt;span class="s1">&amp;#39;{print $NF}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;[0-9a-zA-Z_.-]+&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> sed &lt;span class="s1">&amp;#39;s/^v//g&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> ! kubecolor --kubecolor-version &lt;span class="p">|&lt;/span> grep -qF &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s2">&amp;#34;Updating kubecolor to %s\n&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;https://github.com/hidetatz/kubecolor/releases/download/%s/kubecolor_%s_Linux_%s.tar.gz&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="s2">&amp;#34;v&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>uname -p &lt;span class="p">|&lt;/span> sed &lt;span class="s1">&amp;#39;s/unknown/x86_64/g&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> tr -d &lt;span class="s1">&amp;#39;[[:space:]]&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> xargs curl -sSL &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> tar -xpzf - kubecolor
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> install kubecolor ~/.local/bin/kubecolor -m &lt;span class="m">0755&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f kubecolor
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! &lt;span class="nb">command&lt;/span> -v kubecolor &lt;span class="p">&amp;amp;&lt;/span>&amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> _update_kubecolor
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">alias&lt;/span> &lt;span class="nv">kubectl&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubecolor&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">typeset&lt;/span> -g &lt;span class="nv">POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">|kubecolor&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Так же, для ряда команд, если они такие есть, выполняется автоматическая подгрузка дополнений подсказки, чтобы zsh знал что подсказывать.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Completions for 3-d party binaries&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> COMMAND in kubectl helm k3d flux kubepug&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">command&lt;/span> -v &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$COMMAND&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">source&lt;/span> &amp;lt;&lt;span class="o">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$COMMAND&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> completion zsh&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="раздельные-окружения">Раздельные окружения &lt;a href="#%d1%80%d0%b0%d0%b7%d0%b4%d0%b5%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d0%be%d0%ba%d1%80%d1%83%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f">¶&lt;/a>&lt;/h3>
&lt;p>Вот тут самая хитрая и в то же время простая штука из моего арсенала. Самая ценная вещь в работе. Дело в том, что когда работаешь на разных проектах\окружениях, то самая страшная вещь, которую ты можешь сделать это что-то сломать. Так вот нет способа проще это сделать, чем &lt;strong>забыть переключится&lt;/strong> на нужное окружение и применить что-то не туда куда думал.&lt;/p>
&lt;p>Вот от этого как раз и спасает этот кусок кода.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -f env.sh &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">source&lt;/span> ./env.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Да всё так просто. А что собственно происходит? Дело в том, что zsh разово, при запуске, проверяет ту папку, в которой он запустился и если там есть файл с точным именем &lt;em>env.sh&lt;/em>, то включает его в контекст. Объясняю.&lt;/p>
&lt;p>Я использую &lt;a class="link" href="https://github.com/ranger/ranger" target="_blank" rel="noopener"
>Ranger&lt;/a> для навигации по папкам из терминала. Допустим я работаю на проекте и у меня ещё блог есть. Создал вот такие папочки для проектов.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plaintext" data-lang="plaintext">&lt;span class="line">&lt;span class="cl">.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── MyBlog
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   ├── env.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   └── kubeconfig.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── SuperWorkProject
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── development
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │   ├── env.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │   └── kubeconfig.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── production
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── env.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── kubeconfig.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">4 directories, 6 files
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>На боевом проекте у меня есть два окружения, везде Kubernetes, везде свои &lt;strong>раздельные&lt;/strong> &lt;em>kubeconfig.yaml&lt;/em>. Допустим мне нужно поработать на production. В его env.sh я запишу следующее.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">KUBECONFIG&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;~/projects/SuperWorkProject/production/kubeconfig.yaml&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">AWS_PROFILE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;production&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pf&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nohup sh -c &lt;span class="s1">&amp;#39;kubectl get po -n monitoring -l app.kubernetes.io/name=grafana -o name | xargs -I{} kubectl port-forward {} 3000&amp;#39;&lt;/span> 1&amp;gt;/dev/null &lt;span class="p">&amp;amp;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь, подключу открыв zsh в этой папке или просто через &lt;code>source ./env.sh&lt;/code>. Всё, теперь я точно уверен, что работаю с production. Кроме того, объявил себе функцию для port-forward.&lt;/p></description></item><item><title>Kubernetes авторизация через OIDC</title><link>https://vlasov.pro/ru/p/kubernetes-oidc/</link><pubDate>Thu, 01 Dec 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/kubernetes-oidc/</guid><description>&lt;img src="https://vlasov.pro/ru/p/kubernetes-oidc/kubernetes-oidc.webp" alt="Featured image of post Kubernetes авторизация через OIDC" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Для того, чтобы авторизоваться в Kubernetes через kubeconfig для доступа через &lt;a class="link" href="https://kubernetes.io/docs/tasks/tools/" target="_blank" rel="noopener"
>kubectl&lt;/a>, как правило, используют ServiceAccounts. Их просто проще создать, но это совсем неправильно. Токены от ServiceAccount доступны любому, кто может читать секреты в пространстве имён, где создан ServiceAccount, а значит от Вашего имени можно произвести диверсию. Небезопасненько&amp;hellip;&lt;/p>
&lt;p>Можно создать сертификат, подписать в кластере и ходить как User. Вот это уже отлично, никто не может от Вашего имени ничего сделать, потому что приватную часть мы, естественно, генерировали локально и ни с кем не делились. Как это сделать, я тут заодно напишу, раз разобрался.&lt;/p>
&lt;p>Недавно, таки дошли руки попробовать &lt;a class="link" href="https://goauthentik.io" target="_blank" rel="noopener"
>Authentik&lt;/a>, а заодно попробовал привязать к нему кластер через &lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens" target="_blank" rel="noopener"
>настройку API сервера&lt;/a>. Оказалось, это даже проще, местами, чем возится с сертификатами для пользователя. Вот об этом всём и разскажу&lt;/p>
&lt;h2 id="доступ-через-serviceaccount">Доступ через ServiceAccount &lt;a href="#%d0%b4%d0%be%d1%81%d1%82%d1%83%d0%bf-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-serviceaccount">¶&lt;/a>&lt;/h2>
&lt;p>Создаём ServiceAccount.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl create serviceaccount &lt;span class="nb">test&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Раньше, до Kubernetes 1.22, автоматически генерировался токен, сейчас его нужно создавать отдельно. Можно сгенерировать временный.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl create token &lt;span class="nb">test&lt;/span> --duration&lt;span class="o">=&lt;/span>10m
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Можно, по-старинке, получить постоянный, создав для него секрет.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl apply -f - &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">apiVersion: v1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kind: Secret
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> name: test-sa-secret
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> annotations:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> kubernetes.io/service-account.name: test
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">type: kubernetes.io/service-account-token
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SA_TOKEN&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>kubectl get -o yaml secret test-sa-secret -o &lt;span class="nv">jsonpath&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;{.data.token}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> base64 -d&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>И вот мы его уже можем прописать в kubeconfig и использовать.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl config current-context &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>xargs kubectl config get-contexts --no-headers &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>awk &lt;span class="s1">&amp;#39;{print $4}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>xargs kubectl config set-credentials &lt;span class="s2">&amp;#34;--token=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SA_TOKEN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="создание-пользователя">Создание пользователя &lt;a href="#%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d0%b5-%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d1%82%d0%b5%d0%bb%d1%8f">¶&lt;/a>&lt;/h2>
&lt;p>Тут придётся заморочится. Нужно создать сертификат, запрос на подпись, подписать, забрать публичную часть и вот только теперь мы приплыли. Скрипт я свой прилагаю, а описывать это всё не хочу. Горит именно о OIDC рассказать, так что воспринимайте это как приятный бонус &amp;#x1f604;&lt;/p>
&lt;p>Как пользоваться:&lt;/p>
&lt;ol>
&lt;li>Пишем своё имя в переменную &lt;em>NAME&lt;/em>&lt;/li>
&lt;li>Пишем имя компании в переменную &lt;em>GROUP&lt;/em>&lt;/li>
&lt;li>Меняем &lt;em>CLUSTERROLE&lt;/em> если очень хочется&lt;/li>
&lt;li>Запускаем и читаем инструкцию на экране&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">NAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;john-johnson&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">GROUP&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;asdfqwer&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CLUSTERROLE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;cluster-admin&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">openssl ecparam -genkey -name prime256v1 &lt;span class="p">|&lt;/span> openssl ec -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">KEY_BASE64&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>base64 -w0 &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">openssl req -new -key &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span> -subj &lt;span class="s2">&amp;#34;/CN=&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">/O=&lt;/span>&lt;span class="nv">$GROUP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CSR_BASE64&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>base64 -w0 &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rm -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># ┬ ┐┐─┐┬─┐┬─┐ ┌─┐┬─┐┬─┐┬─┐┌┐┐o┌─┐┌┐┐
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># │ │└─┐├─ │┬┘ │ │┬┘├─ │─┤ │ ││ ││││
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># ┘─┘──┘┴─┘┘└┘ └─┘┘└┘┴─┘┘ ┘ ┘ ┘┘─┘┘└┘
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">1. Please, execute following code using kubectl that has access to the cluster (using default admin credentials, for example)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl apply -f - &amp;lt;&amp;lt;EOT
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">apiVersion: certificates.k8s.io/v1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kind: CertificateSigningRequest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> name: $GROUP:$NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">spec:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> expirationSeconds: 31536000 # 1 year
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> signerName: kubernetes.io/kube-apiserver-client
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> usages: [&amp;#34;client auth&amp;#34;]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> username: $NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> request: $CSR_BASE64
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOT
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl certificate approve &amp;#39;$GROUP:$NAME&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl apply -f - &amp;lt;&amp;lt;EOT
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">apiVersion: rbac.authorization.k8s.io/v1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kind: ClusterRoleBinding
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> name: user:${NAME}:${CLUSTERROLE}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">roleRef:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> apiGroup: rbac.authorization.k8s.io
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> kind: ClusterRole
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> name: $CLUSTERROLE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">subjects:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">- apiGroup: rbac.authorization.k8s.io
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> kind: User
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> name: $NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOT
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl get -o jsonpath=&amp;#39;{.status.certificate}&amp;#39; csr &amp;#39;$GROUP:$NAME&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">echo
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">2. Please, execute following code locally, on your PC, where you want to have that credentials inserted
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl config set &amp;#34;users.$GROUP:$NAME.client-key-data&amp;#34; &amp;#34;$KEY_BASE64&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl config set &amp;#34;users.$GROUP:$NAME.client-certificate-data&amp;#34; &amp;#34;-&amp;#34; --set-raw-bytes=true
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">3. Now place certificate that has been printed during step #1 in your kubeconfig client-certificate-data for user $GROUP:$NAME marker
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">4. Specify $GROUP:$NAME user in the context you want to use
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="google-oidc">Google OIDC &lt;a href="#google-oidc">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>Настраиваем &lt;a class="link" href="https://console.cloud.google.com/apis/credentials/consent" target="_blank" rel="noopener"
>&lt;strong>OAuth consent screen&lt;/strong>&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Создаём &lt;a class="link" href="https://console.cloud.google.com/apis/credentials/oauthclient" target="_blank" rel="noopener"
>OAuth2 креды&lt;/a> тип Web application, Authorized redirect URIs - в списке ниже.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plaintext" data-lang="plaintext">&lt;span class="line">&lt;span class="cl">http://127.0.0.1:18000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">http://127.0.0.1:8000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">http://localhost:18000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">http://localhost:8000
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>
&lt;p>В итоге получили Client ID и Client Secret&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Отлично, теперь нужно поставить &lt;a class="link" href="https://github.com/int128/kubelogin" target="_blank" rel="noopener"
>kubectl oidc-login плагин&lt;/a>.&lt;/p>
&lt;p>После установки, пробуем, чтобы у нас всё работало.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl oidc-login setup &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-issuer-url&lt;span class="o">=&lt;/span>https://accounts.google.com &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-client-id&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;YOUR CLIENT ID&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-client-secret&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;YOUR CLIENT SECRET&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Если всё в порядке, то у Вас открылся браузер, залогинились под кем-то и в консоли появилась большая красивая инструкция. Типо такой.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plaintext" data-lang="plaintext">&lt;span class="line">&lt;span class="cl">authentication in progress...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Opening in existing browser session.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 2. Verify authentication
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">You got a token with the following claims:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;iss&amp;#34;: &amp;#34;https://accounts.google.com&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;azp&amp;#34;: &amp;#34;longalphanum&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;aud&amp;#34;: &amp;#34;longalphanum&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;sub&amp;#34;: &amp;#34;longalphanum&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;at_hash&amp;#34;: &amp;#34;longalphanum&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;nonce&amp;#34;: &amp;#34;longalphanum&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;iat&amp;#34;: longalphanum,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;exp&amp;#34;: longalphanum
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 3. Bind a cluster role
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Run the following command:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> kubectl create clusterrolebinding oidc-cluster-admin --clusterrole=cluster-admin --user=&amp;#39;https://accounts.google.com#12345678901234567890&amp;#39;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 4. Set up the Kubernetes API server
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Add the following options to the kube-apiserver:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --oidc-issuer-url=https://accounts.google.com
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --oidc-client-id=longalphanum
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 5. Set up the kubeconfig
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Run the following command:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> kubectl config set-credentials oidc \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-api-version=client.authentication.k8s.io/v1beta1 \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-command=kubectl \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-arg=oidc-login \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-arg=get-token \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-arg=--oidc-issuer-url=https://accounts.google.com \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-arg=--oidc-client-id=longalphanum \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-arg=--oidc-client-secret=longalphanum
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 6. Verify cluster access
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Make sure you can access the Kubernetes cluster.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> kubectl --user=oidc get nodes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">You can switch the default context to oidc.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> kubectl config set-context --current --user=oidc
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">You can share the kubeconfig to your team members for on-boarding.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь просто следуем тому, что написано выше и перезапускаем API сервер разок.&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/kubernetes-oidc/google-prompt.png"
width="457"
height="505"
srcset="https://vlasov.pro/ru/p/kubernetes-oidc/google-prompt_hu2333402501022948420.png 480w, https://vlasov.pro/ru/p/kubernetes-oidc/google-prompt_hu8156114830533147923.png 1024w"
loading="lazy"
alt="Вот так мы теперь авторизуемся в браузере"
class="gallery-image"
data-flex-grow="90"
data-flex-basis="217px"
>&lt;/p>
&lt;h2 id="authentik">Authentik &lt;a href="#authentik">¶&lt;/a>&lt;/h2>
&lt;p>Штука отличная! Из прямых аналогов, стоит отметить &lt;a class="link" href="https://www.okta.com" target="_blank" rel="noopener"
>Okta&lt;/a> и &lt;a class="link" href="https://www.keycloak.org" target="_blank" rel="noopener"
>Keycloak&lt;/a>. Все 3 продукта великолепные, на Okta вообще часто равняются как на эталон. Другое либо лучше, либо хуже, но всегда по сравнению с Okta &amp;#x1f604;&lt;/p>
&lt;p>Ставил я Authentik из &lt;a class="link" href="https://artifacthub.io/packages/helm/goauthentik/authentik" target="_blank" rel="noopener"
>официального чарта&lt;/a>. Он у меня запущен локально, а сертификат нужен. Получил certbot-ом используя DNS проверку. После этого делаем следующее.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;em>Applications &amp;gt; Providers&lt;/em>&lt;/p>
&lt;p>Создаём провайдер &lt;strong>Kubernetes&lt;/strong> типа OAuth2/OIDC&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Client type&lt;/strong>: Confidential&lt;/li>
&lt;li>&lt;strong>Client ID&lt;/strong>: запоминаем&lt;/li>
&lt;li>&lt;strong>Client Secret&lt;/strong>: запоминаем&lt;/li>
&lt;li>&lt;strong>Redirect URIs&lt;/strong>: &lt;code>http://(127.0.0.1|localhost):1?8000(/.*)?&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;em>Application &amp;gt; Applications&lt;/em>&lt;/p>
&lt;p>Создаем приложение &lt;strong>Kubernetes&lt;/strong> и выбираем провайдером то, что создали в пункте 1.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;em>System&lt;/em>&lt;/p>
&lt;p>В пользователях создаём пользователей (как неожиданно, неправда ли?), тут же создаём группы. Я сделал &lt;em>kubernetes:admin&lt;/em> и &lt;em>kubernetes:restricted&lt;/em>. Первым будет выдаваться cluster-admin роль в самом Kubernetes, а вторым - что-то readonly. Не забываем добавить пользователей в соответсвующие группы.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;em>System &amp;gt; Certificates&lt;/em>&lt;/p>
&lt;p>Вот тут не уверен, просто не проверял без этого. Я загрузил сюда сертификат, который получил ранее certbot-ом, а потом этот сертификат выбрал в &lt;em>Application &amp;gt; Providers &amp;gt; Kubernetes &amp;gt; Edit &amp;gt; Signing Key&lt;/em>. Kubernetes не ругался, может можно тут и self-signed было стандартный использовать, не знаю, в общем. Попробуете сами.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;em>Customization &amp;gt; Property Mappings&lt;/em>&lt;/p>
&lt;p>Создаём вот с такими параметрами&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Name&lt;/strong>: Kubernetes&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Scope name&lt;/strong>: kubernetes&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Expression&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">all_groups&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;kubernetes:admin&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;kubernetes:restricted&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">return&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">groups&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">group&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">group&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">all_groups&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">ak_is_group_member&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ul>
&lt;p>Таким образом, для тех кто запросит этот скоуп, Authentik будет дописывать группы, в которых состоит пользователь, перебирая только кубовские.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Проверяем kube-oidc-login&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl oidc-login setup &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-issuer-url&lt;span class="o">=&lt;/span>https://authentik.example.com/application/o/kubernetes/ &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-client-id&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;YOUR CLIENT ID&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-client-secret&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;YOUR CLIENT SECRET&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-extra-scope&lt;span class="o">=&lt;/span>kubernetes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Всё там заводится, следуем дальше инструкциям.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Выделяем права на группу в Kubernetes&lt;/p>
&lt;p>Authentik передаст список групп, теперь нужно чтобы Kubernetes на это обратил внимание. Добавляем к API серверу вот такие аргументы.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">--oidc-groups-claim&lt;span class="o">=&lt;/span>groups
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">--oidc-groups-prefix&lt;span class="o">=&lt;/span>oidc:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь, можно создать, к примеру, такие ресурсы.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io/v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ClusterRoleBinding&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">oidc:kubernetes:admin&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">roleRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">apiGroup&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ClusterRole&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cluster-admin&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">subjects&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">apiGroup&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Group&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">oidc:kubernetes:admin&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io/v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ClusterRoleBinding&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">this-name-is-custom&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">roleRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">apiGroup&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ClusterRole&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">view&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">subjects&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">apiGroup&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Group&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">oidc:kubernetes:restricted&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ol></description></item><item><title>wg-quick network namespace</title><link>https://vlasov.pro/ru/p/wg-quick-netns/</link><pubDate>Fri, 25 Nov 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/wg-quick-netns/</guid><description>&lt;img src="https://vlasov.pro/ru/p/wg-quick-netns/wireguard.webp" alt="Featured image of post wg-quick network namespace" />&lt;h2 id="tldr">TL;DR &lt;a href="#tldr">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="na">PreUp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">ip netns list | grep -qF -- %i &amp;amp;&amp;amp; ip netns delete %i || true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">PostUp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">(ip netns list | grep -qF -- %i || ip netns add %i) &amp;amp;&amp;amp; ip -n %i link set up lo &amp;amp;&amp;amp; IPS=&amp;#34;$(ip address save dev %i | base64)&amp;#34; &amp;amp;&amp;amp; ip link set %i netns %i &amp;amp;&amp;amp; echo &amp;#34;$IPS&amp;#34; | base64 -d | ip -n %i address restore dev %i &amp;amp;&amp;amp; ip -n %i link set up %i &amp;amp;&amp;amp; (ip -n %i route show default | grep -qF default || ip -n %i route add default dev %i) &amp;amp;&amp;amp; echo &amp;#39;IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCgpuZXRucz0nJXMnCgpjYXQgPDxFT0YgfCB4YXJncyAtMCBzdWRvIC1FIG5zZW50ZXIgIi0tbmV0PS92YXIvcnVuL25ldG5zLyRuZXRucyIgdW5zaGFyZSAtLW1vdW50IHNoIC1jCmZvciBjb25mIGluICIkbmV0bnMiICJ0dW4uJG5ldG5zIjsgZG8KICBpZiBbIC1mICIvdmFyL3J1bi9yZXNvbHZjb25mL2ludGVyZmFjZXMvXCRjb25mIiBdOyB0aGVuCiAgICBtb3VudCAtLWJpbmQgIi92YXIvcnVuL3Jlc29sdmNvbmYvaW50ZXJmYWNlcy9cJGNvbmYiIC9ldGMvcmVzb2x2LmNvbmYKICBmaQpkb25lCmV4cG9ydCBEQlVTX1NFU1NJT05fQlVTX0FERFJFU1M9dW5peDpwYXRoPS9kZXYvbnVsbApzdWRvIC1FIC11ICcjJHtTVURPX1VJRDotJChpZCAtdSl9JyAtZyAnIyR7U1VET19HSUQ6LSQoaWQgLWcpfScgLS0gJEAKRU9GCg==&amp;#39; | base64 -d | xargs -0 -I{} printf {} %i &amp;gt; /usr/local/bin/wg-%i-exec &amp;amp;&amp;amp; echo &amp;#39;IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCgppZiBbICIkKGlkIC11KSIgLW5lIDAgXTsgdGhlbgogIGVjaG8gImVycm9yOiBydW4gbWUgYXMgcm9vdCIgMT4mMgogIGV4aXQgMQpmaQoKbmV0bnM9JyVzJwppcCBuZXRucyBleGVjICIkbmV0bnMiIGlwIGxpbmsgc2V0ICIkbmV0bnMiIG5ldG5zIDEKaXAgbmV0bnMgZGVsZXRlICIkbmV0bnMiCnN5c3RlbWN0bCBzdG9wICJ3Zy1xdWlja0AkbmV0bnMuc2VydmljZSIK&amp;#39; | base64 -d | xargs -0 -I{} printf {} %i &amp;gt; /usr/local/bin/wg-%i-down &amp;amp;&amp;amp; chmod 0755 /usr/local/bin/wg-%i-* &amp;amp;&amp;amp; chown root:root /usr/local/bin/wg-%i-* &amp;amp;&amp;amp; echo &amp;#39;bmV0bnM9JyVzJwpjYXQgPDxFT0YKIyAg4pSQIOKUrG/ilKzilIDilJDilKzilIDilJDilIzilIDilJDilKwg4pSQ4pSs4pSA4pSQ4pSs4pSA4pSQ4pSs4pSA4pSQICDilIzilJDilJDilKzilIDilJDilIzilJDilJDilIzilJDilJDilJDilIDilJAKIyAg4pSC4pSC4pSC4pSC4pSC4pSs4pSY4pSc4pSAIOKUgiDilKzilIIg4pSC4pSC4pSA4pSk4pSC4pSs4pSY4pSCIOKUgiAg4pSC4pSC4pSC4pSc4pSAICDilIIg4pSC4pSC4pSC4pSU4pSA4pSQCiMgIOKUlOKUtOKUmOKUmOKUmOKUlOKUmOKUtOKUgOKUmOKUmOKUgOKUmOKUmOKUgOKUmOKUmCDilJjilJjilJTilJjilJjilIDilJggIOKUmOKUlOKUmOKUtOKUgOKUmCDilJgg4pSY4pSU4pSY4pSA4pSA4pSYClRoYW5rcyBmb3IgdXNpbmcgbmV0bnMgd2ctcXVpY2sgd3JhcHBlciEKCi91c3IvbG9jYWwvYmluL3dnLSRuZXRucy1leGVjIENPTU1BTkQgICAtIGV4ZWN1dGUgc2hlbGwgY29tbWFuZCBpbiAkbmV0bnMgbmV0d29yayBuYW1lc3BhY2UKL3Vzci9sb2NhbC9iaW4vd2ctJG5ldG5zLWRvd24gICAgICAgICAgIC0gdXNlIGl0IGluc3RlYWQgb2Ygd2ctcXVpY2sgZG93biAkbmV0bnMKRU9G&amp;#39; | base64 -d | xargs -0 -I{} printf {} %i | sh - &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">PostDown&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">rm -f /usr/local/bin/wg-%i-* || true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://www.wireguard.com" target="_blank" rel="noopener"
>Wireguard&lt;/a> – обалденный, простой VPN, который &lt;a class="link" href="https://www.wireguard.com" target="_blank" rel="noopener"
>уже включён в состав ядра&lt;/a>. Очень мощный и простой инструмент. Ставиться в разы проще чем &lt;a class="link" href="https://openvpn.net" target="_blank" rel="noopener"
>OpenVPN&lt;/a>. Для его простой настройки используется утилита &lt;a class="link" href="https://www.man7.org/linux/man-pages/man8/wg-quick.8.html" target="_blank" rel="noopener"
>wg-quick&lt;/a>, которая входит в состав wireguard tools. Для более полного понимания, дополнительно уточню, что из моего опыта большинство решений, таких как &lt;a class="link" href="https://github.com/donaldzou/WGDashboard" target="_blank" rel="noopener"
>WGDashboard&lt;/a> и &lt;a class="link" href="https://github.com/ngoduykhanh/wireguard-ui" target="_blank" rel="noopener"
>wireguard-ui&lt;/a> генерируют клиентские конфиги именно под wg-quick.&lt;/p>
&lt;h2 id="постановка-задачи">Постановка задачи &lt;a href="#%d0%bf%d0%be%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-%d0%b7%d0%b0%d0%b4%d0%b0%d1%87%d0%b8">¶&lt;/a>&lt;/h2>
&lt;p>Переносить wireguard интерфейс в отдельное сетевое пространство имён, чтобы потом в нём запускать приложения. Зачем это делать? Это избавляет от необходимости проксировать трафик на заблокированные сайты через Wireguard какими-то сложными решениями. Нужно зайти куда-то в такое место - просто запустил ещё один браузер в пространстве Wireguard и всё! Я так, к примеру, переписал Exec строку в ярлыке &lt;a class="link" href="https://www.thunderbird.net/en-US/" target="_blank" rel="noopener"
>Thunderbird&lt;/a>, которому альтернативы пока столь же функциональной нет, и теперь он всегда запускается через VPN и может спокойно собирать почту с любых SMTP.
Использовать нужно ванильный wg-quick без доработок, чтобы это работало с ходу.&lt;/p>
&lt;h2 id="разбор-решения">Разбор решения &lt;a href="#%d1%80%d0%b0%d0%b7%d0%b1%d0%be%d1%80-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d1%8f">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://www.man7.org/linux/man-pages/man8/wg-quick.8.html" target="_blank" rel="noopener"
>В документации&lt;/a>, есть 4 пути к дополнительной настройке wg-quick интерфейса. PreUp, PostUp, PreDown, PostDown. Значит нужно написать скрипты таким образом, чтобы они делали всё что нужно. Готовое решение представлено в начале статьи, а теперь его разберём. Я преобразую этот ужатый код в человекочитаемый вид, выглядит иначе, но содержательно буква в букву. &lt;strong>Замечание:&lt;/strong> в коде встречается &lt;code>%i&lt;/code>, это макрос самого wg-quick, везде где он встретит этот макрос, подставит имя создаваемого интерфейса.&lt;/p>
&lt;h3 id="preup">PreUp &lt;a href="#preup">¶&lt;/a>&lt;/h3>
&lt;p>Тут всё просто.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># в списке сетевых пространств ищем наше&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ip netns list &lt;span class="p">|&lt;/span> grep -qF -- %i&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># если нашли - удаляем&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ip netns delete %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="postup">PostUp &lt;a href="#postup">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! ip netns list &lt;span class="p">|&lt;/span> grep -qF -- %i&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># создаём сетевое пространство если его ещё нет (а его и не должно быть)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ip netns add %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># запускаем там loopback интерфейс (127.0.0.1 который)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ip -n %i link &lt;span class="nb">set&lt;/span> up lo
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># сохраняем список сетевых адресов которые wg-quick навесил на интерфейс при создании&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># и кодируем это в base64, потому что это бинарный поток в формате утилиты ip&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">IPS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>ip address save dev %i &lt;span class="p">|&lt;/span> base64&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># переносим интерфейс в наше специальное пространство имён&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ip link &lt;span class="nb">set&lt;/span> %i netns %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># навешиваем адреса обратно, раскодируя их из переменной созданной ранее&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$IPS&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> base64 -d &lt;span class="p">|&lt;/span> ip -n %i address restore dev %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># запускаем сетевой интерфейс в том пространстве имён&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ip -n %i link &lt;span class="nb">set&lt;/span> up %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ищем маршрут на 0.0.0.0/0 в списке путей нашего пространства имён&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! ip -n %i route show default &lt;span class="p">|&lt;/span> grep -qF default&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># добавляем если не нашли&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ip -n %i route add default dev %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># тут был скрипт в base64, я его прямо для вас в тексте раскодировал, чтобы просто было понятно что там&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># скрипт этот раскодируется и в него с помощью printf вставляется имя интерфейса с которым всегда будет&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># работать скрипт&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOT | xargs -0 -I{} printf {} %i &amp;gt; /usr/local/bin/wg-%i-exec
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">set -e
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># вот сюда это имя интерфейса залетит в переменную
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">netns=&amp;#39;%s&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># а вот эту лабуду я отдельно поясню
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">cat &amp;lt;&amp;lt;EOF | xargs -0 sudo -E nsenter &amp;#34;--net=/var/run/netns/$netns&amp;#34; unshare --mount sh -c
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">for conf in &amp;#34;$netns&amp;#34; &amp;#34;tun.$netns&amp;#34;; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> if [ -f &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; ]; then
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> mount --bind &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; /etc/resolv.conf
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> fi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">done
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">export DBUS_SESSION_BUS_ADDRESS=unix:path=/dev/null
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">sudo -E -u &amp;#39;#${SUDO_UID:-$(id -u)}&amp;#39; -g &amp;#39;#${SUDO_GID:-$(id -g)}&amp;#39; -- $@
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># вот такой же скрипт, но мы там выполняем не пользовательскую команду, а wg-quick down&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOT | xargs -0 -I{} printf {} %i &amp;gt; /usr/local/bin/wg-%i-down
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">set -e
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># необходимо запускать от рута
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">if [ &amp;#34;$(id -u)&amp;#34; -ne 0 ]; then
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> echo &amp;#34;error: run me as root&amp;#34; 1&amp;gt;&amp;amp;2
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> exit 1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">fi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">netns=&amp;#39;%s&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># возвращаем интерфейс обратно в корневой netns
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">ip netns exec &amp;#34;$netns&amp;#34; ip link set &amp;#34;$netns&amp;#34; netns 1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># сносим наш кастомный netns
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">ip netns delete &amp;#34;$netns&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># и останавливаем через wg-quick, который сам снесёт интерфейс
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">systemctl stop &amp;#34;wg-quick@$netns.service&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># меняем собственника и права на файлы&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">chmod &lt;span class="m">0755&lt;/span> /usr/local/bin/wg-%i-*
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">chown root:root /usr/local/bin/wg-%i-*
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># просто выводим текст на экран в момент поднятия интерфейса - справка для пользователя,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># которая рассказывает о двух скриптах созданных ранее. Этот текст раскодируется и прямо&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># кидается в sh, то есть выполняется на ходу, а там только и есть что один cat&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOT | xargs -0 -I{} printf {} %i | sh -
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">netns=&amp;#39;%s&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">cat &amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># ┐ ┬o┬─┐┬─┐┌─┐┬ ┐┬─┐┬─┐┬─┐ ┌┐┐┬─┐┌┐┐┌┐┐┐─┐
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># │││││┬┘├─ │ ┬│ ││─┤│┬┘│ │ │││├─ │ │││└─┐
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># └┴┘┘┘└┘┴─┘┘─┘┘─┘┘ ┘┘└┘┘─┘ ┘└┘┴─┘ ┘ ┘└┘──┘
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">Thanks for using netns wg-quick wrapper!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/usr/local/bin/wg-$netns-exec COMMAND - execute shell command in $netns network namespace
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/usr/local/bin/wg-$netns-down - use it instead of wg-quick down $netns
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOT&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>А вот тут самое сумашествие. Поясняю основные моменты.&lt;/p>
&lt;ol>
&lt;li>Когда переносишь сетефой интерфейс в другое пространство, с него, к сожалению, слетают все IP адреса. По-этому, мы их в начале сохраняем, а потом восстанавливаем, после переноса.&lt;/li>
&lt;li>Loopback интерфейс в новом пространстве по умолчанию выключен, по-этому мы его включаем сами&lt;/li>
&lt;li>Добавляется маршрут только на &lt;code>0.0.0.0/0&lt;/code> потому что у нас в принципе трафику кроме как на wireguard ходить некуда, по-этому весь туда пускаем и без разницы, что в AllowedIPs на интерфейсе прописано. Так скрипт проще, работает так же, уязвимостей не создаёт.&lt;/li>
&lt;li>Создаются два скрипта: &lt;code>wg-%i-exec&lt;/code>, &lt;code>wg-%i-down&lt;/code>. Первый нужен чтобы ним запускать программы в нашем сетевом пространстве, а второй нужен чтобы просто сделать &lt;code>wg-quick down&lt;/code>, потому что просто выполнив &lt;code>wg-quick down&lt;/code> остановить интерфейс не выйдет, нужно &lt;em>wg-quick&lt;/em> выполнять внутри нашего пространства имён&lt;/li>
&lt;/ol>
&lt;h3 id="как-работает-wg-i-exec">Как работает wg-%i-exec &lt;a href="#%d0%ba%d0%b0%d0%ba-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d0%b5%d1%82-wg-i-exec">¶&lt;/a>&lt;/h3>
&lt;p>Тут есть ряд проблем, которые решает скрипт:&lt;/p>
&lt;ol>
&lt;li>Внутри пространства имён нет resolv.conf-а, или может не быть. Всегда его создаёт себе сам wg-quick через &lt;a class="link" href="https://manpages.ubuntu.com/manpages/trusty/man8/resolvconf.8.html" target="_blank" rel="noopener"
>resolvconf&lt;/a>, даже без всех наших ухищрений. То есть он создаётся для интерфейса. Это нужно для разрешение DNS имён.&lt;/li>
&lt;li>Нужно сделать так, чтобы даже запукая exec пользователь, не получал права root в подарок, а оставался со своими привилегиями.&lt;/li>
&lt;/ol>
&lt;p>Я раскидаю скрипт по строкам в, возможно, даже не рабочий shell код, но так удобнее будет коментировать.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># вот сюда это имя интерфейса залетит в переменную&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">netns&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;%s&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># а вот эту лабуду я отдельно поясню&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF | xargs -0 sudo -E nsenter &amp;#34;--net=/var/run/netns/$netns&amp;#34; unshare --mount sh -c
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">for conf in &amp;#34;$netns&amp;#34; &amp;#34;tun.$netns&amp;#34;; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> if [ -f &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; ]; then
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> mount --bind &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; /etc/resolv.conf
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> fi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">done
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">export DBUS_SESSION_BUS_ADDRESS=unix:path=/dev/null
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">sudo -E -u &amp;#39;#${SUDO_UID:-$(id -u)}&amp;#39; -g &amp;#39;#${SUDO_GID:-$(id -g)}&amp;#39; -- $@
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># выполняем от имени судо, сохраняя env текущего пользователя, это будет всё равно с правами рута&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo -E
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># nsenter запустит нам в этом пространстве имён&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nsenter &lt;span class="s2">&amp;#34;--net=/var/run/netns/&lt;/span>&lt;span class="nv">$NETNS&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># а потом размонтирует, всё что монтировалось&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">unshare --mount
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># команду shell-a, который выполнит скрипт&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sh -c
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"># где мы монтируем resolv.conf созданный wg-quick-ом, если такой вообще есть
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"># на Ubuntu и Fedora это нужно, на Manjaro - /etc/resolv.conf и так на месте
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">for conf in &amp;#34;$netns&amp;#34; &amp;#34;tun.$netns&amp;#34;; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> if [ -f &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; ]; then
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> mount --bind &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; /etc/resolv.conf
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> fi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">done
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"># браузеры не запускаются без этого
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">export DBUS_SESSION_BUS_ADDRESS=unix:path=/dev/null
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"># и с помощью sudo сохраняя всё тот же env текущего пользователя
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">sudo -E
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"># не не от имени рута, а уже от имени пользователя, который запустил exec скрипт
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">-u &amp;#39;&lt;/span>&lt;span class="c1">#${SUDO_UID:-$(id -u)}&amp;#39; &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-g &lt;span class="s1">&amp;#39;#${SUDO_GID:-$(id -g)}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># выполняем то, что он попросил&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-- &lt;span class="nv">$@&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="итог">Итог &lt;a href="#%d0%b8%d1%82%d0%be%d0%b3">¶&lt;/a>&lt;/h2>
&lt;p>Просто вставляем эти 3 строки в конфиг и всё! Никакого Ansible, танцев с бубном, сложной настройки и поддержки.&lt;/p></description></item><item><title>GPT (UEFI) for Btrfs (/ and /boot) over dm-crypt</title><link>https://vlasov.pro/ru/p/gpt-btrfs-gnome/</link><pubDate>Sun, 20 Mar 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/gpt-btrfs-gnome/</guid><description>&lt;img src="https://vlasov.pro/ru/p/gpt-btrfs-gnome/gparted.png" alt="Featured image of post GPT (UEFI) for Btrfs (/ and /boot) over dm-crypt" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Программа на фото статьи это &lt;a class="link" href="https://gparted.org" target="_blank" rel="noopener"
>GParted&lt;/a>. Люблю, практикую. Удобно и просто можно творить с разделами всё, что вздумается. Не смог выбрать, что поставить заглавным изображением статьи. Пусть будет моя текущая разметка &amp;#x1f604;&lt;br>
Системы я переставлял и переставляю довольно часто, пару раз в год будет. Причины разные: то сервачок собрал, то на рабочий ПК поменял на ноутбук, то на компьютер родителей винт побольше поставил&amp;hellip; По мелочи в общем. Опыт и с Windows, и с разными дистрибутивами Linux имел обширный, как мне кажется. Статься в целом, больше болтология, не обижайтесь. Если кто-то вдруг обнаружит, что на сайте комментарии уже как полгода можно оставлять, буду искренне рад &amp;#x1f604;&lt;/p>
&lt;h2 id="тип-таблицы-разделов">Тип таблицы разделов &lt;a href="#%d1%82%d0%b8%d0%bf-%d1%82%d0%b0%d0%b1%d0%bb%d0%b8%d1%86%d1%8b-%d1%80%d0%b0%d0%b7%d0%b4%d0%b5%d0%bb%d0%be%d0%b2">¶&lt;/a>&lt;/h2>
&lt;p>Как я думал раньше: &amp;ldquo;Вот, есть старый добрый MBR, а GPT придумали с этими их UEFI-ями проклятыми, чтобы на ноуты катать и не давать людям другие ОСи ставить! 4 раздела ограничение - ну и что. Хочешь больше - логические в помощь.&amp;rdquo;
Думал я так до января 2022, а потом получил по работе &lt;a class="link" href="https://www.lenovo.com/ua/uk/laptops/ideapad/5-series/IdeaPad-5-14ARE05/p/88IPS501392" target="_blank" rel="noopener"
>ноутбук&lt;/a>, ну и конечно, стал думать как чем бы его зарядить. &amp;ldquo;А попробую-ка GPT, ну никогда не брал ведь. Пусть будет, какая разница. Работать будет и ладно&amp;rdquo;. Итог: &lt;em>GPT UEFI форева!&lt;/em> Почему&amp;hellip;&lt;/p>
&lt;ol>
&lt;li>Нет ограничения по количеству разделов&lt;/li>
&lt;li>Нет области прописывания загрузчика в начале диска, то есть BIOS грузит не диск, следуя на нём по ссылке в самом начале, &lt;em>а конкретную найденную на одном из сколько хош FAT32 разделов программу&lt;/em>.&lt;/li>
&lt;li>&lt;a class="link" href="https://www.gnu.org/software/grub/" target="_blank" rel="noopener"
>GRUB&lt;/a> видит всех соседей на диске, а также &lt;strong>сам BIOS&lt;/strong> так как оказалось, что точка входа в него это точно такая же UEFI программа. Можно из меню загрузчика попасть в BIOS, оттуда опять в загрузчик, оттуда опять в BIOS, ну вы поняли&amp;hellip;&lt;/li>
&lt;li>Когда ты ставишь Windows и она сносит MBR тебя даже не спрашивая (своё красноречивое, нецензурное мнение по поводу уважения Microsoft к продуктам иным, нежели тем, которые были разработаны в Microsoft, я писать здесь не буду), а потом тебе нужно с LiveUSB восстанавливать GRUB, или просто система неудачно обновилась какая-то. Не важно, что случилось. Ты просто грузишь другую ОС прямо из BIOS-a! Вот это мне очень понравилось.&lt;/li>
&lt;li>Недостатком, но просто мелочью по факту, является то, что программы UEFI могут быть только на разделах FAT32. Ну и ладно. Создал и забыл.&lt;/li>
&lt;li>Windows в начале не планировалась, но когда появилась, оказалось, что она прекрасно может стать на любые по порядку разделы, а не только на первый как в случае MBR, а это очень большой плюс.&lt;/li>
&lt;/ol>
&lt;h2 id="файловые-системы">Файловые системы &lt;a href="#%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d1%8b%d0%b5-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d1%8b">¶&lt;/a>&lt;/h2>
&lt;p>Я переехал на BTRFS везде, и на рабочей машине, и на сервере, и раздел архива (авто, мото, фото &amp;hellip;) тоже на BTRFS. Очень люблю и уважаю, попробовал тоже недавно. Искал разные &lt;a class="link" href="https://www.phoronix.com/scan.php?page=news_item&amp;amp;px=Linux-5.14-File-Systems" target="_blank" rel="noopener"
>замеры производительности&lt;/a> и понял, что в среднем BTRFS такая же, как EXT4, но медленнее XFS. &amp;ldquo;Брать или не брать?&amp;rdquo; - думал я. Так вот взял по одной простой, но понятной причине: мои машины это не высоконагруженные сервера и разницы я не почувствую этой в производительности &amp;#x1f604; Выбором остался доволен.&lt;/p>
&lt;ol>
&lt;li>У меня на домашнем сервере BTRFS RAID1 на двух HDD Barracuda 1TB - программный рейд, без проблемы и с одного тычка.&lt;/li>
&lt;li>Встроенные: сжатие, дефрагментация, контроль ошибок (по которому можно судить, когда винты умирают), снапшоты. Сказка!&lt;/li>
&lt;li>Как оказалось, GRUB грузит BTRFS и грузится с BTRFS без проблем!&lt;/li>
&lt;li>Жаль нет встроенного шифрования. Пришлось навесить сверху dm-crypt - и ничего, всё отлично.&lt;/li>
&lt;li>Весь BTRFS это как логический раздел с резиновыми разделами внутри, которые не располагаются привычно нам друг за другом, а просто есть, скопом &amp;#x1f604; Не нужно добавлять места, если закончилось или как-то продумывать что, сколько будет есть.&lt;/li>
&lt;/ol>
&lt;p>Из забавного, пришлось переносить ОС с одного железа на другое. Так вот с BTRFS выглядело это примерно так.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем корень btrfs на старой машине&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount /dev/sda1 -o &lt;span class="nv">subvol&lt;/span>&lt;span class="o">=&lt;/span>/ /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># то же на новой машине&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh user@new-pc mount /dev/sda1 -o &lt;span class="nv">subvol&lt;/span>&lt;span class="o">=&lt;/span>/ /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># делаем readonly снапшот раздела с системой&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">btrfs subvolume snapshot -r /mnt/@manjaro /mnt/@manjaro-ro
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># пересылаем по SSH! обалдеть просто...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">btrfs send /mnt/@manjaro-ro &lt;span class="p">|&lt;/span> ssh user@new-pc btrfs receive /mnt/@manjaro-ro
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># там на месте из полученного readonly делаем readwrite снапшот&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh user@new-pc btrfs subvolume snapshot /mnt/@manjaro-ro /mnt/@manjaro
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># удаляем readonly&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh user@new-pc btrfs subvolume del /mnt/@manjaro-ro
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># размонтируем всё&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh user@new-pc umount /mnt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Так просто и легко я ещё не перезжал. Что нужно не забыть, конечно, сделать потом руками:&lt;/p>
&lt;ol>
&lt;li>Поправить UUID-ы в &lt;code>/etc/fstab&lt;/code>&lt;/li>
&lt;li>Поправить &lt;code>/etc/hostname&lt;/code>&lt;/li>
&lt;li>&lt;code>grub-install ... &amp;amp;&amp;amp; grub-mkconfig ...&lt;/code>&lt;/li>
&lt;/ol>
&lt;h2 id="разделы-gpt">Разделы GPT &lt;a href="#%d1%80%d0%b0%d0%b7%d0%b4%d0%b5%d0%bb%d1%8b-gpt">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Если Windows нужно будет больше места - отрежу с конца у Manjaro&lt;/li>
&lt;li>Если нужен будет ещё Linux, то для него понадобиться тоже EFI раздел, а вот boot - нет! Потому что из одного BTRFS boot могут грузиться сколько хочешь линуксов - просто разделы (subvolume) разные&lt;/li>
&lt;/ol>
&lt;h2 id="операционные-системы">Операционные системы &lt;a href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d0%be%d0%bd%d0%bd%d1%8b%d0%b5-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d1%8b">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Лучше Manjaro трудно что-то представить. Мне очень нравиться всё - &lt;a class="link" href="https://wiki.manjaro.org/index.php/Main_Page" target="_blank" rel="noopener"
>документация&lt;/a>, утилиты, &lt;a class="link" href="https://wiki.manjaro.org/index.php/Manjaro_Kernels" target="_blank" rel="noopener"
>простота контроля обновления ядра с mhwd-kernel&lt;/a>, совместимость со всей документацией Vanilla Arch. Свежий софт, но не настолько как у Fedora, что тоже радует! &lt;a class="link" href="https://stabyourself.net/mari0/" target="_blank" rel="noopener"
>Есть mari0&lt;/a>&lt;/li>
&lt;li>Windows 10, просто для игрушек и Steam.&lt;/li>
&lt;/ol>
&lt;h2 id="важные-заметки">Важные заметки &lt;a href="#%d0%b2%d0%b0%d0%b6%d0%bd%d1%8b%d0%b5-%d0%b7%d0%b0%d0%bc%d0%b5%d1%82%d0%ba%d0%b8">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Windows никого не спрашивает и форматирует раздел с флагами &lt;code>boot,esp&lt;/code> в FAT32 и кладёт туда свой EFI. Решилось ручным созданием раздела EFI-Windows и навешиванием на него этих флагов. Linux-у фиолетово где они висят - на загрузку не влияет, а вот установка Windows влезла в нужное мне место.&lt;/li>
&lt;li>Я вначале boot не выносил и он тоже был зашифрован! Работает на ура! Есть одна неприятность: GRUB драйвера не подтягивает и для расшифровки раздела использует программно реализованные алгоритмы, не привлекая аппаратные возможности CPU. Первоначальная расшифровка занимала у меня 5-7 секунд. Люди в сети жалованись на десятки&amp;hellip; Для меня было не критично те 5-7 секунд, тем более, что на работе потом это не сказывается, только на самом начале загрузки, но решил убрать эту задержку, безопасность мне параноидальная тоже не нужна.&lt;/li>
&lt;li>Для восстановления загрузчика нужно также примонтировать &lt;em>efivars&lt;/em> перед chroot&lt;/li>
&lt;li>&lt;a class="link" href="https://wiki.manjaro.org/index.php/GRUB/Restore_the_GRUB_Bootloader#EFI_System" target="_blank" rel="noopener"
>Вот отличная документация&lt;/a> по вопросу восстановления загрузчика&lt;/li>
&lt;li>Лучше &lt;a class="link" href="https://wiki.archlinux.org/title/Dm-crypt/Encrypting_an_entire_system#Configuring_mkinitcpio" target="_blank" rel="noopener"
>документации по установке системы, чем эта&lt;/a>, на зашифрованный раздел (по всякому) просто представить трудно&lt;/li>
&lt;li>UUID-ы из &lt;code>/etc/fstab&lt;/code> должны совпадать с нужными Вам из вывода &lt;code>blkid&lt;/code>&lt;/li>
&lt;/ol>
&lt;h2 id="не-важные-заметки">Не важные заметки &lt;a href="#%d0%bd%d0%b5-%d0%b2%d0%b0%d0%b6%d0%bd%d1%8b%d0%b5-%d0%b7%d0%b0%d0%bc%d0%b5%d1%82%d0%ba%d0%b8">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>А вот &lt;a class="link" href="https://raw.githubusercontent.com/adi1090x/files/master/plymouth-themes/previews/29.gif" target="_blank" rel="noopener"
>так&lt;/a> у меня выглядит экран загрузки благодаря &lt;a class="link" href="https://wiki.archlinux.org/title/plymouth" target="_blank" rel="noopener"
>plymouth&lt;/a>. &lt;a class="link" href="https://github.com/adi1090x/plymouth-themes" target="_blank" rel="noopener"
>Тема Pack 2 - Flame&lt;/a>. (подёргивания картинки только в браузере, во время загрузки всё гладко)&lt;/li>
&lt;li>&lt;a class="link" href="https://www.gnome-look.org/browse?cat=109" target="_blank" rel="noopener"
>Здесь&lt;/a> я тему выбрал себе для самого Grub. &lt;a class="link" href="https://www.gnome-look.org/p/1603282" target="_blank" rel="noopener"
>Вот та, которую я взял.&lt;/a>&lt;/li>
&lt;li>dm-crypt можно пропатчить и сделать &lt;a class="link" href="https://www.kali.org/tools/cryptsetup-nuke-password/" target="_blank" rel="noopener"
>nuke пароль&lt;/a>. Если его ввести, то все ключи будут уничтожены и раздел уже не расшифровать. Сколько бы вас не пытали, они уже ничего не получат&amp;hellip; ха-ха.. ха&amp;hellip; мда.. ну что есть, то есть&lt;/li>
&lt;/ol>
&lt;h3 id="grub-recovery-script">Grub recovery script &lt;a href="#grub-recovery-script">¶&lt;/a>&lt;/h3>
&lt;p>Имена разделов точно как у меня на изображении к посту. Это поможет сориентироваться.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># расшивровуем раздел с системой&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cryptsetup luksOpen /dev/nvme0n1p1 cryptroot
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем систему&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount /dev/mapper/cryptroot -o &lt;span class="nv">subvol&lt;/span>&lt;span class="o">=&lt;/span>@root /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем boot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount /dev/nvme0n1p2 -o &lt;span class="nv">subvol&lt;/span>&lt;span class="o">=&lt;/span>@boot /mnt/boot
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># создаём папку efi если нет&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mkdir -p /mnt/boot/efi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем efi в boot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount /dev/nvme0n1p3 /mnt/boot/efi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем кучу всего для chroot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> i in dev proc sys &lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span> mount --bind /&lt;span class="nv">$i&lt;/span> /mnt/&lt;span class="nv">$i&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем efivars а то grub не встанет&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount --bind /sys/firmware/efi/efivars /mnt/sys/firmware/efi/efivars
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># запрыгиваем в нашу систему&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">chroot /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ставим grub. тут нужны пояснения&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. в случае с mbr мы привыкли указывать диск, куда прописать загрузчик&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># в случае с efi он ничего никуда не прописывает, а просто наполняет /boot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. bootloader-id это просто для красоты - именно так BIOS будет подписывать нашу ось в списке&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># можно и не писать, там по умолчанию будет manjaro&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">grub-install --bootloader-id&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Manjaro&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># если профукал весь раздел /boot вместе с образами ядра, то вот так они перегенерятся&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pacman -S linux
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># собираем initramfs образы&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mkinitcpio -P
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># собираем меню grub&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">grub-mkconfig -o /boot/grub/grub.cfg
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># выходим из chroot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">exit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># размонтируем и закрываем всё в обратном порядке&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /mnt/sys/firmware/efi/efivars
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> i in dev proc sys&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span> umount /mnt/&lt;span class="nv">$i&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /mnt/boot/efi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /mnt/boot
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cryptsetup luksClose cryptroot
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="простыми-словами-о-загрузке-ос-efi">Простыми словами о загрузке ОС (EFI) &lt;a href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%bc%d0%b8-%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d0%bc%d0%b8-%d0%be-%d0%b7%d0%b0%d0%b3%d1%80%d1%83%d0%b7%d0%ba%d0%b5-%d0%be%d1%81-efi">¶&lt;/a>&lt;/h3>
&lt;ol>
&lt;li>BIOS запускается и находит всё FAT32, в которых есть папка EFI и знакомые ему файлы. Грузит одну из найденных програм, какую попросили.&lt;/li>
&lt;li>Программа EFI штука не такая тупая как MBR и может делать, что угодно. В нашем случае, она лезет на /boot раздел c GRUB, открывает для себя BTRFS и подгужает меню GRUB и именно здесь загружается и отрисовывается тема, которую мы выбрали для GRUB&lt;/li>
&lt;li>Теперь мы в меню GRUB выбираем что грузить&lt;/li>
&lt;li>GRUB загружает в оперативку целяком initramfs того, что мы попросили грузить. Это то, что мы генерили командой &lt;a class="link" href="https://wiki.archlinux.org/title/mkinitcpio" target="_blank" rel="noopener"
>mkinitcpio&lt;/a>. Initcpio это программа на подобии EFI, но когда его придумывали, EFI ещё не было, был только тупой MBR. Что-то мне кажется, что можно напрямую с EFI грузить систему без лишней прослойки. Ну да ладно&amp;hellip; Кроме того, вместе с initramfs именно тут грузится уже ядро, так как оно вынесено на /boot тоже.&lt;/li>
&lt;li>Initcpio это слоёный пирог &lt;a class="link" href="https://wiki.archlinux.org/title/mkinitcpio#HOOKS" target="_blank" rel="noopener"
>хуков&lt;/a>, которые выполняются по очереди. Каждый делает что-то важное и нужное. Так вот если мы поставили plymouth, вот тут же, в одном из самых первых хуков на экран рисуется какая-то красотень, чтобы спрятать кучу логов загрузки.&lt;/li>
&lt;li>Один из хуков это &lt;em>encrypt&lt;/em> или &lt;em>plymouth-encrypt&lt;/em>. Вот как раз этот кусочек слоёного пирога initramfs спрашивает у нас пароль от зашифрованного root-а. То есть, до этого момента он вообще не трогался &amp;#x1f604;&lt;/li>
&lt;li>Расшифровка, создание первого процесса, запуск служб, драйвером, графической оболочки и процего шлака.&lt;/li>
&lt;/ol>
&lt;h2 id="вопросы">Вопросы &lt;a href="#%d0%b2%d0%be%d0%bf%d1%80%d0%be%d1%81%d1%8b">¶&lt;/a>&lt;/h2>
&lt;p>Если будут вопросы или чем помочь, подсказать как у меня настроен конкретно тот или иной кусок - пишите в Telegram или в комментарии. Буду рад помочь!&lt;/p></description></item><item><title>Обзор k9s</title><link>https://vlasov.pro/ru/p/k9s/</link><pubDate>Mon, 17 Jan 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/k9s/</guid><description>&lt;img src="https://vlasov.pro/ru/p/k9s/k9s.webp" alt="Featured image of post Обзор k9s" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://github.com/derailed/k9s" target="_blank" rel="noopener"
>k9s&lt;/a> - мой любимый инструмент для работы с кластерами Kubernetes. Обожаю эту штуку, есть довольно неплохие аналоги и даже намного красивее, но именно тут, хорошо работают горячие клавиши и из терминала очень удобно пользоваться.&lt;/p>
&lt;p>Всё, что он умеет почитайте на странице репозитория, здесь же я укажу именно то, что свежо в памяти, только то, что я постоянно использую.&lt;/p>
&lt;h2 id="обзор">Обзор &lt;a href="#%d0%be%d0%b1%d0%b7%d0%be%d1%80">¶&lt;/a>&lt;/h2>
&lt;h3 id="просмотр-логов">Просмотр логов &lt;a href="#%d0%bf%d1%80%d0%be%d1%81%d0%bc%d0%be%d1%82%d1%80-%d0%bb%d0%be%d0%b3%d0%be%d0%b2">¶&lt;/a>&lt;/h3>
&lt;p>Просто по нажатию &lt;code>L&lt;/code> можно смотреть логи отдельно взятого пода, там же цифрами можно выбрать быстро один из диапазонов по времени, за который эти логи показывать.&lt;/p>
&lt;h3 id="копирование-в-буфер-обмена">Копирование в буфер обмена &lt;a href="#%d0%ba%d0%be%d0%bf%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b2-%d0%b1%d1%83%d1%84%d0%b5%d1%80-%d0%be%d0%b1%d0%bc%d0%b5%d0%bd%d0%b0">¶&lt;/a>&lt;/h3>
&lt;p>По нажатию &lt;code>C&lt;/code> в режиме просмотра логов или манифеста объекта, содержимое экрана (весь файл или лог, не только видимое содержимое) копируется в буфер обмена. Нужно чтобы был установлен так же &lt;code>xsel&lt;/code>.&lt;/p>
&lt;h3 id="проброс-портов">Проброс портов &lt;a href="#%d0%bf%d1%80%d0%be%d0%b1%d1%80%d0%be%d1%81-%d0%bf%d0%be%d1%80%d1%82%d0%be%d0%b2">¶&lt;/a>&lt;/h3>
&lt;p>Нажав &lt;code>Shift + F&lt;/code> можно выбрать какие порты пробросить на локальную машину, чтобы достучаться до какого-нибудь сервиса.&lt;/p>
&lt;h3 id="просмотр-проблемных-подов">Просмотр проблемных подов &lt;a href="#%d0%bf%d1%80%d0%be%d1%81%d0%bc%d0%be%d1%82%d1%80-%d0%bf%d1%80%d0%be%d0%b1%d0%bb%d0%b5%d0%bc%d0%bd%d1%8b%d1%85-%d0%bf%d0%be%d0%b4%d0%be%d0%b2">¶&lt;/a>&lt;/h3>
&lt;p>Нажав &lt;code>Ctrl + Z&lt;/code> в списке подов остаются только те, что не Running.&lt;/p>
&lt;h3 id="поиск-по-подстроке">Поиск по подстроке &lt;a href="#%d0%bf%d0%be%d0%b8%d1%81%d0%ba-%d0%bf%d0%be-%d0%bf%d0%be%d0%b4%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%b5">¶&lt;/a>&lt;/h3>
&lt;p>Просто нажимаем слеш и пишем подстроку которую нужно искать в имени или метках объектов из списка. Удобно, когда объектов много.&lt;/p>
&lt;h2 id="демонстрация">Демонстрация &lt;a href="#%d0%b4%d0%b5%d0%bc%d0%be%d0%bd%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f">¶&lt;/a>&lt;/h2>
&lt;script id="asciicast-462297" src="https://asciinema.org/a/462297.js" async>&lt;/script></description></item><item><title>Заметки о Terraform</title><link>https://vlasov.pro/ru/p/terraform-notes/</link><pubDate>Sun, 16 Jan 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/terraform-notes/</guid><description>&lt;img src="https://vlasov.pro/ru/p/terraform-notes/terraform.webp" alt="Featured image of post Заметки о Terraform" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://www.terraform.io" target="_blank" rel="noopener"
>Terraform&lt;/a> - это прекрасный инструмент для автоматизации создания ресурсов в облаках AWS, Azure, GCP, Hetzner и ещё много где. Штука классная. С помощью &lt;a class="link" href="https://github.com/tfutils/tfenv" target="_blank" rel="noopener"
>tfenv&lt;/a> можно просто и удобно обновлять сам Terraform локально и выбирать нужную версию. Можно &lt;a class="link" href="https://github.com/tfutils/tfenv#terraform-version-file" target="_blank" rel="noopener"
>создать файлик в корне проекта&lt;/a> и прописать нужную версию, чтобы tfenv автоматически нужную версию Terraform подставлял под проект.&lt;br>
Есть ряд практических рекомендаций которые я вывел для себя читая официальную документацию, которая прям очень хороша, а так же модули и код написанный AWS-ом.&lt;/p>
&lt;h2 id="рекомендации">Рекомендации &lt;a href="#%d1%80%d0%b5%d0%ba%d0%be%d0%bc%d0%b5%d0%bd%d0%b4%d0%b0%d1%86%d0%b8%d0%b8">¶&lt;/a>&lt;/h2>
&lt;p>Проштудируйте &lt;a class="link" href="https://www.terraform-best-practices.com" target="_blank" rel="noopener"
>официальные рекомендации&lt;/a>. От себя я написал далее.&lt;/p>
&lt;h3 id="1-не-дублировать-тип-ресурса-в-имени">1. Не дублировать тип ресурса в имени &lt;a href="#1-%d0%bd%d0%b5-%d0%b4%d1%83%d0%b1%d0%bb%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d1%82%d1%8c-%d1%82%d0%b8%d0%bf-%d1%80%d0%b5%d1%81%d1%83%d1%80%d1%81%d0%b0-%d0%b2-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b8">¶&lt;/a>&lt;/h3>
&lt;p>Не правильно&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_vpc&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;production_vpc&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">cidr_block&lt;/span> = &lt;span class="s2">&amp;#34;172.16.0.0/16&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">tags&lt;/span> = &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Name&lt;/span> = &lt;span class="s2">&amp;#34;Production VPC&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Правильно&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_vpc&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;production&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">cidr_block&lt;/span> = &lt;span class="s2">&amp;#34;172.16.0.0/16&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">tags&lt;/span> = &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Name&lt;/span> = &lt;span class="s2">&amp;#34;Production&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Пояснения&lt;/p>
&lt;ol>
&lt;li>В коде всё равно обращение к ресурсу будет &lt;code>${aws_vpc.production.id}&lt;/code> - тут и так понятно, что это VPC, нет смысла тратить символы на то, что уже написано&lt;/li>
&lt;li>В имени ресурса тоже самое, ведь Вы в любом случае будете смотреть на VPC в списке на странице VPC в AWS Console, там другого-то и не будет. Опять же, зачем тогда дублировать.&lt;/li>
&lt;/ol>
&lt;h3 id="2-использовать-this-как-имя-но-только-в-модулях">2. Использовать this как имя, но только в модулях &lt;a href="#2-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d1%82%d1%8c-this-%d0%ba%d0%b0%d0%ba-%d0%b8%d0%bc%d1%8f-%d0%bd%d0%be-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%b2-%d0%bc%d0%be%d0%b4%d1%83%d0%bb%d1%8f%d1%85">¶&lt;/a>&lt;/h3>
&lt;p>Допустим у Вас есть модуль, который создаём виртуалку и минимальный обвес к ней. В пределах модуля виртуалка одна.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_instance&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;this&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">ami&lt;/span> = &lt;span class="nb">data&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">aws_ami&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">id&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">instance_type&lt;/span> = &lt;span class="nb">var&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">instance_type&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Зачем же придумывать имена для ресурсов, если он в пределах модуля единственный? Незачем. Опять же, нужно понимать, что это имя объекта в пределах кода Terraform. Удобно, когда любой тип ресурса это просто this, но делать так, нужно только в пределах одного модуля, который создаёт логическую единицу, ведь виртуальная машина без своей Security Group, которая открывает к ней порты не имеет смысла, значит логически - это один кусок.&lt;/p>
&lt;h3 id="3-создавать-стандартные-файлы-для-модулей">3. Создавать стандартные файлы для модулей &lt;a href="#3-%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%b2%d0%b0%d1%82%d1%8c-%d1%81%d1%82%d0%b0%d0%bd%d0%b4%d0%b0%d1%80%d1%82%d0%bd%d1%8b%d0%b5-%d1%84%d0%b0%d0%b9%d0%bb%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%bc%d0%be%d0%b4%d1%83%d0%bb%d0%b5%d0%b9">¶&lt;/a>&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Файл&lt;/th>
&lt;th>Содержание&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>vars.tf&lt;/td>
&lt;td>Все переменные&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>outputs.tf&lt;/td>
&lt;td>Выходные параметры&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>versions.tf&lt;/td>
&lt;td>Секция с &lt;a class="link" href="https://www.terraform.io/language/settings#specifying-provider-requirements" target="_blank" rel="noopener"
>требованиями к провайдерам&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>main.tf&lt;/td>
&lt;td>Файл с корневым содержимым&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="4-не-объявлять-провайдеры-в-модулях">4. Не объявлять провайдеры в модулях &lt;a href="#4-%d0%bd%d0%b5-%d0%be%d0%b1%d1%8a%d1%8f%d0%b2%d0%bb%d1%8f%d1%82%d1%8c-%d0%bf%d1%80%d0%be%d0%b2%d0%b0%d0%b9%d0%b4%d0%b5%d1%80%d1%8b-%d0%b2-%d0%bc%d0%be%d0%b4%d1%83%d0%bb%d1%8f%d1%85">¶&lt;/a>&lt;/h3>
&lt;p>Пропишите &lt;a class="link" href="https://www.terraform.io/language/settings#specifying-provider-requirements" target="_blank" rel="noopener"
>version constraints&lt;/a>, но оставьте инициализацию на усмотрение того, кто будет использовать Ваш модуль.&lt;/p>
&lt;h3 id="5-переменная-tags">5. Переменная tags &lt;a href="#5-%d0%bf%d0%b5%d1%80%d0%b5%d0%bc%d0%b5%d0%bd%d0%bd%d0%b0%d1%8f-tags">¶&lt;/a>&lt;/h3>
&lt;p>Добавьте переменную, через которые будут навешиваться теги на абсолютно все ресурсы в модуле.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">variable&lt;/span> &lt;span class="s2">&amp;#34;tags&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">type&lt;/span> =&lt;span class="nb"> map&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">string&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">description&lt;/span> = &lt;span class="s2">&amp;#34;Extra tags.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">default&lt;/span> = &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">locals&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">default_tags&lt;/span> = &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Custom&lt;/span> = &lt;span class="s2">&amp;#34;Some default tags&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Terraform&lt;/span> = &lt;span class="s2">&amp;#34;Path to module folder in your Git repo - helps to find code in repo fast&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">tags&lt;/span> =&lt;span class="nb"> merge&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">local&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">default_tags&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">var&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">tags&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_vpc&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;production&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">cidr_block&lt;/span> = &lt;span class="s2">&amp;#34;172.16.0.0/16&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">tags&lt;/span> =&lt;span class="nb"> merge&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">local&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">tags&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Name&lt;/span> = &lt;span class="s2">&amp;#34;Production&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Вот тут в переменную local.tags мы вначале собираем итоговый словарь, а потом его используем где нужно в пределах модуля.&lt;/p>
&lt;h3 id="6-именование-ресурсов-с-name_prefix">6. Именование ресурсов с name_prefix &lt;a href="#6-%d0%b8%d0%bc%d0%b5%d0%bd%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%80%d0%b5%d1%81%d1%83%d1%80%d1%81%d0%be%d0%b2-%d1%81-name_prefix">¶&lt;/a>&lt;/h3>
&lt;p>Всегда, обязательно используйте префикс имени для создания ресурсов. Поменяв одну эту переменную код должен создать абсолютно такую же инфраструктуру, в том же аккаунте и ничего не должно конфликтовать - это хороший модуль, который может быть использован вновь.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">variable&lt;/span> &lt;span class="s2">&amp;#34;name_prefix&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">type&lt;/span> = &lt;span class="nx">string&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">description&lt;/span> = &lt;span class="s2">&amp;#34;Name prefix for all resources (required).&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">validation&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">condition&lt;/span> = &lt;span class="nb">can&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">regex&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;^[a-z][a-z0-9-]+[a-z]$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">var&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">name_prefix&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;tls_private_key&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;this&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">algorithm&lt;/span> = &lt;span class="s2">&amp;#34;RSA&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">rsa_bits&lt;/span> = &lt;span class="m">4096&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_key_pair&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;this&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">key_name&lt;/span> = &lt;span class="nb">var&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">name_prefix&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">public_key&lt;/span> = &lt;span class="nx">tls_private_key&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">public_key_openssh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>И нет смысла дописывать что-то к имени если ресурс один. Допустим этот код того же часть модуля для создания виртуалки, значит он будет использоваться примерно так.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">module&lt;/span> &lt;span class="s2">&amp;#34;ec2_backend&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">source&lt;/span> = &lt;span class="s2">&amp;#34;./ec2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">name_prefix&lt;/span> = &lt;span class="s2">&amp;#34;production-backend&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">instance_type&lt;/span> = &lt;span class="s2">&amp;#34;t3a.small&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>То есть, всё для того же EC2 Key Pair в списке будет понятно, к какой он виртуалке относиться просто по префиксу. Другое дело будь их два, тогда имя в коде было бы &lt;code>&amp;quot;${var.name_prefix}-some-suffix&amp;quot;&lt;/code>.&lt;/p>
&lt;h3 id="7-никаких-дефисов-в-именах-ресурсов">7. Никаких дефисов в именах ресурсов &lt;a href="#7-%d0%bd%d0%b8%d0%ba%d0%b0%d0%ba%d0%b8%d1%85-%d0%b4%d0%b5%d1%84%d0%b8%d1%81%d0%be%d0%b2-%d0%b2-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0%d1%85-%d1%80%d0%b5%d1%81%d1%83%d1%80%d1%81%d0%be%d0%b2">¶&lt;/a>&lt;/h3>
&lt;p>Забудьте напрочь про дефис в имени ресурса. Ломает анализатор кода в IDE и это капец как мешает ещё в некоторых моментах.&lt;/p>
&lt;p>Неправильно&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">module&lt;/span> &lt;span class="s2">&amp;#34;ec2-backend&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">source&lt;/span> = &lt;span class="s2">&amp;#34;./ec2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">name_prefix&lt;/span> = &lt;span class="s2">&amp;#34;production-backend&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">instance_type&lt;/span> = &lt;span class="s2">&amp;#34;t3a.small&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">output&lt;/span> &lt;span class="s2">&amp;#34;backend-ip&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">value&lt;/span> &lt;span class="nb">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ec2&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nx">backend&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">private&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nx">ipv4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Правильно&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">module&lt;/span> &lt;span class="s2">&amp;#34;ec2_backend&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">source&lt;/span> = &lt;span class="s2">&amp;#34;./ec2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">name_prefix&lt;/span> = &lt;span class="s2">&amp;#34;production-backend&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">instance_type&lt;/span> = &lt;span class="s2">&amp;#34;t3a.small&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">output&lt;/span> &lt;span class="s2">&amp;#34;backend_ip&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">value&lt;/span> &lt;span class="nb">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ec2_backend&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">private_ipv4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Обращу внимание, что для имени самого ресурса в облаке, рекомендую по максимуму использовать именно дефис - красивее, но в Terraform - никогда.&lt;/p></description></item><item><title>Figlet ASCII графика</title><link>https://vlasov.pro/ru/p/figlet/</link><pubDate>Fri, 07 Jan 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/figlet/</guid><description>&lt;img src="https://vlasov.pro/ru/p/figlet/bomberman.webp" alt="Featured image of post Figlet ASCII графика" />&lt;blockquote>
&lt;p>&lt;a class="link" href="https://www.asciiart.eu/video-games/atomic-bomberman" target="_blank" rel="noopener"
>&lt;em>Бомберман отсюда&lt;/em>.&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl"># ┬ ┬┬─┐┬ ┬ ┌─┐ # ┳━┓┳━┓┏┓┓┳━┓┳━┓┳━┓┓━┓┳━┓┓━┓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># │─┤├─ │ │ │ │ # ┃ ┃┃━┫ ┃ ┃━┫┃━┃┃━┫┗━┓┣━ ┗━┓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># ┘ ┴┴─┘┘─┘┘─┘┘─┘ # ┇━┛┛ ┇ ┇ ┛ ┇┇━┛┛ ┇━━┛┻━┛━━┛
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># ┳━┓┓ ┳┓━┓ ┳━┓┏━┓┏━┓ # ┌┐┐┬─┐┌┐┐┐ ┬┌─┐┬─┐┬┌
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># ┃━┫┃┃┃┗━┓ ┣━ ┃ ┏━┛ # │││├─ │ ││││ ││┬┘├┴┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># ┛ ┇┗┻┇━━┛ ┻━┛┗━┛┗━━ # ┘└┘┴─┘ ┘ └┴┘┘─┘┘└┘┘ ┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Вот такого рода надписи я вставляю в исходные коды чтобы визуально разделить на куски. В Terraform, к примеру.&lt;/p>
&lt;h2 id="установка">Установка &lt;a href="#%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0">¶&lt;/a>&lt;/h2>
&lt;p>Устанавливаем &lt;a class="link" href="https://www.google.com/search?q=figlet%20install" target="_blank" rel="noopener"
>figlet&lt;/a> как угодно для своего дистрибутива.&lt;br>
Качаем дополнительные шрифты.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">curl -Lo- &lt;span class="s1">&amp;#39;https://github.com/vlasov-y/figlet-fonts/archive/refs/tags/v1.1.tar.gz&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>sudo tar -C &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>figlet -I2&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> --strip-components &lt;span class="m">1&lt;/span> -xpzvf -
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="просмотр-всех-шрифтов">Просмотр всех шрифтов &lt;a href="#%d0%bf%d1%80%d0%be%d1%81%d0%bc%d0%be%d1%82%d1%80-%d0%b2%d1%81%d0%b5%d1%85-%d1%88%d1%80%d0%b8%d1%84%d1%82%d0%be%d0%b2">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">find &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>figlet -I2&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -type f -name &lt;span class="s1">&amp;#39;*.*f&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="k">while&lt;/span> &lt;span class="nb">read&lt;/span> -r i&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&amp;gt; &lt;/span>&lt;span class="nv">$i&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> figlet -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$i&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>basename &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$i&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span> &lt;span class="p">|&lt;/span> less
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="функция-для-bashrc">Функция для .bashrc &lt;a href="#%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f-%d0%b4%d0%bb%d1%8f-bashrc">¶&lt;/a>&lt;/h2>
&lt;p>Вот тут внимательно. В подавляющем большинстве шрифтов используются знаки, которые у ваших коллег, которые тот же код из Git стянут, либо вообще не отобразятся, либо будут показаны не правильно, прямоугольниками. Я методом проб и ошибок нашёл для себя универсальный и красивый шрифт - &lt;em>Rusto&lt;/em>. Есть ещё &lt;em>RustoFat&lt;/em>, и он мне даже больше нравиться, но он уже проблемный &amp;#x1f622;&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┬─┐┬ ┐┐─┐┌┐┐┌─┐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># │┬┘│ │└─┐ │ │ │&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┘└┘┘─┘──┘ ┘ ┘─┘&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┳━┓┳ ┓┓━┓┏┓┓┏━┓┳━┓┳━┓┏┓┓&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┃┳┛┃ ┃┗━┓ ┃ ┃ ┃┣━ ┃━┫ ┃ &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┇┗┛┇━┛━━┛ ┇ ┛━┛┇ ┛ ┇ ┇ &lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Надписи выше, я получил уже используя свою функцию, по этому у Вас Rusto будет немного отличаться. Добавьте эту функцию к себе в .bashrc или .zshrc и можно будет пользоваться. Кроме того, нужно будет поставить xsel.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">rusto &lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> figlet -f rusto &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$*&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> sed &lt;span class="s2">&amp;#34;s@^@&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">P&lt;/span>&lt;span class="k">:-&lt;/span>&lt;span class="p"># &lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">@g; s@┆@┘@g&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> tee /tmp/tt &lt;span class="p">|&lt;/span> xsel -i -b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> cat /tmp/tt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f /tmp/tt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rustofat &lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> figlet -f rustofat &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$*&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> sed &lt;span class="s2">&amp;#34;s@^@&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">P&lt;/span>&lt;span class="k">:-&lt;/span>&lt;span class="p"># &lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">@g&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> tee /tmp/tt &lt;span class="p">|&lt;/span> xsel -i -b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> cat /tmp/tt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f /tmp/tt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Что тут творится? Выполняя команду в консоли &lt;code>rusto&lt;/code> или &lt;code>rustofat&lt;/code> текст, который будет передан как аргументы к командам, будет преобразован, написан на экране и сразу скопирован в буфер обмена. И да, ещё символ &lt;code>┆&lt;/code> заменяется на &lt;code>┘&lt;/code>, чтобы &lt;em>Rusto&lt;/em> был полностью безпроблемным. Также, дописывается &lt;code># &lt;/code> к началу каждой строки, чтобы можно было сразу в исходники вставлять. Решётку можно заменить указав переменную P.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">❯ rusto hello world
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┬ ┬┬─┐┬ ┬ ┌─┐ ┐ ┬┌─┐┬─┐┬ ┬─┐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># │─┤├─ │ │ │ │ ││││ ││┬┘│ │ │&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┘ ┴┴─┘┘─┘┘─┘┘─┘ └┴┘┘─┘┘└┘┘─┘┘─┘&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❯ &lt;span class="nv">P&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;// &amp;#39;&lt;/span> rustofat changed comment char
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">// ┏━┓┳ ┳┳━┓┏┓┓┏━┓┳━┓┳━┓ ┏━┓┏━┓┏┏┓┏┏┓┳━┓┏┓┓┏┓┓ ┏━┓┳ ┳┳━┓┳━┓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">// ┃ ┃━┫┃━┫┃┃┃┃ ┳┣━ ┃ ┃ ┃ ┃ ┃┃┃┃┃┃┃┣━ ┃┃┃ ┃ ┃ ┃━┫┃━┫┃┳┛
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">// ┗━┛┇ ┻┛ ┇┇┗┛┇━┛┻━┛┇━┛ ┗━┛┛━┛┛ ┇┛ ┇┻━┛┇┗┛ ┇ ┗━┛┇ ┻┛ ┇┇┗┛
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="бонус">Бонус &lt;a href="#%d0%b1%d0%be%d0%bd%d1%83%d1%81">¶&lt;/a>&lt;/h2>
&lt;p>Форму для дневные отчётов я генерю так.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">LC_ALL&lt;/span>&lt;span class="o">=&lt;/span>C.POSIX date &lt;span class="s1">&amp;#39;+%d %B&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>figlet &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>xargs -0 &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;```\n%s```\nNo blocks\nNo questions\nDone\\Doing:\n&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>xsel -ib
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Получается вот такое.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="l">```&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">___ __ _ &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">/ _ \ / /_ | | __ _ _ __ _ _ __ _ _ __ _ _ &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">| | | | &amp;#39;_ \ _ | |/ _` | &amp;#39;_ \| | | |/ _` | &amp;#39;__| | | |&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">| |_| | (_) | | |_| | (_| | | | | |_| | (_| | | | |_| |&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">\___/ \___/ \___/ \__,_|_| |_|\__,_|\__,_|_| \__, |&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">|___/ &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">```&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="kc">No&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">blocks&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="kc">No&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">questions&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">Done\Doing&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="l">Drinking tee&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="l">Sleeping&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="l">Writing evening report&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="l">Emulating work&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Потом дописываю что я делал и сбрасываю в Slack.&lt;/p></description></item><item><title>Безопасное обновление Manjaro</title><link>https://vlasov.pro/ru/p/manjaro-update/</link><pubDate>Thu, 06 Jan 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/manjaro-update/</guid><description>&lt;img src="https://vlasov.pro/ru/p/manjaro-update/manjaro.webp" alt="Featured image of post Безопасное обновление Manjaro" />&lt;h2 id="история">История &lt;a href="#%d0%b8%d1%81%d1%82%d0%be%d1%80%d0%b8%d1%8f">¶&lt;/a>&lt;/h2>
&lt;p>Как-то так вышло, что обновив систему полностью у меня сломалось две машины: рабочая и личный сервер. Библиотека Python 3.10 падала в segfault, что привело к неработоспособности &lt;a class="link" href="https://kodi.tv" target="_blank" rel="noopener"
>Kodi&lt;/a> медиасервера. Пропал &lt;a class="link" href="https://pypi.org/project/pip/" target="_blank" rel="noopener"
>Python Pip&lt;/a>. Весело в общем. Хорошо, что был бекап.&lt;br>
К слову, я очень люблю &lt;a class="link" href="https://manjaro.org" target="_blank" rel="noopener"
>Manjaro&lt;/a> - это лучшая операционная система для профессионального использования, и проблем с обновлением никогда не было, кроме Нового года &amp;#x1f604; У меня это второй раз и оба раза были на Новый Год.&lt;br>
&lt;strong>31 декабря 2020&lt;/strong> я сделал полное обновление системы, а на утро в Новом Году обнаружил, что X11 не стартуют, потому что отпали драйвера на Nvidia. И вот, чиню я их открыв новый tty, просто установив снова через mhwd и перезапустив lightdm и думаю: &amp;ldquo;Ну ладно я, починил за 5 минут, а вот как другие? Не DevOps-ы или вообще простые обыватели? Это ж разрабы дистрибутива спешили к Новому Году так&amp;hellip;&amp;rdquo;. Насколько я понял, там был перенос драйверов в репозитории дистрибутива, переименование просто, но этого хватило.&lt;br>
И вот снова Новый Год! Я ставлю обнову и ломается Python3 на уровне .so библиотеки &amp;#x1f604; Система в целом работает, но он много где нужен и часть программного обеспечения может отказать. Сразу перестал работать &lt;a class="link" href="https://github.com/ranger/ranger" target="_blank" rel="noopener"
>ranger&lt;/a>, пришлось ставить снова.&lt;br>
Вот такая история, а скрипт я ниже оставлю.&lt;/p>
&lt;h2 id="скрипт">Скрипт &lt;a href="#%d1%81%d0%ba%d1%80%d0%b8%d0%bf%d1%82">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="c1">## Making root btrfs subvolume snapshot before making full Manjaro update&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">PARTITION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mount &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;$3~/^\/$/{print $1}&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SUBVOL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mount &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;$3~/^\/$/{print $6}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;subvol=[^,)]+&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> cut -d&lt;span class="o">=&lt;/span> -f2- &lt;span class="p">|&lt;/span> sed -r &lt;span class="s1">&amp;#39;s/^\///g&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">MOUNTPOINT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;/mnt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">BACKUP&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>date +%Y-%m-%d &lt;span class="p">|&lt;/span> xargs &lt;span class="nb">printf&lt;/span> &lt;span class="s2">&amp;#34;backup/%s-%s&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SUBVOL&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">main&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> backup
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">backup&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Mounting &lt;/span>&lt;span class="nv">$PARTITION&lt;/span>&lt;span class="s2"> to &lt;/span>&lt;span class="nv">$MOUNTPOINT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mount &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$PARTITION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MOUNTPOINT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -o &lt;span class="nv">subvol&lt;/span>&lt;span class="o">=&lt;/span>/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">cd&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MOUNTPOINT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> dirname &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$BACKUP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> xargs mkdir -p
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -d &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$BACKUP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Backing up &lt;/span>&lt;span class="nv">$SUBVOL&lt;/span>&lt;span class="s2"> to &lt;/span>&lt;span class="nv">$BACKUP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> btrfs sub snap -r &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SUBVOL&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$BACKUP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$BACKUP&lt;/span>&lt;span class="s2"> exists already&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">cd&lt;/span> /
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Unmounting &lt;/span>&lt;span class="nv">$MOUNTPOINT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> umount &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MOUNTPOINT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">update&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Running update&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> yay -Syu
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">main &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$@&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="пример-работы">Пример работы &lt;a href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d1%8b">¶&lt;/a>&lt;/h2>
&lt;script id="asciicast-460238" src="https://asciinema.org/a/460238.js" async>&lt;/script>
&lt;p>А вот что будет, если бэкап за сегодня уже есть.&lt;/p>
&lt;script id="asciicast-460241" src="https://asciinema.org/a/460241.js" async>&lt;/script></description></item><item><title>PulseAudio по TCP</title><link>https://vlasov.pro/ru/p/pulseaudio-tcp/</link><pubDate>Wed, 17 Nov 2021 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/pulseaudio-tcp/</guid><description>&lt;img src="https://vlasov.pro/ru/p/pulseaudio-tcp/pulseaudio.webp" alt="Featured image of post PulseAudio по TCP" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://www.freedesktop.org/wiki/Software/PulseAudio/" target="_blank" rel="noopener"
>PulseAudio&lt;/a> – звуковой сервер, в моём понимании. Выполняется на любом Linux ПК. Микрофоны, динамики, виртуальные устройства - всё идёт через PulseAudio и им контролируется.&lt;/p>
&lt;h2 id="задача">Задача &lt;a href="#%d0%b7%d0%b0%d0%b4%d0%b0%d1%87%d0%b0">¶&lt;/a>&lt;/h2>
&lt;p>Есть сервачок, который подключён к настенному телевизору. Работаю я на ПК с &lt;a class="link" href="https://manjaro.org" target="_blank" rel="noopener"
>Manjaro&lt;/a> и наушники, прямо скажем, не очень. Для работы - сгодится. Хочется слушать музыку, но чтобы телевизор проигрывал это у себя.&lt;/p>
&lt;h2 id="источники">Источники &lt;a href="#%d0%b8%d1%81%d1%82%d0%be%d1%87%d0%bd%d0%b8%d0%ba%d0%b8">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>&lt;a class="link" href="https://wiki.archlinux.org/title/PulseAudio/Examples#Selecting_the_server_with_Zeroconf" target="_blank" rel="noopener"
>Arch Wiki PulseAudio Examples&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://medium.com/@joao.paulo.silvasouza/how-to-configure-pulseaudio-for-multiple-devices-at-the-same-time-in-ubuntu-4943ef0c16db" target="_blank" rel="noopener"
>Статья Joao Paulo Silva de Souza на Medium&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://unix.stackexchange.com/a/443064" target="_blank" rel="noopener"
>Хороший ответ на Unix Overflow&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://unix.stackexchange.com/questions/443013/pulseaudio-simultanious-add-two-devices" target="_blank" rel="noopener"
>И ещё один&lt;/a>&lt;/li>
&lt;/ol>
&lt;h2 id="решение">Решение &lt;a href="#%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Трафик будет передаваться по TCP с ПК на сервер (для простоты буду просто называть его в тексте ТВ, но по факту это сервер на Manjaro).&lt;/p>
&lt;p>И там, и там ставим модуль Zeroconf, чтобы компы друг друга находили без проблем.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">yay -S pulseaudio-zeroconf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь, возьмём cookie файл с одного и скопируем на второй, чтобы были одинаковые. Я нашёл у себя на ПК в домашнем каталоге у пользователя.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">scp ~/.config/pulse/cookie server:/etc/pulse/cookie
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo cp -f ~/.config/pulse/cookie /etc/pulse/cookie
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>А теперь настраиваем:&lt;/p>
&lt;ol>
&lt;li>ТВ будет PulseAudio &lt;strong>сервером&lt;/strong>, потому что он &lt;strong>принимает&lt;/strong> аудио поток&lt;/li>
&lt;li>ПК будет PulseAudio &lt;strong>клиентом&lt;/strong>, потому что он &lt;strong>отдаёт&lt;/strong> поток&lt;/li>
&lt;/ol>
&lt;p>На ТВ - выполняем от имени обычного пользователя, потому что &lt;code>pulseaudio --kill/--start&lt;/code> от рута не нужно запускать.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SUBNET&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;192.168.0.0/24&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo mkdir -p /etc/pulse/default.pa.d/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF | sudo tee /etc/pulse/default.pa.d/zeroconf.pa
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;${SUBNET}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">load-module module-zeroconf-publish
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> --now avahi-daemon.service
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --kill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --start
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>На ПК то же самое почти.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SUBNET&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;192.168.0.0/24&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo mkdir -p /etc/pulse/default.pa.d/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF | sudo tee /etc/pulse/default.pa.d/zeroconf.pa
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;${SUBNET}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">load-module module-zeroconf-discover
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> --now avahi-daemon.service
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --kill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --start
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Вот и всё. Теперь в pavucontrol можно какое-то приложение направить по туннелю до ПК!&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/pulseaudio-tcp/pavucontrol.png"
width="814"
height="502"
srcset="https://vlasov.pro/ru/p/pulseaudio-tcp/pavucontrol_hu15804026729683766190.png 480w, https://vlasov.pro/ru/p/pulseaudio-tcp/pavucontrol_hu1219485386400571975.png 1024w"
loading="lazy"
alt="Pavucontrol в котором Chrome вещает прямо на ТВ через HDMI сервера"
class="gallery-image"
data-flex-grow="162"
data-flex-basis="389px"
>&lt;/p>
&lt;h2 id="бонус-который-не-работает">Бонус, который не работает &lt;a href="#%d0%b1%d0%be%d0%bd%d1%83%d1%81-%d0%ba%d0%be%d1%82%d0%be%d1%80%d1%8b%d0%b9-%d0%bd%d0%b5-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d0%b5%d1%82">¶&lt;/a>&lt;/h2>
&lt;p>Что хочется дальше? Правильно, то что совсем не пригодиться, но интересно. Хочется чтобы и ПК, и ТВ проигрывали один и тот же поток.&lt;/p>
&lt;p>На ПК посмотрим какие у нас есть outputы и получим их имена.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># pacmd list-sinks | grep name:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">name: &amp;lt;alsa_output.pci-0000_00_1b.0.analog-stereo&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">name: &amp;lt;tunnel.aurelius.local.auto_null&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">name: &amp;lt;tunnel.aurelius.local.auto_null.2&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">name: &amp;lt;tunnel.aurelius.local.alsa_output.pci-0000_00_0e.0.hdmi-stereo&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Вот и видно, что первый, похоже, наушники, а остальное прилетело по сети. 2-й и 3-й скорее всего задний и фронтальный выходы на корпусе, а последний явно HDMI компьютера - то что нужно. Объединить, значится, нужно 1-й и 4-й.&lt;/p>
&lt;p>Всё там же на ПК&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SLAVE_1&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;alsa_output.pci-0000_00_1b.0.analog-stereo&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SLAVE_2&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;tunnel.aurelius.local.alsa_output.pci-0000_00_0e.0.hdmi-stereo&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEFAULT_SLAVE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SLAVE_1&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF | sudo tee -a /etc/pulse/default.pa.d/zeroconf.pa
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">load-module module-combine-sink sink_name=combined sink_properties=&amp;#34;device.description=&amp;#39;Combined TV and PC&amp;#39; slaves=${SLAVE_1},${SLAVE_2}&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">set-default-sink ${DEFAULT_SLAVE}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --kill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --start
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Вот и всё &amp;#x1f604; &amp;hellip; Вот только не работает. Не знаю почему. Устройство-то добавилось, выбрать можно, ошибок в журнале нет, но звук идёт только в наушники и не идёт на ТВ. В то же время, просто выбираю ТВ - работает. Значит просто этот модуль не может совместить туннельное и простое устройство. Решил всё равно написать, может кому пригодиться.&lt;/p></description></item><item><title>Wireguard Ansible</title><link>https://vlasov.pro/ru/p/wireguard-ansible/</link><pubDate>Tue, 16 Nov 2021 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/wireguard-ansible/</guid><description>&lt;img src="https://vlasov.pro/ru/p/wireguard-ansible/wireguard.webp" alt="Featured image of post Wireguard Ansible" />&lt;p>&lt;a class="link" href="https://github.com/vlasov-y/wireguard-ansible" target="_blank" rel="noopener"
>&lt;strong>GitHub&lt;/strong>&lt;/a>&lt;/p>
&lt;h2 id="обновление-от-25-ноября-2022">Обновление от 25 ноября 2022 &lt;a href="#%d0%be%d0%b1%d0%bd%d0%be%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%be%d1%82-25-%d0%bd%d0%be%d1%8f%d0%b1%d1%80%d1%8f-2022">¶&lt;/a>&lt;/h2>
&lt;p>Перешёл на классический wg-quick с этого Ansible. Решение получилось в целом много проще технически, а по функционалу меня удовлетворяет.&lt;/p>
&lt;h2 id="обновление-от-21-марта-2022">Обновление от 21 марта 2022 &lt;a href="#%d0%be%d0%b1%d0%bd%d0%be%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%be%d1%82-21-%d0%bc%d0%b0%d1%80%d1%82%d0%b0-2022">¶&lt;/a>&lt;/h2>
&lt;p>Убрал автоматическую генерацию ключей из-за чрезмерной сложности реализации и невозможности настраивать сервера по отдельности, только все вместе можно было. Теперь иначе. Изменения в конфигурации не совместивы со старой, проверь примеры в репозитории, я там докуменатцию дописал.&lt;/p>
&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://www.wireguard.com" target="_blank" rel="noopener"
>Wireguard&lt;/a> – обалденный, простой VPN, который &lt;a class="link" href="https://www.wireguard.com" target="_blank" rel="noopener"
>уже включён в состав ядра&lt;/a>. Очень мощный и простой инструмент. Ставиться в разы проще чем &lt;a class="link" href="https://openvpn.net" target="_blank" rel="noopener"
>OpenVPN&lt;/a>.&lt;/p>
&lt;h2 id="постановка-задачи">Постановка задачи &lt;a href="#%d0%bf%d0%be%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-%d0%b7%d0%b0%d0%b4%d0%b0%d1%87%d0%b8">¶&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>Я живу в Украине и, к сожалению, у нас заблокированы некоторые Интернет ресурсы, а доступ иногда нужен.&lt;/li>
&lt;li>Хочется иметь возможность достучаться по удалённому доступу с телефона или чужого компьютера до домашнего сервера.&lt;/li>
&lt;li>Хочется, чтобы на ПК проксировался трафик только на домены из списка, а не вообще всё.&lt;/li>
&lt;/ul>
&lt;p>Вот с такими запросами я стал работать. Для себя, всё для себя. Больше пока никому не нужен, хотя на &lt;a class="link" href="https://github.com/vlasov-y/wireguard-ansible" target="_blank" rel="noopener"
>GitHub&lt;/a> выложил. Выложил - это тоже громко сказано. Ни документации, ничего! Да! Лень просто написать&amp;hellip; Ну да ладно.&lt;/p>
&lt;h2 id="обзор-решения">Обзор решения &lt;a href="#%d0%be%d0%b1%d0%b7%d0%be%d1%80-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d1%8f">¶&lt;/a>&lt;/h2>
&lt;p>Использовал Ansible, который может настроить сразу сеть. Что умеет:&lt;/p>
&lt;ol>
&lt;li>Использование константного preshared ключа для всех соединений&lt;/li>
&lt;li>Возможность прописывать свои AllowedIPs&lt;/li>
&lt;li>Возможность добавлять пиров со статически прописанными ключами (на телефоне-то Ansible не запустить)&lt;/li>
&lt;li>Автоматический подбор свободных rt_table ID и fwmark-ов&lt;/li>
&lt;li>Возможность за один запуск поднимать больше одной сети на тех же машинах!&lt;/li>
&lt;/ol>
&lt;p>Чего не умеет.&lt;/p>
&lt;ol>
&lt;li>Отдельный запуск на одном или подгруппе хостов. Только на всём сразу.&lt;/li>
&lt;/ol>
&lt;h2 id="разбираем-переменные-ansible">Разбираем переменные Ansible &lt;a href="#%d1%80%d0%b0%d0%b7%d0%b1%d0%b8%d1%80%d0%b0%d0%b5%d0%bc-%d0%bf%d0%b5%d1%80%d0%b5%d0%bc%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-ansible">¶&lt;/a>&lt;/h2>
&lt;blockquote>
&lt;p>all.yml&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># CIDR сетей&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">192.168.99.0&lt;/span>&lt;span class="l">/24&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.0.0&lt;/span>&lt;span class="l">/24&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># марки для маршрутизации - для каждой сети своя&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_fwmarks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># по прешаренному ключу на сеть&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_preshared_keys&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># ключи каждого сервера в каждой сети где он есть&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_keys&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public_host&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">private&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home_server&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">private&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">laptop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">private&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public_host&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">private&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">laptop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">private&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">smartphone&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># у телефона, только публичный, так как приватный тут не нужен&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_addresses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># адреса каждого сервера в каждой сети&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public_host&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">192.168.99.1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">laptop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">192.168.99.2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home_server&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">192.168.99.3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public_host&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.0.1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">laptop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.0.2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">smartphone&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.0.3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>У нас есть сервер с публичным IP и вот он-то послужит точкой подключения для всех. Топология - звезда.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># это переменнные для отдельно взятого хоста - сервера&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">yes&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># wireguard-tools поставили уже, по-этому тут это выключаем&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_install_tools&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">no&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># список пиров&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_peers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># для домашней сети&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># первый пир это наш ноутбук, на котором мы Ansible запускаем&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">laptop&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># а второй, имеет inventory_hostname home_server&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">home_server&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># и поддерживай сеть, чтобы всегда можно было достучаться,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># потому что сервер за NAT-ом&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">keepalive_seconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">25&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># вторую сеть только с телефона и ПК использовать будем&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">laptop&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># а вот и телефон&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">smartphone&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># ну и выберем порты, по которым он должен слушать&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># для остальных можно не указывать - не важно, а вот&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># для сервера лучше всё сразу прописать статикой&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># чтобы ничего не было перегенерено если что&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># и не нужно было перенастраивать всех клиентов&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># на новые креды сервера&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">3000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># включаем маскарад, чтобы сервер через себя в Интернет&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># выпускал трафик пиров как gateway&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_masquarade&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">auto&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>А теперь укажем переменные для ноутбука, за которым работаем.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># и опять включем роль явным образом&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">yes&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_peers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># из пиров в сети VPN только наш публичный сервер&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">hostname&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">public_host&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># у нас есть домен, который указывает на сервер чтобы адрес не запоминать&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">endpoint&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">vpn.example.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># направляем через VPN весь трафик, и тут важно понимать,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># что мы не весь трафик системы пускаем через wireguard&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># мы говорим wireguard-у на хосте, что в эту сетку пускай&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># всё, что к тебе конкретно пришло на выход и не подходит&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># в другие сети по более узким правилам&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">allowed_ips&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="m">0.0.0.0&lt;/span>&lt;span class="l">/0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="p">::&lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">keepalive_seconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">25&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># точкой связи для домашней сети является он же&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">hostname&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">public_host&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">endpoint&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">vpn.example.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">keepalive_seconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">25&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">allowed_ips&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># а в путях прописываем только подсеть домашней сети&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;{{ wireguard_networks.home }}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># и включаем проксирование отдельных доменов через сеть VPN&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_proxy_domains&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">list&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">site.we.want.access&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">another.one&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ну и домашний сервер, просто должен быть доступен. В VPN ему ни к чему.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># тут я надеюсь уже всё понятно&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">yes&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_peers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">hostname&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">public_host&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">endpoint&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">vpn.example.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">allowed_ips&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;{{ wireguard_networks.home }}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">keepalive_seconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">25&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="итог">Итог &lt;a href="#%d0%b8%d1%82%d0%be%d0%b3">¶&lt;/a>&lt;/h2>
&lt;p>С любого пира на любой есть доступ в пределах сети. Трафик находит свой путь через публичный сервер. Всё работает. Померял iperf-ом, из 80 Мбит, Wireguard отдаёт ~60 - как по мне, так это блестящий результат!&lt;/p></description></item><item><title>Age шифрование</title><link>https://vlasov.pro/ru/p/age/</link><pubDate>Sun, 12 Sep 2021 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/age/</guid><description>&lt;img src="https://vlasov.pro/ru/p/age/age.webp" alt="Featured image of post Age шифрование" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://age-encryption.org" target="_blank" rel="noopener"
>Age&lt;/a> – новейшая утилита, написанная на Go, которая по заверениям выполняет прекрасное потоковове ассиметричное шифрование и не только. По виду действительно простая и, мне лично, чем-то напоминает &lt;a class="link" href="https://www.wireguard.com" target="_blank" rel="noopener"
>Wireguard&lt;/a> (утилиту wg).
Шифрует входоной поток в выходной. Просто и понятно. Из отличительных особенностей, можно зашифровать для &lt;em>группы получателей, так чтобы каждый мог расшифровать&lt;/em>.&lt;br>
На повестке дня у меня нынче мысли о создании бекапов btrfs разделов с домашними фото\видео куда-то в облако, например в &lt;a class="link" href="https://www.backblaze.com" target="_blank" rel="noopener"
>Backblaze&lt;/a>, чтобы подешевле было. Вот только облакам доверия нет (никаким). Данные нужно шифровать. Раздел, допустим, &lt;strong>300 GiB&lt;/strong> и грузить его одним куском, да и хранить в целом, очень не интересно. &lt;a class="link" href="https://man7.org/linux/man-pages/man1/split.1.html" target="_blank" rel="noopener"
>Split&lt;/a> поможет раздробить файл на куски.&lt;/p>
&lt;h2 id="генерируем-ключ">Генерируем ключ &lt;a href="#%d0%b3%d0%b5%d0%bd%d0%b5%d1%80%d0%b8%d1%80%d1%83%d0%b5%d0%bc-%d0%ba%d0%bb%d1%8e%d1%87">¶&lt;/a>&lt;/h2>
&lt;p>Утверждается, что можно просто SSH public key использовать, кроме ключа age. Попробуем и то, и то.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ssh-keygen -t ed25519 -o -a &lt;span class="m">150&lt;/span> -qN &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span> -f id_ed25519
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">age-keygen -o age.key
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">age-keygen -y age.key &amp;gt; recipients.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat id_ed25519.pub &amp;gt;&amp;gt; recipients.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Получаем вот такие ключи.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">age1qrcn5glms66thfv9cj5pzdwl3z87t9evzaqlxdj9ksravmw3mypswawuag
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIObk2OuhYlrr3ezvf5gAWXgUdcLn4XQFa8B8GCRpBr9q user@host
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="шифрование">Шифрование &lt;a href="#%d1%88%d0%b8%d1%84%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Для простоты, просто сгенерим 10 MiB со случайными данными и сразу сделаем копию, чтобы потом сравнить хеш-суммы.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">dd &lt;span class="k">if&lt;/span>&lt;span class="o">=&lt;/span>/dev/urandom &lt;span class="nv">of&lt;/span>&lt;span class="o">=&lt;/span>data &lt;span class="nv">bs&lt;/span>&lt;span class="o">=&lt;/span>1M &lt;span class="nv">count&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cp data data.orig
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь можно шифровать. Использую и архивацию, и разделение.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">tar -cz data &lt;span class="p">|&lt;/span> age -R recipients.txt &lt;span class="p">|&lt;/span> split -b 1MiB -d - chunk-
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Получаем 10 файлов от chunk-00 до chunk-10.&lt;/p>
&lt;h2 id="расшифровка">Расшифровка &lt;a href="#%d1%80%d0%b0%d1%81%d1%88%d0%b8%d1%84%d1%80%d0%be%d0%b2%d0%ba%d0%b0">¶&lt;/a>&lt;/h2>
&lt;p>Расшифруем используя SSH ключ.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">cat chunk-* &lt;span class="p">|&lt;/span> age -d -i id_ed25519 &lt;span class="p">|&lt;/span> tar xz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mv data data.ssh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Расшифруем используя Age ключ.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">cat chunk-* &lt;span class="p">|&lt;/span> age -d -i age.key &lt;span class="p">|&lt;/span> tar xz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mv data data.age
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="проверка">Проверка &lt;a href="#%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b0">¶&lt;/a>&lt;/h2>
&lt;p>Сверим Hash суммы.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># sha256sum data*&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">5ebc271a22cfb9af0430253c2d8f3b83d1c3f5fdd062dd0ecc6c1f2d7925b828 data.age
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">5ebc271a22cfb9af0430253c2d8f3b83d1c3f5fdd062dd0ecc6c1f2d7925b828 data.orig
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">5ebc271a22cfb9af0430253c2d8f3b83d1c3f5fdd062dd0ecc6c1f2d7925b828 data.ssh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Вроде работает. Как и всегда, позже найдут какие-то уязвимости, но использовать можно. Множественные адресаты это интересная особенность.&lt;/p></description></item><item><title>Установка Python пакетов в оффлайн</title><link>https://vlasov.pro/ru/p/python3-pip-air-gap/</link><pubDate>Sun, 29 Aug 2021 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/python3-pip-air-gap/</guid><description>&lt;img src="https://vlasov.pro/ru/p/python3-pip-air-gap/python.webp" alt="Featured image of post Установка Python пакетов в оффлайн" />&lt;p>Допустим, мы хотим поставить &lt;a class="link" href="https://www.ansible.com" target="_blank" rel="noopener"
>Ansible&lt;/a> в оффлайне.&lt;/p>
&lt;h2 id="создаём-virtualenv">Создаём Virtualenv &lt;a href="#%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d1%91%d0%bc-virtualenv">¶&lt;/a>&lt;/h2>
&lt;p>Создадим виртуальное окружение для того, чтобы скачать все зависимости, но при этом не захватить ненароком лишнего.
Поставим virtualenv.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">python3 -m pip install --upgrade --user virtualenv
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 -m pip virtualenv venv
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь можем активировать его.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">. ./venv/bin/activate
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь до конца терминальной сессии, мы в изолированном Python virtualenv.&lt;/p>
&lt;h2 id="готовим-нужные-пакеты">Готовим нужные пакеты &lt;a href="#%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%b8%d0%bc-%d0%bd%d1%83%d0%b6%d0%bd%d1%8b%d0%b5-%d0%bf%d0%b0%d0%ba%d0%b5%d1%82%d1%8b">¶&lt;/a>&lt;/h2>
&lt;p>Установив в чистом окружении только то, что нужно, мы заодно подтянем все зависимости, но кроме всего прочего, &lt;strong>захватите с собой ещё setuptools и pip&lt;/strong>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">python3 -m pip install --upgrade pip setuptools ansible
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь можем составить список того, что получилось.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">python3 -m pip freeze &amp;gt; requirements.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;blockquote>
&lt;p>Можно просто дописать pip и setuptools в requirements.txt без указания версий (если их вообще нет в списке)&lt;/p>
&lt;/blockquote>
&lt;p>Пример requirements.txt&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="n">ansible&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">ansible&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">base&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">11&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">cryptography&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">8&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">jinja2&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">11&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">netaddr&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">7&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">19&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">pbr&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">jmespath&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">9&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">ruamel&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">16&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">ruamel&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">clib&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">MarkupSafe&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">pip&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">setuptools&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Имея список пакетов с зависимостями, мы можем их скачать &lt;strong>даже без venv&lt;/strong>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">python3 -m pip download --dest my-pip-packages -r requirements.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Для удобства, упакуем всё в архив.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">tar -cpvzf pips.tgz my-pip-packages requirements.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="устанавливаем-в-окружении-без-интернета">Устанавливаем в окружении без Интернета &lt;a href="#%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%b0%d0%b2%d0%bb%d0%b8%d0%b2%d0%b0%d0%b5%d0%bc-%d0%b2-%d0%be%d0%ba%d1%80%d1%83%d0%b6%d0%b5%d0%bd%d0%b8%d0%b8-%d0%b1%d0%b5%d0%b7-%d0%b8%d0%bd%d1%82%d0%b5%d1%80%d0%bd%d0%b5%d1%82%d0%b0">¶&lt;/a>&lt;/h2>
&lt;blockquote>
&lt;p>Python должен быть уже установлен заранее&lt;/p>
&lt;/blockquote>
&lt;p>Распакуем свой архив и установим всё что принесли. &lt;strong>Pip&lt;/strong> и &lt;strong>setuptools&lt;/strong> поставим отдельно в начале, а потом всё остальное.
Если команда выполняется не от имени суперпользователя, то нужно либо:&lt;/p>
&lt;ol>
&lt;li>Добавить &lt;code>sudo&lt;/code> в начале&lt;/li>
&lt;li>Добавить аргумент &lt;code>--user&lt;/code> к pip-у для установки пакетов только для пользователя выполняющего команду&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">tar -xpzvf pips.tgz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 -m pip install --upgrade --no-index --find-links python-packages pip setuptools
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 -m pip install --upgrade --no-index --find-links my-pip-packages -r requirements.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь можно запускать Ansible!&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">root@289f34a67cbd:/host# ansible --version
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ansible 2.10.11
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> config &lt;span class="nv">file&lt;/span> &lt;span class="o">=&lt;/span> None
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> configured module search &lt;span class="nv">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">[&lt;/span>&lt;span class="s1">&amp;#39;/root/.ansible/plugins/modules&amp;#39;&lt;/span>, &lt;span class="s1">&amp;#39;/usr/share/ansible/plugins/modules&amp;#39;&lt;/span>&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ansible python module &lt;span class="nv">location&lt;/span> &lt;span class="o">=&lt;/span> /usr/local/lib/python3.6/dist-packages/ansible
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> executable &lt;span class="nv">location&lt;/span> &lt;span class="o">=&lt;/span> /usr/local/bin/ansible
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> python &lt;span class="nv">version&lt;/span> &lt;span class="o">=&lt;/span> 3.6.9 &lt;span class="o">(&lt;/span>default, Jan &lt;span class="m">26&lt;/span> 2021, 15:33:00&lt;span class="o">)&lt;/span> &lt;span class="o">[&lt;/span>GCC 8.4.0&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="локали">Локали &lt;a href="#%d0%bb%d0%be%d0%ba%d0%b0%d0%bb%d0%b8">¶&lt;/a>&lt;/h2>
&lt;p>Случалось так, что в сильно урезанном окружении, как, к примеру, Docker Ubuntu 18.04, утановка пакетов падает со следующей ошибкой.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="nl">ERROR&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Exception&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">Traceback&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">most&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">recent&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">call&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">last&lt;/span>&lt;span class="p">):&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">File&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/cli/base_command.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">173&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">_main&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">status&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">self&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">options&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">args&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">File&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/cli/req_command.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">203&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">wrapper&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">func&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">self&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">options&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">args&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">File&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/commands/install.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">316&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">reqs&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">check_supported_wheels&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">not&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">options&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">target_dir&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">...&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">File&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/operations/prepare.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">249&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">unpack_url&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nf">unpack_file&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">path&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">location&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">content_type&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">File&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/utils/unpacking.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">256&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">unpack_file&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nf">untar_file&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">filename&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">location&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">File&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/utils/unpacking.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">226&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">untar_file&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">with&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;wb&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">as&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">destfp&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nl">UnicodeEncodeError&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">ascii&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">codec&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">can&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">character&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="n">xe9&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">position&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">117&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ordinal&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">not&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">128&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Решается установкой переменных окружения перед установкой пакетов.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LANGUAGE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LANG&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_CTYPE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_NUMERIC&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_TIME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_COLLATE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_MONETARY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_MESSAGES&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_PAPER&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_NAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_ADDRESS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_TELEPHONE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_MEASUREMENT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_IDENTIFICATION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_ALL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Создаём виртуальную камеру для конференций</title><link>https://vlasov.pro/ru/p/v4l2loopback/</link><pubDate>Thu, 22 Jul 2021 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/v4l2loopback/</guid><description>&lt;img src="https://vlasov.pro/ru/p/v4l2loopback/aHR0cHM6Ly91bnNwbGFzaC5jb20vcGhvdG9zLzgyRW5odS1FQTVrCg==.webp" alt="Featured image of post Создаём виртуальную камеру для конференций" />&lt;p>Не всегда хочется включать камеру во время конференции, придумалось поискать как можно показывать видео или статическую картинку. Средствами ОС или браузера из коробки это не делается. Нашёл &lt;a class="link" href="https://github.com/umlaeute/v4l2loopback" target="_blank" rel="noopener"
>статью&lt;/a> и, собственно, модуль ядра для создания виртуальной камеры, которая браузером определяется как обычная камера &amp;#x1f604;&lt;br>
Ниже представлен скрипт с подробными комментариями. Единственным аргументом к нему служит путь к файлу или изображению, которое должно транслироваться в потоке.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># label for the new webcam as it will be seen in browser&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">LABEL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;VirtualCam #0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># module insertion in case if it was not inserted during this boot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! lsmod &lt;span class="p">|&lt;/span> grep -qE &lt;span class="s1">&amp;#39;^v4l2loopback&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># camera is being created during the module loading&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sudo modprobe v4l2loopback &lt;span class="nv">devices&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> &lt;span class="nv">exclusive_caps&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> &lt;span class="nv">max_buffers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">2&lt;/span> &lt;span class="nv">card_label&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LABEL&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># wait for a while to finish module initialization&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sleep &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># path to media file&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">F&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">1&lt;/span>&lt;span class="p">:?File is not passed&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># getting path to newly created camera device&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEV&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>v4l2-ctl --list-devices 2&amp;gt;/dev/null &lt;span class="p">|&lt;/span> grep -A1 &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LABEL&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;/dev/video[0-9]+&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$F&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># check in case if media file path does not exists&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;error: file &lt;/span>&lt;span class="nv">$F&lt;/span>&lt;span class="s2"> does not exists&amp;#34;&lt;/span> &amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># get file type and use proper streaming command&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">case&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>file --mime-type --brief &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$F&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> cut -d/ -f1&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> in
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> video&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># in case if file is video&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ffmpeg -re -i &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$F&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -f v4l2 -vcodec rawvideo -pix_fmt yuv420p &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$DEV&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> image&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># in case if file is picture&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ffmpeg -loop &lt;span class="m">1&lt;/span> -re -i &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$F&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -f v4l2 -vcodec rawvideo -pix_fmt yuv420p &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$DEV&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> *&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># in case if file is something else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;error: unknown mime type&amp;#39;&lt;/span> &amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">esac&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Как итог, получилось стримить Rick Ashley - Never Gonna Give You Up.&lt;/p>
&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
&lt;p>Из недостатков стоит упомянуть потребление почти целого ядра ffmpeg-ом. Также, мы, понятное дело, передаём только картинку, без звука.&lt;/p></description></item><item><title>Обновление CEPH</title><link>https://vlasov.pro/ru/p/ceph-upgrade/</link><pubDate>Mon, 16 Nov 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/ceph-upgrade/</guid><description>&lt;img src="https://vlasov.pro/ru/p/ceph-upgrade/ceph.webp" alt="Featured image of post Обновление CEPH" />&lt;h2 id="вводные">Вводные &lt;a href="#%d0%b2%d0%b2%d0%be%d0%b4%d0%bd%d1%8b%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Имеется такой кластер&lt;/p>
&lt;ul>
&lt;li>Ceph 15.2.1 установленный с cephadm&lt;/li>
&lt;li>14 OSD&lt;/li>
&lt;li>3 MON&lt;/li>
&lt;li>3 RGW&lt;/li>
&lt;li>3 MDS&lt;/li>
&lt;li>3 CRUSH&lt;/li>
&lt;/ul>
&lt;p>Вышла версия &lt;em>15.2.4&lt;/em>, хотим обновиться.&lt;/p>
&lt;h2 id="запускаемся">Запускаемся &lt;a href="#%d0%b7%d0%b0%d0%bf%d1%83%d1%81%d0%ba%d0%b0%d0%b5%d0%bc%d1%81%d1%8f">¶&lt;/a>&lt;/h2>
&lt;p>Cephadm предоставляет механизм для обновления, но с ходу у меня он не завёлся, пришлось его &lt;strong>сопровождать&lt;/strong>. Давайте посмотрим что вообще нужно обновить.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ceph orch upgrade check ceph/ceph 15.2.4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Перед глазами JSON со списком демонов, которые уже обновлены и те, которые ещё отличаются от запрошенной версии, то есть все, на данный момент. Пора запускаться.&lt;br>
Так, процедура запущена, теперь есть насколько команд, которые стоит выполнять для получения сводки.&lt;/p>
&lt;ol>
&lt;li>&lt;code>ceph status&lt;/code> - для получения обобщённой информации о состоянии кластера. Можно в отдельном терминале запустить так: &lt;code>watch -n 10 ceph status&lt;/code>&lt;/li>
&lt;li>&lt;code>ceph status -W cephadm&lt;/code> - вот эту команду точно стоит запустить в терминале, чтобы смотреть именно лог оркестратора.&lt;/li>
&lt;/ol>
&lt;h2 id="временные-трудности">Временные трудности &lt;a href="#%d0%b2%d1%80%d0%b5%d0%bc%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d1%82%d1%80%d1%83%d0%b4%d0%bd%d0%be%d1%81%d1%82%d0%b8">¶&lt;/a>&lt;/h2>
&lt;p>Вызываем &lt;code>ceph orch ps&lt;/code> и видим, что все &lt;em>мониторы&lt;/em> и &lt;em>менеджеры обновлены&lt;/em>, хорошо, но теперь мы в &lt;strong>HEALTH_ERROR&lt;/strong> с ошибкой, что я привёл ниже.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">module &amp;#39;cephadm&amp;#39; has failed: auth get failed: failed to find client.crash.01 in keyring retval: -2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Оказывается, не хватает ключей. Создать нужно по одному для каждого crash-a и перезапустить оркестрацию.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> i in &lt;span class="k">$(&lt;/span>ceph orch ps &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;crash.[0-9]+&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ceph auth get-or-create &lt;span class="s2">&amp;#34;client.&lt;/span>&lt;span class="nv">$i&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> mgr &lt;span class="s2">&amp;#34;profile crash&amp;#34;&lt;/span> mon &lt;span class="s2">&amp;#34;profile crash&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph orch upgrade stop
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph mgr module disable cephadm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph mgr module &lt;span class="nb">enable&lt;/span> cephadm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph orch upgrade start ceph/ceph 15.2.4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>И вот мы видим, что &lt;em>crash-ы&lt;/em> тоже готовы, хорошо, но дальше что-то всё висит. Да, HEALTH_OK, но &lt;code>ceph orch ps&lt;/code> показывает, что все &lt;em>OSD&lt;/em> ещё на старой версии. В логах видим следующее.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">Upgrade: It is NOT safe to stop osd.0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ага, оркестратор боится останавливать демоны osd с данными. Поможем. У меня ситуация обстоит так.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ceph osd tree&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-1 14.00000 root default
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-3 5.00000 host &lt;span class="m">01&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">0&lt;/span> hdd 1.00000 osd.0 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">1&lt;/span> hdd 1.00000 osd.1 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">2&lt;/span> hdd 1.00000 osd.2 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">3&lt;/span> hdd 1.00000 osd.3 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">4&lt;/span> hdd 1.00000 osd.4 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-5 5.00000 host &lt;span class="m">02&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">5&lt;/span> hdd 1.00000 osd.5 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">6&lt;/span> hdd 1.00000 osd.6 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">7&lt;/span> hdd 1.00000 osd.7 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">8&lt;/span> hdd 1.00000 osd.8 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">9&lt;/span> hdd 1.00000 osd.9 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-7 4.00000 host &lt;span class="m">03&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">10&lt;/span> hdd 1.00000 osd.10 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">11&lt;/span> hdd 1.00000 osd.11 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">12&lt;/span> hdd 1.00000 osd.12 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">13&lt;/span> hdd 1.00000 osd.13 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Сначала я останавливал osd по одному.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ceph osd out osd.0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Потом расслабился и стал выбрасывать по очереди целый сервер. Когда мы выводим из оборота osd.0, через время, когда балансировка заканчивается, &lt;code>ceph status -W cephadm&lt;/code> жалуется уже на osd.1, а &lt;code>ceph orch ps&lt;/code> показывает, что osd.0 обновлён. Мысль ясна, главное назад не забыть ввести.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ceph osd in osd.0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Короче говоря, выводим osd первого сервера, ждём пока cephadm жалуется на следующие и вводим обратно. Дальше, &lt;strong>стоит дождаться HEALTH_OK, прежде чем выводить osd следующего сервера&lt;/strong>, а то так и без данных не долго остаться&amp;hellip;&lt;br>
&lt;strong>Опираясь на свой osd tree&lt;/strong>, план, если делать начисто, таков:&lt;/p>
&lt;ol>
&lt;li>out 0, 1, 2, 3, 4&lt;/li>
&lt;li>ждём жалобу на 5&lt;/li>
&lt;li>in 0, 1, 2, 3, 4&lt;/li>
&lt;li>ждём HEALTH_OK&lt;/li>
&lt;li>out 5, 6, 7, 8, 9&lt;/li>
&lt;li>ждём жалобу на 10&lt;/li>
&lt;li>in 5, 6, 7, 8, 9&lt;/li>
&lt;li>ждём HEALTH_OK&lt;/li>
&lt;li>out 10, 11, 12, 13&lt;/li>
&lt;li>смотрим, что всё обновилось &lt;code>ceph orch ps&lt;/code>&lt;/li>
&lt;li>in 10, 11, 12, 13&lt;/li>
&lt;li>ждём HEALTH_OK&lt;/li>
&lt;/ol>
&lt;div class="ascii-art">
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">╔═╗╔═╗╔═╗╦ ╦ ╦ ╦╔═╗╔═╗╦═╗╔═╗╔╦╗╔═╗╔╦╗┬
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">║ ║╣ ╠═╝╠═╣ ║ ║╠═╝║ ╦╠╦╝╠═╣ ║║║╣ ║║│
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">╚═╝╚═╝╩ ╩ ╩ ╚═╝╩ ╚═╝╩╚═╩ ╩═╩╝╚═╝═╩╝o
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/div>
&lt;h2 id="заметки">Заметки &lt;a href="#%d0%b7%d0%b0%d0%bc%d0%b5%d1%82%d0%ba%d0%b8">¶&lt;/a>&lt;/h2>
&lt;p>Кластер &lt;em>полупустой&lt;/em>, по этому было быстро. Будь оно иначе, заняло бы дни&amp;hellip;&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">% sudo ceph osd df &lt;span class="o">[&lt;/span>22&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">0&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.4 GiB &lt;span class="m">438&lt;/span> MiB &lt;span class="m">39&lt;/span> KiB &lt;span class="m">1024&lt;/span> MiB 5.5 TiB 0.03 1.11 &lt;span class="m">37&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">1&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.4 GiB &lt;span class="m">454&lt;/span> MiB 2.2 MiB &lt;span class="m">1022&lt;/span> MiB 5.5 TiB 0.03 1.12 &lt;span class="m">46&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">2&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.3 GiB &lt;span class="m">314&lt;/span> MiB 1.0 MiB &lt;span class="m">1023&lt;/span> MiB 5.5 TiB 0.02 1.01 &lt;span class="m">24&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">3&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.2 GiB &lt;span class="m">161&lt;/span> MiB 2.5 MiB &lt;span class="m">1022&lt;/span> MiB 5.5 TiB 0.02 0.90 &lt;span class="m">34&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">4&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.2 GiB &lt;span class="m">242&lt;/span> MiB &lt;span class="m">21&lt;/span> KiB &lt;span class="m">1024&lt;/span> MiB 5.5 TiB 0.02 0.96 &lt;span class="m">34&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">5&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.2 GiB &lt;span class="m">212&lt;/span> MiB 3.0 MiB &lt;span class="m">1021&lt;/span> MiB 5.5 TiB 0.02 0.93 &lt;span class="m">34&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">6&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.5 GiB &lt;span class="m">485&lt;/span> MiB &lt;span class="m">533&lt;/span> KiB &lt;span class="m">1023&lt;/span> MiB 5.5 TiB 0.03 1.14 &lt;span class="m">35&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">7&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.3 GiB &lt;span class="m">280&lt;/span> MiB 1.8 MiB &lt;span class="m">1022&lt;/span> MiB 5.5 TiB 0.02 0.99 &lt;span class="m">41&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">8&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.3 GiB &lt;span class="m">265&lt;/span> MiB &lt;span class="m">19&lt;/span> MiB &lt;span class="m">1005&lt;/span> MiB 5.5 TiB 0.02 0.97 &lt;span class="m">38&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">9&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.4 GiB &lt;span class="m">359&lt;/span> MiB &lt;span class="m">949&lt;/span> KiB &lt;span class="m">1023&lt;/span> MiB 5.5 TiB 0.02 1.05 &lt;span class="m">28&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">10&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.2 GiB &lt;span class="m">179&lt;/span> MiB &lt;span class="m">467&lt;/span> KiB &lt;span class="m">1024&lt;/span> MiB 5.5 TiB 0.02 0.91 &lt;span class="m">33&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">11&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.1 GiB &lt;span class="m">132&lt;/span> MiB 2.8 MiB &lt;span class="m">1021&lt;/span> MiB 5.5 TiB 0.02 0.87 &lt;span class="m">23&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">12&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.3 GiB &lt;span class="m">358&lt;/span> MiB &lt;span class="m">19&lt;/span> MiB &lt;span class="m">1005&lt;/span> MiB 5.5 TiB 0.02 1.04 &lt;span class="m">36&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">13&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.3 GiB &lt;span class="m">301&lt;/span> MiB &lt;span class="m">734&lt;/span> KiB &lt;span class="m">1023&lt;/span> MiB 5.5 TiB 0.02 1.00 &lt;span class="m">39&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> TOTAL &lt;span class="m">76&lt;/span> TiB &lt;span class="m">18&lt;/span> GiB 4.1 GiB &lt;span class="m">54&lt;/span> MiB &lt;span class="m">14&lt;/span> GiB &lt;span class="m">76&lt;/span> TiB 0.02
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">MIN/MAX VAR: 0.87/1.14 STDDEV: 0.00
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Знакомство с Docker</title><link>https://vlasov.pro/ru/p/docker/</link><pubDate>Fri, 21 Aug 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/docker/</guid><description>&lt;img src="https://vlasov.pro/ru/p/docker/docker.webp" alt="Featured image of post Знакомство с Docker" />&lt;blockquote>
&lt;p>Написано вместе с &lt;a class="link" href="https://rebrainme.com/blog/docker/docker-ustanovka-nastrojka-i-pervye-shagi-v-sisteme/" target="_blank" rel="noopener"
>ReBrainMe&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>&lt;a class="link" href="https://www.docker.com/" target="_blank" rel="noopener"
>Docker&lt;/a> – де-факто стандартный движок контейнеризации, который повсеместно используется для запуска приложения как в окружениях для разработки, так и в публичных\высоконагруженных средах. Подробнее о терминологии можно узнать &lt;a class="link" href="https://rebrainme.com/blog/docker/terminologiya-v-docker/" target="_blank" rel="noopener"
>здесь&lt;/a>.&lt;/p>
&lt;p>Задача данной статьи состоит в том, чтобы поставить и запустить Docker локально, начать знакомство с этой интереснейшей системой и усвоить основы.&lt;/p>
&lt;h2 id="установка-docker">Установка Docker &lt;a href="#%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-docker">¶&lt;/a>&lt;/h2>
&lt;p>У Docker есть &lt;a class="link" href="https://docs.docker.com/get-docker/" target="_blank" rel="noopener"
>официальные инструкции&lt;/a> по установке. На практике, я пользовался установочным скриптом (для Linux):&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">curl -LO get.docker.com &lt;span class="p">|&lt;/span> sudo sh -
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Если утилита curl у Вас не установлена, &lt;a class="link" href="https://get.docker.com/" target="_blank" rel="noopener"
>скачайте скрипт&lt;/a> и выполните его вручную:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sh /path/to/downloaded/script.sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Если Вы хотите установить определённую версию Docker, то можете воспользоваться установочными скриптами &lt;a class="link" href="https://rancher.com/docs/rancher/v2.x/en/installation/requirements/installing-docker/" target="_blank" rel="noopener"
>Rancher-a&lt;/a>, которые можно &lt;a class="link" href="https://github.com/rancher/install-docker" target="_blank" rel="noopener"
>подобрать и скачать здесь&lt;/a>. Запускается так же, можете прямо в команде с curl адрес поменять, всё будет работать.&lt;/p>
&lt;h2 id="настройка-docker">Настройка Docker &lt;a href="#%d0%bd%d0%b0%d1%81%d1%82%d1%80%d0%be%d0%b9%d0%ba%d0%b0-docker">¶&lt;/a>&lt;/h2>
&lt;p>Всё работает из коробки, единственное что, есть всего пара моментов, которые исходя из личного опыта можно было бы рекомендовать подправить сразу.&lt;/p>
&lt;h3 id="настроить-logging-driver">Настроить logging driver &lt;a href="#%d0%bd%d0%b0%d1%81%d1%82%d1%80%d0%be%d0%b8%d1%82%d1%8c-logging-driver">¶&lt;/a>&lt;/h3>
&lt;p>Дело в том, что по умолчанию используется драйвер &lt;a class="link" href="https://docs.docker.com/config/containers/logging/json-file/" target="_blank" rel="noopener"
>json-file&lt;/a>, который по умолчанию не имеет ограничения на размер [JSON](&lt;a class="link" href="https://ru.wikipedia.org/wiki/JSON#:~:text=JSON%20%28%D0%B0%D0%BD%D0%B3%D0%BB.,JSON%20%D0%B1%D1%8B%D0%BB%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0%D0%BD%20%D0%94%D1%83%D0%B3%D0%BB%D0%B0%D1%81%D0%BE%D0%BC%20%D0%9A%D1%80%D0%BE%D0%BA%D1%84%D0%BE%D1%80%D0%B4%D0%BE%D0%BC.%29" target="_blank" rel="noopener"
>https://ru.wikipedia.org/wiki/JSON#:~:text=JSON%20(%D0%B0%D0%BD%D0%B3%D0%BB.,JSON%20%D0%B1%D1%8B%D0%BB%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0%D0%BD%20%D0%94%D1%83%D0%B3%D0%BB%D0%B0%D1%81%D0%BE%D0%BC%20%D0%9A%D1%80%D0%BE%D0%BA%D1%84%D0%BE%D1%80%D0%B4%D0%BE%D0%BC.)&lt;/a> файла, где будут скапливаться логи с соответствующего контейнера. Подправить на Linux это можно отредактировав файл &lt;em>/etc/docker/daemon.json&lt;/em>. Файла, по умолчанию, может и не быть – создайте. Содержимое к добавлению:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;log-driver&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;json-file&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;log-opts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;max-size&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;100m&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;max-file&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Таким образом мы настраиваем json-file, чтобы он не создавал более одного файла с логами на контейнер, причём файл не должен превышать &lt;code>100 МБ&lt;/code>. Это всё можно переопределить на этапе запуска контейнера, но в будущем, эти умолчания освобождают от поисков ответа на вопрос: &lt;em>&amp;ldquo;Куда делить 6 ГБ за день?&amp;rdquo;&lt;/em>&lt;/p>
&lt;h3 id="запустить-службу-docker">Запустить службу Docker &lt;a href="#%d0%b7%d0%b0%d0%bf%d1%83%d1%81%d1%82%d0%b8%d1%82%d1%8c-%d1%81%d0%bb%d1%83%d0%b6%d0%b1%d1%83-docker">¶&lt;/a>&lt;/h3>
&lt;p>Бывает, не запускается он сам после установки. Можно поправить на Linux с помощью:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> --now docker.service
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Здесь, мы с помощью &lt;a class="link" href="https://wiki.archlinux.org/index.php/Systemd_%28%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9%29" target="_blank" rel="noopener"
>systemctl&lt;/a>, запустили Docker Engine и поставили его в автозагрузку.&lt;/p>
&lt;h3 id="добавить-пользователя-в-группу-docker">Добавить пользователя в группу docker &lt;a href="#%d0%b4%d0%be%d0%b1%d0%b0%d0%b2%d0%b8%d1%82%d1%8c-%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d1%82%d0%b5%d0%bb%d1%8f-%d0%b2-%d0%b3%d1%80%d1%83%d0%bf%d0%bf%d1%83-docker">¶&lt;/a>&lt;/h3>
&lt;p>Чтобы иметь возможность обращаться к Docker Engine от имени &lt;em>не привилегированного пользователя&lt;/em> (без sudo), нужно добавить его в группу docker.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">sudo usermod -aG docker &amp;#34;$USER&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Для того, чтобы изменения вступили в силу нужно перезагрузиться или воспользоваться &lt;a class="link" href="https://wiki.archlinux.org/index.php/Access_Control_Lists_%28%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9%29" target="_blank" rel="noopener"
>ACL&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-gdscript3" data-lang="gdscript3">&lt;span class="line">&lt;span class="cl">&lt;span class="n">sudo&lt;/span> &lt;span class="n">setfacl&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">m&lt;/span> &lt;span class="s2">&amp;#34;u:${USER}:rwx&amp;#34;&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="k">var&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">docker&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sock&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="знакомство-с-dockerhub">Знакомство с DockerHub &lt;a href="#%d0%b7%d0%bd%d0%b0%d0%ba%d0%be%d0%bc%d1%81%d1%82%d0%b2%d0%be-%d1%81-dockerhub">¶&lt;/a>&lt;/h2>
&lt;p>&lt;em>Контейнеры&lt;/em>, создаются из &lt;em>образов&lt;/em>. Образ – упорядоченный набор слоёв файловой системы, которые были получены на этапе сборки. Люди делятся образами выкладывая их на Docker Registry. Самый популярный – &lt;a class="link" href="https://hub.docker.com/" target="_blank" rel="noopener"
>DockerHub&lt;/a>. Множество программных продуктов выкладываются здесь и поддерживаются &lt;strong>официально&lt;/strong>, а есть много инструментов, собранных простыми людьми или небольшим сообществом, которые не уступают по качеству и поддержке официальным. &lt;strong>Важно&lt;/strong>, смотрите, что Вы качаете и выполняете – noname не понятно какой и без документации, или официальную сборку, которая регулярно обновляется и сопровождается ясной документацией. Бывали слухи, что в noname образах майнеры попадались&amp;hellip; но это больше редкость, чем правило (исходя из личного опыта).&lt;/p>
&lt;p>Для примера, вот несколько ссылок на официальные образы: &lt;a class="link" href="https://hub.docker.com/_/haproxy" target="_blank" rel="noopener"
>HaProxy&lt;/a>, &lt;a class="link" href="https://hub.docker.com/_/nginx" target="_blank" rel="noopener"
>Nginx&lt;/a>, &lt;a class="link" href="https://hub.docker.com/_/postgres" target="_blank" rel="noopener"
>PostgreSQL&lt;/a>, &lt;a class="link" href="https://hub.docker.com/_/mysql" target="_blank" rel="noopener"
>MySQL&lt;/a>, &lt;a class="link" href="https://hub.docker.com/r/grafana/grafana" target="_blank" rel="noopener"
>Grafana&lt;/a>, &lt;a class="link" href="https://hub.docker.com/r/prom/prometheus" target="_blank" rel="noopener"
>Prometheus&lt;/a>.&lt;/p>
&lt;h2 id="запустим-первый-контейнер">Запустим первый контейнер &lt;a href="#%d0%b7%d0%b0%d0%bf%d1%83%d1%81%d1%82%d0%b8%d0%bc-%d0%bf%d0%b5%d1%80%d0%b2%d1%8b%d0%b9-%d0%ba%d0%be%d0%bd%d1%82%d0%b5%d0%b9%d0%bd%d0%b5%d1%80">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker run --rm -it -p 8080:80 nginx:stable-alpine
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Открыв &lt;a class="link" href="http://localhost:8080" target="_blank" rel="noopener"
>http://localhost:8080&lt;/a> видим:&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/docker/nginx-welcome.png"
width="549"
height="205"
srcset="https://vlasov.pro/ru/p/docker/nginx-welcome_hu17821898986438557257.png 480w, https://vlasov.pro/ru/p/docker/nginx-welcome_hu8976578484894536805.png 1024w"
loading="lazy"
alt="Nginx welcome page"
class="gallery-image"
data-flex-grow="267"
data-flex-basis="642px"
>&lt;/p>
&lt;p>Что мы сделали? Разберём команду по порядку.&lt;/p>
&lt;p>&lt;em>sudo&lt;/em> – запуск последующей команды от имени другого пользователя, по умолчанию – суперпользователя root.&lt;br>
&lt;em>docker&lt;/em> – запускаем исполняемый файл Docker-а, который командная оболочка найдёт в одном из путей, найденных в переменной PATH.&lt;br>
&lt;em>run&lt;/em> – создать и запустить новый контейнер.&lt;br>
&lt;em>&amp;ndash;rm&lt;/em> – после завершения его выполнения – удалить, чтобы место не занимал.&lt;br>
&lt;em>-i&lt;/em> – присоединить stdin/out/err из командной оболочки в контейнер; запуск в интерактивном режиме.&lt;br>
&lt;em>-t&lt;/em> – создать tty для контейнера.&lt;br>
&lt;em>-p 8080:80&lt;/em> – перенаправить порт 8080 с хоста на 80 внутри контейнера.&lt;br>
&lt;em>nginx:stable-alpine&lt;/em> – использовать для создания контейнера образ nginx с тегом stable-alpine. Другие теги можно найти на странице &lt;a class="link" href="https://hub.docker.com/_/nginx" target="_blank" rel="noopener"
>Nginx на DockerHub&lt;/a>.&lt;/p>
&lt;h2 id="монтирование">Монтирование &lt;a href="#%d0%bc%d0%be%d0%bd%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Часто необходимо подключить какие-то данные в контейнер, или вынести их из него, чтобы не потерять при пересоздании. Подробнее можно почитать &lt;a class="link" href="https://docs.docker.com/storage/volumes/" target="_blank" rel="noopener"
>здесь&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Hello world! Date: &lt;/span>&lt;span class="k">$(&lt;/span>date&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &amp;gt; /tmp/my_file.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo docker run --rm -it -p 8080:80 -v /tmp/my_file.txt:/usr/share/nginx/html/index.html:ro nginx:stable-alpine
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Здесь мы создали файл &lt;em>/tmp/my_file.txt&lt;/em> и примонтировали его по пути &lt;em>/usr/share/nginx/html/index.html&lt;/em>. Согласно описанию контейнера, можно так же эмпирическим путём определить, что путь к файлам веб-сервера в стандартном конфигурационном файле именно &lt;em>/usr/share/nginx/html&lt;/em>, а файл по умолчанию, который будет открываться как главная – index.html. Вот мы и монтируем с хоста в контейнер по найденному пути.&lt;/p>
&lt;p>С монтированием нужно быть внимательным. &lt;strong>Монтируя файл&lt;/strong> он уже должен существовать к моменту запуска на хосте, иначе создастся папка. Монтируя, &lt;strong>путь на хосте должен быть абсолютным&lt;/strong>. Монтируя директорию, содержимое целевого пути внутри контейнера, если там что-то было, просто &lt;strong>исчезнет&lt;/strong> и будет то, что находится в папке на хосте.&lt;/p>
&lt;h2 id="запуск-в-фоновом-режиме">Запуск в фоновом режиме &lt;a href="#%d0%b7%d0%b0%d0%bf%d1%83%d1%81%d0%ba-%d0%b2-%d1%84%d0%be%d0%bd%d0%be%d0%b2%d0%be%d0%bc-%d1%80%d0%b5%d0%b6%d0%b8%d0%bc%d0%b5">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker run -d --name my1 -p 3000:3000 grafana/grafana
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Здесь появилась пара новых ключей. &lt;em>-d&lt;/em> – запуск в фоне. &lt;em>&amp;ndash;name my1&lt;/em> – задать имя контейнеру &amp;ldquo;my1&amp;rdquo;, так как по умолчанию генерируется случайное, а мы хотим назначить своё. Проверим состояние контейнера.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker ps
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo docker stats
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Первая команда выводит информацию о всех запущенных контейнерах, вторая – отдаёт краткую сводку по потреблению ресурсов. &lt;a class="link" href="https://localhost:3000" target="_blank" rel="noopener"
>Откроем Grafana&lt;/a>.&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/docker/grafana-login.webp"
width="562"
height="570"
srcset="https://vlasov.pro/ru/p/docker/grafana-login_hu3519326263104635802.webp 480w, https://vlasov.pro/ru/p/docker/grafana-login_hu5812811221392077487.webp 1024w"
loading="lazy"
alt="Grafana login page"
class="gallery-image"
data-flex-grow="98"
data-flex-basis="236px"
>&lt;/p>
&lt;p>Можем зайти, поизучать (логин admin, пароль admin), а потом остановить контейнер.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker stop my1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo docker ps -a
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Как видим, контейнер остановлен, но не удалён. Можно вновь запустить, а можно удалить.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker start my1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo docker rm -f my1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="заключение">Заключение &lt;a href="#%d0%b7%d0%b0%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Мы поставили Docker, познакомились с DockerHub, запустили пару контейнеров и опробовали базовые команды для запуска приложений с помощью Docker Community Edition.&lt;/p></description></item><item><title>Планы</title><link>https://vlasov.pro/ru/plan/</link><pubDate>Wed, 22 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/plan/</guid><description>&lt;h2 id="статьи-к-написанию">Статьи к написанию &lt;a href="#%d1%81%d1%82%d0%b0%d1%82%d1%8c%d0%b8-%d0%ba-%d0%bd%d0%b0%d0%bf%d0%b8%d1%81%d0%b0%d0%bd%d0%b8%d1%8e">¶&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> &lt;strong>Обратное SSH туннелирование&lt;/strong>. Была статья, да потерялась. Проброс порта с удалённого хоста на текущий используя SSH&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> &lt;strong>Переезд с &lt;a class="link" href="https://ghost.org" target="_blank" rel="noopener"
>GHost&lt;/a> на &lt;a class="link" href="https://gohugo.io" target="_blank" rel="noopener"
>Hugo&lt;/a>&lt;/strong>. О том как и почему я решился переехать на Hugo&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> &lt;strong>Утилита &lt;a class="link" href="https://github.com/derailed/k9s" target="_blank" rel="noopener"
>k9s&lt;/a>&lt;/strong>. Отличное приложение, которое я использую каждый день для работы с Kubernetes&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> &lt;strong>Советы по &lt;a class="link" href="https://www.terraform.io/" target="_blank" rel="noopener"
>Terraform&lt;/a>&lt;/strong>. Трюки, примеры и полезные ссылки по работе с Terraform&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> &lt;strong>Болтология о проявлении правила 20\80 в IT&lt;/strong>. Как многие знают, 20% усилий дают 80% результата, но для оставшихся 20% результата, нужно потратить целых 80% усилий. Из этого можно сделать много умозаключений&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> &lt;strong>Wireguard Ansible&lt;/strong>. Статья о собственной разработке - Ansible плейбуки для установки и настройки Wireguard&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> &lt;a class="link" href="https://healthcheck.io" target="_blank" rel="noopener"
>&lt;strong>Healthcheck.io&lt;/strong>&lt;/a>. Замечательный сервис, с которым можно быть уверенным в том, что бекапы точно проходят.&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Как искать и работать с Helm чартами.&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Мой опыт с &lt;a class="link" href="https://argo-cd.readthedocs.io/en/stable/" target="_blank" rel="noopener"
>ArgoCD&lt;/a>. &lt;em>(Стабильно, автоматизированно, гибко, но не без изъянов, причём значительных. Использую на большом проде с чистой душой. Рекоммендую)&lt;/em>&lt;/li>
&lt;/ul></description></item><item><title>Резюме</title><link>https://vlasov.pro/ru/resume/</link><pubDate>Wed, 22 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/resume/</guid><description>&lt;div class="resume">
&lt;iframe class="resume" src="https://vlasov.pro/Resume Yurii Vlasov.pdf"> &lt;/embed>
&lt;/div></description></item><item><title>xFreeRDP</title><link>https://vlasov.pro/ru/p/xfreerdp/</link><pubDate>Tue, 07 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/xfreerdp/</guid><description>&lt;img src="https://vlasov.pro/ru/p/xfreerdp/xfreerdp.webp" alt="Featured image of post xFreeRDP" />&lt;p>&lt;a class="link" href="http://www.freerdp.com/" target="_blank" rel="noopener"
>xFreeRDP&lt;/a> – утилита для подключения по RDP c Linux. После переезда на &lt;a class="link" href="https://manjaro.org/" target="_blank" rel="noopener"
>Manjaro&lt;/a> я не смог поставить &lt;a class="link" href="https://vlasov.pro/ru/p/remmina/" >Remmina&lt;/a>, пришлось искать альтeрнативу. Этот вариант меня порадовал. Можно создать по однострочному скрипту для хостов, к которым Вы часто подключаетесь и пользоваться как каталогом.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>xfreerdp /v:1.2.3.4 /u:username /p:password /w:1360 /h:730 /drive:tmp,/tmp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Здесь я явно задаю размер дисплея для подключения и монтирую &lt;em>/tmp&lt;/em> с локальной машины на удалённую, чтобы иметь возможность забрать какие-то файлы.&lt;/p></description></item><item><title>Архив</title><link>https://vlasov.pro/ru/archives/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/archives/</guid><description/></item><item><title>О себе</title><link>https://vlasov.pro/ru/about/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/about/</guid><description>&lt;h2 id="о-себе">О себе &lt;a href="#%d0%be-%d1%81%d0%b5%d0%b1%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Работаю системным инженером &lt;em>(DevOps)&lt;/em>, учусь и стараюсь делать своё дело хорошо. В процессе труда я понял, насколько всё, порою, плачевно с наличием системного понимания процессов протекающих на разных этапах &lt;em>жизненного цикла разработки ПО&lt;/em>.&lt;br>
Обучался в &lt;a class="link" href="https://csn.khai.edu/" target="_blank" rel="noopener"
>ХАИ&lt;/a> на компьютерного инженера и получил магистра в мае 2020.
Вам стоит отнестись к сказанному на этом сайте критично - не стоит верить всему на слово. Я бываю невежествен во многих вопросах, но в любом случае стараюсь писать то, в чём уверен.&lt;br>
&lt;strong>Почему блог на русском, а не на английском?&lt;/strong> - Очень много хорошего материала на англ. языке. Кто если не мы напишем лучше на русском?&lt;/p>
&lt;h2 id="вектор-целей">Вектор целей &lt;a href="#%d0%b2%d0%b5%d0%ba%d1%82%d0%be%d1%80-%d1%86%d0%b5%d0%bb%d0%b5%d0%b9">¶&lt;/a>&lt;/h2>
&lt;p>Список содержит цели, которые я преследую поддерживая на плаву этот блог. Упорядочены по приоритету важности в порядке убывания:&lt;/p>
&lt;ol>
&lt;li>Не писать чушь.&lt;/li>
&lt;li>Написать и поддерживать в актуальном состоянии набор материала, который покрывает минимум тех знаний, которые абсолютно точно нужны каждому профессионалу, работающему в ИТ индустрии.&lt;/li>
&lt;li>Публиковать статьи, которые имеют в своей основе интересные необычные решения. Такие решения стандартными и необходимыми к изучению не назвать, но должно быть интересно.&lt;/li>
&lt;li>Поддерживать обратную связь и корректировать курс этого блога.&lt;/li>
&lt;li>Использовать данный ресурс как &amp;ldquo;резюме&amp;rdquo; при переходе в любую другую компанию.&lt;/li>
&lt;/ol></description></item><item><title>Поиск</title><link>https://vlasov.pro/ru/search/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/search/</guid><description/></item><item><title>Rsnapshot</title><link>https://vlasov.pro/ru/p/rsnapshot/</link><pubDate>Tue, 12 May 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/rsnapshot/</guid><description>&lt;img src="https://vlasov.pro/ru/p/rsnapshot/rsnapshot.webp" alt="Featured image of post Rsnapshot" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://wiki.archlinux.org/index.php/Rsnapshot" target="_blank" rel="noopener"
>Rsnapshot&lt;/a> - классная утилита которая умеет:&lt;/p>
&lt;ol>
&lt;li>Делать бекапы папок по пути в локальной системе и складывать их в бекап хранилище (специально отведённая папка тут же где-то)&lt;/li>
&lt;li>Выполнять скрипты которые делают бекапы, ложат рядом с собой, а rsnapshot берёт эти данные и складывает в то же хранилище-папку&lt;/li>
&lt;li>Может закинуть бекапы по sftp куда-то&lt;/li>
&lt;li>Хранит только diff-ы между бекапами, что экономит место&lt;/li>
&lt;/ol>
&lt;h2 id="retantion">Retantion &lt;a href="#retantion">¶&lt;/a>&lt;/h2>
&lt;p>У rsnapshot есть Retantion Policies (могу не точно называть), они в конфигурации начинаются с &lt;em>retain&lt;/em>. Это описание &lt;em>абстрактных планов&lt;/em> по поводу того, сколько последних копий бэкапов хранить. &lt;em>Я долго мучался пока не понял, что их названия ни на что не влияют.&lt;/em> То есть, если план называется &lt;em>daily&lt;/em> rsnapshot каждый день его запускать не будет, можете его в cron-е хоть раз в месяц запускать. Мне удобнее использовать для конфигурации (чтения, сопровождения) daily, weekly, monthly и т. д.&lt;/p>
&lt;p>Те retention, которые в конфиге записаны ниже, считаються теми, что должны делаться реже верхних, то есть цифра у них должна быть меньше. Rsnapshot для каждого retention &lt;code>i+1&lt;/code> берёт содержимое со старшего сделанного для retention &lt;code>i&lt;/code>. Пример:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ date
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>Tue May 12 05:58:33 UTC 2020
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ rsnapshot daily
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ ls -la /data/backups
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>total 48
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxrwxr-x. 11 y.vlasov y.vlasov 4096 May 12 05:57 .
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxrwxr-x+ 6 root root 4096 Apr 27 09:43 ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 12 05:57 daily.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 12 00:00 daily.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 11 00:00 daily.2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 10 00:00 daily.3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 9 00:00 daily.4
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 8 00:00 daily.5
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 7 00:00 daily.6
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 4 00:00 weekly.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 2 00:00 weekly.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ rsnapshot weekly
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ ls -la /data/backups
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>total 48
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxrwxr-x. 11 y.vlasov y.vlasov 4096 May 12 05:57 .
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxrwxr-x+ 6 root root 4096 Apr 27 09:43 ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 12 05:57 daily.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 12 00:00 daily.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 11 00:00 daily.2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 10 00:00 daily.3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 9 00:00 daily.4
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 8 00:00 daily.5
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 7 00:00 weekly.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 4 00:00 weekly.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 2 00:00 weekly.2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="backup-backup_script">Backup, backup_script &lt;a href="#backup-backup_script">¶&lt;/a>&lt;/h2>
&lt;p>Как собственно он делает бекап? Rsnapshot делает бекапы &lt;strong>по всем шагам&lt;/strong>, которые есть в конфигурации &lt;strong>при каждом вызове&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>&lt;em>backup&lt;/em> - указываешь путь к папке, которую нужно сохранять и он её полностью к себе копирует в хранилище;&lt;/li>
&lt;li>&lt;em>backup_script&lt;/em> - указываешь путь к Shell скрипту, которые делает бекап сам и складывает результирующие файлы\папки рядом с собой, rsnapshot их перемещает в хранилище;&lt;/li>
&lt;li>&lt;em>другие варианты&lt;/em> - &lt;code>man rsnapshot&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h2 id="план">План &lt;a href="#%d0%bf%d0%bb%d0%b0%d0%bd">¶&lt;/a>&lt;/h2>
&lt;ol start="0">
&lt;li>Создать папку по пути &lt;em>snapshot_root&lt;/em>.&lt;/li>
&lt;li>Написать rsnapshot.conf файл (по умолчанию берётся &lt;em>/etc/rsnapshot.conf&lt;/em>).&lt;/li>
&lt;li>Добавить вызов rsnapshot в планировщик - cron.&lt;/li>
&lt;/ol>
&lt;h2 id="пример">Пример &lt;a href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80">¶&lt;/a>&lt;/h2>
&lt;p>Создадим папку snapshot_root: &lt;code>mkdir -p /data/backups&lt;/code>.&lt;/p>
&lt;h3 id="содержимое-etcrsnapshotconf">Содержимое /etc/rsnapshot.conf &lt;a href="#%d1%81%d0%be%d0%b4%d0%b5%d1%80%d0%b6%d0%b8%d0%bc%d0%be%d0%b5-etcrsnapshotconf">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Заметка 1: Вы обязаны использовать табы для разделения аргументов в одной строке&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">config_version 1.2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">snapshot_root /data/backups
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">no_create_root &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Заметка 2: Пути могут вариироваться от ОСи к ОСи&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmd_rm /usr/bin/rm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmd_rsync /usr/bin/rsync
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmd_logger /usr/bin/logger
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Конфигурация планов сохранения&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">retain daily &lt;span class="m">7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">retain weekly &lt;span class="m">4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Настройки логгирования&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">verbose &lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">loglevel &lt;span class="m">3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">lockfile /var/run/rsnapshot.pid
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Собственно описание совершаемых действий&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">backup /data/ghost ghost/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">backup_script /srv/my_soft/backup.sh my_soft/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="содержимое-crontab">Содержимое crontab &lt;a href="#%d1%81%d0%be%d0%b4%d0%b5%d1%80%d0%b6%d0%b8%d0%bc%d0%be%d0%b5-crontab">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">0 0 * * * /usr/bin/rsnapshot daily 2&amp;gt;&amp;amp;1 | systemd-cat -t rsnapshot-daily
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">10 0 * * 0 /usr/bin/rsnapshot weekly 2&amp;gt;&amp;amp;1 | systemd-cat -t rsnapshot-weekly
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="содержимое-srvmy_softbackupsh">Содержимое /srv/my_soft/backup.sh &lt;a href="#%d1%81%d0%be%d0%b4%d0%b5%d1%80%d0%b6%d0%b8%d0%bc%d0%be%d0%b5-srvmy_softbackupsh">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CMD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">rm -rf backup; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">pg_basebackup -U my_user -X stream -F plain -D backup 1&amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;&amp;amp; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">tar -C backup -czf - $(ls backup)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">&amp;#39;&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -w /tmp &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> my_soft.postgres &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> /bin/sh -c &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CMD&lt;/span>&lt;span class="s2"> 1&amp;gt;pg_basebackup.tgz
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="содержимое-daily0">Содержимое daily.0 &lt;a href="#%d1%81%d0%be%d0%b4%d0%b5%d1%80%d0%b6%d0%b8%d0%bc%d0%be%d0%b5-daily0">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">/data/backups/daily.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── ghost
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   └── data
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── my_soft
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   └── pg_basebackup.tgz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── proxy
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   ├── certificates.tgz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   └── haproxy.tgz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── another_one
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── another_backup_from_backup_script.tgz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">5 directories, 4 files
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>RPM2PKG</title><link>https://vlasov.pro/ru/p/rpm2pkg/</link><pubDate>Mon, 27 Apr 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/rpm2pkg/</guid><description>&lt;img src="https://vlasov.pro/ru/p/rpm2pkg/rpm2pkg.webp" alt="Featured image of post RPM2PKG" />&lt;blockquote>
&lt;p>Оказалось, что и Skype, и Slack можно поставить из AUR одной коммандой&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">yay -S slack-desktop skype
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Статью оставил просто для истории&lt;/p>
&lt;/blockquote>
&lt;p>Перешёл на &lt;a class="link" href="https://manjaro.org/" target="_blank" rel="noopener"
>Manjaro&lt;/a> и столкнулся с тем, что Skype и Viber поставляются в RPM и DEB. Что делать с Arch?
На &lt;a class="link" href="https://gitlab.com/vlasov-y/rpm2pkg" target="_blank" rel="noopener"
>GitLab&lt;/a> я поместил простой скрипт, который конвертирует rpm в pkg.&lt;/p>
&lt;h2 id="использование-скрипта">Использование скрипта &lt;a href="#%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%81%d0%ba%d1%80%d0%b8%d0%bf%d1%82%d0%b0">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Ставим зависимости&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo pacman -S rpm rpm2cpio cpio git
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 -m pip install --upgrade --user pip pyyaml jinja2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>Клонируем репозиторий&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git clone --depth &lt;span class="m">1&lt;/span> --single-branch git@gitlab.com:vlasov-y/rpm2pkg.git
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> rpm2pkg
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>Конвертируем&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">curl -fLO https://repo.skype.com/latest/skypeforlinux-64.rpm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 rpm2pkg skypeforlinux-64.rpm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># or add --install to install package automatically (interactive mode, will prompt you for confirmation)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># python3 rpm2pkg --install skypeforlinux-64.rpm&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="4">
&lt;li>Устанавливаем&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo pacman -U skype*.pkg.tar.gz
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="5">
&lt;li>Удаляем&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo pacman -R skype
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Nextcloud</title><link>https://vlasov.pro/ru/p/nextcloud/</link><pubDate>Sat, 25 Apr 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/nextcloud/</guid><description>&lt;img src="https://vlasov.pro/ru/p/nextcloud/nextcloud.webp" alt="Featured image of post Nextcloud" />&lt;h2 id="запускаем-стек">Запускаем стек &lt;a href="#%d0%b7%d0%b0%d0%bf%d1%83%d1%81%d0%ba%d0%b0%d0%b5%d0%bc-%d1%81%d1%82%d0%b5%d0%ba">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://nextcloud.com/" target="_blank" rel="noopener"
>&lt;strong>Nextcloud&lt;/strong>&lt;/a> - личное облако с галереей, проверкой почты, онлайн редактированием документов, прослушиванием аудио и радио, и т. д. Демо можно посмотреть &lt;a class="link" href="https://try.nextcloud.com/" target="_blank" rel="noopener"
>здесь&lt;/a>. Клон &lt;a class="link" href="https://owncloud.org/" target="_blank" rel="noopener"
>OwnCloud&lt;/a>, пробовал вначале и его - претензий нет, но тут приложений чутка больше, как мне показалось.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.7&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">nextcloud&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nextcloud:18.0.3-apache&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nextcloud&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unless-stopped&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">depends_on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">postgres&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s1">&amp;#39;8080:80&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">./nextcloud:/var/www/html:rw&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">logging&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">json-file&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">options&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">max-size&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">100m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">postgres&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">postgres:11.7-alpine&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">postgres&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unless-stopped&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">nextcloud&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">./postgres:/var/lib/postgresql/data:rw&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">POSTGRES_DB=nextcloud&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">POSTGRES_USER=nextcloud&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">POSTGRES_PASSWORD=94dbd6b2-bd9f-4867-99af-37f8e4444640&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">logging&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">json-file&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">options&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">max-size&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">100m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="заметки">Заметки &lt;a href="#%d0%b7%d0%b0%d0%bc%d0%b5%d1%82%d0%ba%d0%b8">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Пробовал обновиться с 16.0.4.1 до 18.0.3 через 17.0.5 - поломалось всё. Переустанавливал и закидывал назад файлы предварительно скачав их себе из &lt;code>./nextcloud/data/username/files&lt;/code>. Назад забросил используя синхронизацию через &lt;a class="link" href="https://nextcloud.com/install/#install-clients" target="_blank" rel="noopener"
>клиентское приложение&lt;/a>.&lt;/li>
&lt;li>Admin не удаляется через UI. Я создал себе аккаунт, а потом захотел удалить стандартный так как считаю, что аккаунты &lt;em>всегда должны быть именными, никакой шары&lt;/em>. Удалить можно так:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker-compose &lt;span class="nb">exec&lt;/span> -u www-data nextcloud php occ user:delete admin
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>Для правильной работы WebDAV, CalDAV нужно настроить перенаправление, если перед Nextcloud есть прокси. В моём случае HAproxy.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-gdscript3" data-lang="gdscript3">&lt;span class="line">&lt;span class="cl">&lt;span class="n">global&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">log&lt;/span> &lt;span class="mf">127.0&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mf">0.1&lt;/span> &lt;span class="n">local0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">stats&lt;/span> &lt;span class="n">socket&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="k">var&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">haproxy&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sock&lt;/span> &lt;span class="n">mode&lt;/span> &lt;span class="mi">660&lt;/span> &lt;span class="n">level&lt;/span> &lt;span class="n">admin&lt;/span> &lt;span class="n">expose&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">fd&lt;/span> &lt;span class="n">listeners&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">stats&lt;/span> &lt;span class="n">timeout&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="n">s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">user&lt;/span> &lt;span class="n">root&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">group&lt;/span> &lt;span class="n">root&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">daemon&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">maxconn&lt;/span> &lt;span class="mi">4096&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">nbproc&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Default SSL material locations&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ca&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">base&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">etc&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">ssl&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">certs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">crt&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">base&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">etc&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">ssl&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">private&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># general SSL config&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ssl&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">default&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">bind&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">ciphersuites&lt;/span> &lt;span class="n">TLS_AES_128_GCM_SHA256&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">TLS_AES_256_GCM_SHA384&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">TLS_CHACHA20_POLY1305_SHA256&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ssl&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">default&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">bind&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">options&lt;/span> &lt;span class="n">no&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">sslv3&lt;/span> &lt;span class="n">no&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">tlsv10&lt;/span> &lt;span class="n">no&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">tlsv11&lt;/span> &lt;span class="n">no&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">tlsv12&lt;/span> &lt;span class="n">no&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">tls&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">tickets&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tune&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ssl&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">default&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">dh&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">param&lt;/span> &lt;span class="mi">4096&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ssl&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">default&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">server&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">ciphersuites&lt;/span> &lt;span class="n">TLS_AES_128_GCM_SHA256&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">TLS_AES_256_GCM_SHA384&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">TLS_CHACHA20_POLY1305_SHA256&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ssl&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">default&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">server&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">options&lt;/span> &lt;span class="n">no&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">sslv3&lt;/span> &lt;span class="n">no&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">tlsv10&lt;/span> &lt;span class="n">no&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">tlsv11&lt;/span> &lt;span class="n">no&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">tlsv12&lt;/span> &lt;span class="n">no&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">tls&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">tickets&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">defaults&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">log&lt;/span> &lt;span class="n">global&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">mode&lt;/span> &lt;span class="n">http&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">option&lt;/span> &lt;span class="n">http&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">request&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">option&lt;/span> &lt;span class="n">httplog&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">option&lt;/span> &lt;span class="n">dontlognull&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">option&lt;/span> &lt;span class="n">forwardfor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span> &lt;span class="n">connect&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="n">s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span> &lt;span class="n">client&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="n">s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span> &lt;span class="n">server&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="n">s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span> &lt;span class="n">tunnel&lt;/span> &lt;span class="mi">3600&lt;/span>&lt;span class="n">s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span> &lt;span class="n">http&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">keep&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">alive&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="n">s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span> &lt;span class="n">http&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">request&lt;/span> &lt;span class="mi">15&lt;/span>&lt;span class="n">s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span> &lt;span class="n">queue&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="n">s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">timeout&lt;/span> &lt;span class="n">tarpit&lt;/span> &lt;span class="mi">60&lt;/span>&lt;span class="n">s&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">compression&lt;/span> &lt;span class="n">algo&lt;/span> &lt;span class="n">gzip&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">compression&lt;/span> &lt;span class="n">type&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">plain&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">css&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">xml&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">javascript&lt;/span> &lt;span class="n">application&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">javascript&lt;/span> &lt;span class="n">application&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">javascript&lt;/span> &lt;span class="n">application&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">xml&lt;/span> &lt;span class="n">application&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">json&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">errorfile&lt;/span> &lt;span class="mi">400&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">usr&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">local&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">etc&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">haproxy&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">errors&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mf">400.&lt;/span>&lt;span class="n">http&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">errorfile&lt;/span> &lt;span class="mi">403&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">usr&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">local&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">etc&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">haproxy&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">errors&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mf">403.&lt;/span>&lt;span class="n">http&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">errorfile&lt;/span> &lt;span class="mi">408&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">usr&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">local&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">etc&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">haproxy&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">errors&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mf">408.&lt;/span>&lt;span class="n">http&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">errorfile&lt;/span> &lt;span class="mi">500&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">usr&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">local&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">etc&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">haproxy&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">errors&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mf">500.&lt;/span>&lt;span class="n">http&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">errorfile&lt;/span> &lt;span class="mi">502&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">usr&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">local&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">etc&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">haproxy&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">errors&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mf">502.&lt;/span>&lt;span class="n">http&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">errorfile&lt;/span> &lt;span class="mi">503&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">usr&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">local&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">etc&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">haproxy&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">errors&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mf">503.&lt;/span>&lt;span class="n">http&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">errorfile&lt;/span> &lt;span class="mi">504&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">usr&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">local&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">etc&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">haproxy&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">errors&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mf">504.&lt;/span>&lt;span class="n">http&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">frontend&lt;/span> &lt;span class="n">http_https&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bind&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="mi">80&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bind&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="mi">443&lt;/span> &lt;span class="n">ssl&lt;/span> &lt;span class="n">crt&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">certificates&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">cloudflare&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">haproxy&lt;/span> &lt;span class="n">alpn&lt;/span> &lt;span class="n">h2&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">http&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mf">1.1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># acls&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">acl&lt;/span> &lt;span class="n">dav&lt;/span> &lt;span class="n">path_reg&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">^/.&lt;/span>&lt;span class="n">well&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">known&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">carddav&lt;/span>&lt;span class="o">|&lt;/span>&lt;span class="n">caldav&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.*$&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">acl&lt;/span> &lt;span class="n">webfinger&lt;/span> &lt;span class="n">path_reg&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">^/.&lt;/span>&lt;span class="n">well&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">known&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">carddav&lt;/span>&lt;span class="o">|&lt;/span>&lt;span class="n">caldav&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.*$&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># proxy headers&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">http&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">request&lt;/span> &lt;span class="n">set&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">header&lt;/span> &lt;span class="n">X&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">Forwarded&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">Port&lt;/span> &lt;span class="o">%&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">dst_port&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">forwarded_port&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># http-response set-header Access-Control-Allow-Credentials &amp;#34;true&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">http&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">request&lt;/span> &lt;span class="n">add&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">header&lt;/span> &lt;span class="n">X&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">Forwarded&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">Proto&lt;/span> &lt;span class="n">https&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">https&lt;/span> &lt;span class="n">forwarded_proto&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">http&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">request&lt;/span> &lt;span class="n">replace&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">path&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">.*&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">remote&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">php&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">dav&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">dav&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">http&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">request&lt;/span> &lt;span class="n">replace&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">path&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">.*&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">public&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">php&lt;/span>&lt;span class="err">?&lt;/span>&lt;span class="n">service&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">webfinger&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">webfinger&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">default_backend&lt;/span> &lt;span class="n">cloud&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">backend&lt;/span> &lt;span class="n">nextcloud&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">http&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">response&lt;/span> &lt;span class="n">set&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">header&lt;/span> &lt;span class="n">Strict&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">Transport&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">Security&lt;/span> &lt;span class="s2">&amp;#34;max-age=63072000; includeSubDomains; preload;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">server&lt;/span> &lt;span class="n">default&lt;/span> &lt;span class="n">nextcloud&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">80&lt;/span> &lt;span class="n">check&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="4">
&lt;li>Авторизация крутилась бесконечно, и лишь F5 нам позволял входить. Проблемы на ПК не стало, но как с клиентом для Android быть? &lt;a class="link" href="https://github.com/nextcloud/android/issues/3623#issuecomment-568992424" target="_blank" rel="noopener"
>Тут&lt;/a>, оказалось, можно очень просто, решить проблему раз и навсегда - добавь в конфиг волшебное ты слово и сможешь заходить и выходить.&lt;/li>
&lt;/ol></description></item><item><title>Remmina</title><link>https://vlasov.pro/ru/p/remmina/</link><pubDate>Wed, 22 Apr 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/remmina/</guid><description>&lt;img src="https://vlasov.pro/ru/p/remmina/remmina.webp" alt="Featured image of post Remmina" />&lt;p>Отличное клиентское приложения для подключения по RDP/VNC/etc. Установил на Ubuntu 18.04 вот так:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo add-apt-repository ppa:remmina-ppa-team/remmina-next
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt install remmina &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-exec &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-kwallet &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-nx &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-rdp &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-secret &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-spice &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-vnc &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-www &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-xdmcp &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> libfreerdp-plugins-standard
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo ln -s /usr/lib/x86_64-linux-gnu/libssh.so.4 /usr/lib/x86_64-linux-gnu/libssh_threads.so.4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Больше информации у них на &lt;a class="link" href="https://remmina.org/" target="_blank" rel="noopener"
>странице&lt;/a>.&lt;/p></description></item><item><title>Знакомство с CEPH</title><link>https://vlasov.pro/ru/p/ceph-intro/</link><pubDate>Wed, 22 Apr 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/ceph-intro/</guid><description>&lt;img src="https://vlasov.pro/ru/p/ceph-intro/ceph.webp" alt="Featured image of post Знакомство с CEPH" />&lt;h2 id="установка">Установка &lt;a href="#%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://ceph.io/" target="_blank" rel="noopener"
>&lt;strong>CEPH&lt;/strong>&lt;/a> - распределённое сетевое хранилище, которое выбрасывает S3, iSCSI, RBD etc. Классная вещь, документации много, но очень сильно подводит то, что не сразу ясно стало, как правильно установить.&lt;/p>
&lt;h3 id="rook">Rook &lt;a href="#rook">¶&lt;/a>&lt;/h3>
&lt;p>Официально рекомендуемый способ установки в Kubernetes. Опыт ребят из &lt;a class="link" href="https://flant.com/" target="_blank" rel="noopener"
>Фланта&lt;/a>-а можно почитать &lt;a class="link" href="https://habr.com/ru/company/flant/blog/451818/" target="_blank" rel="noopener"
>здесь&lt;/a>.&lt;/p>
&lt;h3 id="cephadm">Cephadm &lt;a href="#cephadm">¶&lt;/a>&lt;/h3>
&lt;p>Написал на основе этого Ansible playbook-и и успешно эксплуатировал кластер развёрнутый на хосте. По локалке принял в себя 40 Gib за 2 минуты и остался жив :)&lt;/p>
&lt;h3 id="deprecated--not-recommended">Deprecated / not recommended &lt;a href="#deprecated--not-recommended">¶&lt;/a>&lt;/h3>
&lt;p>То, что я пробовал, а потом оказалось, что оно либо не рабочее, либо deprecated:&lt;/p>
&lt;ul>
&lt;li>&lt;a class="link" href="https://docs.ceph.com/docs/master/rados/deployment/" target="_blank" rel="noopener"
>&lt;strong>ceph-deploy&lt;/strong>&lt;/a> где-то в документации нарывался на то, что этот способ не рекомендуется. Жаль потратил на него на тот момент уже пару дней. Ссылку привести не могу, у ребят истёк SSL сертификат и из-за HTST меня не пускает на сайт с документацией :)&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/ceph/ceph-ansible" target="_blank" rel="noopener"
>&lt;strong>ceph ansible&lt;/strong>&lt;/a> - жирно, классно, много функционала, но master CentOS 7 уже не поддерживает, мониторы у меня так и не засинхронизировались, возможности поставить dashboard без мониторинга я не нашёл, реализовал сам, набрался опыта с Ansible, но потом полезли новые проблемы и я с этого комбайна слез на &lt;em>cephadm&lt;/em>, чему очень рад.&lt;/li>
&lt;/ul>
&lt;h2 id="полезные-команды">Полезные команды &lt;a href="#%d0%bf%d0%be%d0%bb%d0%b5%d0%b7%d0%bd%d1%8b%d0%b5-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4%d1%8b">¶&lt;/a>&lt;/h2>
&lt;p>Ну прежде всего, вот понравившийся мне &lt;a class="link" href="https://sabaini.at/pages/ceph-cheatsheet.html" target="_blank" rel="noopener"
>cheatsheet&lt;/a>.&lt;br>
Посмотреть список используемых винтов по серверам:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ceph orch device ls
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph device ls
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph device ls-by-host ceph-server-0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Посмотреть сводку занимаемого места.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ceph osd df
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph df
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph df &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;[0-9.]+\s*[a-zA-Z]+$&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> uniq &lt;span class="p">|&lt;/span> sort -n
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Посмотреть состояние кластера.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ceph status
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph -w
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Посмотреть инфраструктуру, какие сервисы\контейнеры работают и где.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ceph orch ls
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph orch ps
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="замена-osd">Замена OSD &lt;a href="#%d0%b7%d0%b0%d0%bc%d0%b5%d0%bd%d0%b0-osd">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://m.habr.com/ru/company/flant/blog/495870/" target="_blank" rel="noopener"
>Вот хорошая статья&lt;/a> от тех же Флантов-цев и &lt;a class="link" href="https://m.habr.com/ru/company/flant/blog/495870/comments/#comment_21477582" target="_blank" rel="noopener"
>полезный комментарий&lt;/a> под ней. Друг друга они хорошо дополняют.&lt;br>
OSD я пересоздавал когда на сервере (виртуалке) расширял блочное устройство, чтобы места в кластер добавить. Для себя вывел следующий алгоритм:&lt;/p>
&lt;ol>
&lt;li>Кластер должен быть в состоянии HEALTH_OK&lt;/li>
&lt;li>Выводим OSD из кластера&lt;/li>
&lt;li>Удаляем демон (контейнер по факту), который держит этот osd&lt;/li>
&lt;li>Делаем purge&lt;/li>
&lt;li>Очищаем раздел&lt;/li>
&lt;li>Подключаем снова&lt;/li>
&lt;li>Ждём HEALTH_OK&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># OSD который мы хотим пересоздать&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">OSD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;osd.0&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># находим хост&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">HOST&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>ceph device ls &lt;span class="p">|&lt;/span> awk &lt;span class="s2">&amp;#34;/&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">OSD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/{print \$2}&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> cut -d: -f1&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># и имя блочного устройства отведённого под OSD&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEV&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;/dev/&lt;/span>&lt;span class="k">$(&lt;/span>ceph device ls &lt;span class="p">|&lt;/span> awk &lt;span class="s2">&amp;#34;/&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">OSD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/{print \$2}&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> cut -d: -f2&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph health &lt;span class="p">|&lt;/span> grep -q &lt;span class="s1">&amp;#39;HEALTH_OK&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph osd out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$OSD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph orch daemon rm &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$OSD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> --force
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph osd purge &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$OSD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> --force
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph orch device zap &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">HOST&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEV&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> --force
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">NEW_ID&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;osd.&lt;/span>&lt;span class="k">$(&lt;/span>ceph orch daemon add osd &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">HOST&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEV&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#39; | awk &amp;#39;{print &lt;/span>&lt;span class="nv">$3&lt;/span>&lt;span class="s2">}&amp;#39;)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sleep &lt;span class="m">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph osd crush reweight &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NEW_ID&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">while&lt;/span> ! ceph health &lt;span class="p">|&lt;/span> grep -q &lt;span class="s1">&amp;#39;HEALTH_OK&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sleep &lt;span class="m">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Из моего опыта, на замену OSD в котором было 15 GiB занято, уходит 30 минут. Тестировал на трёх &lt;a class="link" href="https://www.hetzner.com/cloud#pricing" target="_blank" rel="noopener"
>CX21 Hetzner&lt;/a>.&lt;/p>
&lt;h2 id="rbd-and-docker">RBD and Docker &lt;a href="#rbd-and-docker">¶&lt;/a>&lt;/h2>
&lt;p>Запуск RBD и связка с Docker:&lt;/p>
&lt;ol>
&lt;li>Создать пул.&lt;/li>
&lt;li>Проинициализировать пул.&lt;/li>
&lt;li>Создать пользователя для запуска.&lt;/li>
&lt;li>Выключить лишние фичи. Дело в том, что в ядре линукс до 4.17 не поддерживается ряд фич для RBD, которые пришлось отключить. Посмотреть справку можно так:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ceph config &lt;span class="nb">help&lt;/span> rbd_default_features
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol>
&lt;li>Поставить Docker volume plugin.&lt;/li>
&lt;li>Проверить на контейнере.&lt;/li>
&lt;li>Примонтироваться и посмотреть, есть ли файл.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph osd pool create rbd
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rbd pool init rbd
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph auth get-or-create client.rbd mon &lt;span class="s1">&amp;#39;profile rbd&amp;#39;&lt;/span> osd &lt;span class="s1">&amp;#39;profile rbd pool=rbd&amp;#39;&lt;/span> mgr &lt;span class="s1">&amp;#39;profile rbd pool=rbd&amp;#39;&lt;/span> &amp;gt; /etc/ceph/ceph.client.rbd.keyring
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph config &lt;span class="nb">set&lt;/span> global rbd_default_features &lt;span class="m">7&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ставил вот этот &lt;a class="link" href="https://github.com/wetopi/docker-volume-rbd" target="_blank" rel="noopener"
>volume driver&lt;/a>. Всё остальное, что находилось, последний раз обновлялось 3-4 года назад (проект скорее мёртв, чем жив). Кроме того, этот драйвер не требует запуска чего либо на стороне, &lt;a class="link" href="https://docs.docker.com/engine/extend/" target="_blank" rel="noopener"
>встраивается в сам Docker&lt;/a>. Поставить можно так:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker plugin install wetopi/rbd &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --alias&lt;span class="o">=&lt;/span>rbd &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --grant-all-permissions &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">LOG_LEVEL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">RBD_CONF_POOL&lt;/span>&lt;span class="o">=&lt;/span>rbd &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">RBD_CONF_CLUSTER&lt;/span>&lt;span class="o">=&lt;/span>ceph &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">RBD_CONF_KEYRING_USER&lt;/span>&lt;span class="o">=&lt;/span>client.rbd &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">MOUNT_OPTIONS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;--options=noatime,discard&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Запустим простой docker-compose стек и примонтируем образ:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;3.8&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">test&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">alpine&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">sh -c &amp;#39;cat /vol/test; date | tee /vol/test&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">data-volume:/vol&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">data-volume&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">vol1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbd&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver_opts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">size&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">123&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># MiB&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Запускаем и проверяем:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo docker-compose up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># п.7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rbd map vol1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mkdir /tmp/vol1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount /dev/rbd0 /tmp/vol1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> /tmp/vol1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ls -la
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="nb">test&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> /
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /tmp/vol1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rbd unmap /dev/rbd0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Настройка командной строки</title><link>https://vlasov.pro/ru/p/shells/</link><pubDate>Wed, 22 Apr 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/shells/</guid><description>&lt;img src="https://vlasov.pro/ru/p/shells/bash.webp" alt="Featured image of post Настройка командной строки" />&lt;blockquote>
&lt;p>Написано вместе с &lt;a class="link" href="https://rebrainme.com/blog/" target="_blank" rel="noopener"
>ReBrainMe&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>Оболочка командной строки используется для любых манипуляций с сервером. Настраивать сервера можно по разному. Важно, чтобы это было комфортно для администратора, а вот &lt;strong>главное&lt;/strong>, чтобы это было &lt;strong>эффективно&lt;/strong> по затратам и времени, и сил. Командная строка может быть красочной, стрелочками разных цветов показывать путь к текущей директории, время, загрузку ЦП и прочий хлам. Приведу пример &lt;a class="link" href="https://github.com/ohmyzsh/ohmyzsh/" target="_blank" rel="noopener"
>отсюда&lt;/a>:&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/shells/ohmyzsh.webp"
width="633"
height="346"
srcset="https://vlasov.pro/ru/p/shells/ohmyzsh_hu14244436401278716114.webp 480w, https://vlasov.pro/ru/p/shells/ohmyzsh_hu6890038653941497772.webp 1024w"
loading="lazy"
alt="ohmyzsh"
class="gallery-image"
data-flex-grow="182"
data-flex-basis="439px"
>&lt;/p>
&lt;p>Красиво - да, но множество цветов отвлекает от сути. Кроме того, указывается ветка Git репозитория, которая занимает жизненно важное место в левой части, а можно было бы вправо перенести.&lt;/p>
&lt;h2 id="оболочки-командной-строки">Оболочки командной строки &lt;a href="#%d0%be%d0%b1%d0%be%d0%bb%d0%be%d1%87%d0%ba%d0%b8-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4%d0%bd%d0%be%d0%b9-%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%b8">¶&lt;/a>&lt;/h2>
&lt;p>Оболочки бывают разные, пусть и решают одни и те же проблемы очень похожим способом, но настраиваются по разному, обладают разным функционалом. &lt;em>Попробуйте разные и найдите свою! &amp;hellip; или напишите сами&lt;/em>&lt;/p>
&lt;ul>
&lt;li>&lt;em>bash&lt;/em> – де-факто стандартная оболочка, базовая автоподстановка и дополнение путей, есть в большинстве дистрибутивов по умолчанию, часто используется как оболочка для скриптов.&lt;/li>
&lt;li>&lt;em>fish&lt;/em> и &lt;em>zsh&lt;/em> – две разные оболочки, которые намного превосходят bash по функционалу, часто на слуху.&lt;/li>
&lt;li>&lt;em>ksh, tsh, csh &amp;hellip;&lt;/em> другие оболочки, могут быть ничем не хуже и даже лучше, просто чуть менее распространены&lt;/li>
&lt;/ul>
&lt;p>Задача данной статьи &lt;strong>субъективно&lt;/strong> разобраться в том, чем действительно нужно занимать окно терминала и &lt;em>предложить решение&lt;/em> на базе &lt;strong>zsh&lt;/strong>.&lt;/p>
&lt;p>Что нужно для того, чтобы использование командной строки было эффективным?&lt;/p>
&lt;h2 id="требования-к-оболочке">Требования к оболочке &lt;a href="#%d1%82%d1%80%d0%b5%d0%b1%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%ba-%d0%be%d0%b1%d0%be%d0%bb%d0%be%d1%87%d0%ba%d0%b5">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>&lt;em>Автодополнение путей&lt;/em>. Это бесспорно главная функция, которая требуется для перемещения по древу директорий. Казалось бы, в Bash по умолчанию есть автодополнение путей по нажатию Tab дважды. Попробуйте Zsh – там нужно нажать Tab один раз, мелочь казалось бы &amp;hellip; А теперь вернитесь на Bash :) Кроме того, Zsh можно настроить таким образом, что выбрасывается список файлов подпадающих под заданный префикс, что &lt;em>лишает необходимости прерывать ввод и делать ls -la, можно вообще стрелочками вариант выбрать&lt;/em>. Это не часто используется, но удобно.&lt;/li>
&lt;li>&lt;em>Поиск по истории команд&lt;/em>. Если Вы уже перешли на &lt;a class="link" href="https://github.com/ranger/ranger" target="_blank" rel="noopener"
>ranger&lt;/a>, то главным значимым для Вас требованием скорее всего станет это. Сначала мы узнаём про &lt;strong>Ctrl+R&lt;/strong> для поиска команды в истории уже набранных. Удобно, но не совсем. В Zsh можно просто набрать кусочек команды и стрелочками выбрать нужную из автоподсказки. Субъективно удобнее и вот почему: для показа следующей команды из истории нужно опять нажать Ctrl+R, что не совсем удобно, особенно когда прощёлкал нужную.&lt;/li>
&lt;li>&lt;em>Выделение начала приглашения ко вводу&lt;/em>. Когда листаешь большое количество логов в терминале от разных команд, начинаешь теряться и тратить дополнительное время на различение того, к какой команде относиться тот или иной блок логов, где сама команда и т. д. Выделять текст приглашения ко вводу действительно нужно, но не так, чтобы он затмевал всё&amp;hellip; Зачастую, первое что меняет начинающий пользователь нестандартной оболочки – это содержимое переменной &lt;strong>PS1&lt;/strong>. &lt;a class="link" href="https://linoxide.com/how-tos/change-bash-prompt-variable-ps1/" target="_blank" rel="noopener"
>Вот неплохое описание переменных PS1-4&lt;/a>.&lt;/li>
&lt;li>&lt;em>Легковесность&lt;/em>. Вкратце: когда ломишься на сервер, на котором loadavg в десятки раз превышена, очень жалеешь, что поставил в motd или начало .zshrc (.bashrc) прожорливый код по выводу развёрнутой статистики о потреблении ресурсов процессора, памяти, сети, диска и т. д.&lt;/li>
&lt;li>&lt;em>Не перегруженность&lt;/em>. Пусть и выбрана zsh для ежедневного пользования, все скрипты пишу с shabang на классический sh, потому что она практически везде есть, и синтаксис унифицирован. Иными словами, не рекомендуется писать скрипты используя нестандартные синтаксисы крутых оболочек, заморочишься ставить их на каждый сервер.&lt;/li>
&lt;li>&lt;em>Комфортность&lt;/em>. Эффективность и комфорт, всё-таки, плотно связаны. Поставить полупрозрачную картинку на фон или подобрать шрифты по вкусу тоже очень важно, когда ловишь себя на мысли, что корявые шрифты и угловатость интерфейса отбивает желание трудиться напрочь. &lt;em>Главное не переусердствовать&lt;/em>.&lt;/li>
&lt;/ol>
&lt;h2 id="алиасы">Алиасы &lt;a href="#%d0%b0%d0%bb%d0%b8%d0%b0%d1%81%d1%8b">¶&lt;/a>&lt;/h2>
&lt;p>Очень удобно объявлять алиасы для ускорения набора команд.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> ..&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;cd .. &amp;amp;&amp;amp; ls -lhA --color=auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">a&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ls -lhA --color=auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">d&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo docker&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">dc&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo docker-compose&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">die&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo shutdown now&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">e&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;exit&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">g&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;git&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">j&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo journalctl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubectl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">l&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ls -lh --color=auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">la&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ls -lhA --color=auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">p&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ping 8.8.8.8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">r&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ranger&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">reborn&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo shutdown -r now&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">sctl&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo systemctl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">sr&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;screen -R&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">svi&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo vim&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">svim&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo vim&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">t&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;terraform&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ну и немного юмора: &lt;em>alias please=&amp;lsquo;sudo&amp;rsquo;&lt;/em> сделает Ваше общение с компьютером намного мягче.&lt;/p>
&lt;h2 id="конфигурация-zsh">Конфигурация zsh &lt;a href="#%d0%ba%d0%be%d0%bd%d1%84%d0%b8%d0%b3%d1%83%d1%80%d0%b0%d1%86%d0%b8%d1%8f-zsh">¶&lt;/a>&lt;/h2>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/shells/my-zsh.png"
width="676"
height="276"
srcset="https://vlasov.pro/ru/p/shells/my-zsh_hu5659858168636195027.png 480w, https://vlasov.pro/ru/p/shells/my-zsh_hu10784998609317191711.png 1024w"
loading="lazy"
alt="Пример пользовательской настройки zsh"
class="gallery-image"
data-flex-grow="244"
data-flex-basis="587px"
>&lt;/p>
&lt;p>Как можно заметить, выделяется каждая команда между операндами разделения типа &lt;code>; &amp;amp;&amp;amp; |&lt;/code>, при этом команда вводиться на второй строке, после приглашения с указанием каталога текущей директории и имени пользователя с хостом, это сделало длинные команды более удобными для чтения и сопровождения. Справа честно &lt;em>взятое&lt;/em> из стандартных настроек поставляемых к zsh в &lt;a class="link" href="https://manjaro.org/" target="_blank" rel="noopener"
>Manjaro&lt;/a> указание текущей ветки Git репозитория. В случае наличия изменений, удалений, добавлений появляются жёлтый, зелёный, красный кружочки – много места не занимало, по этому решено оставить. Пусть будет.
При наборе команды, предлагается последняя, которая подходит по префиксу. Подтвердить выбор можно нажав стрелочку вправо. Окно эмулятора &lt;a class="link" href="https://terminator-gtk3.readthedocs.io/en/latest/" target="_blank" rel="noopener"
>Terminator&lt;/a>.&lt;/p>
&lt;p>Для установки и настройки окна терминала как в примере нужно сделать следующее.&lt;/p>
&lt;ol>
&lt;li>&lt;a class="link" href="https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH" target="_blank" rel="noopener"
>Установить&lt;/a> ohmyzsh&lt;/li>
&lt;li>Скопировать &lt;a class="link" href="files/dot.zshrc" >.zshrc&lt;/a> к себе в домашний каталог&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">install -o &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>id -u&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -g &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>id -g&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -m &lt;span class="m">0644&lt;/span> .zshrc ~/.zshrc
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>Распаковать &lt;a class="link" href="files/plugins.tgz" >плагины&lt;/a>&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo tar -xpzvf plugins.tgz /
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo usermod -s &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">command&lt;/span> -v zsh&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$USER&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="4">
&lt;li>Сделать zsh интерпретатором по умолчанию&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo usermod -s &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">command&lt;/span> -v zsh&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$USER&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Основы SSH</title><link>https://vlasov.pro/ru/p/ssh-intro/</link><pubDate>Mon, 09 Mar 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/ssh-intro/</guid><description>&lt;img src="https://vlasov.pro/ru/p/ssh-intro/openssh.webp" alt="Featured image of post Основы SSH" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>&lt;strong>S&lt;/strong>ecure &lt;strong>Sh&lt;/strong>ell - де-факто стандартный способ получения доступа к терминалу на удалённом\виртуальном сервере. На компьютере, куда нужно получить доступ устанавливается &lt;strong>ssh сервер&lt;/strong>, на компьютер за которым работает оператор - &lt;strong>ssh клиент&lt;/strong>. Посредством SSH можно:&lt;/p>
&lt;ol>
&lt;li>Передавать файлы&lt;/li>
&lt;li>Выполнять команды на целевом сервере&lt;/li>
&lt;li>Получать информацию о целевой системе и выполнять простейшую автоматизацию&lt;/li>
&lt;/ol>
&lt;p>На Linux и MacOS у нас есть терминал - SSH, как правило, установлен по умолчанию. Для Windows я использовал такие варианты:&lt;/p>
&lt;ol>
&lt;li>&lt;a class="link" href="https://mobaxterm.mobatek.net/" target="_blank" rel="noopener"
>MobaXTerm&lt;/a> - удобно, но платно. Для некомерческого использования подходит, для использования в компании - придётся купить лицензию. Преимущества:
&lt;ul>
&lt;li>сразу предоставляет файловый менеджер с drag-n-drop файлов на целевую систему&lt;/li>
&lt;li>нормальная подстветка и поддержка RSA ключей&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a class="link" href="https://git-scm.com/" target="_blank" rel="noopener"
>Git&lt;/a> - при установке Git-a, он в комплекте поставляет Git Bash и SSH клиент. Очень приближённая среда к обычному &lt;a class="link" href="https://ru.wikipedia.org/wiki/Bash" target="_blank" rel="noopener"
>Bash&lt;/a>.&lt;/li>
&lt;/ol>
&lt;h2 id="как-подключаться">Как подключаться? &lt;a href="#%d0%ba%d0%b0%d0%ba-%d0%bf%d0%be%d0%b4%d0%ba%d0%bb%d1%8e%d1%87%d0%b0%d1%82%d1%8c%d1%81%d1%8f">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ssh &lt;span class="o">[&lt;/span>-p &amp;lt;ssh порт&amp;gt;&lt;span class="o">]&lt;/span> &amp;lt;пользователь&amp;gt;@&amp;lt;ip целевого хоста&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Порт указывается опционально, по умолчанию это порт &lt;strong>22&lt;/strong>, но &lt;em>настоятельно рекомендуется&lt;/em> не запускать SSH сервер на стандартном порту, так как в мире полным полно автоматизированных ботов, которые сканируют подсети облачных провайдеров и выискивают виртуалки с SSH-ем на стандратном порту и простеньким паролеи, чтобы приобщить оную к какому-нибуть ботнету. Однажды я на этом попался, но это совсем другая история&amp;hellip;&lt;/p>
&lt;h2 id="копирование-файлов">Копирование файлов &lt;a href="#%d0%ba%d0%be%d0%bf%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2">¶&lt;/a>&lt;/h2>
&lt;p>Скопировать файлы на целевой хост, можно с помощью scp.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">scp &lt;span class="o">[&lt;/span>-P &amp;lt;ssh порт&amp;gt;&lt;span class="o">]&lt;/span> /path/to/local/file &amp;lt;пользователь&amp;gt;@&amp;lt;ip целевого хоста&amp;gt;:&amp;lt;путь на сервере назначения&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Обратите внимание:&lt;/p>
&lt;ol>
&lt;li>Порт у scp указывается с помощью &lt;code>-P&lt;/code>, в то время как для обычного ssh - &lt;code>-p&lt;/code>.&lt;/li>
&lt;li>Папка на целевой машине должна принадлежать пользователю от имени которого вы подключаетесь, или должны быть разрешения для него на запись в ту папку\файл.&lt;/li>
&lt;/ol></description></item><item><title>Первый пост в Ghost</title><link>https://vlasov.pro/ru/p/ghost/</link><pubDate>Sun, 08 Mar 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/ghost/</guid><description>&lt;img src="https://vlasov.pro/ru/p/ghost/ghost-logo.webp" alt="Featured image of post Первый пост в Ghost" />&lt;blockquote>
&lt;p>&lt;em>Сейчас блог написан на &lt;a class="link" href="https://docs.stack.jimmycai.com" target="_blank" rel="noopener"
>Hugo&lt;/a>. Эта статья является первым постом из старого блога, который, как раз, был на Ghost.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;ul>
&lt;li>&lt;a class="link" href="#%d0%b7%d0%b0%d0%bc%d0%b5%d1%82%d0%ba%d0%b8" >Заметки&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Первая статья. Вспомнился рассказ Айзека Азимова &amp;ldquo;&lt;a class="link" href="https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B8%D0%B9_%D0%B2%D0%BE%D0%BF%D1%80%D0%BE%D1%81" target="_blank" rel="noopener"
>Последний вопрос&lt;/a>&amp;rdquo;, прослушанный по пути на работу в один из обычных дней. Хорошая вещь - рекомендую.&lt;br>
Писать хорошие статьи, прочтение которых будет разумной тратой времени, не так просто, как могло показаться. Причин тому две:&lt;/p>
&lt;ol>
&lt;li>Мысли должны быть &lt;em>полезными&lt;/em>.&lt;/li>
&lt;li>Изложение должно быть систематизированным.&lt;/li>
&lt;/ol>
&lt;p>Система запущена на &lt;a class="link" href="https://ghost.org" target="_blank" rel="noopener"
>Ghost&lt;/a> - сервер хороший, шустренький, запустился легко, инструментария для такого псевдо-блогера как я более чем хватает. Есть встроенны плагин для выбора картинок с &lt;a class="link" href="https://unsplash.com/" target="_blank" rel="noopener"
>Unspalsh&lt;/a> - изображения, которые можно публиковать и не боятся, что к тебе придут с претензией на нарушение авторских прав.&lt;br>
docker-compose.yml, которым это всё дело можно с лёгкостью поднять, представлен ниже.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.7&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ghost&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ghost:3.9.0-alpine&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ghost&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unless-stopped&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s1">&amp;#39;80:2368&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">/data/ghost:/var/lib/ghost/content:rw&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">url=http://example.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">logging&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">json-file&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">options&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">max-size&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">100m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="заметки">Заметки &lt;a href="#%d0%b7%d0%b0%d0%bc%d0%b5%d1%82%d0%ba%d0%b8">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Всегда &lt;em>стоит закреплять версию&lt;/em> образа, с которого будет запускаться контейнер. Это поможет избежать проблем с перезапуском стека в дальнейшем. Если версия была &lt;code>latest&lt;/code>, то при пересоздании стека по каким-то причинам &lt;code>down -&amp;gt; up&lt;/code> может стянуться более новая версия, которая будет не совместима с текущими данными\настройками и т. д. Кроме того, невозможно через неделю быстро и легко вспомнить &lt;em>какая же точно версия была запущена на момент старта?&lt;/em>&lt;/li>
&lt;li>&lt;strong>Всегда&lt;/strong> нужно контролировать процесс логгирования. Если используется стандартный Docker logging driver - json-file, то, по умолчанию, Docker daemon будет принимать логи и писать их в json файл для этого контейнера пока &lt;em>место на диске не закончится.&lt;/em> По умолчанию, файл всегда будет один, а вот его место мы можем ограничить установив значение опции &lt;code>max-size: 100m&lt;/code> (я взял такое, просто так - больше 100 МБ логов вряд ли кто-либо будет читать). &lt;a class="link" href="https://docs.docker.com/config/containers/logging/json-file/" target="_blank" rel="noopener"
>Подробнее о json-file Docker logging driver&lt;/a>.&lt;/li>
&lt;li>Рекомендую всегда прописывать &lt;code>container_name&lt;/code> - удобнее потом читать &lt;code>docker ps&lt;/code>.&lt;/li>
&lt;/ol></description></item><item><title>Обратные SSH тунели</title><link>https://vlasov.pro/ru/p/reverse-ssh/</link><pubDate>Sun, 20 Oct 2019 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/reverse-ssh/</guid><description>&lt;img src="https://vlasov.pro/ru/p/reverse-ssh/ssh.png" alt="Featured image of post Обратные SSH тунели" />&lt;h2 id="введение">Введение &lt;a href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5">¶&lt;/a>&lt;/h2>
&lt;p>Если нужно добраться до сервера, который находиться за &lt;a class="link" href="https://www.webopedia.com/definitions/nat/" target="_blank" rel="noopener"
>NAT&lt;/a>, то напрямую это сделать нельзя, нужно как-то извращаться. Рассмотрим как можно использовать прямые и обратные SSH туннели для этих целей.&lt;/p>
&lt;h2 id="о-туннелях">О туннелях &lt;a href="#%d0%be-%d1%82%d1%83%d0%bd%d0%bd%d0%b5%d0%bb%d1%8f%d1%85">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>&lt;em>Обратный туннель&lt;/em> – создаётся от целевого сервера (ЦС) к промежуточному (ПС). Сокет в этом случае создаётся на ПС.&lt;/li>
&lt;li>&lt;em>Прямой туннель&lt;/em> – создаётся от начального сервера (НС) к ПС. Сокет в этом случае находиться на НС.&lt;/li>
&lt;/ol>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/reverse-ssh/diagram.png"
width="542"
height="317"
srcset="https://vlasov.pro/ru/p/reverse-ssh/diagram_hu17955256524260640580.png 480w, https://vlasov.pro/ru/p/reverse-ssh/diagram_hu3505688432812524674.png 1024w"
loading="lazy"
alt="Схема работы предложенного метода"
class="gallery-image"
data-flex-grow="170"
data-flex-basis="410px"
>&lt;/p>
&lt;p>Используя два туннеля мы можем добраться до ЦС. Можно пробросить порт какого-то сайта или просто выбросить порт SSH сервера ЦС, а через него войти в систему. Так же можно пробросить SOCKS5 прокси и выходить в сеть через ЦС. Вариантов достаточно.&lt;/p>
&lt;blockquote>
&lt;p>Промежуточный сервер обязательно должен быть доступен как с целевого, так и с начального&lt;/p>
&lt;/blockquote>
&lt;h2 id="создание-пользователя-на-пс">Создание пользователя на ПС &lt;a href="#%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d0%b5-%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d1%82%d0%b5%d0%bb%d1%8f-%d0%bd%d0%b0-%d0%bf%d1%81">¶&lt;/a>&lt;/h2>
&lt;p>Удобно и безопасно использовать пользователя, который может только создавать тунели, чтобы через него нельзя было зайти на ПС. Код представленный ниже как раз наценен на создание пользователя без домашнего каталога и интерпретатора для входа.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo adduser -s /bin/false -M -N tunnel
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo usermod -d / tunnel
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;tunnel:tunnel&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> sudo chpasswd
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF | sudo tee -a /etc/ssh/sshd_config
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">Match User tunnel
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> PasswordAuthentication yes
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> AuthenticationMethods &amp;#34;password&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl restart sshd
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="обратный-тунель">Обратный тунель &lt;a href="#%d0%be%d0%b1%d1%80%d0%b0%d1%82%d0%bd%d1%8b%d0%b9-%d1%82%d1%83%d0%bd%d0%b5%d0%bb%d1%8c">¶&lt;/a>&lt;/h2>
&lt;p>Теперь давайте приступим к созданию тунелей. Нам понадобиться обратный от ПС к ЦС. Далее используется &lt;a class="link" href="https://gist.github.com/arunoda/7790979" target="_blank" rel="noopener"
>sshpass&lt;/a>, который нужен для автоматического ввода пароля при подключении по SSH.&lt;/p>
&lt;p>Для создания обратного тунеля, его нужно создавать со стороны ЦС. Добавим ПС в список известных на ЦС.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">mkdir -p ~/.ssh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh-keyscan -H jump-host &amp;gt;&amp;gt; ~/.ssh/known_hosts
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>И создадим тунель.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sshpass -p &lt;span class="s1">&amp;#39;password&amp;#39;&lt;/span> ssh -fNR 2222:localhost:22 tunnel@jump-host
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ul>
&lt;li>&lt;em>ssh-keyscan -H jump-host&lt;/em> - добавляем ключи SSH сервера на ПС в список доверенных на ЦС&lt;/li>
&lt;li>&lt;em>sshpass -p &amp;lsquo;password&amp;rsquo;&lt;/em> – sshpass введёт пароль к новосозданному ранее пользователю на ПС&lt;/li>
&lt;li>&lt;em>-fN&lt;/em> – выполнить команду и не создавать сессию tty&lt;/li>
&lt;li>&lt;em>-R&lt;/em> - создание обратного тунеля&lt;/li>
&lt;li>&lt;em>2222:localhost:22&lt;/em> – формат такой &lt;code>&amp;lt;адрес в начале тунеля&amp;gt;:&amp;lt;порт в начале тунеля&amp;gt;:&amp;lt;адрес на конце тунеля&amp;gt;:&amp;lt;порт на конце тунеля&amp;gt;&lt;/code>. Стало быть, команда делает конкретно следующее: проксирует 127.0.0.1:2222 (адрес начала по умолчанию это localhost) к ПС на 127.0.0.1:22 но уже ПС. Теперь мы можем достучаться до ЦС с ПС. Проверить можно командой ниже&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ssh -p &lt;span class="m">2222&lt;/span> localhost hostname
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;blockquote>
&lt;p>Начало тунеля на ПС, конец на ЦС. Для прямого было бы наоборот.
Если обратиться на внешний IP адресс ПС на порт 22, то в тунель мы не попадём, так как трафик должен заходить только с 127.0.0.1, то есть с самого ПС&lt;/p>
&lt;/blockquote>
&lt;h2 id="прямой-тунель">Прямой тунель &lt;a href="#%d0%bf%d1%80%d1%8f%d0%bc%d0%be%d0%b9-%d1%82%d1%83%d0%bd%d0%b5%d0%bb%d1%8c">¶&lt;/a>&lt;/h2>
&lt;p>Для того, чтобы попасть в обратный тунель от ПС до ЦС, нам нужно пробросить трафик с НС внутрь ПС. Для этого создадим &lt;em>прямой тунель&lt;/em> выполнив код представленный ниже на НС.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">mkdir -p ~/.ssh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh-keyscan -H jump-host &amp;gt;&amp;gt; ~/.ssh/known_hosts
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sshpass -p &lt;span class="s1">&amp;#39;password&amp;#39;&lt;/span> ssh -fNL 1234:localhost:2222 tunnel@jump-host
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ul>
&lt;li>&lt;em>1234:localhost:2222&lt;/em> – проксируем трафик с 127.0.0.1:1234 НС на 127.0.0.1:2222 ПС, а фактически трафик пойдёт сразу по обратноме тунелю к ЦС на порт 22.&lt;/li>
&lt;/ul>
&lt;h2 id="socks5-proxy">SOCKS5 proxy &lt;a href="#socks5-proxy">¶&lt;/a>&lt;/h2>
&lt;p>Мы можем настроить любой браузер, чтобы тот использовал SOCKS5 прокси для направления всего трафика. Это удобно, если нужно обратиться к ресурсам в локальной сети ЦС с НС. Выполним команду ниже на НС (после создания всех тунелей).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ssh -fND &lt;span class="m">1329&lt;/span> -p &lt;span class="m">1234&lt;/span> user-on-th@localhost
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Осталось настроить использование прокси. Может выглядеть так.&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/reverse-ssh/proxy-settings.webp"
width="1020"
height="700"
srcset="https://vlasov.pro/ru/p/reverse-ssh/proxy-settings_hu6932171806291270442.webp 480w, https://vlasov.pro/ru/p/reverse-ssh/proxy-settings_hu17882682458861990530.webp 1024w"
loading="lazy"
alt="Настройки прокси в KDE Plasma"
class="gallery-image"
data-flex-grow="145"
data-flex-basis="349px"
>&lt;/p></description></item><item><title>OpenSSL снипет</title><link>https://vlasov.pro/ru/p/openssl-snippet/</link><pubDate>Thu, 25 Apr 2019 00:00:00 +0000</pubDate><guid>https://vlasov.pro/ru/p/openssl-snippet/</guid><description>&lt;img src="https://vlasov.pro/ru/p/openssl-snippet/https.webp" alt="Featured image of post OpenSSL снипет" />&lt;p>Здесь очень много полезных команд, но полную работоспособность проверять лень &amp;#x1f604;&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;span class="lnt">88
&lt;/span>&lt;span class="lnt">89
&lt;/span>&lt;span class="lnt">90
&lt;/span>&lt;span class="lnt">91
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># path to private part of CA (PEM encoded)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CA_KEY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;ca.key&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># path to public part of CA (PEM encoded)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CA_CRT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;ca.crt&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># password to use CA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CA_PASSWORD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;longalphanum&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Country&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">C&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;UA&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># State&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">ST&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;Kiev&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Location&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">L&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;Kiev&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Organization&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">O&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;No organization&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Organization unit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">OU&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;No unit&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Domain to issue final cert for&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;vlasov.pro&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Days while the certificate will be valid&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DAYS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;365&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">subj&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;/C=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">C&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/ST=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">ST&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/L=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">L&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/O=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">O&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/OU=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">OU&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/CN=&lt;/span>&lt;span class="nv">$1&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_KEY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$1&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;-ca&amp;#39;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;basicConstraints=CA:true&amp;#39;&lt;/span> &amp;gt; extfile.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># CA - used for signing of both server and client certs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># generate private key&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl ecparam -genkey -name prime256v1 &lt;span class="p">|&lt;/span> openssl ec -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_KEY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># generate signing request&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl req -new -key &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_KEY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -out ca.csr -subj &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>subj &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$O&lt;/span>&lt;span class="s2"> CA&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># csr + key = crt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl x509 -req -days &lt;span class="m">3650&lt;/span> -in ca.csr -signkey &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_KEY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -extfile extfile.txt -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f ca.csr
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># convert crt to DER format&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl x509 -inform PEM -outform DER -in &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">.der&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;Generated CA&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># generate and sign certificate&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> cat &lt;span class="s">&amp;lt;&amp;lt;EOF &amp;gt;extfile.txt
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">[ req ]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">req_extensions = req_ext
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">distinguished_name = req_distinguished_name
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">[req_distinguished_name]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">[ req_ext ]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">basicConstraints = CA:FALSE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">keyUsage = nonRepudiation, digitalSignature, keyEncipherment
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">subjectAltName = @alt_names
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">[alt_names]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">DNS.1 = $DOMAIN
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">DNS.2 = *.$DOMAIN
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># issue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl ecparam -genkey -name prime256v1 &lt;span class="p">|&lt;/span> openssl ec -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span> &lt;span class="c1"># key&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl req -new -key &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span> -config extfile.txt -subj &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>subj &lt;span class="nv">$DOMAIN&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="c1"># csr&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl x509 -req &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -days &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$DAYS&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -in &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -CA &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.crt&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -CAkey &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_KEY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -CAcreateserial &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -passin &lt;span class="s2">&amp;#34;pass:&lt;/span>&lt;span class="nv">$CA_PASSWORD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -extensions req_ext -extfile extfile.txt &lt;span class="c1"># csr + rootCA.crt = crt &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># convert DER -&amp;gt; PEM&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl x509 -inform PEM -outform DER -in &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.crt&amp;#34;&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.der.crt&amp;#34;&lt;/span> &lt;span class="c1"># convert&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># convert PEM -&amp;gt; pkcs12&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl pkcs12 -export &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -inkey &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -in &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.crt&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.pfx&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -password &lt;span class="s2">&amp;#34;pass:&lt;/span>&lt;span class="nv">$JKS_PASSWORD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -name &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$DOMAIN&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># create fullchain&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> cat &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.crt&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &amp;gt; &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.full&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># verify&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl verify -CAfile &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.crt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># info&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> log_info &lt;span class="s2">&amp;#34;Generated &lt;/span>&lt;span class="nv">$DOMAIN&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rm -f extfile.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item></channel></rss>