<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ITcompressor</title>
        <link>https://itcompressor.e7.by/</link>
        <description>Статьи и заметки по инфраструктуре, Linux, сетям и LLM — сжато и по делу.</description>
        <language>ru</language>
        <lastBuildDate>Sun, 26 Jul 2026 00:00:00 GMT</lastBuildDate>
        <atom:link href="https://itcompressor.e7.by/rss.xml" rel="self" type="application/rss+xml"/>
        <item>
            <title>Рейтинг LLM — собственные бенчмарки</title>
            <link>https://itcompressor.e7.by/articles/llm/llm-rating-2026-07-19/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/llm/llm-rating-2026-07-19/</guid>
            <pubDate>Sun, 26 Jul 2026 00:00:00 GMT</pubDate>
            <description>26 генеративных и 5 embedding-моделей на собственном бенчмарк-наборе: код, перевод, суммаризация — сводная таблица, лидеры по задачам и задержки.</description>
            <category>llm</category>
            <category>benchmark</category>
            <category>ollama</category>
            <content:encoded>
&lt;p&gt;Замеры выполнены на собственном бенчмарк-наборе через &lt;strong&gt;Ollama 0.32.1&lt;/strong&gt; 19 июля 2026 года. Прогнаны 26 уникальных генеративных моделей (задачи: генерация кода, перевод, суммаризация, custom-задачи) и 5 embedding-моделей (retrieval, классификация, семантическая близость STS). Оценки &lt;code&gt;avg_score&lt;/code&gt; — в диапазоне 0–1 (больше — лучше), &lt;code&gt;avg_latency&lt;/code&gt; — средняя задержка в секундах.&lt;/p&gt;
&lt;h2 id=&quot;генеративные-модели&quot;&gt;Генеративные модели&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B3%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5-%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Сводная таблица по четырём задачам. Колонки — &lt;code&gt;avg_score&lt;/code&gt; по бенчмарку, &lt;strong&gt;Ср.скор&lt;/strong&gt; — средний балл по всем задачам, &lt;strong&gt;Ср.лат&lt;/strong&gt; — средняя задержка, сек. Сортировка — по убыванию среднего балла.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;right&quot;&gt;#&lt;/th&gt;
&lt;th&gt;Модель&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Контекст&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Код&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Перевод&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Саммари&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Custom&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Ср.скор&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Ср.лат&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gemma4:12b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.772&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.347&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.780&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2.41&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gemma4:26b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;240k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.722&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.396&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.780&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2.09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kimi-k2.7-code:cloud&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.820&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.281&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.775&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;glm-5.2:cloud&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.762&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.335&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.774&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;7.97&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;minimax-m3:cloud&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.794&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.289&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.771&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3.35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;6&lt;/td&gt;
&lt;td&gt;&lt;code&gt;deepseek-v4-flash:cloud&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.749&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.308&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.764&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2.41&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;7&lt;/td&gt;
&lt;td&gt;&lt;code&gt;deepseek-v4-pro:cloud&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.777&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.278&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.764&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3.67&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;8&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gemma4:12b-it-qat&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.714&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.336&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.762&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2.39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;9&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gemma4:26b-a4b-it-qat&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.655&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.355&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.753&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;10&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nemotron-3-ultra:cloud&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.635&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.281&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.729&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;7.04&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;11&lt;/td&gt;
&lt;td&gt;&lt;code&gt;qwen3.6:27b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;96k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.588&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.313&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.725&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3.57&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;12&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gpt-oss:20b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;128k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.633&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.246&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.720&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3.48&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;13&lt;/td&gt;
&lt;td&gt;&lt;code&gt;devstral-small-2:24b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;52k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.601&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.264&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.982&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.712&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3.81&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;14&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gemma4:e2b-it-qat&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;128k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.938&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.581&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.284&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.701&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4.35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;15&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gemma4:e4b-it-qat&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;128k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.481&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.302&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.991&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.694&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;16&lt;/td&gt;
&lt;td&gt;&lt;code&gt;glm-4.7-flash:latest&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;88k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.487&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.295&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.991&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.693&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;17&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gemma4:e2b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;128k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.950&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.522&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.285&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.689&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4.12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;18&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gemma4:e4b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;128k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.434&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.266&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.991&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.673&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4.08&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;19&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ornith:9b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.950&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.485&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.267&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.975&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.669&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3.86&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;20&lt;/td&gt;
&lt;td&gt;&lt;code&gt;laguna-xs-2.1:latest&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;80k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.950&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.483&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.242&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.669&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;21&lt;/td&gt;
&lt;td&gt;&lt;code&gt;translategemma:4b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;128k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.950&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.375&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.228&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.984&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.634&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2.03&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;22&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t-lite-it-1.0:7b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;32k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.988&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.390&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.265&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.877&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.630&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3.74&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;23&lt;/td&gt;
&lt;td&gt;&lt;code&gt;north-mini-code-1.0:latest&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;80k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.477&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.258&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.659&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.599&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3.28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;24&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lfm2.5:8b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;125k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.967&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.293&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.215&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.681&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.539&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2.51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;25&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gigachat3.1:10b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;256k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.264&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.178&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.481&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.481&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4.11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;26&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t-lite-it-2.1:8b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;40k&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.550&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.499&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.171&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.651&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.468&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5.42&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;лидеры-по-задачам-генеративные&quot;&gt;Лидеры по задачам (генеративные)&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BB%D0%B8%D0%B4%D0%B5%D1%80%D1%8B-%D0%BF%D0%BE-%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0%D0%BC-%D0%B3%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Генерация кода&lt;/strong&gt;: &lt;code&gt;deepseek-v4-flash:cloud&lt;/code&gt; (1.000) · &lt;code&gt;glm-5.2:cloud&lt;/code&gt; (1.000) · &lt;code&gt;kimi-k2.7-code:cloud&lt;/code&gt; (1.000)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Перевод&lt;/strong&gt;: &lt;code&gt;kimi-k2.7-code:cloud&lt;/code&gt; (0.820) · &lt;code&gt;minimax-m3:cloud&lt;/code&gt; (0.794) · &lt;code&gt;deepseek-v4-pro:cloud&lt;/code&gt; (0.777)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Суммаризация&lt;/strong&gt;: &lt;code&gt;gemma4:26b&lt;/code&gt; (0.396) · &lt;code&gt;gemma4:26b-a4b-it-qat&lt;/code&gt; (0.355) · &lt;code&gt;gemma4:12b&lt;/code&gt; (0.347)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom-задачи&lt;/strong&gt;: &lt;code&gt;deepseek-v4-flash:cloud&lt;/code&gt; (1.000) · &lt;code&gt;glm-5.2:cloud&lt;/code&gt; (1.000) · &lt;code&gt;kimi-k2.7-code:cloud&lt;/code&gt; (1.000)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Самые быстрые&lt;/strong&gt; (по средней задержке): &lt;code&gt;glm-4.7-flash:latest&lt;/code&gt; (1.45 с) · &lt;code&gt;gemma4:26b-a4b-it-qat&lt;/code&gt; (1.75 с) · &lt;code&gt;laguna-xs-2.1:latest&lt;/code&gt; (1.80 с)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;embedding-модели&quot;&gt;Embedding-модели&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#embedding-%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Сводная таблица по трём задачам: &lt;strong&gt;retrieval&lt;/strong&gt; (NDCG), &lt;strong&gt;классификация&lt;/strong&gt; (micro-F1), &lt;strong&gt;STS&lt;/strong&gt; (семантическая близость, Spearman). Сортировка — по убыванию среднего балла.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;right&quot;&gt;#&lt;/th&gt;
&lt;th&gt;Модель&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Retrieval&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Классификация&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;STS&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Ср.скор&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nomic-embed-text-v2-moe:latest&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.942&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.802&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.915&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;qwen3-embedding:8b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.942&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.791&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.911&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;qwen3-embedding:4b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.972&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.750&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.907&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;embeddinggemma:300m&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.972&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.726&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.899&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;qwen3-embedding:0.6b&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.972&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.000&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.666&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.880&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;лидеры-по-задачам-embedding&quot;&gt;Лидеры по задачам (embedding)&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BB%D0%B8%D0%B4%D0%B5%D1%80%D1%8B-%D0%BF%D0%BE-%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0%D0%BC-embedding&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Retrieval (NDCG)&lt;/strong&gt;: &lt;code&gt;embeddinggemma:300m&lt;/code&gt; (0.972) · &lt;code&gt;qwen3-embedding:0.6b&lt;/code&gt; (0.972) · &lt;code&gt;qwen3-embedding:4b&lt;/code&gt; (0.972)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Классификация (F1)&lt;/strong&gt;: &lt;code&gt;nomic-embed-text-v2-moe:latest&lt;/code&gt; (1.000) · &lt;code&gt;embeddinggemma:300m&lt;/code&gt; (1.000) · &lt;code&gt;qwen3-embedding:0.6b&lt;/code&gt; (1.000)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;STS (Spearman)&lt;/strong&gt;: &lt;code&gt;nomic-embed-text-v2-moe:latest&lt;/code&gt; (0.802) · &lt;code&gt;qwen3-embedding:8b&lt;/code&gt; (0.791) · &lt;code&gt;qwen3-embedding:4b&lt;/code&gt; (0.750)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;методология-и-заметки&quot;&gt;Методология и заметки&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D0%BE%D0%BB%D0%BE%D0%B3%D0%B8%D1%8F-%D0%B8-%D0%B7%D0%B0%D0%BC%D0%B5%D1%82%D0%BA%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Среда:&lt;/strong&gt; Ollama 0.32.1, замеры 2026-07-19. Модели с суффиксом &lt;code&gt;:cloud&lt;/code&gt; опрашивались по облачному endpoint, остальные — по локальным Ollama-инстансам.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Метрики:&lt;/strong&gt; для текстовых задач &lt;code&gt;avg_score&lt;/code&gt; агрегирует F1/BLEU/ROUGE/Levenshtein/code-sim; дополнительно замерена &lt;code&gt;avg_latency&lt;/code&gt; (сек). Для embedding — &lt;code&gt;avg_score&lt;/code&gt; это NDCG (retrieval), micro-F1 (классификация), Spearman (STS).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Дедупликация:&lt;/strong&gt; если модель повторялась в нескольких запусках, оставлен последний (с большим &lt;code&gt;run_id&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Контекст&lt;/strong&gt; указан в тыс. токенов (&lt;code&gt;k&lt;/code&gt;); для embedding-моделей контекст не релевантен.&lt;/li&gt;
&lt;li&gt;Сырой CSV содержит и промежуточные метрики (BLEU, ROUGE1/2/L, Levenshtein, code-sim, MSE, Pearson, cosine и т.д.) — здесь оставлены только сводные.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Актуальные сетапы моделей (glm-5.3, Qwen3.8-27B на llama.cpp и др.) — на вкладке &lt;a href=&quot;https://itcompressor.e7.by/#llm&quot;&gt;LLM&lt;/a&gt;.&lt;/p&gt;
</content:encoded>
        </item>
        <item>
            <title>Установка и настройка tuwunel через docker</title>
            <link>https://itcompressor.e7.by/articles/devops/tuwunel/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/devops/tuwunel/</guid>
            <pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate>
            <description>Установка и настройка tuwunel через docker. Без дополнительных настроек. Только базовый функционал</description>
            <category>matrix</category>
            <category>nginx</category>
            <category>devops</category>
            <content:encoded>
&lt;blockquote&gt;
&lt;p&gt;Tuwunel — это self-hosted сервер Matrix, который можно использовать вместо matrix-synapse, но написан на Rust вместо Python.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Это максимально упрощенный гайд по установке и настройке, основное:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tuwunel + element web (веб клиент) через докер&lt;/li&gt;
&lt;li&gt;с проксирование через nginx (reverse proxy на один домен)&lt;/li&gt;
&lt;li&gt;wireguard как связка домашнего сервера с внешним миром, &lt;a href=&quot;https://itcompressor.e7.by/articles/networking/wireguard/&quot;&gt;гайд по wireguard тут&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;0-переменные-которые-стоит-будет-менять-под-себя-или-оставить-если-ок&quot;&gt;0. Переменные, которые стоит будет менять под себя (или оставить если ок)&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#0-%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%B5-%D1%81%D1%82%D0%BE%D0%B8%D1%82-%D0%B1%D1%83%D0%B4%D0%B5%D1%82-%D0%BC%D0%B5%D0%BD%D1%8F%D1%82%D1%8C-%D0%BF%D0%BE%D0%B4-%D1%81%D0%B5%D0%B1%D1%8F-%D0%B8%D0%BB%D0%B8-%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%B8%D1%82%D1%8C-%D0%B5%D1%81%D0%BB%D0%B8-%D0%BE%D0%BA&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;10.0.3.197&lt;/code&gt; - это мой внутренний айпи сервера, меняете на свое, если все делается на одном сервере, то можно &lt;code&gt;127.0.0.1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;next-way.by&lt;/code&gt; - мой домен, по которому происходит доступ, меняете на свой&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/opt/matrix&lt;/code&gt; - мой путь на сервере, где распологаются все файлы для Tuwunel&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dff315b705ce&lt;/code&gt; - &lt;code&gt;CONTAINER ID&lt;/code&gt; моего инстанса &lt;code&gt;jevolk/tuwunel:main&lt;/code&gt; на домашнем сервере, у вас будет другой id&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;1-установка-и-настройка-докер&quot;&gt;1. Установка и настройка докер&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#1-%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D0%B8-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D0%B4%D0%BE%D0%BA%D0%B5%D1%80&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Если докер старой версии, то может быть сложность при скачивании контейнера (будет ошибка что-то про TAR). Чуть что если у вас старая версия docker, например 20ая, то обновите ее, гайд &lt;a href=&quot;https://itcompressor.e7.by/articles/devops/installation_docker/&quot;&gt;тут&lt;/a&gt; или офф &lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/&quot;&gt;https://docs.docker.com/engine/install/ubuntu/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;2-поднимаем-tuwunel-element-web&quot;&gt;2. Поднимаем tuwunel + element web&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#2-%D0%BF%D0%BE%D0%B4%D0%BD%D0%B8%D0%BC%D0%B0%D0%B5%D0%BC-tuwunel-element-web&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Создаем файл для docker-compose, например как &lt;code&gt;tuwunel.yaml&lt;/code&gt; в папке &lt;code&gt;/opt/matrix&lt;/code&gt;. Чтобы не было проблем, сразу поработаем с правами на папку (поменяем владельца на текущего пользователя) командой:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo chown -R $USER:$USER /opt/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Далее создаем файл &lt;code&gt;nano /opt/matrix/tuwunel.yaml&lt;/code&gt; где необходимо только поменять &lt;code&gt;TUWUNEL_SERVER_NAME&lt;/code&gt; и &lt;code&gt;TUWUNEL_REGISTRATION_TOKEN&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;services:

  homeserver:
    ### If you already built the tuwunel image with &#39;docker build&#39; or want to use a registry image,
    ### then you are ready to go.
    image: jevolk/tuwunel:main
    restart: unless-stopped
    ports:
      - 8008:6167
    volumes:
      - /opt/matrix/tuwunel:/var/lib/tuwunel
      #- ./tuwunel.toml:/etc/tuwunel.toml
    environment:
      TUWUNEL_SERVER_NAME: next-way.by # EDIT THIS
      TUWUNEL_DATABASE_PATH: /var/lib/tuwunel
      TUWUNEL_PORT: 6167
      TUWUNEL_MAX_REQUEST_SIZE: 20000000 # in bytes, ~20 MB
      TUWUNEL_ALLOW_REGISTRATION: &#39;true&#39;
      TUWUNEL_REGISTRATION_TOKEN: &#39;change-it&#39; # A registration token is required when registration is allowed.
      #TUWUNEL_YES_I_AM_VERY_VERY_SURE_I_WANT_AN_OPEN_REGISTRATION_SERVER_PRONE_TO_ABUSE: &#39;true&#39;
      TUWUNEL_ALLOW_FEDERATION: &#39;true&#39;
      TUWUNEL_TRUSTED_SERVERS: &#39;[&quot;matrix.org&quot;]&#39;
      #TUWUNEL_LOG: warn,state_res=warn
      TUWUNEL_ADDRESS: 0.0.0.0
      #TUWUNEL_CONFIG: &#39;/etc/tuwunel.toml&#39; # Uncomment if you mapped config toml above


  element-web:
    image: vectorim/element-web:latest
    restart: unless-stopped
    ports:
      - 8009:80
    volumes:
      - /opt/matrix/element_config.json:/app/config.json
    depends_on:
      - homeserver
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;21-настройка-element-web&quot;&gt;2.1. Настройка &lt;code&gt;element-web&lt;/code&gt;&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#21-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-element-web&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Чтобы &lt;strong&gt;element-web&lt;/strong&gt; заработал для него необходимо создать конфиг &lt;code&gt;nano /opt/matrix/element_config.json&lt;/code&gt;, где необходимо поменять для себя значения в &lt;code&gt;m.homeserver&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;default_server_config&quot;: {
    &quot;m.homeserver&quot;: {
      &quot;base_url&quot;: &quot;https://next-way.by&quot;,
      &quot;server_name&quot;: &quot;next-way.by&quot;
    },
    &quot;m.identity_server&quot;: {
      &quot;base_url&quot;: &quot;https://vector.im&quot;
    }
  },
  &quot;disable_custom_urls&quot;: false,
  &quot;disable_guests&quot;: false,
  &quot;disable_login_language_selector&quot;: false,
  &quot;disable_3pid_login&quot;: false,
  &quot;force_verification&quot;: false,
  &quot;brand&quot;: &quot;Element&quot;,
  &quot;integrations_ui_url&quot;: &quot;https://scalar.vector.im/&quot;,
  &quot;integrations_rest_url&quot;: &quot;https://scalar.vector.im/api&quot;,
  &quot;integrations_widgets_urls&quot;: [
    &quot;https://scalar.vector.im/_matrix/integrations/v1&quot;,
    &quot;https://scalar.vector.im/api&quot;,
    &quot;https://scalar-staging.vector.im/_matrix/integrations/v1&quot;,
    &quot;https://scalar-staging.vector.im/api&quot;
  ],
  &quot;default_widget_container_height&quot;: 280,
  &quot;default_country_code&quot;: &quot;GB&quot;,
  &quot;show_labs_settings&quot;: false,
  &quot;features&quot;: {},
  &quot;default_federate&quot;: true,
  &quot;default_theme&quot;: &quot;light&quot;,
  &quot;room_directory&quot;: {
    &quot;servers&quot;: [
      &quot;matrix.org&quot;
    ]
  },
  &quot;enable_presence_by_hs_url&quot;: {
    &quot;https://matrix.org&quot;: false,
    &quot;https://matrix-client.matrix.org&quot;: false
  },
  &quot;setting_defaults&quot;: {
    &quot;breadcrumbs&quot;: true
  },
  &quot;jitsi&quot;: {
    &quot;preferred_domain&quot;: &quot;meet.element.io&quot;
  },
  &quot;element_call&quot;: {
    &quot;url&quot;: &quot;https://call.element.io&quot;,
    &quot;brand&quot;: &quot;Element Call&quot;
  },
  &quot;map_style_url&quot;: &quot;https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;22-сам-запуск&quot;&gt;2.2. Сам запуск&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#22-%D1%81%D0%B0%D0%BC-%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D0%BA&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker compose -f tuwunel.yaml up -d

