<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://cyberbrain.cc/feed.xml" rel="self" type="application/atom+xml" /><link href="https://cyberbrain.cc/" rel="alternate" type="text/html" /><updated>2025-10-01T10:33:28+00:00</updated><id>https://cyberbrain.cc/feed.xml</id><title type="html">Dreaming in digital…</title><subtitle>Здесь, наверное, нужно написать что-нибудь мотивирующее и и глубокомысленное, но мне лень.</subtitle><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><entry><title type="html">Настройка доступа к Ingress нескольких кластеров Kubernetes, находящихся в сети за NAT</title><link href="https://cyberbrain.cc/2023/12/14/%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%B0-%D0%BA-ingress-%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85-%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BE%D0%B2-kubernetes-%D0%BD%D0%B0%D1%85%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D1%85%D1%81%D1%8F-%D0%B2-%D1%81%D0%B5%D1%82%D0%B8-%D0%B7%D0%B0-nat.html" rel="alternate" type="text/html" title="Настройка доступа к Ingress нескольких кластеров Kubernetes, находящихся в сети за NAT" /><published>2023-12-14T11:39:00+00:00</published><updated>2023-12-14T11:39:00+00:00</updated><id>https://cyberbrain.cc/2023/12/14/%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%B0-%D0%BA-ingress-%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85-%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BE%D0%B2-kubernetes-%D0%BD%D0%B0%D1%85%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D1%85%D1%81%D1%8F-%D0%B2-%D1%81%D0%B5%D1%82%D0%B8-%D0%B7%D0%B0-nat</id><content type="html" xml:base="https://cyberbrain.cc/2023/12/14/%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%B0-%D0%BA-ingress-%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85-%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BE%D0%B2-kubernetes-%D0%BD%D0%B0%D1%85%D0%BE%D0%B4%D1%8F%D1%89%D0%B8%D1%85%D1%81%D1%8F-%D0%B2-%D1%81%D0%B5%D1%82%D0%B8-%D0%B7%D0%B0-nat.html"><![CDATA[<p>Есть у меня две мелких инсталляции кубера на домашнем сервере. Использую их для тестирования различных пайплайнов деплоя разрабатываемых приложений. Один кубер условно “тестовый”, другой условно “продакшен”. Нужно сделать приложения, запущенные в этих кубах, доступными из интернетов по https с минимальными усилиями по настройке tls с моей стороны.</p>

<h2 id="disclaimer">Disclaimer</h2>

<p>Настройки сети, пробросы портов и т.д. оставлю за кадром.</p>

<h2 id="nginx-to-the-rescue">Nginx to the rescue</h2>

<p>Для проброса TCP-соединений буду использовать модуль stream. В этом случае мне не придётся настраивать терминацию SSL на Nginx.</p>

<h3 id="установка-модуля-stream">Установка модуля stream</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt-get <span class="nb">install </span>libnginx-mod-stream
</code></pre></div></div>

<p>Подразумевается, что сам Nginx уже установлен и кеш пакетов apt свежий.</p>

<h3 id="настройка-модуля-stream">Настройка модуля stream</h3>