# -f - указывает на файл
# up -d - запускает в бекграунде
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Можем с помощью &lt;code&gt;docker ps&lt;/code&gt; проверить что все запустилось без ошибок&lt;/p&gt;
&lt;h2 id=&quot;3-настройка-nginx&quot;&gt;3. Настройка nginx&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#3-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-nginx&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Необходимо также завести VPS и создать &lt;code&gt;A&lt;/code&gt; запись на домен, но это уже выходит за пределы гайда, все действия по настройке nginx происходят на VPS с внешним айпишником и на котором уже установлен &lt;code&gt;wireguard&lt;/code&gt; для связи VPS + домашний сервер&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Первым делом сгенерируем сертификаты для &lt;code&gt;Let&#39;s Encrypt&lt;/code&gt; с помощью &lt;code&gt;cerbot&lt;/code&gt; (Установку cerbot найдете тут &lt;a href=&quot;https://certbot.eff.org/instructions/&quot;&gt;https://certbot.eff.org/instructions/&lt;/a&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;certbot --nginx -d next-way.by
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;После чего нужно будет удалить лишнее, что добавил cerbot, единственное запомните пути к публичному и приватному ключу, мало ли cerbot будет распологать эти ключи в каком-то другом месте чем у меня по гайду.&lt;/p&gt;
&lt;p&gt;Создадим конфиг для проксирования на Tuwunel и element web &lt;code&gt;nano /etc/nginx/sites-enabled/next-way.by&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;upstream tuwunel {
  server 10.0.3.197:8008; # IP and port where tuwunel is listening
}

server {
  # Client-Server API over HTTPS (port 443)
  listen 443 ssl;
  listen [::]:443 ssl;
  # Matrix Federation over HTTPS (port 8448)
  # Only needed if you want to federate with other homeservers
  # Don&#39;t forget to open port 8448 in your firewall!
  listen 8448 ssl;
  listen [::]:8448 ssl;
#  http2 on;
  server_name next-way.by;

  # Nginx standard body size is 1MB, which is quite small for media uploads
  # Increase this to match the max_request_size in your tuwunel.toml
  client_max_body_size 100M;
  location / {
    proxy_pass http://10.0.3.197:8009;

    # Preserve host and scheme - critical for proper Matrix operation
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto https;
  }

  # Forward requests to Tuwunel
  location ~ ^(/_matrix|/_synapse/client|/_synapse/admin|/_synapse/mas) {
    proxy_pass http://10.0.3.197:8008;

    # Preserve host and scheme - critical for proper Matrix operation
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto https;
  }

  # TLS configuration (Let&#39;s Encrypt example using certbot)
  ssl_certificate /etc/letsencrypt/live/next-way.by/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/next-way.by/privkey.pem; # managed by Certbot
}