<p>Добавляю в <code class="language-plaintext highlighter-rouge">/etc/nginx/nginx.conf</code> секцию stream для <strong>трафика с TLS</strong>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>stream <span class="o">{</span>
    map_hash_bucket_size 64<span class="p">;</span>

    map <span class="nv">$ssl_preread_server_name</span> <span class="nv">$targetBackend</span> <span class="o">{</span>
        hostnames<span class="p">;</span>

        <span class="k">*</span>.domain1.tld   k8s1<span class="p">;</span>
        domain1.tld     k8s1<span class="p">;</span>

        <span class="k">*</span>.domain2.tld   k8s2<span class="p">;</span>
        domain2.tld     k8s2<span class="p">;</span>

        default         <span class="nb">local</span><span class="p">;</span>
    <span class="o">}</span>

    upstream k8s1 <span class="o">{</span>
        server 10.0.0.2:443<span class="p">;</span>
    <span class="o">}</span>

    upstream k8s2 <span class="o">{</span>
        server 10.0.0.3:443<span class="p">;</span>
    <span class="o">}</span>

    upstream <span class="nb">local</span> <span class="o">{</span>
        server 127.0.0.1:8443<span class="p">;</span>
    <span class="o">}</span>

    server <span class="o">{</span>
        listen      0.0.0.0:443<span class="p">;</span>

        ssl_preread on<span class="p">;</span>

        proxy_pass  <span class="nv">$targetBackend</span><span class="p">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Где <code class="language-plaintext highlighter-rouge">upstream k8s1</code> - адрес ингресса первого кубера, <code class="language-plaintext highlighter-rouge">upstream k8s2</code> - адрес ингресса второго кубера, <code class="language-plaintext highlighter-rouge">upstream local</code> - локальный сервер nginx.</p>

<p>Для того, чтобы корректно перенаправить SSL-трафик на разные upstream, использую параметр <code class="language-plaintext highlighter-rouge">ssl_preread on</code>, позволяющий получить FQDN из SNI и записать его в переменную <code class="language-plaintext highlighter-rouge">$ssl_preread_server_name</code>. Далее, на основе заданного маппинга сопоставляем <code class="language-plaintext highlighter-rouge">$ssl_preread_server_name</code> с соответствующим <code class="language-plaintext highlighter-rouge">$targetBackend</code>.</p>

<p>Локальный nginx придётся перенастроить чтобы он слушал обращения к сайтам с TLS на <a href="https://127.0.0.1:8443">https://127.0.0.1:8443</a>.</p>

<p>Перезапускаю nginx после изменения конфигурации для применения новых настроек.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart nginx
</code></pre></div></div>

<h3 id="дополнительная-настройка-nginx-для-корректной-работы-cert-manager">Дополнительная настройка nginx для корректной работы Cert Manager</h3>

<p>Cert Manager уже задеплоен в кубере и настроен для автоматизации получения SSL-сертификатов от Let’s Encrypt. Создаём для Nginx по конфигу сайта под каждый кубер, чтобы туда мог подключиться проверяющий адреса бот. Приведена минимальная конфигурация, дополняйте по обстоятельствам.</p>

<p><code class="language-plaintext highlighter-rouge">/etc/nginx/sites-enabled/k8s1</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># HTTP</span>
server <span class="o">{</span>
    listen      80<span class="p">;</span>

    server_name <span class="k">*</span>.domain1.tld domain1.tld<span class="p">;</span>

    location    / <span class="o">{</span>
        allow               all<span class="p">;</span>

        proxy_pass          http://10.0.0.2:80<span class="p">;</span>
        proxy_pass_header   Set-Cookie<span class="p">;</span>

        proxy_set_header    X-Real-IP           <span class="nv">$remote_addr</span><span class="p">;</span>
        proxy_set_header    X-Forwarded-Proto   <span class="nv">$scheme</span><span class="p">;</span>
        proxy_set_header    X-Forwarded-For     <span class="nv">$remote_addr</span><span class="p">;</span>
        proxy_set_header    Host                <span class="nv">$host</span><span class="p">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">/etc/nginx/sites-enabled/k8s2</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># HTTP</span>
server <span class="o">{</span>
    listen      80<span class="p">;</span>

    server_name <span class="k">*</span>.domain2.tld domain2.tld<span class="p">;</span>

    location    / <span class="o">{</span>
        allow               all<span class="p">;</span>

        proxy_pass          http://10.0.0.3:80<span class="p">;</span>
        proxy_pass_header   Set-Cookie<span class="p">;</span>

        proxy_set_header    X-Real-IP           <span class="nv">$remote_addr</span><span class="p">;</span>
        proxy_set_header    X-Forwarded-Proto   <span class="nv">$scheme</span><span class="p">;</span>
        proxy_set_header    X-Forwarded-For     <span class="nv">$remote_addr</span><span class="p">;</span>
        proxy_set_header    Host                <span class="nv">$host</span><span class="p">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<h2 id="бонусы">Бонусы</h2>

<h3 id="перенаправление-http-на-https">Перенаправление http на https</h3>

<p><code class="language-plaintext highlighter-rouge">/etc/nginx/sites-enabled/http2https</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server <span class="o">{</span>
    listen  80  default_server<span class="p">;</span>

    <span class="k">return  </span>301 https://<span class="nv">$host$request_uri</span><span class="p">;</span>
<span class="o">}</span>
</code></pre></div></div>

<h3 id="сайт-заглушка">Сайт-заглушка</h3>

<p><code class="language-plaintext highlighter-rouge">/etc/nginx/sites-enabled/landing</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server <span class="o">{</span>
    listen      127.0.0.1:8443 ssl http2 default_server<span class="p">;</span>

    root        /srv/landing<span class="p">;</span>

    index       index.html<span class="p">;</span>

    location    / <span class="o">{</span>
        try_files <span class="nv">$uri</span> <span class="nv">$uri</span>/ /index.html<span class="p">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>]]></content><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><summary type="html"><![CDATA[Есть у меня две мелких инсталляции кубера на домашнем сервере. Использую их для тестирования различных пайплайнов деплоя разрабатываемых приложений. Один кубер условно “тестовый”, другой условно “продакшен”. Нужно сделать приложения, запущенные в этих кубах, доступными из интернетов по https с минимальными усилиями по настройке tls с моей стороны.]]></summary></entry><entry><title type="html">Проходные выключатели без проводов</title><link href="https://cyberbrain.cc/2022/01/17/prohodnye-vyklyuchateli-bez-provodov.html" rel="alternate" type="text/html" title="Проходные выключатели без проводов" /><published>2022-01-17T10:45:31+00:00</published><updated>2022-01-17T10:45:31+00:00</updated><id>https://cyberbrain.cc/2022/01/17/prohodnye-vyklyuchateli-bez-provodov</id><content type="html" xml:base="https://cyberbrain.cc/2022/01/17/prohodnye-vyklyuchateli-bez-provodov.html"><![CDATA[<p>Первое, что заставило меня задуматься о внедрении какого-нибудь «умного света» (ещё даже не умного дома) — это необходимость топать практически до санузла чтобы включить свет в коридоре. Особенно шикарно делать это ночью в полной темноте. Собираешь все выступы.</p>

<p>Появилась мысль закинуть в подрозетник к выключателю какое-нибудь реле с удалённым управлением, а пульт от него положить на тумбочку у кровати. От этой мысли я отказался почти сразу, потому что в тот момент уже искал куда закинул пульт от телевизора. Как начальный вариант — прикинул купить ночник с таймером и воткнуть его в одну из розеток в коридоре, но все попадавшиеся мне подобные ночники были либо уродливыми, либо неудобными. В итоге, первой моей домашней автоматизацией оказался электронный таймер для выключения на ночь вентилятора, обдувающего мою домашнюю «серверную». Второй такой же таймер, купленный через полгода, включал вечером гирлянду, повешенную в комнате за занавесками. Но проблему с выключателями это не решало. На тот момент я уже обладал начальной информацией про умный дом от Xiaomi и решился на покупку шлюза, нескольких розеток и датчиков. Ну и заказал из Китая для этой системы управляемые выключатели. Как я монтировал эти выключатели в квадратные китайские подрозетники (которые продавец положил в комплект, кстати) — отдельная история.</p>

<p>В общем, схема следующая:</p>

<p><img src="/assets/2022/01/Prohodnye-vyklYu-chateli-1.png" alt="Схема" /></p>

<p>Розовая «шестерёнка» — выключатель на две клавиши в прихожей у двери, управляет светом в прихожей (вторая клавиша оставлена под автоматизацию). Красная «шестерёнка» — выключатель на три клавиши на стене справа от входа в санузел, управляет светом в ванной, вытяжкой в ванной и светом в коридоре Розовая «звёздочка» — беспроводной выключатель на две клавиши на стене между входами в кухню и комнату, дублирует управление светом в прихожей и светом в коридоре. Зелёная «звёздочка» — беспроводной выключатель на стене в ванной, дублирует управление светом в ванной и вытяжкой в ванной.</p>

<p>Автоматизации в Mi Home выглядят следующим образом:</p>

<p><img src="/assets/2022/01/Screenshot_20220117-132912_Mi-Home.jpg" alt="Автоматизации" /><br />
<img src="/assets/2022/01/Screenshot_20220117-132952_Mi-Home.jpg" alt="Автоматизации" /><br />
<img src="/assets/2022/01/Screenshot_20220117-133000_Mi-Home.jpg" alt="Автоматизации" /><br />
<img src="/assets/2022/01/Screenshot_20220117-133009_Mi-Home.jpg" alt="Автоматизации" /></p>

<p>Второй выключатель по аналогии.</p>

<p>P.S.: а нормальные люди в обед обедают…</p>]]></content><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><summary type="html"><![CDATA[Первое, что заставило меня задуматься о внедрении какого-нибудь «умного света» (ещё даже не умного дома) — это необходимость топать практически до санузла чтобы включить свет в коридоре. Особенно шикарно делать это ночью в полной темноте. Собираешь все выступы.]]></summary></entry><entry><title type="html">Моё приложение для Android прошло государственную регистрацию</title><link href="https://cyberbrain.cc/2021/06/10/moyo-prilozhenie-dlya-android-proshlo-gosudarstvennuyu-registraciyu.html" rel="alternate" type="text/html" title="Моё приложение для Android прошло государственную регистрацию" /><published>2021-06-10T14:16:57+00:00</published><updated>2021-06-10T14:16:57+00:00</updated><id>https://cyberbrain.cc/2021/06/10/moyo-prilozhenie-dlya-android-proshlo-gosudarstvennuyu-registraciyu</id><content type="html" xml:base="https://cyberbrain.cc/2021/06/10/moyo-prilozhenie-dlya-android-proshlo-gosudarstvennuyu-registraciyu.html"><![CDATA[<p>А я забыл об этом написать)</p>

<p>Ссылки на репозитории (код закрыт, ссылки для соавторов): <a href="https://gitlab.cyberbrain.pw/custom-wearable-assistant/mobile-applications/android/cardioservice-legacy">Мой Gitlab</a>, <a href="https://bitbucket.org/custom_wearable_assistant/cardioservice">зеркало на Bitbucket</a></p>

<p><img src="/assets/2021/06/1594023031263-df4dc66d-77b1-4b3f-a1bb-5fc7bb9dfca7.jpg" alt="Свидетельство о регистрации" /></p>]]></content><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><summary type="html"><![CDATA[А я забыл об этом написать)]]></summary></entry><entry><title type="html">Как отключить отображение системных пользователей на экране входа в систему (LightDM)</title><link href="https://cyberbrain.cc/2020/08/04/kak-otklyu-chit-otobrazhenie-sistemnyh-polzovatelej-na-jekrane-vhoda-v-sistemu-lightdm.html" rel="alternate" type="text/html" title="Как отключить отображение системных пользователей на экране входа в систему (LightDM)" /><published>2020-08-04T09:24:52+00:00</published><updated>2020-08-04T09:24:52+00:00</updated><id>https://cyberbrain.cc/2020/08/04/kak-otklyu-chit-otobrazhenie-sistemnyh-polzovatelej-na-jekrane-vhoda-v-sistemu-lightdm</id><content type="html" xml:base="https://cyberbrain.cc/2020/08/04/kak-otklyu-chit-otobrazhenie-sistemnyh-polzovatelej-na-jekrane-vhoda-v-sistemu-lightdm.html"><![CDATA[<p>If your system uses <code class="language-plaintext highlighter-rouge">AccountsService</code>, you <strong>can not</strong> hide a user from the greeter screen by reconfiguring <code class="language-plaintext highlighter-rouge">lightdm</code> because it defers to <code class="language-plaintext highlighter-rouge">AccountsService</code>. That is stated very clearly in the comments in <code class="language-plaintext highlighter-rouge">/etc/lightdm/users.conf</code>.</p>

<hr />

<p><strong>What you need to do</strong> instead is to reconfigure <code class="language-plaintext highlighter-rouge">AccountsService</code>.</p>

<p>To hide a user named <code class="language-plaintext highlighter-rouge">XXX</code>, create a file named</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/var/lib/AccountsService/users/XXX
</code></pre></div></div>

<p>containing two lines:</p>

<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[User]</span>
<span class="py">SystemAccount</span><span class="p">=</span><span class="s">true</span>
</code></pre></div></div>

<p>If the file already exists, make sure you append the <code class="language-plaintext highlighter-rouge">SystemAccount=true</code> line to the <code class="language-plaintext highlighter-rouge">[User]</code> section.</p>

<p>Via <a href="https://askubuntu.com/a/575390">https://askubuntu.com/a/575390</a></p>]]></content><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><summary type="html"><![CDATA[If your system uses AccountsService, you can not hide a user from the greeter screen by reconfiguring lightdm because it defers to AccountsService. That is stated very clearly in the comments in /etc/lightdm/users.conf.]]></summary></entry><entry><title type="html">Acer Nitro 5 (AN515-55-53TJ) disable RST</title><link href="https://cyberbrain.cc/2020/08/03/acer-nitro-5-an515-55-53tj-disable-rst.html" rel="alternate" type="text/html" title="Acer Nitro 5 (AN515-55-53TJ) disable RST" /><published>2020-08-03T10:19:59+00:00</published><updated>2020-08-03T10:19:59+00:00</updated><id>https://cyberbrain.cc/2020/08/03/acer-nitro-5-an515-55-53tj-disable-rst</id><content type="html" xml:base="https://cyberbrain.cc/2020/08/03/acer-nitro-5-an515-55-53tj-disable-rst.html"><![CDATA[<p>Для изменения режима работы с дисковой подсистемой нужно в BIOS на вкладке Main нажать Ctrl-S чтобы появилось скрытое меню.</p>

<p>Via <a href="https://community.acer.com/en/discussion/comment/845387/#Comment_845387">https://community.acer.com/en/discussion/comment/845387/#Comment_845387</a></p>]]></content><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><summary type="html"><![CDATA[Для изменения режима работы с дисковой подсистемой нужно в BIOS на вкладке Main нажать Ctrl-S чтобы появилось скрытое меню.]]></summary></entry><entry><title type="html">Замена сбойного диска в программном RAID</title><link href="https://cyberbrain.cc/2020/07/28/trashed.html" rel="alternate" type="text/html" title="Замена сбойного диска в программном RAID" /><published>2020-07-28T19:51:52+00:00</published><updated>2020-07-28T19:51:52+00:00</updated><id>https://cyberbrain.cc/2020/07/28/trashed</id><content type="html" xml:base="https://cyberbrain.cc/2020/07/28/trashed.html"><![CDATA[<p>Ситуация (для примера): с помощью mdadm собран программный RAID1(зеркало) /dev/md0 из 2-х разделов /dev/sda1 и /dev/sdb1.<br />
Задача: заменить сбойный диск /dev/sdb.</p>

<p>Прежде всего, смотрим диагностику:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> /proc/mdstat
</code></pre></div></div>

<p>или</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mdadm <span class="nt">--detail</span> /dev/md0
</code></pre></div></div>

<p>Если вместо [UU] видим [U_], то дело плохо, целостность одного из дисков нарушена — нужно менять диск.</p>

<p>Помечаем раздел как сбойный:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mdadm <span class="nt">--manage</span> /dev/md0 <span class="nt">--fail</span> /dev/sdb1
</code></pre></div></div>

<p>Отключаем раздел (удаляем из RAID1):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mdadm <span class="nt">--manage</span> /dev/md0 <span class="nt">--remove</span> /dev/sdb1
</code></pre></div></div>

<p>Выключаем машину, меняем диск.</p>

<p>Создаем через cfdisk или fdisk идентичные разделы, или c помощью sfdisk автоматически копируем структуру разделов первого диска /dev/sda:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sfdisk <span class="nt">-d</span> /dev/sda | sfdisk /dev/sdb
</code></pre></div></div>

<p>Этим способом можно пользоваться, поскольку в нашем примере «зеркальный» RAID1. При других уровнях (raid level), нужно разбить диск на раздел(ы) и пометить его(их) типом ФС «Linux raid autodetect».</p>

<p>Добавляем раздел в RAID1 массив:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mdadm <span class="nt">--manage</span> /dev/md0 <span class="nt">--add</span> /dev/sdb1
</code></pre></div></div>

<p>Ждем синхронизации массива:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>watch <span class="nb">cat</span> /proc/mdstat
</code></pre></div></div>

<hr />

<p>Ссылки:</p>

<p><a href="http://avreg.net/howto_software-raid-replacing-faulty-drive.html">http://avreg.net/howto_software-raid-replacing-faulty-drive.html</a></p>

<p><a href="http://xgu.ru/wiki/mdadm">http://xgu.ru/wiki/mdadm</a></p>]]></content><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><summary type="html"><![CDATA[Ситуация (для примера): с помощью mdadm собран программный RAID1(зеркало) /dev/md0 из 2-х разделов /dev/sda1 и /dev/sdb1. Задача: заменить сбойный диск /dev/sdb.]]></summary></entry><entry><title type="html">12 друзей Docker-а – опенсорсные инструменты в помощь разработке</title><link href="https://cyberbrain.cc/2019/06/23/12-druzej-docker-a-opensorsnye-instrumenty-v-pomosch-razrabotke.html" rel="alternate" type="text/html" title="12 друзей Docker-а – опенсорсные инструменты в помощь разработке" /><published>2019-06-23T09:55:30+00:00</published><updated>2019-06-23T09:55:30+00:00</updated><id>https://cyberbrain.cc/2019/06/23/12-druzej-docker-a-opensorsnye-instrumenty-v-pomosch-razrabotke</id><content type="html" xml:base="https://cyberbrain.cc/2019/06/23/12-druzej-docker-a-opensorsnye-instrumenty-v-pomosch-razrabotke.html"><![CDATA[<p><a href="https://proglib.io/p/12-docker-tools/">12 друзей Docker-а – опенсорсные инструменты в помощь разработке</a></p>]]></content><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><summary type="html"><![CDATA[12 друзей Docker-а – опенсорсные инструменты в помощь разработке]]></summary></entry><entry><title type="html">Сюрпризы от Erlang и Docker-compose</title><link href="https://cyberbrain.cc/2019/04/17/syurprizy-ot-erlang-i-docker-compose.html" rel="alternate" type="text/html" title="Сюрпризы от Erlang и Docker-compose" /><published>2019-04-17T07:12:34+00:00</published><updated>2019-04-17T07:12:34+00:00</updated><id>https://cyberbrain.cc/2019/04/17/syurprizy-ot-erlang-i-docker-compose</id><content type="html" xml:base="https://cyberbrain.cc/2019/04/17/syurprizy-ot-erlang-i-docker-compose.html"><![CDATA[<!-- excerpt -->

<h2 id="преамбула">Преамбула</h2>

<p>Есть такая интересная штука, как RabbitMQ. Написана на Erlang (это важно). В Docker запускается с пол-пинка, в кластер собирается тремя с половиной командами. Это если всё делать вручную по <a href="https://hub.docker.com/r/zimniy/rabbitmq">инструкции</a>. Сразу скажу, корректные FQDN серверов и контейнеров — обязательное условие работоспособности.</p>

<p>Запускаем на первом сервере первую ноду будущего кластера:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">-dit</span> <span class="nt">-h</span> docker-rabbitmq-01.domain.tld               <span class="se">\</span>
           <span class="nt">--name</span> rabbit                                       <span class="se">\</span>
           <span class="nt">-p</span> <span class="s2">"4369:4369"</span>                                      <span class="se">\</span>
           <span class="nt">-p</span> <span class="s2">"5671:5671"</span>                                      <span class="se">\</span>
           <span class="nt">-p</span> <span class="s2">"15671:15671"</span>                                    <span class="se">\</span>
           <span class="nt">-p</span> <span class="s2">"25672:25672"</span>                                    <span class="se">\</span>
           <span class="nt">-p</span> <span class="s2">"35197:35197"</span>                                    <span class="se">\</span>
           <span class="nt">-e</span> <span class="s2">"RABBITMQ_ERLANG_COOKIE=S0meL3ttersAndNumber5"</span>   <span class="se">\</span>
           <span class="nt">-v</span> rabbitmq_data:/var/lib/rabbitmq                  <span class="se">\</span>
           <span class="nt">-v</span> /opt/ssl:/opt/ssl:ro                             <span class="se">\</span>
           <span class="nt">--restart</span> unless-stopped                            <span class="se">\</span>
           zimniy/rabbitmq:latest
</code></pre></div></div>

<p>Сразу определяем политику HA (запускаем также на первом сервере):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker <span class="nb">exec </span>rabbit rabbitmqctl set_policy ha-all <span class="s2">".*"</span> <span class="s1">'{"ha-mode":"all", "ha-sync-mode": "automatic"}'</span>
</code></pre></div></div>

<p>Запускаем на втором сервере вторую ноду будущего кластера:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">-dit</span> <span class="nt">-h</span> docker-rabbitmq-02.domain.tld               <span class="se">\</span>
           <span class="nt">--name</span> rabbit                                       <span class="se">\</span>
           <span class="nt">-p</span> <span class="s2">"4369:4369"</span>                                      <span class="se">\</span>
           <span class="nt">-p</span> <span class="s2">"5671:5671"</span>                                      <span class="se">\</span>
           <span class="nt">-p</span> <span class="s2">"15671:15671"</span>                                    <span class="se">\</span>
           <span class="nt">-p</span> <span class="s2">"25672:25672"</span>                                    <span class="se">\</span>
           <span class="nt">-p</span> <span class="s2">"35197:35197"</span>                                    <span class="se">\</span>
           <span class="nt">-e</span> <span class="s2">"RABBITMQ_ERLANG_COOKIE=S0meL3ttersAndNumber5"</span>   <span class="se">\</span>
           <span class="nt">-v</span> rabbitmq_data:/var/lib/rabbitmq                  <span class="se">\</span>
           <span class="nt">-v</span> /opt/ssl:/opt/ssl:ro                             <span class="se">\</span>
           <span class="nt">--restart</span> unless-stopped                            <span class="se">\</span>
           zimniy/rabbitmq:latest
</code></pre></div></div>

<p>Со второго сервера подключаем вторую ноду к первой:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker <span class="nb">exec </span>rabbit rabbitmqctl stop_app
docker <span class="nb">exec </span>rabbit rabbitmqctl join_cluster rabbit@docker-rabbitmq-01.domain.tld
docker <span class="nb">exec </span>rabbit rabbitmqctl start_app
</code></pre></div></div>

<p>Всё, кластер собран и уже работает. Можно подключаться с учёткой guest:guest.</p>

<h2 id="фабула">Фабула</h2>

<p>Короче, теперь про то, какая гадость этот docker-compose…</p>

<p>Оказывается, у него есть два параметра: hostname и domainname.</p>

<p>И если задать только hostname как FQDN «docker-rabbitmq-01.domain.tld», то оно в контейнере обрезается до «docker-rabbitmq-01». Так что нужно обязательно задать ещё и domainname «domain.tld» иначе Erlang, на котором написан RabbitMQ, свой FQDN не определит и будет игнорировать попытки подключения.</p>

<p>В общем, используя docker-compose, нужно делать так:</p>

<div class="language-docker highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker-rabbitmq:
  image: zimniy/rabbitmq:latest
  container_name: rabbit
  hostname: docker-rabbitmq-01.domain.tld 
  domainname: domain.tld
  restart: unless-stopped
  ports:
    - "4369:4369"
    - "5671:5671"
    - "15671:15671"
    - "25672:25672"
    - "35197:35197"
  volumes:
    - "/opt/ssl:/opt/ssl:ro"
    - "rabbitmq_data:/var/lib/rabbitmq"
</code></pre></div></div>

<p>Внимание, hostname задать именно как FQDN.</p>

<p>И, для того, чтобы это выяснить, пришлось аж в исходники лезть…</p>]]></content><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Proxmox и надоедливое сообщение о подписке</title><link href="https://cyberbrain.cc/2018/06/19/proxmox-i-nadoedlivoe-soobsch-enie-o-podpiske.html" rel="alternate" type="text/html" title="Proxmox и надоедливое сообщение о подписке" /><published>2018-06-19T08:43:33+00:00</published><updated>2018-06-19T08:43:33+00:00</updated><id>https://cyberbrain.cc/2018/06/19/proxmox-i-nadoedlivoe-soobsch-enie-o-podpiske</id><content type="html" xml:base="https://cyberbrain.cc/2018/06/19/proxmox-i-nadoedlivoe-soobsch-enie-o-podpiske.html"><![CDATA[<p>Убирается двумя файлами.</p>