server {
    if ($host = next-way.by) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80 ;
    listen [::]:80 ;
    server_name next-way.by;
    return 404; # managed by Certbot
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;У меня конфиг не отрабатывал с &lt;code&gt;http2 on;&lt;/code&gt;, но у вас возможно все заведется, моя проблема скорее всего в том что я менял глобальные настройки ранее. Правило для &lt;code&gt;element web&lt;/code&gt; взял из &lt;a href=&quot;https://habr.com/ru/articles/1028012/&quot;&gt;https://habr.com/ru/articles/1028012/&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Проверяем конфиг командой&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nginx -t
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;и если все хорошо, то применяем командой&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;service nginx reload
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Если все хорошо, то при открытии своего домена вы увидите &lt;code&gt;element-web&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;4-заведение-пользователя&quot;&gt;4. Заведение пользователя&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#4-%D0%B7%D0%B0%D0%B2%D0%B5%D0%B4%D0%B5%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&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Т.к. мы запустили &lt;code&gt;Tuwunel&lt;/code&gt; в docker, то прямого доступа к cli у нас нет и для этого необходимо запускать cli из под докер контейнера. Для этого на домашнем сервере выполняем &lt;code&gt;docker ps&lt;/code&gt; чтобы узнать &lt;code&gt;CONTAINER ID&lt;/code&gt; для &lt;code&gt;jevolk/tuwunel:main&lt;/code&gt; и создаем юзера с админ правами:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# проверяем что доступ к cli есть
docker exec -it dff315b705ce tuwunel -h

# создаем юзера
docker exec -it dff315b705ce tuwunel --execute &quot;users create_user your_user_name&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;После чего вам в ответе придет логин и пароль. Лично у меня были в последующем проблемы с логином, но все это починилось простой перезагрузкой контейнера &lt;code&gt;docker restart dff315b705ce&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;послесловие&quot;&gt;Послесловие&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D0%B5&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Клиент я использую FluffyChat &lt;a href=&quot;https://matrix.org/ecosystem/clients/fluffychat/&quot;&gt;https://matrix.org/ecosystem/clients/fluffychat/&lt;/a&gt;, он немного неудобный, но зато поддерживает &lt;strong&gt;Multi Account&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;После логина вы попадете в комнату (чат) где также будет находиться бот &lt;code&gt;@conduit:next-way.by&lt;/code&gt; (у вас будет с вашим доменом), который может выполнять команды cli через команды в чат. Для получения справки можете написать в чате:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;!admin --help&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded>
        </item>
        <item>
            <title>Работа с архивами через консоль</title>
            <link>https://itcompressor.e7.by/articles/linux/archives/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/linux/archives/</guid>
            <pubDate>Sun, 30 Jun 2024 00:00:00 GMT</pubDate>
            <description>Основные команды для работы с архивами: ZIP, RAR, TAR, GZ, XZ и 7z</description>
            <category>archives</category>
            <category>compression</category>
            <category>linux</category>
            <content:encoded>&lt;p&gt;Форматы делятся на три группы: &lt;strong&gt;контейнеры&lt;/strong&gt; (&lt;code&gt;tar&lt;/code&gt;) — только собирают файлы
вместе, &lt;strong&gt;сжиматели&lt;/strong&gt; (&lt;code&gt;gzip&lt;/code&gt;, &lt;code&gt;bzip2&lt;/code&gt;, &lt;code&gt;xz&lt;/code&gt;) — сжимают один файл, &lt;strong&gt;архиваторы&lt;/strong&gt;
(&lt;code&gt;zip&lt;/code&gt;, &lt;code&gt;rar&lt;/code&gt;, &lt;code&gt;7z&lt;/code&gt;) — сами и собирают, и сжимают.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Формат&lt;/th&gt;
&lt;th&gt;Расширение&lt;/th&gt;
&lt;th&gt;Пакет&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;ZIP&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.zip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;zip&lt;/code&gt;, &lt;code&gt;unzip&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAR&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.rar&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rar&lt;/code&gt;, &lt;code&gt;unrar&lt;/code&gt; (non-free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TAR&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.tar&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;предустановлен&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GZIP&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.gz&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;предустановлен&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BZIP2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.bz2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;предустановлен&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XZ&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.xz&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;предустановлен&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7Z&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.7z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;p7zip-full&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Все примеры дальше — вокруг одного каталога:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;project/
├── app.py
└── data/
    └── customers.csv
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;zip-архивы&quot;&gt;ZIP архивы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#zip-%D0%B0%D1%80%D1%85%D0%B8%D0%B2%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Нужны пакеты &lt;code&gt;zip&lt;/code&gt; и &lt;code&gt;unzip&lt;/code&gt; (в Debian-подобных: &lt;code&gt;apt install zip unzip&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Создать архив каталога целиком
zip -r project.zip project/

# Добавить файл в уже собранный архив
zip project.zip notes.txt

# Распаковать в текущий каталог
unzip project.zip

# Распаковать в конкретный каталог
unzip project.zip -d ~/restore
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Посмотреть содержимое, не распаковывая
unzip -l project.zip

# Создать с паролем (спросит интерактивно)
zip -e -r project.zip project/

# Распаковать защищённый архив — пароль спросит здесь
unzip project.zip
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Внутри ZIP сжимает каждый файл по отдельности — удобно точечно
добавлять/забирать файлы, но на каталоге целиком ZIP проигрывает
&lt;code&gt;tar.gz&lt;/code&gt; и &lt;code&gt;7z&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;rar-архивы&quot;&gt;RAR архивы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#rar-%D0%B0%D1%80%D1%85%D0%B8%D0%B2%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Проприетарный формат: для &lt;strong&gt;создания&lt;/strong&gt; нужен пакет &lt;code&gt;rar&lt;/code&gt;, для распаковки
хватает бесплатного &lt;code&gt;unrar&lt;/code&gt; (в Debian-подобных оба лежат в non-free).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Создать архив каталога (a = add)
rar a project.rar project/

# С паролем (спросит интерактивно)
rar a -p project.rar project/

# Многотомный архив по 100 МБ каждый
rar a -v100m project.rar project/
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Распаковать с сохранением структуры каталогов
unrar x project.rar

# Ссыпать всё содержимое в текущую папку, пути отбрасываются
unrar e project.rar
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Команды &lt;code&gt;rar&lt;/code&gt; и &lt;code&gt;unrar&lt;/code&gt; симметричны: &lt;code&gt;rar x project.rar&lt;/code&gt; и
&lt;code&gt;rar e project.rar&lt;/code&gt; работают так же. Разница &lt;code&gt;x&lt;/code&gt;/&lt;code&gt;e&lt;/code&gt; — только в
сохранении путей.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;tar-контейнеры&quot;&gt;TAR контейнеры&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#tar-%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%B9%D0%BD%D0%B5%D1%80%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;tar&lt;/code&gt; сам не сжимает — склеивает файлы в один поток. Сжатие включается
фильтром-флагом: &lt;code&gt;z&lt;/code&gt; — gzip, &lt;code&gt;j&lt;/code&gt; — bzip2, &lt;code&gt;J&lt;/code&gt; — xz.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Флаг&lt;/th&gt;
&lt;th&gt;Что делает&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;создать архив&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;x&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;извлечь&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;показать содержимое&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;фильтр gzip (&lt;code&gt;.tar.gz&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;j&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;фильтр bzip2 (&lt;code&gt;.tar.bz2&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;J&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;фильтр xz (&lt;code&gt;.tar.xz&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;подробный вывод&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;дальше — имя файла архива&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-C&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;сменить каталог&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Создать сжатый архив каталога (gzip)
tar -czf project.tar.gz project/

# То же с xz: сжатие сильнее, процесс медленнее
tar -cJf project.tar.xz project/

# Посмотреть содержимое, не распаковывая
tar -tzf project.tar.gz

# Распаковать в текущий каталог
tar -xzf project.tar.gz

# Распаковать в конкретный каталог
tar -xzf project.tar.gz -C ~/restore
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;GNU tar угадывает фильтр по расширению: &lt;code&gt;tar -xf project.tar.xz&lt;/code&gt;
сработает так же, как &lt;code&gt;-xzf&lt;/code&gt;/&lt;code&gt;-xjf&lt;/code&gt;. Старый синтаксис без дефиса
(&lt;code&gt;tar zxvf …&lt;/code&gt;) ещё работает, но современный GNU-стиль — с дефисом.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;gz-архивы&quot;&gt;GZ архивы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#gz-%D0%B0%D1%80%D1%85%D0%B8%D0%B2%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;gzip&lt;/code&gt; сжимает &lt;strong&gt;один файл&lt;/strong&gt;: &lt;code&gt;app-2026-06-30.log&lt;/code&gt; превращается в
&lt;code&gt;app-2026-06-30.log.gz&lt;/code&gt;, оригинал по умолчанию удаляется.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Сжать лог (оригинал удалится)
gzip app-2026-06-30.log

# Сжать, оставив оригинал (-k = keep)
gzip -k app-2026-06-30.log

# Максимальное сжатие (1..9, по умолчанию 6)
gzip -9 app-2026-06-30.log

# Распаковать (= gzip -d)
gunzip app-2026-06-30.log.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Сжатые логи читаются и grep-аются на лету, без распаковки:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;zcat app-2026-06-30.log.gz          # вывести в stdout
zless app-2026-06-30.log.gz         # постранично
zgrep ERROR app-2026-06-30.log.gz   # поиск по сжатому
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Каталог так не сжать — сначала соберите его в tar:
&lt;code&gt;tar -czf project.tar.gz project/&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;xz-архивы&quot;&gt;XZ архивы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#xz-%D0%B0%D1%80%D1%85%D0%B8%D0%B2%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Работает как gzip, но сжимает сильнее и медленнее — стандарт для образов
дистрибутивов и пакетов.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Сжать образ
xz raspi-lite.img

# Сжать, оставив оригинал
xz -k raspi-lite.img

# Максимальная степень (0..9; 9e — с агрессивной памятью под словарь)
xz -9e raspi-lite.img

# Распаковать (= xz -d)
unxz raspi-lite.img.xz
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;.tar.xz&lt;/code&gt; распаковывается как и любой tar-архив:
&lt;code&gt;tar -xJf project.tar.xz&lt;/code&gt; или универсально &lt;code&gt;tar -xf project.tar.xz&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;7z-архивы&quot;&gt;7z архивы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#7z-%D0%B0%D1%80%D1%85%D0%B8%D0%B2%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Формат с наилучшим сжатием и поддержкой чужих форматов. Нужен пакет
&lt;code&gt;p7zip-full&lt;/code&gt; (в Debian-подобных: &lt;code&gt;apt install p7zip-full&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Создать архив каталога
7z a project.7z project/

# Посмотреть содержимое
7z l project.7z

# Распаковать в текущий каталог
7z x project.7z

# Распаковать в конкретный каталог (путь сразу за -o, без пробела)
7z x project.7z -o$HOME/restore

# С паролем (спросит интерактивно)
7z a -p project.7z project/
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;7z x&lt;/code&gt; вскрывает и чужие форматы: тот же вызов распакует &lt;code&gt;project.zip&lt;/code&gt;,
&lt;code&gt;project.tar.gz&lt;/code&gt; или &lt;code&gt;project.rar&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Полезная связка — конвейер 7z + tar для распаковки на лету:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;7z x -so project.tar.7z | tar xf - -C ~/restore
&lt;/code&gt;&lt;/pre&gt;
</content:encoded>
        </item>
        <item>
            <title>Systemd</title>
            <link>https://itcompressor.e7.by/articles/linux/systemd/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/linux/systemd/</guid>
            <pubDate>Sat, 15 Jul 2023 00:00:00 GMT</pubDate>
            <description>Микрогайд по systemd: основные команды и настройка</description>
            <category>systemd</category>
            <category>services</category>
            <category>linux</category>
            <content:encoded>&lt;p&gt;systemd — система инициализации и управления службами в Linux, потеснившая в
2010-е годы традиционный init. Главная особенность — параллельный запуск служб
при загрузке, за счёт чего система стартует заметно быстрее.&lt;/p&gt;
&lt;p&gt;Все примеры дальше крутятся вокруг одной службы &lt;code&gt;myapp&lt;/code&gt; — как сделать
собственную, показано в разделе «Создание службы».&lt;/p&gt;
&lt;h2 id=&quot;основные-понятия&quot;&gt;Основные понятия&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5-%D0%BF%D0%BE%D0%BD%D1%8F%D1%82%D0%B8%D1%8F&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Юнит&lt;/strong&gt; — базовая единица управления systemd: конфигурационный файл,
описывающий ресурс (службу, сокет, устройство, точку монтирования)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Служба&lt;/strong&gt; — тип юнита для демонов и процессов (&lt;code&gt;*.service&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Таргет&lt;/strong&gt; — группа юнитов, активируемых вместе; наследник runlevel
традиционного init&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cgroup (контрольная группа)&lt;/strong&gt; — механизм ядра: группирует процессы для
учёта и ограничения ресурсов; systemd через cgroup отслеживает процессы
каждой службы&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Соответствие runlevel и таргетов:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Runlevel&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;Что это&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;poweroff.target&lt;/td&gt;
&lt;td&gt;выключение&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;rescue.target&lt;/td&gt;
&lt;td&gt;однопользовательский режим (восстановление)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;multi-user.target&lt;/td&gt;
&lt;td&gt;многопользовательский без графики (серверы)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;graphical.target&lt;/td&gt;
&lt;td&gt;многопользовательский с графикой&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;reboot.target&lt;/td&gt;
&lt;td&gt;перезагрузка&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;управление-службой&quot;&gt;Управление службой&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%BB%D1%83%D0%B6%D0%B1%D0%BE%D0%B9&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Запустить
systemctl start myapp

# Остановить
systemctl stop myapp

# Перезапустить (stop + start)
systemctl restart myapp

# Перечитать конфиг службы без перезапуска
systemctl reload myapp

# Проверить статус: состояние, дерево процессов, свежие строки лога
systemctl status myapp
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Суффикс &lt;code&gt;.service&lt;/code&gt; необязателен: &lt;code&gt;systemctl start myapp&lt;/code&gt; и
&lt;code&gt;systemctl start myapp.service&lt;/code&gt; — одно и то же. По статье пишем без него.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;автозагрузка&quot;&gt;Автозагрузка&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B0%D0%B2%D1%82%D0%BE%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Включить автозапуск и запустить службу сразу
systemctl enable --now myapp

# Включить только автозапуск
systemctl enable myapp

# Убрать из автозагрузки
systemctl disable myapp

# Запретить совсем (замаскировать: не запустится даже вручную)
systemctl mask myapp

# Вернуть обратно
systemctl unmask myapp
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;enable&lt;/code&gt; сам службу не запускает — она стартует при следующей загрузке.
Чтобы включить автозапуск и сразу поднять службу — &lt;code&gt;enable --now&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;создание-службы&quot;&gt;Создание службы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81%D0%BB%D1%83%D0%B6%D0%B1%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Файл юнита кладётся в &lt;code&gt;/etc/systemd/system/&lt;/code&gt; — здесь это &lt;code&gt;myapp.service&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;[Unit]
Description=My Application
After=network.target

[Service]
Type=simple
User=myuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/myapp
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Выбор &lt;code&gt;Type=&lt;/code&gt; под поведение процесса:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Когда использовать&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;simple&lt;/td&gt;
&lt;td&gt;процесс работает на переднем плане и не демонизируется сам (по умолчанию)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;forking&lt;/td&gt;
&lt;td&gt;процесс сам уходит в фон в стиле классических Unix-демонов&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;oneshot&lt;/td&gt;
&lt;td&gt;разовая задача: отработала и завершилась&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;notify&lt;/td&gt;
&lt;td&gt;как simple, но процесс сам сообщает о готовности через &lt;code&gt;sd_notify&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;code&gt;Restart=on-failure&lt;/code&gt; перезапускает службу только при падении; &lt;code&gt;always&lt;/code&gt; — и
после штатного завершения тоже.&lt;/p&gt;
&lt;p&gt;Принимаем юнит в работу:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Перечитать юниты после изменения файлов
sudo systemctl daemon-reload

# Включить автозагрузку и запустить
sudo systemctl enable --now myapp
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;работа-с-таргетами&quot;&gt;Работа с таргетами&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-%D1%82%D0%B0%D1%80%D0%B3%D0%B5%D1%82%D0%B0%D0%BC%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Список доступных таргетов
systemctl list-units --type=target

# Дерево зависимостей таргета
systemctl list-dependencies graphical.target

# Переключить текущую сессию на режим без графики
sudo systemctl isolate multi-user.target
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;isolate&lt;/code&gt; гасит всё, чего нет в целевом таргете и его зависимостях —
включая запущенные графические приложения при уходе из
&lt;code&gt;graphical.target&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Дефолтный таргет для будущих загрузок:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Какой таргет будет активирован при загрузке
systemctl get-default

# Сделать графический режим дефолтом
sudo systemctl set-default graphical.target
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;перезагрузка-и-выключение&quot;&gt;Перезагрузка и выключение&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%B5%D1%80%D0%B5%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B0-%D0%B8-%D0%B2%D1%8B%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Перезагрузить систему
systemctl reboot

# Выключить
systemctl poweroff
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Обе команды — тонкие обёртки над соответствующими таргетами
(&lt;code&gt;reboot.target&lt;/code&gt;, &lt;code&gt;poweroff.target&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id=&quot;логи-службы-journalctl&quot;&gt;Логи службы (journalctl)&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BB%D0%BE%D0%B3%D0%B8-%D1%81%D0%BB%D1%83%D0%B6%D0%B1%D1%8B-journalctl&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Все логи службы
journalctl -u myapp

# С последней загрузки системы
journalctl -u myapp -b

# Последние 100 строк, без пейджера
journalctl -u myapp -n 100 --no-pager

# В реальном времени
journalctl -u myapp -f

# За интервал времени
journalctl -u myapp --since &quot;2026-06-30 10:00&quot; --until &quot;2026-06-30 12:00&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Для уже установленных служб удобно смотреть их юнит с учётом дроп-инов:
&lt;code&gt;systemctl cat myapp&lt;/code&gt;, а править — &lt;code&gt;sudo systemctl edit myapp&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded>
        </item>
        <item>
            <title>MongoDB</title>
            <link>https://itcompressor.e7.by/articles/database/mongo/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/database/mongo/</guid>
            <pubDate>Sat, 01 Jul 2023 00:00:00 GMT</pubDate>
            <description>MongoDB: установка, CRUD-запросы (выборки, обновления, удаления) и настройка реплика-сета</description>
            <category>mongodb</category>
            <category>database</category>
            <category>nosql</category>
            <content:encoded>&lt;p&gt;MongoDB — документоориентированная СУБД: данные хранятся не в таблицах, а в
коллекциях JSON-подобных документов (BSON). Гибкая схема, богатый язык запросов
и встроенная репликация.&lt;/p&gt;
&lt;h2 id=&quot;установка&quot;&gt;Установка&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Официальный репозиторий для Ubuntu 22.04 (MongoDB 7.0):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Ключ подписи репозитория (apt-key устарел — кладём ключ в keyring)
sudo apt install gnupg curl
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
  sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor

# Репозиторий
echo &quot;deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse&quot; | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list

# Установка и запуск
sudo apt update
sudo apt install -y mongodb-org
sudo systemctl enable --now mongod
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Подключение к шеллу (в современных версиях это &lt;code&gt;mongosh&lt;/code&gt;, legacy-клиент
&lt;code&gt;mongo&lt;/code&gt; удалён):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mongosh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Всё ниже — команды шелла (JavaScript). Демонстрируем на коллекции
&lt;code&gt;customers&lt;/code&gt; с документами вида &lt;code&gt;{ name, email, city, age, status }&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;вставка&quot;&gt;Вставка&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B2%D1%81%D1%82%D0%B0%D0%B2%D0%BA%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Один документ
db.customers.insertOne({
  name: &quot;Olga Smirnova&quot;,
  email: &quot;olga@example.com&quot;,
  city: &quot;Minsk&quot;,
  age: 29,
  status: &quot;active&quot;
})

// Массив документов — вставка пачкой
db.customers.insertMany([
  { name: &quot;Ivan Petrov&quot;,  email: &quot;ivan@example.com&quot;, city: &quot;Gomel&quot;, age: 34, status: &quot;inactive&quot; },
  { name: &quot;Anna Koval&quot;,   email: &quot;anna@example.com&quot;, city: &quot;Minsk&quot;, age: 41, status: &quot;active&quot; },
  { name: &quot;Maksim Lee&quot;,   email: &quot;maks@example.com&quot;, city: &quot;Brest&quot;, age: 23, status: &quot;active&quot; }
])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Коллекция создаётся автоматически при первой вставке; у документа без явного
&lt;code&gt;_id&lt;/code&gt; MongoDB сгенерирует его сама.&lt;/p&gt;
&lt;h2 id=&quot;выборки&quot;&gt;Выборки&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B2%D1%8B%D0%B1%D0%BE%D1%80%D0%BA%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;простые&quot;&gt;Простые&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D1%80%D0%BE%D1%81%D1%82%D1%8B%D0%B5&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Все документы коллекции
db.customers.find()

// Один документ, совпавший первым
db.customers.findOne({ name: &quot;Anna Koval&quot; })

// По точному значению поля
db.customers.find({ city: &quot;Minsk&quot; })
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;операторы-сравнения&quot;&gt;Операторы сравнения&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B-%D1%81%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Возраст больше 25
db.customers.find({ age: { $gt: 25 } })

// Комбинированный диапазон: 25 &amp;lt;= age &amp;lt;= 40
db.customers.find({ age: { $gte: 25, $lte: 40 } })

// Вхождение в набор значений
db.customers.find({ city: { $in: [&quot;Minsk&quot;, &quot;Brest&quot;] } })

// Поле существует / отсутствует
db.customers.find({ phone: { $exists: true } })

// Подстрока в начале поля (регулярное выражение)
db.customers.find({ name: { $regex: &quot;^A&quot; } })
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Основные операторы сравнения: &lt;code&gt;$eq&lt;/code&gt;, &lt;code&gt;$ne&lt;/code&gt;, &lt;code&gt;$gt&lt;/code&gt;, &lt;code&gt;$gte&lt;/code&gt;, &lt;code&gt;$lt&lt;/code&gt;, &lt;code&gt;$lte&lt;/code&gt;,
&lt;code&gt;$in&lt;/code&gt;, &lt;code&gt;$nin&lt;/code&gt;, &lt;code&gt;$exists&lt;/code&gt;, &lt;code&gt;$regex&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;логические-операторы&quot;&gt;Логические операторы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BB%D0%BE%D0%B3%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5-%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// И: оба условия одновременно
db.customers.find({
  age: { $gte: 25 },
  status: &quot;active&quot;
})

// Явная форма с $and (нужна, когда условие на одно поле сложное)
db.customers.find({
  $and: [
    { age: { $gte: 25 } },
    { age: { $lte: 40 } }
  ]
})

// ИЛИ: хотя бы одно из условий
db.customers.find({
  $or: [
    { city: &quot;Minsk&quot; },
    { age: { $gte: 35 } }
  ]
})

// Отрицание набора условий
db.customers.find({ $nor: [ { status: &quot;inactive&quot; }, { age: { $lt: 25 } } ] })
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;проекции-сортировка-и-пагинация&quot;&gt;Проекции, сортировка и пагинация&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%86%D0%B8%D0%B8-%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0-%D0%B8-%D0%BF%D0%B0%D0%B3%D0%B8%D0%BD%D0%B0%D1%86%D0%B8%D1%8F&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Только name и email (без _id) у активных клиентов
db.customers.find(
  { status: &quot;active&quot; },
  { name: 1, email: 1, _id: 0 }
)

// Свежие первыми, 10 документов, третья страница
db.customers.find()
  .sort({ age: -1 })
  .limit(10)
  .skip(20)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;агрегации&quot;&gt;Агрегации&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B0%D0%B3%D1%80%D0%B5%D0%B3%D0%B0%D1%86%D0%B8%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Конвейер документов: каждый этап (&lt;code&gt;$match&lt;/code&gt;, &lt;code&gt;$group&lt;/code&gt;, &lt;code&gt;$sort&lt;/code&gt;, …) обрабатывает
поток и передаёт результат следующему.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Группировка по городу: количество и средний возраст
db.customers.aggregate([
  { $match: { status: &quot;active&quot; } },
  { $group: { _id: &quot;$city&quot;, count: { $sum: 1 }, avgAge: { $avg: &quot;$age&quot; } } },
  { $sort: { count: -1 } },
  { $limit: 5 }
])
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;обновления&quot;&gt;Обновления&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BE%D0%B1%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Обновить один документ: заменить поля через $set
db.customers.updateOne(
  { name: &quot;Ivan Petrov&quot; },
  { $set: { status: &quot;active&quot; } }
)

// Обновить все документы под фильтр
db.customers.updateMany(
  { status: &quot;inactive&quot; },
  { $set: { city: &quot;unknown&quot; } }
)

// Инкремент счётчика
db.customers.updateOne(
  { name: &quot;Anna Koval&quot; },
  { $inc: { logins: 1 } }
)

// Добавить элемент в массив
db.customers.updateOne(
  { name: &quot;Anna Koval&quot; },
  { $push: { tags: &quot;vip&quot; } }
)

// Удалить поле целиком
db.customers.updateOne(
  { name: &quot;Anna Koval&quot; },
  { $unset: { phone: &quot;&quot; } }
)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Без &lt;code&gt;$set&lt;/code&gt; и других операторов &lt;code&gt;updateOne({ … }, { age: 30 })&lt;/code&gt; &lt;strong&gt;заменит&lt;/strong&gt;
весь документ на новый. Всегда указывайте оператор.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Довольно частый паттерн — апsert: обновить, а если документа нет, вставить
(пригоден для инкрементальных синхронизаций):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;db.customers.updateOne(
  { email: &quot;new@example.com&quot; },
  { $set: { name: &quot;New User&quot;, status: &quot;active&quot; } },
  { upsert: true }
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;удаления&quot;&gt;Удаления&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Один документ (первый совпавший)
db.customers.deleteOne({ email: &quot;maks@example.com&quot; })

// Все документы под фильтр
db.customers.deleteMany({ status: &quot;inactive&quot; })

// Удалить коллекцию вместе с индексами
db.customers.drop()
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;deleteMany({})&lt;/code&gt; чистит документы, &lt;code&gt;drop()&lt;/code&gt; — коллекцию целиком
(включая индексы). Для «зачистки таблицы» быстрее именно &lt;code&gt;drop()&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;реплика-сет&quot;&gt;Реплика-сет&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%80%D0%B5%D0%BF%D0%BB%D0%B8%D0%BA%D0%B0-%D1%81%D0%B5%D1%82&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Репликация держит копии данных на нескольких узлах: записи принимает один
PRIMARY, остальные синхронизируются с ним по oplog. При падении PRIMARY
участники выбирают нового — кластер продолжает работать.&lt;/p&gt;
&lt;h3 id=&quot;конфигурация-узлов&quot;&gt;Конфигурация узлов&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D1%83%D0%B7%D0%BB%D0%BE%D0%B2&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Одинаковый &lt;code&gt;replSetName&lt;/code&gt; в &lt;code&gt;/etc/mongod.conf&lt;/code&gt; на каждом узле. Обратите
внимание: &lt;code&gt;bindIp&lt;/code&gt; и &lt;code&gt;port&lt;/code&gt; живут в секции &lt;code&gt;net&lt;/code&gt;, а не в &lt;code&gt;replication&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;# /etc/mongod.conf
net:
  bindIp: 0.0.0.0
  port: 27017
replication:
  replSetName: rs0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Затем на каждом узле: &lt;code&gt;sudo systemctl restart mongod&lt;/code&gt;. Узлам нужен доступ друг
к другу и клиентам по порту 27017:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Точечно: только из доверенной подсети
sudo ufw allow from 10.0.0.0/24 to any port 27017
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;инициализация&quot;&gt;Инициализация&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B8%D0%BD%D0%B8%D1%86%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Подключаемся к одному узлу и инициализируем набор — остальные перечислены
в &lt;code&gt;members&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Подключение (реплика-сет указывается в строке подключения)
mongosh &quot;mongodb://mongo1.example.com:27017/?replicaSet=rs0&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Выполняется один раз, на любом перечисленном узле
rs.initiate({
  _id: &quot;rs0&quot;,
  members: [
    { _id: 0, host: &quot;mongo1.example.com:27017&quot; },
    { _id: 1, host: &quot;mongo2.example.com:27017&quot; },
    { _id: 2, host: &quot;mongo3.example.com:27017&quot; }
  ]
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;статус-и-конфигурация&quot;&gt;Статус и конфигурация&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%81%D1%82%D0%B0%D1%82%D1%83%D1%81-%D0%B8-%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Состояние участников: health, state (PRIMARY/SECONDARY), lag
rs.status()

// Текущая конфигурация набора
rs.conf()

// Передать роль PRIMARY другому узлу (например, перед обслуживанием)
rs.stepDown()
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;добавление-и-удаление-участников&quot;&gt;Добавление и удаление участников&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B8-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%BE%D0%B2&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Подключить новый узел (сначала — с тем же replSetName в mongod.conf)
rs.add(&quot;mongo4.example.com:27017&quot;)

// Убрать узел из набора
rs.remove(&quot;mongo3.example.com:27017&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Приоритет участника задаётся в конфиге набора:
&lt;code&gt;rs.conf().members&lt;/code&gt; — поле &lt;code&gt;priority&lt;/code&gt;; узел с наибольшим приоритетом
выигрывает выборы PRIMARY. Для реплика-сета нужны минимум три узла с данным
(или арбитры) — кворум должен быть надёжным.&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded>
        </item>
        <item>
            <title>Apache Kafka</title>
            <link>https://itcompressor.e7.by/articles/devops/kafka/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/devops/kafka/</guid>
            <pubDate>Sat, 10 Jun 2023 00:00:00 GMT</pubDate>
            <description>Apache Kafka: установка, топики, producer/consumer CLI и кластер без ZooKeeper (KRaft)</description>
            <category>kafka</category>
            <category>streaming</category>
            <category>big data</category>
            <content:encoded>&lt;p&gt;Apache Kafka — распределённая потоковая платформа: продюсеры пишут события в
&lt;strong&gt;топики&lt;/strong&gt;, консьюмеры группы читают их независимо. Топик делится на
&lt;strong&gt;партиции&lt;/strong&gt; — единицы параллелизма и порядка (сообщения в пределах партиции
упорядочены).&lt;/p&gt;
&lt;p&gt;Все примеры дальше — вокруг одного топика &lt;code&gt;orders-events&lt;/code&gt; с тремя партициями
на локальном брокере, кластер — в отдельном разделе.&lt;/p&gt;
&lt;h2 id=&quot;установка&quot;&gt;Установка&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Kafka — JVM-приложение: нужен Java 17. Свежую версию и ссылку на архив —
проверяйте на kafka.apache.org/downloads, номера версий в URL ниже
подставьте под актуальную.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Зависимости
sudo apt update
sudo apt install openjdk-17-jdk wget

# Скачивание и распаковка (Kafka 3.9, сборка под Scala 2.13)
wget https://downloads.apache.org/kafka/3.9.0/kafka_2.13-3.9.0.tgz
tar -xzf kafka_2.13-3.9.0.tgz
sudo mv kafka_2.13-3.9.0 /opt/kafka
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;запуск-kraft&quot;&gt;Запуск (KRaft)&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D0%BA-kraft&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;С версии 3.3 Kafka работает в режиме &lt;strong&gt;KRaft&lt;/strong&gt; — метаданные кластера хранятся
в Raft-логе самой Kafka, ZooKeeper не нужен (в 4.0 он удалён полностью).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd /opt/kafka

# Сгенерировать Cluster ID кластера
KAFKA_CLUSTER_ID=&quot;$(bin/kafka-storage.sh random-uuid)&quot;

# Отформатировать директорию метаданных и логов
bin/kafka-storage.sh format -t &quot;$KAFKA_CLUSTER_ID&quot; -c config/kraft/server.properties

# Старт брокера (-daemon — фоновый процесс, лог в logs/server.log)
bin/kafka-server-start.sh -daemon config/kraft/server.properties

# Проверка живости
tail -f /opt/kafka/logs/server.log
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Kafka 3.x ещё умеет классический режим с ZooKeeper
(&lt;code&gt;bin/zookeeper-server-start.sh&lt;/code&gt; + &lt;code&gt;config/zookeeper.properties&lt;/code&gt;), но
новые развёртывания имеет смысл делать только в KRaft.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;топики&quot;&gt;Топики&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%82%D0%BE%D0%BF%D0%B8%D0%BA%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Создать топик: 3 партиции, одна копия данных (одиночный брокер)
bin/kafka-topics.sh --create --topic orders-events \
  --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1

# Список топиков
bin/kafka-topics.sh --list --bootstrap-server localhost:9092

# Описание: партиции, лидеры, офсеты
bin/kafka-topics.sh --describe --topic orders-events --bootstrap-server localhost:9092
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;--partitions&lt;/code&gt; — сколько параллельных потоков чтения и записи (после
создания только увеличивают). &lt;code&gt;--replication-factor 1&lt;/code&gt; — единственный
вариант для одиночного брокера; в кластере ставят 2–3.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;производители-и-потребители&quot;&gt;Производители и потребители&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D0%B8-%D0%B8-%D0%BF%D0%BE%D1%82%D1%80%D0%B5%D0%B1%D0%B8%D1%82%D0%B5%D0%BB%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;производитель&quot;&gt;Производитель&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D1%8C&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Сообщения пишутся построчно со stdin:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;bin/kafka-console-producer.sh --topic orders-events --bootstrap-server localhost:9092
&amp;gt; {&quot;order_id&quot;: 1001, &quot;amount&quot;: 149.99}
&amp;gt; {&quot;order_id&quot;: 1002, &quot;amount&quot;: 59.50}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;потребитель&quot;&gt;Потребитель&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%BE%D1%82%D1%80%D0%B5%D0%B1%D0%B8%D1%82%D0%B5%D0%BB%D1%8C&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Читать с начала истории (--from-beginning), иначе — только новые
bin/kafka-console-consumer.sh --topic orders-events \
  --bootstrap-server localhost:9092 --from-beginning
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;группы-потребителей&quot;&gt;Группы потребителей&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B3%D1%80%D1%83%D0%BF%D0%BF%D1%8B-%D0%BF%D0%BE%D1%82%D1%80%D0%B5%D0%B1%D0%B8%D1%82%D0%B5%D0%BB%D0%B5%D0%B9&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Консьюмеры одной группы делят партиции между собой: каждая партиция
закрепляется ровно за одним потребителем группы — так Kafka масштабирует
обработку, не теряя порядка.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Потребитель из группы billing
bin/kafka-console-consumer.sh --topic orders-events \
  --bootstrap-server localhost:9092 --group billing

# Состояние группы: закрепления, текущие офсеты, отставание (lag)
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
  --describe --group billing
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Офсеты группы Kafka хранит сама (в топике &lt;code&gt;__consumer_offsets&lt;/code&gt;) —
перезапущенный потребитель продолжает с места остановки.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;кластер-из-нескольких-брокеров&quot;&gt;Кластер из нескольких брокеров&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80-%D0%B8%D0%B7-%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D1%85-%D0%B1%D1%80%D0%BE%D0%BA%D0%B5%D1%80%D0%BE%D0%B2&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;В KRaft узлы совмещают роли брокера и контроллера и сами выбирают «мета»-лидера.
Типичной прод-схемой являются три узла &lt;code&gt;kafka1–kafka3&lt;/code&gt;: роли, узлы и кворум
контроллеров описываются в &lt;code&gt;server.properties&lt;/code&gt; каждого узла:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;# config/kraft/server.properties, узел kafka1 (на kafka2/kafka3 — node.id 2 и 3)
process.roles=broker,controller
node.id=1
controller.quorum.voters=1@kafka1.example.com:9093,2@kafka2.example.com:9093,3@kafka3.example.com:9093
listeners=PLAINTEXT://:9092,CONTROLLER://:9093
advertised.listeners=PLAINTEXT://kafka1.example.com:9092
log.dirs=/var/kafka-logs
num.partitions=3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;На каждом узле — свой &lt;code&gt;node.id&lt;/code&gt;, но один и тот же &lt;code&gt;controller.quorum.voters&lt;/code&gt;
и один Cluster ID при форматировании:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;bin/kafka-storage.sh format -t &quot;$KAFKA_CLUSTER_ID&quot; -c config/kraft/server.properties
bin/kafka-server-start.sh -daemon config/kraft/server.properties
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;В кластере создавайте топики с &lt;code&gt;--replication-factor 2–3&lt;/code&gt;: при падении
одного брокера партиция останется читаемой и записываемой за счёт
копии на другом узле.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;брандмауэр&quot;&gt;Брандмауэр&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B1%D1%80%D0%B0%D0%BD%D0%B4%D0%BC%D0%B0%D1%83%D1%8D%D1%80&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Клиентам — консумерский/продюсерский порт
sudo ufw allow from 10.0.0.0/24 to any port 9092

# Между узлами кластера — контроллерный порт (перекрывающие подсети допустимы)
sudo ufw allow from 10.0.0.0/24 to any port 9093
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Порт 2181 (ZooKeeper) больше не участвует в KRaft-развёртывании.&lt;/p&gt;
</content:encoded>
        </item>
        <item>
            <title>Ansible</title>
            <link>https://itcompressor.e7.by/articles/devops/ansible/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/devops/ansible/</guid>
            <pubDate>Thu, 01 Jun 2023 00:00:00 GMT</pubDate>
            <description>Автоматизация управления конфигурациями с Ansible: инвентарь, плейбуки, роли</description>
            <category>ansible</category>
            <category>devops</category>
            <category>automation</category>
            <content:encoded>&lt;p&gt;Ansible — инструмент автоматизации конфигураций и развёртывания: задачи
описываются YAML-плейбуками, исполняются по SSH без агентов на целевых
машинах. Сценарий статьи: инвентарь из групп &lt;code&gt;webservers&lt;/code&gt;/&lt;code&gt;dbservers&lt;/code&gt;,
настраиваем на них nginx.&lt;/p&gt;
&lt;h2 id=&quot;установка&quot;&gt;Установка&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Из репозитория Ubuntu приходит сильно запаздывающая версия — живее брать
из официального PPA:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible

ansible --version
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Альтернатива, дающая самые свежие релизы: &lt;code&gt;pipx install ansible&lt;/code&gt;
(или pip в виртуальном окружении). Не смешивайте оба способа на одной
машине.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;инвентарь&quot;&gt;Инвентарь&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B8%D0%BD%D0%B2%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D1%8C&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Инвентарь описывает хосты и их группы. Файл &lt;code&gt;inventory.ini&lt;/code&gt; рядом с плейбуками:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;[webservers]
web1.example.com
web2.example.com

[dbservers]
db1.example.com
db2.example.com

[all:vars]
ansible_user=admin
ansible_ssh_private_key_file=~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Инвентарь по умолчанию Ansible берёт из &lt;code&gt;ansible.cfg&lt;/code&gt; в каталоге плейбука:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;# ansible.cfg
[defaults]
inventory = ./inventory.ini
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;иначе каждый вызов команды придётся снабжать &lt;code&gt;-i inventory.ini&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;первый-плейбук&quot;&gt;Первый плейбук&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B9-%D0%BF%D0%BB%D0%B5%D0%B9%D0%B1%D1%83%D0%BA&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Плейбук — YAML со списком задач (task). Файл &lt;code&gt;update.yml&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;---
- name: Обновление системных пакетов
  hosts: all
  become: yes
  tasks:
    - name: Обновить кэш пакетов
      apt:
        update_cache: yes

    - name: Установить базовый набор
      apt:
        name:
          - nginx
          - git
          - curl
        state: present
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Запуск:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ansible-playbook update.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Задачи Ansible &lt;strong&gt;идемпотентны&lt;/strong&gt;: повторный прогон плейбука не делает
лишнего — модули сравнивают текущее состояние с желаемым и меняют
только расходящееся.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;модули&quot;&gt;Модули&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Модуль — атомарное действие. Самой ходовой хватает на большинство задач:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Модуль&lt;/th&gt;
&lt;th&gt;Что делает&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;пакеты в Debian/Ubuntu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yum&lt;/code&gt;, &lt;code&gt;dnf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;пакеты в RHEL-семействе&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;copy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;файл на удалённый хост&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;template&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;файл из Jinja2-шаблона с подстановкой переменных&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;права, владельцы, каталоги&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;service&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;запустить/остановить/рестартовать службу&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;user&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;пользователи и группы&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;Полные имена модулей — с префиксом коллекции: &lt;code&gt;ansible.builtin.copy&lt;/code&gt;,
&lt;code&gt;ansible.builtin.service&lt;/code&gt;. Справка по любому: &lt;code&gt;ansible-doc copy&lt;/code&gt;, документация — docs.ansible.com.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;переменные-и-обработчики&quot;&gt;Переменные и обработчики&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%B8-%D0%BE%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Внутри плейбука — &lt;code&gt;vars&lt;/code&gt;; в шаблонах — подстановка через &lt;code&gt;{{ … }}&lt;/code&gt;.
Файл &lt;code&gt;nginx.conf.j2&lt;/code&gt; рядом с плейбуком:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jinja&quot;&gt;server {
    listen {{ http_port }};
    root {{ document_root }};
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Файл &lt;code&gt;webserver.yml&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;---
- name: Настройка веб-сервера
  hosts: webservers
  become: yes
  vars:
    http_port: 80
    document_root: /var/www/html
  tasks:
    - name: Конфигурация nginx из шаблона
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: Перезапустить nginx   # сработает, только если файл изменился

  handlers:
    - name: Перезапустить nginx
      service:
        name: nginx
        state: restarted
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;notify&lt;/code&gt; — обработчик (handler): запускается один раз в конце прогона
и только когда задача реально что-то поменяла. Прогон без изменений
рестартов службы не делает.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;роли&quot;&gt;Роли&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%80%D0%BE%D0%BB%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Роль — переиспользуемый компонент со своей структурой каталогов:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ansible-galaxy init roles/webserver
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;roles/webserver/
├── tasks/main.yml        # задачи роли
├── handlers/main.yml
├── templates/            # nginx.conf.j2 — сюда
├── defaults/main.yml     # переменные по умолчанию
└── vars/main.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Использование — в плейбуке вместо перечисления задач:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;---
- name: Веб-серверы
  hosts: webservers
  become: yes
  roles:
    - webserver
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Готовые роли сообщества — Ansible Galaxy (&lt;code&gt;ansible-galaxy install&lt;/code&gt;
&lt;code&gt;geerlingguy.nginx&lt;/code&gt;), свои кладите в &lt;code&gt;roles/&lt;/code&gt; рядом с плейбуком.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;команды-работы&quot;&gt;Команды работы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D1%8B-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Проверка доступности хостов (модуль ping)
ansible all -m ping

# Только одна группа
ansible webservers -m ping

# Разовая команда на хостах
ansible all -a &quot;uptime&quot;

# Плейбук с суперпользователем на целевых машинах
ansible-playbook webserver.yml --become

# Показать список задач, ничего не выполняя
ansible-playbook webserver.yml --list-tasks

# Сухой прогон: изменения считаются, но не применяются
ansible-playbook webserver.yml --check --diff

# Подробный вывод (v, -vv, -vvv — многословнее)
ansible-playbook webserver.yml -v

# Ограничить прогон одним хостом
ansible-playbook webserver.yml --limit web1.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Секреты (пароли, ключи API) держите в зашифрованных переменных:
&lt;code&gt;ansible-vault encrypt_string&lt;/code&gt; — и в плейбуме как обычную переменную;
расшифровка запрашивает пароль vault при прогоне.&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded>
        </item>
        <item>
            <title>GlassFish</title>
            <link>https://itcompressor.e7.by/articles/java/glassfish/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/java/glassfish/</guid>
            <pubDate>Mon, 15 May 2023 00:00:00 GMT</pubDate>
            <description>GlassFish: установка, asadmin, развёртывание приложений и JDBC-источники</description>
            <category>java</category>
            <category>glassfish</category>
            <category>server</category>
            <content:encoded>&lt;p&gt;GlassFish — открытая реализация Jakarta EE (бывшая Java EE): домен приложения,
веб-консоль администрирования и CLI &lt;code&gt;asadmin&lt;/code&gt; из коробки. В роли сервера
приложений подходит как для разработки, так и для прод-эксплуатации.&lt;/p&gt;
&lt;p&gt;Все команды ниже — &lt;code&gt;./asadmin&lt;/code&gt; из каталога &lt;code&gt;/opt/glassfish7/bin&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;установка&quot;&gt;Установка&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;GlassFish 7 — Jakarta EE 10, нужен JDK 17+. Дистрибутив — zip с Maven
Central; свежую версию проверяйте на glassfish.org:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Зависимости
sudo apt update
sudo apt install openjdk-17-jdk unzip

# Скачивание и распаковка (GlassFish 7.0.20)
wget https://repo1.maven.org/maven2/org/glassfish/main/distributions/glassfish/7.0.20/glassfish-7.0.20.zip
unzip glassfish-7.0.20.zip
sudo mv glassfish7 /opt/glassfish7
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;первый-запуск&quot;&gt;Первый запуск&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B9-%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D0%BA&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd /opt/glassfish7/bin

# Запустить дефолтный домен (domain1)
./asadmin start-domain

# Задать пароль стандартному админу (спросит старый — пустой — и новый)
./asadmin change-admin-password

# Включить шифрование админ-интерфейса (кроме самого первого запроса пароля)
./asadmin enable-secure-admin
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;После &lt;code&gt;enable-secure-admin&lt;/code&gt; домен надо перезапустить
(&lt;code&gt;./asadmin restart-domain&lt;/code&gt;), и админ-трафик пойдёт по TLS.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ещё одного админа добавляют в группу &lt;code&gt;asadmin&lt;/code&gt; той же admin-realm:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;./asadmin create-user --authrealmname admin-realm --groups asadmin backupadmin
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Веб-консоль — &lt;code&gt;http://localhost:4848&lt;/code&gt;, вход — учётка из admin-realm.
Наружу этот порт лучше не открывать (см. брандмауэр в конце).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;управление-доменом&quot;&gt;Управление доменом&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B4%D0%BE%D0%BC%D0%B5%D0%BD%D0%BE%D0%BC&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Запуск / остановка / перезапуск
./asadmin start-domain
./asadmin stop-domain
./asadmin restart-domain

# Список доменов и их статус
./asadmin list-domains
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;start-domain --verbose&lt;/code&gt; — это &lt;strong&gt;передний&lt;/strong&gt; план с логами в консоль
(удобно для отладки), а не фоновый режим. Для автозапуска на сервере
заведите systemd-юнит с &lt;code&gt;/opt/glassfish7/bin/asadmin start-domain&lt;/code&gt;
в &lt;code&gt;ExecStart&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;развёртывание-приложений&quot;&gt;Развёртывание приложений&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%80%D0%B0%D0%B7%D0%B2%D1%91%D1%80%D1%82%D1%8B%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# WAR-приложение
./asadmin deploy /path/to/orders-app.war

# EAR-корпоративное приложение
./asadmin deploy /path/to/orders-app.ear

# Своя контекст-строка вместо имени файла
./asadmin deploy --contextroot=/orders /path/to/orders-app.war

# Что уже развернуто
./asadmin list-applications

# Снять приложение
./asadmin undeploy orders-app
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;deploy&lt;/code&gt; по умолчанию кладёт приложение под контекстом по имени файла
(&lt;code&gt;orders-app.war&lt;/code&gt; доступно на &lt;code&gt;/orders-app&lt;/code&gt;); при повторном развёртывании
того же имени старая версия заменяется — «горячий» деплой работает.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;источники-данных-jdbc&quot;&gt;Источники данных (JDBC)&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B8%D1%81%D1%82%D0%BE%D1%87%D0%BD%D0%B8%D0%BA%D0%B8-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-jdbc&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Драйвер БД — просто jar в &lt;code&gt;lib/ext&lt;/code&gt; домена; после этого — пул соединений
и JDBC-ресурс (JNDI) поверх него:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cp /path/to/postgresql.jar /opt/glassfish7/glassfish/domains/domain1/lib/ext/
./asadmin restart-domain
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Пул соединений к PostgreSQL
./asadmin create-jdbc-connection-pool \
  --datasourceclassname=org.postgresql.ds.PGSimpleDataSource \
  --restype=javax.sql.DataSource \
  --property user=app:password=secret:serverName=10.0.0.14:portNumber=5432:databaseName=ordersdb \
  jdbc/ordersPool

# JDBC-ресурс (JNDI-имя jdbc/ordersDS) — его уже ищут приложения
./asadmin create-jdbc-resource --connectionpoolid jdbc/ordersPool jdbc/ordersDS

# Проверка живости пула
./asadmin ping-connection-pool jdbc/ordersPool
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Свойства (property) разделяются &lt;code&gt;:&lt;/code&gt;, имена &lt;code&gt;serverName&lt;/code&gt;, &lt;code&gt;databaseName&lt;/code&gt;,
&lt;code&gt;portNumber&lt;/code&gt; — для драйвера PostgreSQL; для другого провайдера набор
свойств свой. Тот же ресурс приложения видят через &lt;code&gt;java:comp/env/jdbc/ordersDS&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;брандмауэр&quot;&gt;Брандмауэр&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B1%D1%80%D0%B0%D0%BD%D0%B4%D0%BC%D0%B0%D1%83%D1%8D%D1%80&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# HTTP / HTTPS слушатели приложений — клиентам
sudo ufw allow from 10.0.0.0/24 to any port 8080
sudo ufw allow from 10.0.0.0/24 to any port 8181

# 4848 (админ-консоль) — только из доверенной админ-подсети
sudo ufw allow from 10.0.0.5 to any port 4848
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Порт 4848 наружу не открывайте: консоль позволяет менять домен целиком.&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded>
        </item>
        <item>
            <title>Vim</title>
            <link>https://itcompressor.e7.by/articles/linux/vim/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/linux/vim/</guid>
            <pubDate>Mon, 01 May 2023 00:00:00 GMT</pubDate>
            <description>Основные команды и настройка Vim</description>
            <category>vim</category>
            <category>editor</category>
            <category>linux</category>
            <content:encoded>&lt;p&gt;Vim — модальный текстовый редактор, развитая версия классического vi:
доступен практически в любой Unix-системе, не тратит руки на мышь и после
освоения ощутимо ускоряет правку кода и конфигов.&lt;/p&gt;
&lt;h2 id=&quot;режимы-работы&quot;&gt;Режимы работы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D1%8B-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Вся фишка Vim — в режимах: одна и та же клавиша значит разное, смотря в каком
режиме вы находитесь.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Normal&lt;/strong&gt; — навигация и команды; Vim всегда стартует здесь&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Insert&lt;/strong&gt; — ввод текста (попасть: &lt;code&gt;i&lt;/code&gt; / &lt;code&gt;a&lt;/code&gt; / &lt;code&gt;o&lt;/code&gt;, выйти: &lt;code&gt;Esc&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visual&lt;/strong&gt; — выделение текста (попасть: &lt;code&gt;v&lt;/code&gt; / &lt;code&gt;V&lt;/code&gt; / &lt;code&gt;Ctrl+v&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Command-line&lt;/strong&gt; — команды с двоеточием (&lt;code&gt;:w&lt;/code&gt;, &lt;code&gt;:q&lt;/code&gt;, &lt;code&gt;:%s/…/…/&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;навигация&quot;&gt;Навигация&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BD%D0%B0%D0%B2%D0%B8%D0%B3%D0%B0%D1%86%D0%B8%D1%8F&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Клавиши&lt;/th&gt;
&lt;th&gt;Что делают&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;h&lt;/code&gt; &lt;code&gt;j&lt;/code&gt; &lt;code&gt;k&lt;/code&gt; &lt;code&gt;l&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;влево, вниз, вверх, вправо&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;w&lt;/code&gt; / &lt;code&gt;b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;следующее / предыдущее слово&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt; / &lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;начало / конец строки&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gg&lt;/code&gt; / &lt;code&gt;G&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;начало / конец файла&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;{&lt;/code&gt; / &lt;code&gt;}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;предыдущий / следующий абзац&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Ctrl+d&lt;/code&gt; / &lt;code&gt;Ctrl+u&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;полстраницы вниз / вверх&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;редактирование&quot;&gt;Редактирование&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-vim&quot;&gt;i   — вставка перед курсором        a — вставка после курсора
I   — вставка в начало строки       A — вставка в конец строки
o   — новая строка ниже             O — новая строка выше
x   — удалить символ                r — заменить один символ
dd  — удалить строку                dw — удалить слово
yy  — скопировать (yank) строку     yw — скопировать слово
p   — вставить после курсора        P — вставить перед курсором
u   — отменить                      Ctrl+r — вернуть отменённое
ci&quot; — изменить содержимое в кавычках ci( — в скобках (важный паттерн «c» + объект)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Комбинация «оператор + текстовый объект» работает и с другими
операторами: &lt;code&gt;di(&lt;/code&gt; — удалить содержимое скобок, &lt;code&gt;daw&lt;/code&gt; — удалить слово
вместе с пробелом вокруг, &lt;code&gt;dd&lt;/code&gt; — оператор удаления на целую строку.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;визуальный-режим&quot;&gt;Визуальный режим&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B2%D0%B8%D0%B7%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-%D1%80%D0%B5%D0%B6%D0%B8%D0%BC&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Выделение, затем оператор — так работают массовые правки:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-vim&quot;&gt;v   — посимвольное выделение       V — построчное выделение
Ctrl+v — блочное выделение (колонна)
y   — скопировать выделенное       d — вырезать
&amp;gt; / &amp;lt; — сдвиг выделенного вправо / влево
u / U — выделенное в нижний / верхний регистр
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Классика блочного выделения: &lt;code&gt;Ctrl+v&lt;/code&gt;, спуститься курсором по столбцу,
&lt;code&gt;I&lt;/code&gt; — ввод текста, &lt;code&gt;Esc&lt;/code&gt; — текст появится на каждой строке выделения.&lt;/p&gt;
&lt;h2 id=&quot;поиск-и-замена&quot;&gt;Поиск и замена&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%BE%D0%B8%D1%81%D0%BA-%D0%B8-%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-vim&quot;&gt;/pattern    — поиск вперёд (n — следующее совпадение, N — предыдущее)
?pattern    — поиск назад
:s/old/new/    — замена первого совпадения в строке
:s/old/new/g   — замена в текущей строке (все совпадения)
:%s/old/new/g  — замена во всём файле
:%s/old/new/gc — то же, с подтверждением каждого совпадения
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;сохранение-и-выход&quot;&gt;Сохранение и выход&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B8-%D0%B2%D1%8B%D1%85%D0%BE%D0%B4&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Команда&lt;/th&gt;
&lt;th&gt;Что делает&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:w&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;сохранить&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:q&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;выйти&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:wq&lt;/code&gt; / &lt;code&gt;ZZ&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;сохранить и выйти&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:q!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;выйти без保存 (частый гость новичка)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:w file.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;сохранить в другой файл&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;Забыли открыть файл под sudo, а он не сохраняется? Внутри Vim:
&lt;code&gt;:w !sudo tee %&lt;/code&gt; — файл перезапишется с правами root.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;настройка-vimrc&quot;&gt;Настройка: ~/.vimrc&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-vimrc&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-vim&quot;&gt;&quot; Нумерация строк
set number

&quot; Подсветка синтаксиса
syntax on

&quot; Автоотступы
set autoindent
set smartindent

&quot; Табы и пробелы
set tabstop=4
set shiftwidth=4
set expandtab

&quot; Поиск: без учёта регистра, но с ним — если есть заглавные в запросе
set ignorecase
set smartcase

&quot; Подсветка совпадений поиска
set hlsearch
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;плагины-vim-plug&quot;&gt;Плагины (vim-plug)&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D1%8B-vim-plug&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Менеджер плагинов — один файл-автозагрузка:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Список плагинов в &lt;code&gt;~/.vimrc&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-vim&quot;&gt;call plug#begin(&#39;~/.vim/plugged&#39;)
Plug &#39;tpope/vim-fugitive&#39;    &quot; Git внутри Vim
Plug &#39;airblade/vim-gitgutter&#39; &quot; Знаки изменённых строк
Plug &#39;vim-airline/vim-airline&#39; &quot; Статусная строка
call plug#end()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Установка — из редактора после перезапуска: &lt;code&gt;:PlugInstall&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Neovim — современный форк с той же моделью редактирования; конфиг там
живёт в &lt;code&gt;~/.config/nvim/init.vim&lt;/code&gt;, а многие плагины из списка работают
в обоих редакторах без изменений.&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded>
        </item>
        <item>
            <title>VirtualBox</title>
            <link>https://itcompressor.e7.by/articles/virtualization/virtualbox/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/virtualization/virtualbox/</guid>
            <pubDate>Mon, 10 Apr 2023 00:00:00 GMT</pubDate>
            <description>Создание и настройка виртуальных машин в VirtualBox</description>
            <category>virtualization</category>
            <category>linux</category>
            <category>windows</category>
            <content:encoded>&lt;p&gt;VirtualBox — бесплатный виртуализатор от Oracle: ВМ на десктопе для тестов,
экспериментов и песочниц. Сценарий статьи: виртуальная машина &lt;code&gt;arch-vm&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;установка&quot;&gt;Установка&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install virtualbox
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Для USB 3.0 и RDP-доступа к ВМ нужен ещё Extension Pack с virtualbox.org —
бесплатно для персонального использования (у пакета своя лицензия PUEL).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;создание-виртуальной-машины&quot;&gt;Создание виртуальной машины&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B2%D0%B8%D1%80%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9-%D0%BC%D0%B0%D1%88%D0%B8%D0%BD%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;«Создать» → имя &lt;code&gt;arch-vm&lt;/code&gt;, тип ОС (Linux / Arch 64)&lt;/li&gt;
&lt;li&gt;Оперативная память — половина хостовой, не больше&lt;/li&gt;
&lt;li&gt;Виртуальный диск — динамический VDI под размер гостевой ОС&lt;/li&gt;
&lt;li&gt;Скачанный ISO подключается как оптический привод при первом старте&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;настройка-виртуальной-машины&quot;&gt;Настройка виртуальной машины&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D0%B2%D0%B8%D1%80%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9-%D0%BC%D0%B0%D1%88%D0%B8%D0%BD%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Параметры → разделы (до и после создания):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Система&lt;/strong&gt;: память и число ядер CPU&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Дисплей&lt;/strong&gt;: видеопамять, число экранов&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Носители&lt;/strong&gt;: проброс образов дисков/ISO&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Сеть&lt;/strong&gt;: тип адаптера (см. раздел про сети)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Общие папки&lt;/strong&gt;: шаринг каталогов между хостом и гостем&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;гостевые-дополнения&quot;&gt;Гостевые дополнения&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B3%D0%BE%D1%81%D1%82%D0%B5%D0%B2%D1%8B%D0%B5-%D0%B4%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Дополнения дают интеграцию: общий буфер обмена, ресайз экрана, общие папки.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ВМ запущена → меню «Устройства» → «Вставить образ Дополнений гостевой ОС»&lt;/li&gt;
&lt;li&gt;Внутри гостя примонтировать CD и запустить установщик&lt;/li&gt;
&lt;li&gt;В Linux-госте пользователю для общих папок нужна группа:
&lt;code&gt;sudo usermod -aG vboxsf $USER&lt;/code&gt; (перезелогин после этого)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;снимки&quot;&gt;Снимки&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%81%D0%BD%D0%B8%D0%BC%D0%BA%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Снимок — зафиксированное состояние диска ВМ: откат к нему убирает все
последующие изменения диска.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Зафиксировать состояние
VBoxManage snapshot arch-vm take &quot;чистая система&quot;

# Список снимков
VBoxManage snapshot arch-vm list

# Откат
VBoxManage snapshot arch-vm restore &quot;чистая система&quot;

# Лишний снимок удалить
VBoxManage snapshot arch-vm delete &quot;чистая система&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Откат возвращает диск, а не процессы: состояние внутри запущенной ОС
(кроме «сохранённого» состояния при paused-снимке) будет как после
холодной загрузки.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;управление-вм-из-консоли&quot;&gt;Управление ВМ из консоли&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B2%D0%BC-%D0%B8%D0%B7-%D0%BA%D0%BE%D0%BD%D1%81%D0%BE%D0%BB%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Список машин
VBoxManage list vms

# Запуск с окном GUI / в фоне без окна
VBoxManage startvm arch-vm
VBoxManage startvm arch-vm --type headless

# Корректное выключение / жёсткое
VBoxManage controlvm arch-vm acpipowerbutton
VBoxManage controlvm arch-vm poweroff

# Перезагрузка
VBoxManage controlvm arch-vm reset

# Вычеркнуть ВМ из списка (диски остаются, удаляются отдельно)
VBoxManage unregistervm arch-vm
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;headless&lt;/code&gt; + SSH гостя часто удобнее GUI: машину можно держать на
сервере и подключаться как к обычному хосту (порт-форвардинг NAT —
&lt;code&gt;VBoxManage modifyvm arch-vm --nat-pf1 &quot;ssh,tcp,,2222,,22&quot;&lt;/code&gt; или вкладка
«Сеть → правила портов» в GUI).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;сети-виртуальных-машин&quot;&gt;Сети виртуальных машин&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%81%D0%B5%D1%82%D0%B8-%D0%B2%D0%B8%D1%80%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85-%D0%BC%D0%B0%D1%88%D0%B8%D0%BD&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Тип&lt;/th&gt;
&lt;th&gt;Как работает&lt;/th&gt;
&lt;th&gt;Когда использовать&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;NAT&lt;/td&gt;
&lt;td&gt;ВМ выходит наружу через хост, снаружи не видна&lt;/td&gt;
&lt;td&gt;ВМ нужен интернет по умолчанию&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Мост (bridged)&lt;/td&gt;
&lt;td&gt;ВМ с собственным адресом в сети хоста&lt;/td&gt;
&lt;td&gt;ВМ должна быть видна как обычный хост&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Внутренняя сеть&lt;/td&gt;
&lt;td&gt;только между ВМ, без выхода наружу&lt;/td&gt;
&lt;td&gt;закрытые связки виртуальных машин&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Host-only&lt;/td&gt;
&lt;td&gt;приватная сеть «ВМ ↔ хост»&lt;/td&gt;
&lt;td&gt;доступ к ВМ с самого хоста&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Типы комбинируются: одной ВМ можно дать и NAT, и мост (несколько адаптеров в
настройках «Сеть»).&lt;/p&gt;
</content:encoded>
        </item>
        <item>
            <title>WireGuard VPN</title>
            <link>https://itcompressor.e7.by/articles/networking/wireguard/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/networking/wireguard/</guid>
            <pubDate>Sat, 01 Apr 2023 00:00:00 GMT</pubDate>
            <description>Настройка WireGuard VPN для безопасного подключения</description>
            <category>vpn</category>
            <category>security</category>
            <category>networking</category>
            <content:encoded>&lt;p&gt;WireGuard — современный VPN-протокол: минимум строк конфига, быстрое
рукопожатие и современная криптография из коробки. Сценарий статьи: сервер
с адресом &lt;code&gt;10.0.0.1&lt;/code&gt; в VPN-сети и клиент &lt;code&gt;10.0.0.2&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;установка&quot;&gt;Установка&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install wireguard
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Модуль ядра &lt;code&gt;wireguard&lt;/code&gt; подгружается автоматически при первом поднятии
интерфейса — вручную делать ничего не нужно.&lt;/p&gt;
&lt;h2 id=&quot;ключи&quot;&gt;Ключи&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BA%D0%BB%D1%8E%D1%87%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;У каждого узла своя пара: приватный ключ (никому не показывается) и
публичный (обмен с пиром). На сервере:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo -i
cd /etc/wireguard

# umask закрытой папки и ключей: приватный ключ не должен быть читаем всем
umask 077

# Приватный ключ → публичный
wg genkey &amp;gt; server.key
wg pubkey &amp;lt; server.key &amp;gt; server.pub
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;На клиенте те же две команды — &lt;code&gt;client.key&lt;/code&gt; / &lt;code&gt;client.pub&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Публичный ключ клиента добавляется серверу в &lt;code&gt;[Peer]&lt;/code&gt; — и наоборот.
Приватные ключи никогда не покидают свою машину.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;конфигурация-сервера&quot;&gt;Конфигурация сервера&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;/etc/wireguard/wg0.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = &amp;lt;server.key&amp;gt;

# Клиент со своим публичным ключом и VPN-адресом
[Peer]
PublicKey = &amp;lt;client.pub&amp;gt;
AllowedIPs = 10.0.0.2/32
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Чтобы клиенты с полным туннелем выходили через сервер в интернет, нужен
форвардинг и NAT:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo sysctl -w net.ipv4.ip_forward=1
echo &quot;net.ipv4.ip_forward=1&quot; | sudo tee /etc/sysctl.d/99-wireguard.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;# Дополнение в [Interface] wg0.conf (eth0 — свой внешний интерфейс)
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;конфигурация-клиента&quot;&gt;Конфигурация клиента&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%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%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;wg0.conf&lt;/code&gt; на клиентской машине:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;[Interface]
Address = 10.0.0.2/24
PrivateKey = &amp;lt;client.key&amp;gt;

[Peer]
PublicKey = &amp;lt;server.pub&amp;gt;
Endpoint = &amp;lt;серверный-IP&amp;gt;:51820

# 0.0.0.0/0 — весь трафик через туннель
# Чтобы через VPN ходили только серверные подсети, укажите их вместо этого:
# AllowedIPs = 10.0.0.0/24
AllowedIPs = 0.0.0.0/0, ::/0

# Поддерживать трансляцию живой за NAT
PersistentKeepalive = 25
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;запуск&quot;&gt;Запуск&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D0%BA&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Поднять туннель
sudo wg-quick up wg0

# Состояние: обмен данными, рукопожатия, роуминг
sudo wg

# Опустить
sudo wg-quick down wg0
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;wg show&lt;/code&gt; показывает также последний handshake и сколько байт прошло через
пира — по нему видно, что связка ключей работает.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Автозапуск интерфейса при загрузке — обычная systemd-юнит-семантика
(&lt;code&gt;wg-quick@&amp;lt;имя-интерфейса&amp;gt;&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl enable --now wg-quick@wg0
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;брандмауэр&quot;&gt;Брандмауэр&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B1%D1%80%D0%B0%D0%BD%D0%B4%D0%BC%D0%B0%D1%83%D1%8D%D1%80&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# порт только UDP
sudo ufw allow 51820/udp
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Ключевое отличие от OpenVPN: WireGuard работает только по UDP — TCP-режима
у протокола нет.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;лайфхак-клиент-на-телефон&quot;&gt;Лайфхак: клиент на телефон&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BB%D0%B0%D0%B9%D1%84%D1%85%D0%B0%D0%BA-%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82-%D0%BD%D0%B0-%D1%82%D0%B5%D0%BB%D0%B5%D1%84%D0%BE%D0%BD&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Конфиг удобнее всего передавать QR-кодом — официальное приложение
(iOS/Android) сканирует его:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt install qrencode
qrencode -t ansiutf8 &amp;lt; wg0.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Каждому устройству — свой &lt;code&gt;[Peer]&lt;/code&gt; со своим приватным ключом и адресом:
конфиги не шарятся между устройствами.&lt;/p&gt;
</content:encoded>
        </item>
        <item>
            <title>SSH</title>
            <link>https://itcompressor.e7.by/articles/networking/ssh/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/networking/ssh/</guid>
            <pubDate>Wed, 15 Mar 2023 00:00:00 GMT</pubDate>
            <description>SSH: сервер, ключи, ~/.ssh/config, scp и туннели</description>
            <category>ssh</category>
            <category>security</category>
            <category>linux</category>
            <content:encoded>&lt;p&gt;SSH — протокол шифрованного удалённого доступа: шелл на сервере, копирование
файлов и туннелирование трафика через один порт. Сценарий статьи: сервер
&lt;code&gt;web1.example.com&lt;/code&gt;, пользователь &lt;code&gt;admin&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;установка-сервера&quot;&gt;Установка сервера&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install openssh-server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Клиент (&lt;code&gt;openssh-client&lt;/code&gt;) на Ubuntu уже установлен; на машинах без сервера —
только клиент.&lt;/p&gt;
&lt;h2 id=&quot;настройка-сервера&quot;&gt;Настройка сервера&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Конфигурация — &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;. Базовый безопасный набор:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;Port 22

# Вход root по SSH запрещён
PermitRootLogin no

# Аутентификация по ключам
PubkeyAuthentication yes

# Ключи лежат здесь
AuthorizedKeysFile .ssh/authorized_keys

# Парольный вход — выключить, когда ключи отлажены
PasswordAuthentication no

# Подробный лог попыток подключения
LogLevel VERBOSE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Проверка синтаксиса и перезапуск:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo sshd -t
sudo systemctl restart ssh
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;sshd -t&lt;/code&gt; проверяет конфиг до перезапуска — так не отрежете себе доступ
из-за опечатки. На Ubuntu/Debian служба называется &lt;code&gt;ssh&lt;/code&gt;, в RHEL-семействе —
&lt;code&gt;sshd&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;PasswordAuthentication no&lt;/code&gt; включайте только после того, как ключи уже
работают: иначе останетесь без серверного входа (последний шанс — консоль
хостера/VNC).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;генерация-ключей&quot;&gt;Генерация ключей&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B3%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%B9&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Современный тип — Ed25519 (короткие ключи, быстрая проверка):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ssh-keygen -t ed25519 -C &quot;admin@laptop&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ключи появятся в &lt;code&gt;~/.ssh/&lt;/code&gt;: приватный &lt;code&gt;id_ed25519&lt;/code&gt; (никогда не покидает
машину) и публичный &lt;code&gt;id_ed25519.pub&lt;/code&gt; (его раскидываем по серверам).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;RSA (&lt;code&gt;ssh-keygen -t rsa -b 4096&lt;/code&gt;) — для совсем старых серверов, в которых
Ed25519 ещё не реализован.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Права на &lt;code&gt;~/.ssh&lt;/code&gt; и приватный ключ ssh проверяет жёстко:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;копирование-ключа-на-сервер&quot;&gt;Копирование ключа на сервер&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BB%D1%8E%D1%87%D0%B0-%D0%BD%D0%B0-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ssh-copy-id admin@web1.example.com

# Нестандартный порт сервера
ssh-copy-id -p 2222 admin@web1.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Публичный ключ допишется в &lt;code&gt;authorized_keys&lt;/code&gt; сервера — вход по паролю больше
не понадобится.&lt;/p&gt;
&lt;h2 id=&quot;подключение&quot;&gt;Подключение&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ssh admin@web1.example.com

# Нестандартный порт
ssh -p 2222 admin@web1.example.com

# Разовая команда, без интерактивного шелла
ssh admin@web1.example.com &quot;df -h /&quot;

# Отладка проблем подключения (-vv — многословнее)
ssh -v admin@web1.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;файл-ssh-config&quot;&gt;Файл ~/.ssh/config&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%84%D0%B0%D0%B9%D0%BB-ssh-config&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Псевдонимы хостов: раз — и потом короткие &lt;code&gt;ssh web1&lt;/code&gt; без имён/портов/ключей:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# ~/.ssh/config
Host web1
    HostName web1.example.com
    User admin
    IdentityFile ~/.ssh/id_ed25519

Host db1
    HostName db1.example.com
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ssh web1
scp backup.sh web1:/opt/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Все опции из &lt;code&gt;config&lt;/code&gt; применяются и к &lt;code&gt;scp&lt;/code&gt;, и к &lt;code&gt;ssh-copy-id&lt;/code&gt; — хост с
псевдонимом ведёт себя как обычное имя. Файл должен быть доступен только
вам: &lt;code&gt;chmod 600 ~/.ssh/config&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Для входа через промежуточный сервер (bastion) — опция &lt;code&gt;ProxyJump&lt;/code&gt;:
&lt;code&gt;ssh -J bastion web1&lt;/code&gt; или &lt;code&gt;ProxyJump bastion&lt;/code&gt; в блоке &lt;code&gt;Host web1&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;копирование-файлов-scp&quot;&gt;Копирование файлов: scp&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%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-scp&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Файл на сервер
scp deploy.sh admin@web1.example.com:/tmp/

# Файл с сервера сюда
scp admin@web1.example.com:/var/log/app.log .

# Каталог целиком (рекурсивно)
scp -r ./assets admin@web1.example.com:/var/www/

# Порт указывается заглавной -P (в ssh — строчная -p!)
scp -P 2222 file.txt admin@web1.example.com:~

# Сохранить времена и права файлов (-p)
scp -p admin@web1.example.com:/etc/nginx/nginx.conf .
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Начиная с OpenSSH 9.0 протокол по умолчанию — SFTP; для очень старых
серверов добавьте &lt;code&gt;-O&lt;/code&gt; (режим старого SCP-протокола). Для больших каталогов
и повторяющихся синхронизаций удобнее &lt;code&gt;rsync -avz …&lt;/code&gt; — докачивает и
перекачивает только изменившееся.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;ssh-агент&quot;&gt;SSH-агент&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#ssh-%D0%B0%D0%B3%D0%B5%D0%BD%D1%82&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Агент держит расшифрованные ключи в памяти — пароль ключа спрашивается
один раз за сессию:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;На десктопах (macOS, GNOME) агент обычно уже запущен — достаточно
&lt;code&gt;ssh-add&lt;/code&gt;. На macOS ключ можно держать в связке Keychain:
&lt;code&gt;ssh-add --apple-use-keychain&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;туннели&quot;&gt;Туннели&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%82%D1%83%D0%BD%D0%BD%D0%B5%D0%BB%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Локальное перенаправление: localhost:5432 → БД на стороне сервера
ssh -L 5432:localhost:5432 admin@db1.example.com

# Обратное: порт сервера ведёт на сервис вашей локальной машины
# (покажите локальную разработку коллеге с сервера)
ssh -R 8080:localhost:3000 admin@web1.example.com

# SOCKS-прокси на localhost:1080 — трафик браузера через сервер
ssh -D 1080 admin@web1.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Туннель живёт, пока живо ssh-подключение; запускайте с &lt;code&gt;-N&lt;/code&gt; (без шелла)
и &lt;code&gt;-T&lt;/code&gt;, если нужен только туннель: &lt;code&gt;ssh -N -L 5432:localhost:5432 admin@db1.example.com&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded>
        </item>
        <item>
            <title>Arch Linux</title>
            <link>https://itcompressor.e7.by/articles/linux/installation_archlinux/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/linux/installation_archlinux/</guid>
            <pubDate>Wed, 01 Mar 2023 00:00:00 GMT</pubDate>
            <description>Arch Linux: установка с нуля (UEFI) и полезные приёмы pacman/AUR</description>
            <category>linux</category>
            <category>arch</category>
            <category>installation</category>
            <content:encoded>&lt;p&gt;Arch Linux — минималистичный rolling-release дистрибутив: ставится базовый
каркас, остальное — по вкусу. Установка вручную (без установщика) — часть
философии: после неё система понятна до последнего файла.&lt;/p&gt;
&lt;h2 id=&quot;подготовка&quot;&gt;Подготовка&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BA%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Образ&lt;/strong&gt; — последний ISO с archlinux.org&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Запись на USB&lt;/strong&gt; — &lt;code&gt;dd&lt;/code&gt; или Rufus/Ventoy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Загрузка с USB&lt;/strong&gt; — в UEFI-режиме (Boot menu материнки)&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Записать образ на флешку (осторожно с of= — всё на разделе затирается)
dd if=archlinux-x86_64.iso of=/dev/sdX bs=4M status=progress
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;разметка-диска&quot;&gt;Разметка диска&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%82%D0%BA%D0%B0-%D0%B4%D0%B8%D1%81%D0%BA%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Типичная схема для UEFI: ESP на &lt;code&gt;/boot&lt;/code&gt; + корень на всё остальное:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Диски и точки монтирования
lsblk

# Таблица GPT
parted /dev/sda mklabel gpt

# ESP на /boot и корневой раздел
parted /dev/sda mkpart ESP fat32 1MiB 513MiB
parted /dev/sda set 1 esp on
parted /dev/sda mkpart primary 513MiB 100%

# Файловые системы
mkfs.fat -F32 /dev/sda1
mkfs.ext4 /dev/sda2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Монтирование — прежде чем что-то ставить:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mount /dev/sda2 /mnt
mount --mkdir /dev/sda1 /mnt/boot
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Сеть на ISO поднимается сама (Ethernet). Wi-Fi: &lt;code&gt;iwctl&lt;/code&gt; →
&lt;code&gt;station wlan0 scan&lt;/code&gt; / &lt;code&gt;station wlan0 connect &amp;lt;SSID&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;базовая-система&quot;&gt;Базовая система&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B1%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D1%8F-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Проверка синхронизации времени (UTC на ISO)
timedatectl

# Ключи и списки репозиториев актуальны: сразу обновить keyring
pacman -Sy archlinux-keyring

# Установка каркаса в /mnt
pacstrap -K /mnt base base-devel linux linux-firmware amd-ucode

# fstab по UUID
genfstab -U /mnt &amp;gt; /mnt/etc/fstab

# Переезд в новую систему
arch-chroot /mnt
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;amd-ucode&lt;/code&gt; — микрокод процессоров AMD; для Intel ставьте &lt;code&gt;intel-ucode&lt;/code&gt;.
Фирменные прошивки Wi-Fi/звука — отдельный пакет &lt;code&gt;linux-firmware&lt;/code&gt; уже
включает основной набор.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;настройка-системы&quot;&gt;Настройка системы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Часовой пояс и аппаратные часы
ln -sf /usr/share/zoneinfo/Europe/Minsk /etc/localtime
hwclock --systohc

# Локали
echo &quot;ru_RU.UTF-8 UTF-8&quot; &amp;gt;&amp;gt; /etc/locale.gen
locale-gen
echo &quot;LANG=ru_RU.UTF-8&quot; &amp;gt; /etc/locale.conf

# Имя машины
echo &quot;archlinux&quot; &amp;gt; /etc/hostname
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;/etc/hosts&lt;/code&gt; — запись имени хоста, чтобы сервисы не ругались на резолвинг:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cat &amp;gt; /etc/hosts &amp;lt;&amp;lt;&#39;EOF&#39;
127.0.0.1   localhost
127.0.1.1   archlinux
::1         localhost
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Пароль root:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;passwd
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;загрузчик&quot;&gt;Загрузчик&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D1%87%D0%B8%D0%BA&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Разметка UEFI — GRUB ставится в ESP:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pacman -S grub efibootmgr

grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;BIOS-режим (legacy): тот же &lt;code&gt;grub-install /dev/sda&lt;/code&gt;, но ESP тогда не нужен.
Если рядом стоит другая ОС: пакет &lt;code&gt;os-prober&lt;/code&gt; и строка &lt;code&gt;GRUB_DISABLE_OS_PROBER=false&lt;/code&gt; в &lt;code&gt;/etc/default/grub&lt;/code&gt; перед &lt;code&gt;grub-mkconfig&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;пользователь&quot;&gt;Пользователь&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Работать под root — плохая привычка; создаём обычного пользователя с sudo:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;useradd -m -G wheel -s /bin/bash admin
passwd admin

pacman -S sudo
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;sudo читает каталог &lt;code&gt;/etc/sudoers.d/&lt;/code&gt; — править вендорский sudoers не надо:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &quot;%wheel ALL=(ALL:ALL) ALL&quot; &amp;gt; /etc/sudoers.d/10-wheel
chmod 440 /etc/sudoers.d/10-wheel
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;рабочее-окружение&quot;&gt;Рабочее окружение&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%80%D0%B0%D0%B1%D0%BE%D1%87%D0%B5%D0%B5-%D0%BE%D0%BA%D1%80%D1%83%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Xorg
pacman -S xorg-server xorg-xinit xorg-apps

# Тайловый менеджер i3 + дисплейный менеджер
pacman -S i3-wm i3lock i3status
pacman -S lightdm lightdm-gtk-greeter
systemctl enable lightdm
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Не фанат i3: полноценный вариант — &lt;code&gt;pacman -S plasma sddm&lt;/code&gt; (KDE Plasma)
или &lt;code&gt;pacman -S gnome gdm&lt;/code&gt;. Тайловый стек (i3 + status) — легче на порядок.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;перезагрузка-и-первые-шаги&quot;&gt;Перезагрузка и первые шаги&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D0%B5%D1%80%D0%B5%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B0-%D0%B8-%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B5-%D1%88%D0%B0%D0%B3%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;exit                 # выходим из chroot
reboot               # вынув флешку

# Уже в своей системе: обновляем всё и ставим привычные пакеты
pacman -Syu
pacman -S git curl neovim
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;лайфхаки-pacman-и-aur&quot;&gt;Лайфхаки pacman и AUR&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BB%D0%B0%D0%B9%D1%84%D1%85%D0%B0%D0%BA%D0%B8-pacman-%D0%B8-aur&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Поиск и информация
pacman -Ss nginx                 # поиск по репозиториям
pacman -Qi nginx                 # инфо об установленном
pacman -Ql nginx                 # список файлов пакета
pacman -Qo /usr/bin/nginx        # кто владеет файлом

# Список явно установленных пакетов — бэкап состава системы
pacman -Qe | awk &#39;{print $1}&#39; &amp;gt; pkglist.txt
pacman -S --needed - &amp;lt; pkglist.txt   # восстановить на новой машине

# Кэш пакетов ест много: оставить по 2 версии каждого пакета
pacman -S pacman-contrib
paccache -rk2

# Сироты — пакеты, никто из установленных явно не требует
pacman -Rns $(pacman -Qdtq)

# Свежие быстрые зеркала в mirrorlist
pacman -S reflector
reflector --country BY,PL --sort rate --latest 10 --save /etc/pacman.d/mirrorlist
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Rolling release = обновляйтесь регулярно, а не раз в полгода:
&lt;code&gt;pacman -Syu&lt;/code&gt; раз в неделю-две. Проблемный обновляющийся пакет
(например, ядро) можно заморозить строкой &lt;code&gt;IgnorePkg = linux&lt;/code&gt;
в &lt;code&gt;/etc/pacman.conf&lt;/code&gt; — на свой страх и риск.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;AUR — сторонний репозиторий сообщества со «всем на свете»; ставится через
хелпер (paru или yay): &lt;code&gt;paru -S &amp;lt;название-пакета&amp;gt;&lt;/code&gt;. Хелпер сам вытаскивает
PKGBUILD, собирает пакет и подключает его к pacman-базе. Правило безопасности:
читайте PKGBUILD перед сборкой и не запускайте хелпер под root.&lt;/p&gt;
</content:encoded>
        </item>
        <item>
            <title>Docker и Docker Compose</title>
            <link>https://itcompressor.e7.by/articles/devops/docker/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/devops/docker/</guid>
            <pubDate>Fri, 10 Feb 2023 00:00:00 GMT</pubDate>
            <description>Docker на Ubuntu: установка, контейнеры, образы, сети, тома и Docker Compose</description>
            <category>docker</category>
            <category>devops</category>
            <category>containers</category>
            <content:encoded>&lt;p&gt;Docker — платформа контейнеризации: приложение упаковывается вместе с
окружением и зависимостями в образ, из которого поднимаются изолированные
контейнеры. Один и тот же образ разворачивается одинаково на любой Linux-машине.&lt;/p&gt;
&lt;p&gt;Сценарий статьи: контейнер &lt;code&gt;web&lt;/code&gt; с nginx на 8080-м порту, плюс база в Compose.&lt;/p&gt;
&lt;h2 id=&quot;установка-ubuntu&quot;&gt;Установка (Ubuntu)&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-ubuntu&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Официальный репозиторий Docker:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Ключ подписи репозитория
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Репозиторий (формат deb822)
sudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release &amp;amp;&amp;amp; echo &quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&quot;)
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

# Установка движка и плагинов (включая Compose)
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Пакет из дистрибутива Ubuntu (&lt;code&gt;apt install docker.io&lt;/code&gt;) — допустимая, но
обычно отстающая альтернатива.&lt;/p&gt;
&lt;h2 id=&quot;права-работать-без-sudo&quot;&gt;Права: работать без sudo&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D1%80%D0%B0%D0%B2%D0%B0-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0%D1%82%D1%8C-%D0%B1%D0%B5%D0%B7-sudo&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Демон слушает unix-сокет, доступный группе &lt;code&gt;docker&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo usermod -aG docker $USER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Перезагрузка не нужна — достаточно перелогина (или &lt;code&gt;newgrp docker&lt;/code&gt; в текущей
сессии). Проверка:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Члены группы &lt;code&gt;docker&lt;/code&gt; фактически имеют root-доступ к хосту (можно смонтировать
корень хоста &lt;code&gt;/&lt;/code&gt; в контейнер) — давайте её только тем, кому доверяете как root&#39;у.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;контейнеры&quot;&gt;Контейнеры&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%B9%D0%BD%D0%B5%D1%80%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Запустить web: nginx из 8080 хоста на 80 контейнера, имя web (-d — в фон)
docker run -d --name web -p 8080:80 nginx

# Что сейчас работает / всё, включая остановленные
docker ps
docker ps -a

# Логи (следить: -f)
docker logs web

# Остановка / запуск / перезапуск
docker stop web
docker start web
docker restart web

# Внутрь запущенного контейнера — шелл
docker exec -it web bash

# Одноразовый контейнер: убить после выхода (--rm)
docker run -it --rm ubuntu bash

# Удалить остановленный контейнер
docker rm web
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Имя &lt;code&gt;web&lt;/code&gt; используется во всех командах вместо длинного ID. &lt;code&gt;--rm&lt;/code&gt; —
для разовых задач; именованные контейнеры — для служб.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;образы&quot;&gt;Образы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Скачать образ с Docker Hub
docker pull nginx

# Локальные образы
docker images

# Сборка из Dockerfile в текущем каталоге
docker build -t my-app .

# Удалить образ
docker rmi nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;сети&quot;&gt;Сети&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%81%D0%B5%D1%82%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Пользовательская сеть
docker network create my-network

# Список сетей
docker network ls

# Запуск контейнера в этой сети
docker run -d --name web --network my-network nginx

# Удаление сети
docker network rm my-network
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Внутри пользовательской сети контейнеры резолвятся по именам: &lt;code&gt;web&lt;/code&gt;
доступен соседям просто по &lt;code&gt;http://web:80&lt;/code&gt; — без парентов IP. В дефолтной
bridge-сети такого DNS нет.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;тома&quot;&gt;Тома&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%82%D0%BE%D0%BC%D0%B0&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Создать именованный том
docker volume create app-data

# Список томов
docker volume ls

# Бросить том в контейнер
docker run -d --name web -v app-data:/var/lib/nginx nginx

# Удалить
docker volume rm app-data
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Том (&lt;code&gt;-v app-data:/путь&lt;/code&gt;) живёт отдельно от контейнера — данные
переживают удаление контейнера. Привязка каталога хоста работает так же:
&lt;code&gt;-v ./html:/usr/share/nginx/html&lt;/code&gt; (bind mount).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;docker-compose&quot;&gt;Docker Compose&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#docker-compose&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Compose описывает многоконтейнерное приложение в одном YAML — состав,
сети, тома и переменные. &lt;code&gt;compose.yaml&lt;/code&gt; (v2: секция &lt;code&gt;version&lt;/code&gt; больше не нужна):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;services:
  web:
    image: nginx
    ports:
      - &quot;8080:80&quot;
    volumes:
      - ./html:/usr/share/nginx/html
  db:
    image: postgres
    environment:
      POSTGRES_PASSWORD: example
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Команды (современный CLI — &lt;code&gt;docker compose&lt;/code&gt; одним словом, плагин из
установки выше; дефисный &lt;code&gt;docker-compose&lt;/code&gt; — legacy v1):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Поднять всё приложение фоном
docker compose up -d

# Что работает
docker compose ps

# Логи (следить: -f) по одному сервису или всем
docker compose logs -f web

# Пересобрать образы после правок Dockerfile
docker compose build

# Шелл внутри сервиса
docker compose exec web bash

# Остановить и убрать контейнеры/сети
docker compose down

# То же, но с wipe&#39;ом данных томов
docker compose down --volumes
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;docker compose down&lt;/code&gt; не трогает тома — базы переживают перезапуск;
чтобы потереть и данные, добавляют &lt;code&gt;--volumes&lt;/code&gt;. Сервисы Compose резолвятся
по имени внутри пользовательской сети, которую Compose создаёт сам.&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded>
        </item>
        <item>
            <title>О производительности Raspberry Pi 4 Model B</title>
            <link>https://itcompressor.e7.by/articles/hardware/pi4_performance/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/hardware/pi4_performance/</guid>
            <pubDate>Sun, 02 Jan 2022 00:00:00 GMT</pubDate>
            <description>Миниатюрный одноплатный компьютер Raspberry Pi 4 Model B — это полноценная замена десктопу на Linux. Платформа подходит не только для веб-сёрфинга и разработки приложений, но и может стать «мозгом» для робота или умного дома, медиацентром, узлом распределённой вычислительной системы или промышленным контроллером.</description>
            <category>linux</category>
            <category>rpi</category>
            <category>pi4</category>
            <content:encoded>
&lt;p&gt;Миниатюрный одноплатный компьютер Raspberry Pi 4 Model B — это полноценная замена десктопу на Linux. Платформа подходит не только для веб-сёрфинга и разработки приложений, но и может стать «мозгом» для робота или умного дома, медиацентром, узлом распределённой вычислительной системы или промышленным контроллером.&lt;/p&gt;
&lt;h2 id=&quot;фото-raspberry-pi-4&quot;&gt;Фото Raspberry Pi 4&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%84%D0%BE%D1%82%D0%BE-raspberry-pi-4&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;details&gt;&lt;summary&gt;Фото самой малинки&lt;/summary&gt;
&lt;p&gt;

&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://itcompressor.e7.by/images/hardware/rpi/pi4_3.png&quot; alt=&quot;pi4_3.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;/details&gt;

&lt;h2 id=&quot;проверка-производительности&quot;&gt;Проверка производительности&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0-%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Решил проверить производительность малинки, запустив на ней большую часть своих ботов и был приятно удивлен.&lt;/p&gt;
&lt;p&gt;Использую стандартную ОС: Raspbian GNU/Linux 10 (buster) armv7l, запущено 6 spring boot application, 5 из которых боты (4 телеграмм бота), бд (в основном mongodb) - внешняя.&lt;/p&gt;
&lt;h2 id=&quot;мониторинг-загрузки&quot;&gt;Мониторинг загрузки&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BC%D0%BE%D0%BD%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%BD%D0%B3-%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ниже представлен скриншот мониторинга загрузки:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://itcompressor.e7.by/images/hardware/rpi/pi4_performance.png&quot; alt=&quot;pi4_performance.png&quot;&gt;&lt;/p&gt;
</content:encoded>
        </item>
        <item>
            <title>История о стареньком Philips Xenium W6610</title>
            <link>https://itcompressor.e7.by/articles/hardware/philips/</link>
            <guid isPermaLink="true">https://itcompressor.e7.by/articles/hardware/philips/</guid>
            <pubDate>Fri, 05 Jul 2019 00:00:00 GMT</pubDate>
            <description>История о том, как я пытался освободить свой смартфон от слежки Google, блокируя их серверы через hosts и iptables.</description>
            <category>android</category>
            <category>google</category>
            <content:encoded>
&lt;p&gt;История о том, как я пытался освободить свой смартфон от слежки Google, блокируя их серверы через hosts и iptables.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://itcompressor.e7.by/images/hardware/philips.png&quot; alt=&quot;philips&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;проблема-с-google-сервисами&quot;&gt;Проблема с Google сервисами&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D0%BF%D1%80%D0%BE%D0%B1%D0%BB%D0%B5%D0%BC%D0%B0-%D1%81-google-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%B0%D0%BC%D0%B8&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Уже давно я потрошил один из своих андроид смартфонов (Philips Xenium W6610) и заметил, что даже при полностью удаленных гугл сервисах гугл не отпускает смартфон на свободу, при этом смарт держит связь с несколькими серверами гугл (германия, штаты) + как бонус 2 китайских серверов (определить владельцев не удалось).&lt;/p&gt;
&lt;h2 id=&quot;решение-проблемы&quot;&gt;Решение проблемы&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BF%D1%80%D0%BE%D0%B1%D0%BB%D0%B5%D0%BC%D1%8B&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Решал проблему баном доменов через &lt;code&gt;/system/etc/hosts&lt;/code&gt; (ссылка домена на 127.0.0.1) + запросы по ip банил с помощью &lt;code&gt;iptables&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;При бане заметил переключение на запасные сервера.&lt;/p&gt;
&lt;h3 id=&quot;список-заблокированных-ip-адресов&quot;&gt;Список заблокированных IP-адресов&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-ip-%D0%B0%D0%B4%D1%80%D0%B5%D1%81%D0%BE%D0%B2&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;172.217.23.174&lt;/li&gt;
&lt;li&gt;216.58.205.238&lt;/li&gt;
&lt;li&gt;172.217.21.238&lt;/li&gt;
&lt;li&gt;54.230.230.126&lt;/li&gt;
&lt;li&gt;128.199.105.193&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;список-заблокированных-доменов&quot;&gt;Список заблокированных доменов&lt;a aria-label=&quot;Ссылка на раздел&quot; href=&quot;#%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-%D0%B4%D0%BE%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2&quot; class=&quot;heading-anchor&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;server-54-230-230-126.waw50.r.cloudfront.net&lt;/li&gt;
&lt;li&gt;fra15s24-in-f14.1e100.net&lt;/li&gt;
&lt;li&gt;fra16s25-in-f14.1e100.net&lt;/li&gt;
&lt;/ul&gt;
</content:encoded>
        </item>
    </channel>
</rss>