<p>Хук апта:<br />
<strong>root@brain:~# cat /etc/apt/apt.conf.d/99upgradehook</strong></p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>DPkg::Post-Invoke <span class="o">{</span><span class="s2">"/usr/local/sbin/pve-no-subscription-patcher"</span><span class="p">;</span><span class="o">}</span><span class="p">;</span>
</code></pre></div></div>

<p>Исполнимый скрипт:<br />
<strong>root@brain:~# cat /usr/local/sbin/pve-no-subscription-patcher</strong></p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>

<span class="nv">SFILE</span><span class="o">=</span>/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js

<span class="nb">cat</span> <span class="s2">"</span><span class="k">${</span><span class="nv">SFILE</span><span class="k">}</span><span class="s2">"</span> | <span class="nb">grep</span> <span class="nt">-qi</span> <span class="s2">"data.status !== 'Active'"</span> <span class="o">||</span> <span class="nb">exit </span>0

logger <span class="nt">-t</span> pve-no-subscription-patcher <span class="nt">-s</span> <span class="s2">"Patching Proxmox widget toolkit"</span>
<span class="nb">cp</span> <span class="nt">-f</span> <span class="s2">"</span><span class="k">${</span><span class="nv">SFILE</span><span class="k">}</span><span class="s2">"</span> <span class="s2">"/root/</span><span class="si">$(</span><span class="nb">basename</span> <span class="k">${</span><span class="nv">SFILE</span><span class="k">}</span><span class="si">)</span><span class="s2">.bak"</span>
<span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"</span><span class="k">${</span><span class="nv">SFILE</span><span class="k">}</span><span class="s2">"</span> <span class="nt">-e</span> <span class="s2">"s/data.status</span><span class="se">\ </span><span class="s2">!==</span><span class="se">\ </span><span class="s2">'Active'/false/"</span>
</code></pre></div></div>]]></content><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><summary type="html"><![CDATA[Убирается двумя файлами.]]></summary></entry><entry><title type="html">Samba AD + NTP vs Apparmor или ‘Синхронизируй это^Wвремя’</title><link href="https://cyberbrain.cc/2018/06/02/samba-ad-ntp-vs-apparmor-ili-sinhroniziruj-jeto-wvremya.html" rel="alternate" type="text/html" title="Samba AD + NTP vs Apparmor или ‘Синхронизируй это^Wвремя’" /><published>2018-06-02T10:34:34+00:00</published><updated>2018-06-02T10:34:34+00:00</updated><id>https://cyberbrain.cc/2018/06/02/samba-ad-ntp-vs-apparmor-ili-sinhroniziruj-jeto-wvremya</id><content type="html" xml:base="https://cyberbrain.cc/2018/06/02/samba-ad-ntp-vs-apparmor-ili-sinhroniziruj-jeto-wvremya.html"><![CDATA[<p>Преамбула: холивара «Apparmor vs Selinux» не будет. Ибо равноэскобарно для меня.</p>

<p>Фабула: Решил починить неработающую синхронизацию времени в домашнем домене (да, у меня дома домен). Выяснилось, что apparmor не даёт взаимодействовать ntp-серверу с samba-сервером. Быстрое раскуривание логов и гугление показало, как надо объяснить apparmor’у его неправоту — вставляем в /etc/apparmor.d/local/usr.sbin.ntpd следующие строки:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#include &lt;abstractions/dbus-strict&gt;</span>

<span class="c"># samba4 ntp signing socket</span>
/var/lib/samba/ntp_signd/socket rw,

<span class="c"># samba4 winbindd pipe</span>
/run/samba/winbindd/pipe rw,
</code></pre></div></div>

<p>Перезапускаем сервис apparmor: service apparmor restart. Если ругнулось на синтаксис и упало — значит, где-то закрались лишние пробелы или строки, убираем их. Да, между значком «#» и словом «include» пробела НЕТ, а до этой строки не должно быть пустых строк, разве что с комментариями.</p>

<p>Почему это нельзя запихать в пакеты — наверное, потому что домен на самбе можно приготовить несколькими разными способами…</p>

<hr />

<p>Вишенка на торте: если использовать встроенный в Samba DNS-сервер, то нужно откуда-то узнать, что в Ubuntu без установленного пакета dnsutils не будет работать динамическое обновление адресов…</p>]]></content><author><name>Dmitrii Safronov</name><email>zimniy@cyberbrain.cc</email></author><summary type="html"><![CDATA[Преамбула: холивара «Apparmor vs Selinux» не будет. Ибо равноэскобарно для меня.]]></summary></entry></feed>