<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DevOps Notes</title><link>https://vlasov.pro/en/</link><description>Recent content on DevOps Notes</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Sun, 25 Jan 2026 14:55:27 +0200</lastBuildDate><atom:link href="https://vlasov.pro/en/index.xml" rel="self" type="application/rss+xml"/><item><title>Clever Disk Encryption with dm-crypt Nuke</title><link>https://vlasov.pro/en/p/dm-crypt-nuke/</link><pubDate>Thu, 16 Jan 2025 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/dm-crypt-nuke/</guid><description>&lt;img src="https://vlasov.pro/ru/p/dm-crypt-nuke/logo.webp" alt="Featured image of post Clever Disk Encryption with dm-crypt Nuke" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>Disk encryption using &lt;code>dm-crypt&lt;/code> is a reliable way to protect data. However, in extreme situations, it may be necessary to instantly and irreversibly destroy encryption keys to render the data inaccessible. The &lt;strong>nuke&lt;/strong> mechanism can be used for this purpose, activated by entering a special password.&lt;/p>
&lt;p>In this article, we will explore how to implement &lt;strong>nuke&lt;/strong> in &lt;code>dm-crypt&lt;/code> using &lt;strong>initramfs&lt;/strong>, &lt;code>cryptsetup&lt;/code>, and &lt;code>mkpasswd&lt;/code>.&lt;/p>
&lt;p>The developed hook is capable of:&lt;/p>
&lt;ol>
&lt;li>Decrypting the disk using data from a file.&lt;/li>
&lt;li>Prompting for a password if the file is not found.&lt;/li>
&lt;li>Deleting all keys if the entered password is a nuke password.&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Important!&lt;/strong> This setup works on Ubuntu 22.04.5. Other distributions might require different configurations. In any case, here is an article on &lt;a class="link" href="../gpt-btrfs-gnome/#grub-recovery-script" >recovering Grub&lt;/a>.&lt;/p>
&lt;h2 id="environment-setup">Environment Setup &lt;a href="#environment-setup">¶&lt;/a>&lt;/h2>
&lt;p>Before starting, ensure that the necessary utilities are installed:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">sudo apt update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt install cryptsetup initramfs-tools whois
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="adding-mkpasswd-support-in-initramfs">Adding &lt;code>mkpasswd&lt;/code> Support in initramfs &lt;a href="#adding-mkpasswd-support-in-initramfs">¶&lt;/a>&lt;/h2>
&lt;p>The &lt;strong>nuke&lt;/strong> mechanism requires &lt;code>mkpasswd&lt;/code>, which is used to verify the entered password. We need to add it to initramfs by creating a hook:&lt;/p>
&lt;p>File &lt;code>/etc/initramfs-tools/hooks/mkpasswd&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/bin/sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$1&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;prereqs&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">. /usr/share/initramfs-tools/hook-functions
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! &lt;span class="nb">command&lt;/span> -v mkpasswd 1&amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;error: mkpasswd executable is not found, install it.&amp;#34;&lt;/span> 1&amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">copy_exec &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">command&lt;/span> -v mkpasswd&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">copy_exec &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">command&lt;/span> -v dd&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> /sbin
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Make it executable:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">sudo chmod +x /etc/initramfs-tools/hooks/mkpasswd
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="creating-the-decrypt_smart_nuke-script">Creating the &lt;code>decrypt_smart_nuke&lt;/code> Script &lt;a href="#creating-the-decrypt_smart_nuke-script">¶&lt;/a>&lt;/h2>
&lt;p>File &lt;code>/usr/lib/cryptsetup/scripts/decrypt_smart_nuke&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;span class="lnt">107
&lt;/span>&lt;span class="lnt">108
&lt;/span>&lt;span class="lnt">109
&lt;/span>&lt;span class="lnt">110
&lt;/span>&lt;span class="lnt">111
&lt;/span>&lt;span class="lnt">112
&lt;/span>&lt;span class="lnt">113
&lt;/span>&lt;span class="lnt">114
&lt;/span>&lt;span class="lnt">115
&lt;/span>&lt;span class="lnt">116
&lt;/span>&lt;span class="lnt">117
&lt;/span>&lt;span class="lnt">118
&lt;/span>&lt;span class="lnt">119
&lt;/span>&lt;span class="lnt">120
&lt;/span>&lt;span class="lnt">121
&lt;/span>&lt;span class="lnt">122
&lt;/span>&lt;span class="lnt">123
&lt;/span>&lt;span class="lnt">124
&lt;/span>&lt;span class="lnt">125
&lt;/span>&lt;span class="lnt">126
&lt;/span>&lt;span class="lnt">127
&lt;/span>&lt;span class="lnt">128
&lt;/span>&lt;span class="lnt">129
&lt;/span>&lt;span class="lnt">130
&lt;/span>&lt;span class="lnt">131
&lt;/span>&lt;span class="lnt">132
&lt;/span>&lt;span class="lnt">133
&lt;/span>&lt;span class="lnt">134
&lt;/span>&lt;span class="lnt">135
&lt;/span>&lt;span class="lnt">136
&lt;/span>&lt;span class="lnt">137
&lt;/span>&lt;span class="lnt">138
&lt;/span>&lt;span class="lnt">139
&lt;/span>&lt;span class="lnt">140
&lt;/span>&lt;span class="lnt">141
&lt;/span>&lt;span class="lnt">142
&lt;/span>&lt;span class="lnt">143
&lt;/span>&lt;span class="lnt">144
&lt;/span>&lt;span class="lnt">145
&lt;/span>&lt;span class="lnt">146
&lt;/span>&lt;span class="lnt">147
&lt;/span>&lt;span class="lnt">148
&lt;/span>&lt;span class="lnt">149
&lt;/span>&lt;span class="lnt">150
&lt;/span>&lt;span class="lnt">151
&lt;/span>&lt;span class="lnt">152
&lt;/span>&lt;span class="lnt">153
&lt;/span>&lt;span class="lnt">154
&lt;/span>&lt;span class="lnt">155
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/bin/sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">KEYFILE_ENABLED&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;false&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">NUKE_ENABLED&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;false&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">KEYFILE_PATH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">KEYFILE_OFFSET&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">KEYFILE_SIZE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">NUKE_PASSWORD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CRYPTTAB_TRIED&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CRYPTTAB_TRIED&lt;/span>&lt;span class="p">?:&lt;/span>&lt;span class="nv">CRYPTTAB_TRIED&lt;/span>&lt;span class="p"> is not defined&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CRYPTTAB_NAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CRYPTTAB_NAME&lt;/span>&lt;span class="p">?:&lt;/span>&lt;span class="nv">CRYPTTAB_NAME&lt;/span>&lt;span class="p"> is not defined&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CRYPTTAB_SOURCE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CRYPTTAB_SOURCE&lt;/span>&lt;span class="p">?:&lt;/span>&lt;span class="nv">CRYPTTAB_SOURCE&lt;/span>&lt;span class="p"> is not defined&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">ASKPASS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;/lib/cryptsetup/askpass&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┬─┐┬ ┐┌┐┐┌─┐┌┐┐o┌─┐┌┐┐┐─┐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ├─ │ │││││ │ ││ ││││└─┐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┘ ┘─┘┘└┘└─┘ ┘ ┘┘─┘┘└┘──┘&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Logging helpers. Send the argument list to plymouth(1), or fold it&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># and print it to the standard error.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">message&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">local&lt;/span> &lt;span class="nv">IFS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39; &amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">0&lt;/span>&lt;span class="p">#/scripts/&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> !&lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$0&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="o">[&lt;/span> -x /bin/plymouth &lt;span class="o">]&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> plymouth --ping&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> plymouth message --text&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;cryptsetup: &lt;/span>&lt;span class="nv">$*&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="si">${#&lt;/span>&lt;span class="p">*&lt;/span>&lt;span class="si">}&lt;/span> -lt &lt;span class="m">70&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;cryptsetup: &lt;/span>&lt;span class="nv">$*&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> 1&amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># use busybox&amp;#39;s fold(1) and sed(1) at initramfs stage&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;cryptsetup: &lt;/span>&lt;span class="nv">$*&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> fold -s &lt;span class="p">|&lt;/span> sed &lt;span class="s1">&amp;#39;1! s/^/ /&amp;#39;&lt;/span> 1&amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">parse_options&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">local&lt;/span> &lt;span class="nv">IFS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;,&amp;#34;&lt;/span> key value regex
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> option in &lt;span class="nv">$1&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">option&lt;/span>&lt;span class="p">%%=*&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">option&lt;/span>&lt;span class="p">#*=&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">case&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$key&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> in
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> keyfile-path&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -e &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$value&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> message &lt;span class="s2">&amp;#34;warning: keyfile at &lt;/span>&lt;span class="nv">$value&lt;/span>&lt;span class="s2"> does not exist&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">export&lt;/span> &lt;span class="nv">KEYFILE_ENABLED&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;true&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">export&lt;/span> &lt;span class="nv">KEYFILE_PATH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$value&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> keyfile-offset&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">export&lt;/span> &lt;span class="nv">KEYFILE_OFFSET&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$value&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> keyfile-size&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">export&lt;/span> &lt;span class="nv">KEYFILE_SIZE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$value&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nuke&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">regex&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;(\$[^$]+){3,}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> ! &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$value&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> grep -qE &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$regex&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> message &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">printf&lt;/span> &lt;span class="s2">&amp;#34;error: password hash does not match the regex &amp;#39;%s&amp;#39;: %s\n&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$regex&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$value&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">export&lt;/span> &lt;span class="nv">NUKE_ENABLED&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;true&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">export&lt;/span> &lt;span class="nv">NUKE_PASSWORD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$value&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> none&lt;span class="o">)&lt;/span> true&lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> *&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> message &lt;span class="s2">&amp;#34;error: unknown option &lt;/span>&lt;span class="nv">$key&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="nv">$value&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> 1&amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">esac&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">read_keyfile&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$KEYFILE_ENABLED&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> !&lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;true&amp;#39;&lt;/span> &lt;span class="o">]&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CRYPTTAB_TRIED&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -ne &lt;span class="m">0&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -n &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$KEYFILE_SIZE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> dd &lt;span class="k">if&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$KEYFILE_PATH&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="nv">iflag&lt;/span>&lt;span class="o">=&lt;/span>skip_bytes &lt;span class="nv">skip&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$KEYFILE_OFFSET&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="nv">bs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$KEYFILE_SIZE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="nv">count&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> 2&amp;gt;/dev/null
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> dd &lt;span class="k">if&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$KEYFILE_PATH&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="nv">iflag&lt;/span>&lt;span class="o">=&lt;/span>skip_bytes &lt;span class="nv">skip&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$KEYFILE_OFFSET&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> 2&amp;gt;/dev/null
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nuke&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> YES &lt;span class="p">|&lt;/span> cryptsetup erase &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CRYPTTAB_SOURCE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> 1&amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">2&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ________________
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ____/ ( ( ) ) \___
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> /( ( ( ) _ )) ) )\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> (( ( )( ) ) ( ) )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ((/ ( _( ) ( _) ) ( () ) )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( ( ( (_) (( ( ) .((_ ) . )_
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( ( ) ( ( ) ) ) . ) ( )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( ( ( ( ) ( _ ( _) ). ) . ) ) ( )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( ( ( ) ( ) ( )) ) _)( ) ) )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( ( ( \ ) ( (_ ( ) ( ) ) ) ) )) ( )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( ( ( ( (_ ( ) ( _ ) ) ( ) ) )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( ( ( ( ( ) (_ ) ) ) _) ) _( ( )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> (( ( )( ( _ ) _) _(_ ( (_ )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> (_((__(_(__(( ( ( | ) ) ) )_))__))_)___)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ((__) \\||lll|l||/// \_))
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( /(/ ( ) ) )\ )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( ( ( ( | | ) ) )\ )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( /(| / ( )) ) ) )) )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( ( ((((_(|)_))))) )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( ||\(|(|)|/|| )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( |(||(||)|||| )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ( //|/l|||)|\\ \ )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> (/ / // /|//||||\\ \ \ \ _)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">-----------------------------!!! YOU ARE NUKED !!!-----------------------------
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">&amp;#39;&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> message &lt;span class="s2">&amp;#34;Data destroyed! They may try to extract information from you, but there&amp;#39;s nothing more you can do. Good luck!&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">read_interactive&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">local&lt;/span> password salt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">password&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nv">$ASKPASS&lt;/span> &lt;span class="s2">&amp;#34;Enter passphrase for &lt;/span>&lt;span class="nv">$CRYPTTAB_NAME&lt;/span>&lt;span class="s2"> (&lt;/span>&lt;span class="nv">$CRYPTTAB_SOURCE&lt;/span>&lt;span class="s2">): &amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NUKE_ENABLED&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;true&amp;#39;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">salt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NUKE_PASSWORD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> cut -d$ -f3&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> method in bcrypt bcrypt-a sha256crypt sha512crypt md5crypt&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> mkpasswd -m &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$method&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -S &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$salt&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$password&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> 2&amp;gt;/dev/null &lt;span class="p">|&lt;/span> grep -qF -- &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NUKE_PASSWORD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nuke
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s2">&amp;#34;%s&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$password&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┌─┐┬ ┬┬─┐┌─┐┬┌ ┐─┐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># │ │─┤├─ │ ├┴┐└─┐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># └─┘┘ ┴┴─┘└─┘┘ ┘──┘&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! &lt;span class="nb">command&lt;/span> -v mkpasswd 1&amp;gt;/dev/null 2&amp;gt;&lt;span class="p">&amp;amp;&lt;/span>1&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> message &lt;span class="s2">&amp;#34;error: mkpasswd binary is not found&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">elif&lt;/span> &lt;span class="o">[&lt;/span> ! -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$ASKPASS&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> message &lt;span class="s2">&amp;#34;error: &lt;/span>&lt;span class="nv">$ASKPASS&lt;/span>&lt;span class="s2"> does not exist&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">elif&lt;/span> &lt;span class="o">[&lt;/span> ! -e &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CRYPTTAB_SOURCE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> message &lt;span class="s2">&amp;#34;error: crypttab source device does not exist&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┌┌┐┬─┐o┌┐┐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ││││─┤││││&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┘ ┘┘ ┘┘┘└┘&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">parse_options &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$1&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">read_keyfile
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">read_interactive
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Make it executable:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">sudo chmod +x /usr/lib/cryptsetup/scripts/decrypt_smart_nuke
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="boot-configuration">Boot Configuration &lt;a href="#boot-configuration">¶&lt;/a>&lt;/h2>
&lt;p>Edit &lt;code>/etc/default/grub&lt;/code> and add the &lt;code>cryptdevice&lt;/code> argument:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">GRUB_CMDLINE_LINUX_DEFAULT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;... cryptdevice=UUID=bb85fe0a-4ef7-49c4-b15c-fb613d51e9ef:cryptroot&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Then add the following line to &lt;code>/etc/crypttab&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">cryptroot &lt;span class="nv">UUID&lt;/span>&lt;span class="o">=&lt;/span>bb85fe0a-4ef7-49c4-b15c-fb613d51e9ef keyfile-path&lt;span class="o">=&lt;/span>/dev/mmcblk0,keyfile-offset&lt;span class="o">=&lt;/span>8932578598,keyfile-size&lt;span class="o">=&lt;/span>11045,nuke&lt;span class="o">=&lt;/span>HASH luks,discard,keyscript&lt;span class="o">=&lt;/span>decrypt_smart_nuke
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>To generate a hash for the nuke password:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">mkpasswd -m sha512crypt --rounds&lt;span class="o">=&lt;/span>&lt;span class="m">5000&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="updating-initramfs">Updating initramfs &lt;a href="#updating-initramfs">¶&lt;/a>&lt;/h2>
&lt;p>After making all changes, update initramfs and grub:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">sudo update-initramfs -u
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo update-grub2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="conclusion">Conclusion &lt;a href="#conclusion">¶&lt;/a>&lt;/h2>
&lt;p>Now, if the &lt;strong>nuke password&lt;/strong> is entered at boot, the script will destroy the encryption keys, making the data inaccessible. This method is suitable for critical situations requiring rapid and irreversible data protection.&lt;/p>
&lt;p>Additionally, the system will decrypt itself automatically if the key file is present. If needed, the USB drive can be removed, prompting the system for a password.&lt;/p>
&lt;p>&lt;strong>Backup your LUKS header before enabling this!&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">sudo cryptsetup luksHeaderBackup /dev/sda1 --header-backup-file ./backup.luks
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Kubernetes Node role labeler</title><link>https://vlasov.pro/en/p/node-role-labeler/</link><pubDate>Tue, 08 Oct 2024 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/node-role-labeler/</guid><description>&lt;img src="https://vlasov.pro/ru/p/node-role-labeler/logo.webp" alt="Featured image of post Kubernetes Node role labeler" />&lt;h2 id="description">Description &lt;a href="#description">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://github.com/vlasov-y/node-role-labeler" target="_blank" rel="noopener"
>Node Role Labeler&lt;/a> has long been sought after, a simple operator, but the task is fulfilled. The problem is that Kubernetes, specifically kubelet, cannot assign itself a label of &lt;code>node-role.kubernetes.io/ROLE_NAME&lt;/code> when creating a node, because of the kubernetes.io protected prefix. Not very convenient.&lt;/p>
&lt;p>Here I have &lt;a class="link" href="https://karpenter.sh" target="_blank" rel="noopener"
>Karpenter&lt;/a>, or &lt;a class="link" href="https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler" target="_blank" rel="noopener"
>Cluster Autoscaler&lt;/a>, no matter what, I want nodes to have nice roles immediately, and it does not come out of the box only by hand. Now we can attach &lt;code>node-role.cluster.local/NAME&lt;/code> and the operator will create an automatically copy with a domain kubernetes.io. In reverse also works. More information - read on GitHub.&lt;/p>
&lt;h2 id="demo">Demo &lt;a href="#demo">¶&lt;/a>&lt;/h2>
&lt;script src="https://asciinema.org/a/679600.js" id="asciicast-679600" async="true">&lt;/script>
&lt;h2 id="karpenter-configuration">Karpenter configuration &lt;a href="#karpenter-configuration">¶&lt;/a>&lt;/h2>
&lt;p>Here is how we can immediately attach labels to Karpenter nodes.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;span class="lnt">88
&lt;/span>&lt;span class="lnt">89
&lt;/span>&lt;span class="lnt">90
&lt;/span>&lt;span class="lnt">91
&lt;/span>&lt;span class="lnt">92
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">karpenter.k8s.aws/v1beta1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">EC2NodeClass&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">private&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">amiFamily&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">AL2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">metadataOptions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">httpEndpoint&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">enabled&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">httpProtocolIPv6&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">disabled&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">httpPutResponseHopLimit&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">httpTokens&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">required&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">role&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Karpenter-development-role&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">securityGroupSelectorTerms&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">tags&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">karpenter.sh/discovery&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">development&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">subnetSelectorTerms&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">tags&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">karpenter.sh/discovery/development/subnet&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">private&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">tags&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">karpenter.sh/discovery&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">development&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">karpenter.sh/v1beta1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">NodePool&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">on&lt;/span>-&lt;span class="l">demand-amd64&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">disruption&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">budgets&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">nodes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">20&lt;/span>&lt;span class="l">%&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">nodes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;5&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">duration&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">20h&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">nodes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;0&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">schedule&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">5&lt;/span>&lt;span class="w"> &lt;/span>*&lt;span class="w"> &lt;/span>*&lt;span class="w"> &lt;/span>*&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">consolidationPolicy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">WhenUnderutilized&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">expireAfter&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">720h&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">limits&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;200&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">400Gi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">template&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">labels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">node-role.cluster.local/on-demand-amd64&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">nodeClassRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">private&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">requirements&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">key&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">kubernetes.io/arch&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">In&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">amd64&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">key&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">node.kubernetes.io/instance-type&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">In&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5a.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5a.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5a.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5a.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5a.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">r5.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m6i.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m6i.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m6i.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m6i.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m6i.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5a.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5a.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5a.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5a.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">m5a.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6a.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6a.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6a.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6a.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6a.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">c6.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">t3a.4xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">t3a.2xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">t3a.xlarge&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">t3a.large&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">t3a.medium&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">key&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">karpenter.sh/capacity-type&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">operator&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">In&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">values&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="kc">on&lt;/span>-&lt;span class="l">demand&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>BTRFS checksum benchmark</title><link>https://vlasov.pro/en/p/btrfs-checksum/</link><pubDate>Sun, 30 Jul 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/btrfs-checksum/</guid><description>&lt;img src="https://vlasov.pro/ru/p/btrfs-checksum/logo.webp" alt="Featured image of post BTRFS checksum benchmark" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>I&amp;rsquo;m switching to a new hardware and I&amp;rsquo;m using a clean SSD. Now, I&amp;rsquo;m facing the choice of the algorithm for the BTRFS file system. Here is a script that I used to determine which one was the fastest on my specific processor.&lt;/p>
&lt;h2 id="body">Body &lt;a href="#body">¶&lt;/a>&lt;/h2>
&lt;p>I started by searching for an utility to measure the performance of different hash algorithms. Why? Because, no matter how fast an algorithm seems on paper, if it&amp;rsquo;s not supported by my processor - it will be slow. And how can I know what&amp;rsquo;s supported by my processor? In the specification online, I didn&amp;rsquo;t find any information.&lt;/p>
&lt;p>I stumbled upon the &lt;a class="link" href="https://github.com/rhash/RHash" target="_blank" rel="noopener"
>rhash&lt;/a> utility, which has a &lt;code>--speed&lt;/code> key. That&amp;rsquo;s where I tried to measure performance, but the results of &lt;code>blake2b&lt;/code> and &lt;code>crc32c&lt;/code> were almost identical, which seemed strange to me. In the end, I came up with this script.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env bash
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -eo pipefail
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">TMPFS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mktemp -d&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SIZE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;5G&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount -t tmpfs -o &lt;span class="nv">size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SIZE&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> tmpfs &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">TMPFS&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">TMPFS&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">fallocate -l 4GiB btrfs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> CSUM in crc32c xxhash sha256 blake2&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mkfs.btrfs -f -d single -m single --csum &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CSUM&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> btrfs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mount btrfs /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> cd /mnt
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> echo &amp;#34;&lt;/span>info: &lt;span class="si">${&lt;/span>&lt;span class="nv">CSUM&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> dd if=/dev/urandom of=test bs=4M count=1024 2&amp;gt;/dev/null
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> rm -f test
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> for i in {1..1000}; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> dd if=/dev/urandom of=&amp;#34;&lt;/span>&lt;span class="se">\$&lt;/span>i&lt;span class="s2">&amp;#34; bs=4M count=1 2&amp;gt;/dev/null
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> done
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> rm -f /mnt/*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> /usr/bin/time bash
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> umount /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">TMPFS&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rm -rf &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">TMPFS&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>What&amp;rsquo;s going on here?&lt;/p>
&lt;ol>
&lt;li>A tmpfs temporary mount point is created on 5 GB (right in the RAM, so it doesn&amp;rsquo;t depend on SSD/HDD)&lt;/li>
&lt;li>Inside a file of 4 GB is created and then formatted as BTRFS with different hash algorithms&lt;/li>
&lt;li>For each algorithm, two file writing modes are performed:
&lt;ol>
&lt;li>One large file of 4 GB&lt;/li>
&lt;li>1000 files of 4 MB&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>At the end, the &lt;code>time&lt;/code> command outputs the script execution time&lt;/li>
&lt;/ol>
&lt;p>On my &lt;em>11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz&lt;/em> processor, the best result was shown by the old and good &lt;strong>crc32c&lt;/strong> (~35 seconds), while the others were around ~52 seconds.&lt;/p></description></item><item><title>Redis Migration Script</title><link>https://vlasov.pro/en/p/redis-migration/</link><pubDate>Sun, 25 Jun 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/redis-migration/</guid><description>&lt;img src="https://vlasov.pro/ru/p/redis-migration/logo.webp" alt="Featured image of post Redis Migration Script" />&lt;h2 id="old-method">Old Method &lt;a href="#old-method">¶&lt;/a>&lt;/h2>
&lt;p>Sometimes you need to migrate data from one Redis server to another, or between other databases. Previously, I could transfer data from a server only through a full backup, but this does not allow for migrating data between bases. Here is the algorithm.&lt;/p>
&lt;ol>
&lt;li>Enter into the original Redis and make Save&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">REDISCLI_AUTH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;password&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">redis-cli CONFIG GET DIR
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">redis-cli SAVE
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The first command will print the path to the directory where the dump will be stored.&lt;/p>
&lt;ol start="2">
&lt;li>Add arguments to the target Redis to disable AppendOnly and restart it&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">--dbfilename dump.rdb
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">--appendonly no
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>Copy the dump to the target Redis and execute its loading&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">REDISCLI_AUTH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;password&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">redis-cli BGREWRITEAOF
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="4">
&lt;li>Move the target Redis to the AppendOnly mode by removing previously added keys&lt;/li>
&lt;/ol>
&lt;blockquote>
&lt;p>Why migrate data between bases?&lt;/p>
&lt;/blockquote>
&lt;p>In my old cluster, I had two services, each with their own Redis server. In any Redis there are 16 default databases, why not use #0 for service A and #2 for service B? Here you hit into the migration problem from base to base.&lt;/p>
&lt;h2 id="new-method">New Method &lt;a href="#new-method">¶&lt;/a>&lt;/h2>
&lt;p>Based on &lt;a class="link" href="https://redis.io/commands/migrate/" target="_blank" rel="noopener"
>MIGRATE&lt;/a>. The script is presented below. Its advantages are also.&lt;/p>
&lt;ol>
&lt;li>can migrate between bases&lt;/li>
&lt;li>no need to restart Redis&lt;/li>
&lt;li>no need to copy backups&lt;/li>
&lt;li>There is a check after transferring by calculating the hash sum considering both key contents&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SRC_HOSTNAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;source-redis-hostname&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SRC_PORT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;6379&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SRC_PASSWORD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;password&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SRC_DATABASE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;0&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEST_HOSTNAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;destination-redis-hostname&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEST_PORT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;6379&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEST_PASSWORD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;password&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEST_DATABASE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;1&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">main&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> migrate &lt;span class="p">|&lt;/span> xargs -0 &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;migration status: %s&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">CHECKSUM&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mktemp&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">hash&lt;/span> --no-auth-warning -h &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_HOSTNAME&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -p &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_PORT&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -a &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_PASSWORD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -n &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_DATABASE&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> tee &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CHECKSUM&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> xargs -0 &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;source checksum: %s&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">CHECKSUM_VERIFY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CHECKSUM&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="nb">hash&lt;/span> --no-auth-warning -h &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_HOSTNAME&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -p &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_PORT&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -a &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_PASSWORD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -n &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_DATABASE&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> xargs -0 &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;target checksum validation: %s&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CHECKSUM&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">hash&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">EXTRA_ARGS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="p">@&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> redis-cli &lt;span class="si">${&lt;/span>&lt;span class="nv">EXTRA_ARGS&lt;/span>&lt;span class="si">}&lt;/span> --raw --scan &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> sed -r &lt;span class="s1">&amp;#39;s/&amp;#34;/\\&amp;#34;/g; s/^(.+)$/GET &amp;#34;\1&amp;#34;/g;&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> redis-cli &lt;span class="si">${&lt;/span>&lt;span class="nv">EXTRA_ARGS&lt;/span>&lt;span class="si">}&lt;/span> &lt;span class="p">|&lt;/span> sort &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CHECKSUM_VERIFY&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sha256sum -c &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">CHECKSUM_VERIFY&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sha256sum -
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">migrate&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">AUTH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;--no-auth-warning -h &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_HOSTNAME&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -p &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_PORT&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -a &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_PASSWORD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -n &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SRC_DATABASE&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> redis-cli &lt;span class="si">${&lt;/span>&lt;span class="nv">AUTH&lt;/span>&lt;span class="si">}&lt;/span> --raw --scan &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> tr &lt;span class="s1">&amp;#39;\n&amp;#39;&lt;/span> &lt;span class="s1">&amp;#39;\0&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> xargs -0 redis-cli &lt;span class="si">${&lt;/span>&lt;span class="nv">AUTH&lt;/span>&lt;span class="si">}&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> MIGRATE &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_HOSTNAME&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_PORT&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_DATABASE&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="m">5000&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> COPY REPLACE AUTH &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEST_PASSWORD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> KEYS
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">main
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>My Experience with Git</title><link>https://vlasov.pro/en/p/git-hacks/</link><pubDate>Sun, 18 Jun 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/git-hacks/</guid><description>&lt;img src="https://vlasov.pro/ru/p/git-hacks/logo.webp" alt="Featured image of post My Experience with Git" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>Frequently used commands and explanations for them. I hope this will be as useful to someone else as it has been to me.&lt;/p>
&lt;h2 id="main">Main &lt;a href="#main">¶&lt;/a>&lt;/h2>
&lt;h3 id="git-has-a-built-in-graphical-interface">Git has a built-in graphical interface &lt;a href="#git-has-a-built-in-graphical-interface">¶&lt;/a>&lt;/h3>
&lt;p>&lt;a class="link" href="https://git-scm.com/docs/gitk" target="_blank" rel="noopener"
>Gitk&lt;/a> - a simple built-in graphical interface. I really like it for its precision and clarity. I try not to use any Git UI and do everything with commands, and this one works only in view mode.&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/git-hacks/gitk-interface.png"
width="1570"
height="868"
srcset="https://vlasov.pro/ru/p/git-hacks/gitk-interface_hu9045001261438640488.png 480w, https://vlasov.pro/ru/p/git-hacks/gitk-interface_hu9426254138151857176.png 1024w"
loading="lazy"
alt="Gitk Interface"
class="gallery-image"
data-flex-grow="180"
data-flex-basis="434px"
>&lt;/p>
&lt;ol>
&lt;li>Commit tree with tags and branches&lt;/li>
&lt;li>Hash of the selected commit from the tree&lt;/li>
&lt;li>List of changed files in this commit&lt;/li>
&lt;li>Diff mode toggle&lt;/li>
&lt;li>The diff of the commit with its description at the top&lt;/li>
&lt;/ol>
&lt;p>On Manjaro, in addition to Git itself, you need to install &lt;code>tk&lt;/code> for it to work. I don&amp;rsquo;t know how it works on other distributions.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">pacman -Sy git tk
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="how-to-update-environment-settings-based-on-the-diff-of-the-new-environment">How to update environment settings based on the diff of the new environment &lt;a href="#how-to-update-environment-settings-based-on-the-diff-of-the-new-environment">¶&lt;/a>&lt;/h3>
&lt;p>Here&amp;rsquo;s the thing. In my infrastructure repository, I have, for example, values for Helmfile environments &lt;strong>Development&lt;/strong> and &lt;strong>Production&lt;/strong>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ruby" data-lang="ruby">&lt;span class="line">&lt;span class="cl">&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">├──&lt;/span> &lt;span class="n">development&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">main&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">└──&lt;/span> &lt;span class="n">values&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">cert&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">manager&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">external&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">secrets&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">fluentbit&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">kube&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">prometheus&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">stack&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">├──&lt;/span> &lt;span class="n">loki&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">│&lt;/span> &lt;span class="err">└──&lt;/span> &lt;span class="n">promtail&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">└──&lt;/span> &lt;span class="n">production&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">main&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">└──&lt;/span> &lt;span class="n">values&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">cert&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">manager&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">external&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">secrets&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">fluentbit&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">kube&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">prometheus&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">stack&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">├──&lt;/span> &lt;span class="n">loki&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">└──&lt;/span> &lt;span class="n">promtail&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gotmpl&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mi">5&lt;/span> &lt;span class="n">directories&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">14&lt;/span> &lt;span class="n">files&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>So I was developing new applications, changing settings in development, and now I need to transfer all the same to production. To avoid recalling all the little things that need to be changed, I do the following.&lt;/p>
&lt;ol>
&lt;li>Switch to the branch with the current development&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git checkout development
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>Check when production was last changed&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git log -n &lt;span class="m">1&lt;/span> --oneline -- ./production
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Here, &lt;code>./production&lt;/code> is the path to the folder we are interested in for file changes. You can specify a specific file or multiple sources. In this case, we will get the hash of the last commit that made any changes in production.&lt;/p>
&lt;ol start="3">
&lt;li>Check the changes from that moment to the present&lt;/li>
&lt;/ol>
&lt;p>Now we need to track all changes from the last version of production to the current moment, which is the current development.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git diff 493d3aa..HEAD -- ./development
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The hash &lt;strong>493d3aa&lt;/strong> is the one I obtained in the previous point for production.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl">&lt;span class="gh">diff --git a/development/values/cert-manager.yaml.gotmpl b/development/values/cert-manager.yaml.gotmpl
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gh">index 493d3aa..cb34bd2 100644
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gh">&lt;/span>&lt;span class="gd">--- a/development/values/cert-manager.yaml.gotmpl
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+++ b/development/values/cert-manager.yaml.gotmpl
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>&lt;span class="gu">@@ -34,7 +34,8 @@ asdf:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gu">&lt;/span> alpha: cert-manager-a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> contextKey:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> beta: something-else
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">- key: json
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+ someSetting:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ subkey: cert-manager-example
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> urls:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> api: {{ quote .Values.apiURL }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> web: {{ quote .Values.webURL }}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Thus, we can now manually transfer all the changes we are interested in to production without losing anything.&lt;/p>
&lt;h3 id="how-to-search-for-passwords-and-sensitive-data-using-commit-search">How to search for passwords and sensitive data using commit search &lt;a href="#how-to-search-for-passwords-and-sensitive-data-using-commit-search">¶&lt;/a>&lt;/h3>
&lt;p>Git has a built-in search for files in commits. You can use regular expressions to search for secret data. This is applicable in individual manual operations, but it would be much better to set up and constantly use &lt;a class="link" href="https://gitleaks.io" target="_blank" rel="noopener"
>Gitleaks&lt;/a> or &lt;a class="link" href="https://aquasecurity.github.io/trivy/v0.42/docs/target/git-repository/" target="_blank" rel="noopener"
>Trivy&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git rev-list --all &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>xargs git grep -irnE &lt;span class="s1">&amp;#39;&amp;#34;type&amp;#34;:\s*&amp;#34;service_account&amp;#34;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://vlasov.pro/git-grep-result.png"
loading="lazy"
alt="Search results for the substring &amp;ldquo;val&amp;rdquo;"
>&lt;/p>
&lt;p>This way, you can find all files in history that contain secrets and perform rotation. It doesn&amp;rsquo;t make sense to cut them out of history; it&amp;rsquo;s better just to change the secrets.&lt;/p>
&lt;h3 id="rebase-strategies">Rebase strategies &lt;a href="#rebase-strategies">¶&lt;/a>&lt;/h3>
&lt;p>When you need to perform a rebase with a lot of conflicts and you know that you simply need to keep everything as it is in the current/target branch, you can do the following.&lt;/p>
&lt;ol>
&lt;li>Make sure that our local branch (which we will be rebasing) is pushed and is the same as in the cloud.&lt;/li>
&lt;/ol>
&lt;p>Why is this necessary? For self-control. For example, I have a task to rebase the &lt;em>development&lt;/em> branch onto &lt;em>main&lt;/em> without changing it, just moving it. If at the start of the transfer I checked that there was no diff for &lt;em>origin/development&lt;/em>, then after the transfer, I can compare &lt;code>git diff origin/development..development&lt;/code>, and it should also be empty.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git pull
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git push
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>Perform one of the operations below&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git rebase -i --strategy&lt;span class="o">=&lt;/span>ort -Xtheirs main --empty&lt;span class="o">=&lt;/span>keep
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">git rebase -i --strategy&lt;span class="o">=&lt;/span>ort -Xours main --empty&lt;span class="o">=&lt;/span>keep
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Git will resolve all conflicts in favor of one of the branches, depending on &lt;code>ours&lt;/code> or &lt;code>theirs&lt;/code>.&lt;/p>
&lt;h3 id="how-to-reset-a-local-branch-to-the-state-of-the-cloud-if-someone-pushed-with-force">How to reset a local branch to the state of the cloud if someone pushed with force &lt;a href="#how-to-reset-a-local-branch-to-the-state-of-the-cloud-if-someone-pushed-with-force">¶&lt;/a>&lt;/h3>
&lt;p>This is quite simple. For example, we are working on &lt;em>development&lt;/em>.&lt;/p>
&lt;ol>
&lt;li>Switch to the branch&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git checkout development
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>Perform &lt;code>git fetch&lt;/code>&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git fetch --all
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>Perform a reset&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git reset --hard origin/development
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>That&amp;rsquo;s it; our branch is now exactly as it is in the cloud.&lt;/p></description></item><item><title>Kubernetes in Docker</title><link>https://vlasov.pro/en/p/kind/</link><pubDate>Mon, 12 Jun 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/kind/</guid><description>&lt;img src="https://vlasov.pro/ru/p/kind/logo.webp" alt="Featured image of post Kubernetes in Docker" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>Sometimes you need Kubernetes locally for quick testing.&lt;/p>
&lt;ol>
&lt;li>Checking out a custom Helm chart&lt;/li>
&lt;li>Asking &lt;code>kubectl explain&lt;/code> something&lt;/li>
&lt;li>Checking settings&lt;/li>
&lt;/ol>
&lt;p>Starting to look for some cluster on first available project, which is not good because it can break something accidentally. It&amp;rsquo;s not convenient to do something. Turns out there are many different lightweight and fast installers of Kubernetes. This may not be all of them, but those I either tried or passed by. They work a bit differently.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Minikube&lt;/strong> - one of the oldest, so to say. We met that standard installation kube-prometheus-stack on it simply didn&amp;rsquo;t start, and on the next one - with it.&lt;/li>
&lt;li>&lt;strong>k3s&lt;/strong> - one of three engines from &lt;a class="link" href="https://www.rancher.com" target="_blank" rel="noopener"
>Rancher&lt;/a>. Great thing, used and using them for small projects at work. It&amp;rsquo;s also two personal clusters exactly on k3s, but it&amp;rsquo;s not vanilla, everything is put together in a single binary. It&amp;rsquo;s both good and bad. Very lightweight and easy to install, but I ended up with Wireguard VPN rule issues with IPTables myself. I had to change Wireguard FwMark to &lt;code>0x8000&lt;/code> and everything worked.&lt;/li>
&lt;li>&lt;strong>rke&lt;/strong> - another one of three engines. First one from Rancher. It&amp;rsquo;s very good, especially because there is a &lt;a class="link" href="https://registry.terraform.io/providers/rancher/rke/latest" target="_blank" rel="noopener"
>Terraform Module&lt;/a> - great. I&amp;rsquo;ve already been more similar to vanilla installation.&lt;/li>
&lt;li>&lt;strong>rke2&lt;/strong> - rke + k3s. Everything is put together in one binary, but apiserver, scheduler etc. are still seen as separate pods. I tried it, and it was a shame that there was no support from Terraform like with rke. It didn&amp;rsquo;t impress me, practically speaking, because it was less stable than k3s or maybe my hands were just crooked.&lt;/li>
&lt;li>&lt;strong>Microk8s&lt;/strong> - from Canonical, haven&amp;rsquo;t tried.&lt;/li>
&lt;li>&lt;strong>k0s&lt;/strong> - same as &lt;em>k3s&lt;/em>, but community is smaller and documentation is worse, and that&amp;rsquo;s&amp;hellip; good.&lt;/li>
&lt;li>&lt;strong>kind&lt;/strong> - the highlight of today&amp;rsquo;s program.&lt;/li>
&lt;/ol>
&lt;h2 id="kind">kind &lt;a href="#kind">¶&lt;/a>&lt;/h2>
&lt;p>Why I want to tell you about it? It&amp;rsquo;s the &lt;strong>most vanilla&lt;/strong> way to get Kubernetes locally. There are many advantages.&lt;/p>
&lt;ol>
&lt;li>You can throw in a config&lt;/li>
&lt;li>Creates Kubernetes in Docker&lt;/li>
&lt;li>&lt;strong>You can create more than one node!&lt;/strong>&lt;/li>
&lt;li>Uses &lt;strong>vanilla kubeadm&lt;/strong>!&lt;/li>
&lt;li>All configurations, paths, and formats - standard kubeadm!&lt;/li>
&lt;li>It doesn&amp;rsquo;t mess with iptables on the host&lt;/li>
&lt;/ol>
&lt;p>There are some downsides.&lt;/p>
&lt;ol>
&lt;li>Control plane eats up 900 MiB RAM at a time&lt;/li>
&lt;li>You need to throw out ports from nodes on the host&lt;/li>
&lt;/ol>
&lt;p>Here&amp;rsquo;s an example configuration of kind:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Cluster&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">kind.x-k8s.io/v1alpha4&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">nodes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">role&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">control-plane&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extraMounts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">hostPath&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">/home/bzm/projects/kind/&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">containerPath&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">/host&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kubeadmConfigPatches&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> kind: InitConfiguration
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> nodeRegistration:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> kubeletExtraArgs:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> seccomp-default: &amp;#34;true&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> apiServer:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> extraArgs:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> enable-admission-plugins: NodeRestriction&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">role&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">worker&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extraPortMappings&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">containerPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">hostPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">80&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">listenAddress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;127.0.0.1&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">containerPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">443&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">hostPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">443&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">listenAddress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;127.0.0.1&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>So, you can put a bunch of nodes on one computer and everything is in containers. Configurations and settings are all like the official documentation. You need to try out some keys for api-server - easy. You need to refine something about security - easy. I really liked it.&lt;/p></description></item><item><title>Redis Sentinel Watchdog</title><link>https://vlasov.pro/en/p/redis-watchdog/</link><pubDate>Fri, 09 Jun 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/redis-watchdog/</guid><description>&lt;img src="https://vlasov.pro/ru/p/redis-watchdog/logo.webp" alt="Featured image of post Redis Sentinel Watchdog" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>I really love the charts from &lt;a class="link" href="https://artifacthub.io/packages/search?org=bitnami&amp;amp;sort=relevance&amp;amp;page=1" target="_blank" rel="noopener"
>Bitnami&lt;/a>; they are well-written and quite stable. Among other things, I always deploy &lt;a class="link" href="https://artifacthub.io/packages/helm/bitnami/redis" target="_blank" rel="noopener"
>Redis from their chart&lt;/a>. Everything would be fine if you just needed Redis without any High Availability, but that’s not always the case.&lt;/p>
&lt;blockquote>
&lt;p>What’s the difficulty in setting up Redis HA?&lt;/p>
&lt;/blockquote>
&lt;p>The issue is that the connection drivers to Redis in client services must support Redis Sentinel. When we set up a cluster with Redis, a container with Sentinel is also launched—it&amp;rsquo;s a kind of controller for the cluster that will replace the master if the current one goes down. It&amp;rsquo;s very similar to a &lt;a class="link" href="https://www.mongodb.com/docs/manual/core/replica-set-arbiter/" target="_blank" rel="noopener"
>Mongo Arbiter&lt;/a>. Therefore, the connection mechanism changes because of this Sentinel.&lt;/p>
&lt;ol>
&lt;li>Connect to Sentinel&lt;/li>
&lt;li>Request the master’s address&lt;/li>
&lt;li>Connect to the master&lt;/li>
&lt;li>If the master is unavailable, go back to Sentinel&lt;/li>
&lt;/ol>
&lt;p>Very often, applications do not support this. So what should you do in such a case? I decided that, as always, &lt;strong>workarounds&lt;/strong> would help.&lt;/p>
&lt;p>Below is a fragment of &lt;em>values.yaml&lt;/em> that I use to launch &lt;em>bitnami/redis&lt;/em> using &lt;a class="link" href="https://helmfile.readthedocs.io/en/latest/" target="_blank" rel="noopener"
>Helmfile&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>What’s going on there?&lt;/p>
&lt;/blockquote>
&lt;p>Among other things, I create an additional sidecar container that requests the master’s address from Sentinel every N seconds and updates the service if it differs from the one created as an ExternalName type. Thus, we can simply point applications that do not know how to communicate with Sentinel to this service, and everything will work since the service will always point to the correct pod.&lt;/p>
&lt;p>This sidecar container consumes about &lt;em>65 mCPU&lt;/em> and &lt;em>1 MiB&lt;/em>. Of course, you could build an image and include redis-cli to connect directly, but I don’t want to maintain and store this image or update it.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;span class="lnt">107
&lt;/span>&lt;span class="lnt">108
&lt;/span>&lt;span class="lnt">109
&lt;/span>&lt;span class="lnt">110
&lt;/span>&lt;span class="lnt">111
&lt;/span>&lt;span class="lnt">112
&lt;/span>&lt;span class="lnt">113
&lt;/span>&lt;span class="lnt">114
&lt;/span>&lt;span class="lnt">115
&lt;/span>&lt;span class="lnt">116
&lt;/span>&lt;span class="lnt">117
&lt;/span>&lt;span class="lnt">118
&lt;/span>&lt;span class="lnt">119
&lt;/span>&lt;span class="lnt">120
&lt;/span>&lt;span class="lnt">121
&lt;/span>&lt;span class="lnt">122
&lt;/span>&lt;span class="lnt">123
&lt;/span>&lt;span class="lnt">124
&lt;/span>&lt;span class="lnt">125
&lt;/span>&lt;span class="lnt">126
&lt;/span>&lt;span class="lnt">127
&lt;/span>&lt;span class="lnt">128
&lt;/span>&lt;span class="lnt">129
&lt;/span>&lt;span class="lnt">130
&lt;/span>&lt;span class="lnt">131
&lt;/span>&lt;span class="lnt">132
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># ┬─┐┬─┐┬─┐o┐─┐&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># │┬┘├─ │ ││└─┐&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># ┘└┘┴─┘┘─┘┘──┘&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>{{- &lt;span class="l">$name := &amp;#34;redis&amp;#34; }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>{{- &lt;span class="l">$masterServiceName := printf &amp;#34;%s-master&amp;#34; $name }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">nameOverride&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">$name }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">fullnameOverride&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">$name }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">architecture&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">replication&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">auth&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">password&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">quote .Values.secrets.redisPassword }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">replica&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">replicaCount&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">limits&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">75Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">requests&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">25Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">persistence&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">storageClass&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">standard&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">size&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">1Gi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">podAntiAffinityPreset&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">hard&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">sidecars&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">master-service-watchdog&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;{{`{{ printf &amp;#34;bitnami/kubectl:%s.%s&amp;#34; .Capabilities.KubeVersion.Major .Capabilities.KubeVersion.Minor }}`}}&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">imagePullPolicy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">IfNotPresent&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;/bin/sh&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;-ec&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">args&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> while sleep 5; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> MASTER_ADDRESS=&amp;#34;$(kubectl exec -c sentinel &amp;#34;${POD_NAME}&amp;#34; -- sh -c &amp;#34;REDISCLI_AUTH=&amp;#39;$REDISCLI_AUTH&amp;#39; redis-cli -p &amp;#39;${REDIS_SENTINEL_PORT}&amp;#39; SENTINEL get-master-addr-by-name this&amp;#34; | head -1)&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> if ! kubectl get svc &amp;#34;${MASTER_SERVICE}&amp;#34; -o jsonpath=&amp;#39;{.spec.externalName}&amp;#39; | grep -qF &amp;#34;${MASTER_ADDRESS}&amp;#34;; then
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> echo &amp;#34;info: master address has changed to ${MASTER_ADDRESS}&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> jq -Mnr --arg address &amp;#34;${MASTER_ADDRESS}&amp;#34; &amp;#39;[{op:&amp;#34;replace&amp;#34;,path:&amp;#34;/spec/externalName&amp;#34;,value:$address}]&amp;#39; | \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> xargs -0 kubectl patch svc &amp;#34;${MASTER_SERVICE}&amp;#34; --type=json --patch
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> fi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> done&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">env&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MASTER_SERVICE&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">quote $masterServiceName }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">POD_NAME&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">valueFrom&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">fieldRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">fieldPath&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">metadata.name&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">REDISCLI_AUTH&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">valueFrom&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">secretKeyRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;{{`{{ template &amp;#34;common.names.fullname&amp;#34; . }}`}}&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">key&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">redis-password&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">REDIS_SENTINEL_PORT&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;{{`{{ .Values.sentinel.containerPorts.sentinel }}`}}&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">limits&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">100m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">requests&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">100m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">securityContext&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">readOnlyRootFilesystem&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runAsNonRoot&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runAsUser&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">privileged&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">allowPrivilegeEscalation&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">capabilities&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">drop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="l">ALL]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">seccompProfile&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">RuntimeDefault&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">serviceAccount&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">create&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">sentinel&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">masterSet&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">this&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">automateClusterRecovery&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">downAfterMilliseconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">limits&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">requests&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">50Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">networkPolicy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extraIngress&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">6379&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">namespaceSelector&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">matchLabels&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kubernetes.io/metadata.name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">.Release.Namespace }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">rbac&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">create&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">rules&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># Allow watchdog to update our service&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">apiGroups&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;services&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">verbs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;get&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;update&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;patch&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resourceNames&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">quote $masterServiceName }}]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># Allow exec into Redis pods&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">apiGroups&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;pods/exec&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">verbs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;create&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">apiGroups&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;pods&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">verbs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;get&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;list&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">pdb&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">create&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">raw&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">Service&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Service&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="w"> &lt;/span>&lt;span class="l">$masterServiceName }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">spec&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ExternalName&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># 1.1.1.1 is just a stub value that is used for initial deployment&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># It will be overridden as soon as the first watchdog is ready&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">externalName&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1.1.1.1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">6379&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">protocol&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">TCP&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">targetPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">6379&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">redis&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Timeshift BTRFS Backups on Manjaro</title><link>https://vlasov.pro/en/p/timeshift/</link><pubDate>Sun, 01 Jan 2023 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/timeshift/</guid><description>&lt;img src="https://vlasov.pro/ru/p/timeshift/logo.webp" alt="Featured image of post Timeshift BTRFS Backups on Manjaro" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://github.com/linuxmint/timeshift" target="_blank" rel="noopener"
>Timeshift&lt;/a> is a great tool! It helps making automated system backups. You can do it manually if you want to, but BTRFS snapshots are where it&amp;rsquo;s at!&lt;/p>
&lt;ol>
&lt;li>Copying somewhere with &lt;a class="link" href="https://linux.die.net/man/1/rsync" target="_blank" rel="noopener"
>rsync&lt;/a>, with clever linking to save space as much as possible&lt;/li>
&lt;li>Using BTRFS snapshot&lt;/li>
&lt;/ol>
&lt;p>The first option is pointless. This takes forever and isn&amp;rsquo;t exciting, but BTRFS is what you need! It&amp;rsquo;s done instantly and where duplicates are, the file system saves it itself. Plus, you can load them right when booting up.&lt;/p>
&lt;h2 id="system-requirements">System Requirements &lt;a href="#system-requirements">¶&lt;/a>&lt;/h2>
&lt;p>Part of the page on the main repository, but I also found some more:&lt;/p>
&lt;ol>
&lt;li>The default subvolume for the BTRFS filesystem should be &lt;code>/&lt;/code>&lt;/li>
&lt;/ol>
&lt;p>When mounting a BTRFS partition either without specifying the mount option &lt;em>subvol=&lt;/em> it will mount at the root. If not, the program crashes. Here&amp;rsquo;s a script to check and correct this:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">MP&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mktemp -d&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;/on \/ type btrfs/{print $1}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> sudo xargs -I&lt;span class="o">{}&lt;/span> mount &lt;span class="o">{}&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>sudo btrfs subvolume set-default &lt;span class="m">5&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>sudo umount &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>The root filesystem partition in &lt;code>/etc/fstab&lt;/code> should be correctly configured&lt;/li>
&lt;/ol>
&lt;p>The same &lt;em>subvol=&lt;/em> option should be set to either &lt;code>@*&lt;/code> or &lt;em>/@&lt;/em>, it doesn&amp;rsquo;t matter. Here&amp;rsquo;s a script to tell if everything is correct:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">grep -E &lt;span class="s1">&amp;#39;^[^#].+/\s+btrfs&amp;#39;&lt;/span> /etc/fstab &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>grep -oE &lt;span class="s1">&amp;#39;subvol=[^,]+&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>cut -d&lt;span class="o">=&lt;/span> -f2 &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>grep -qE &lt;span class="s1">&amp;#39;^/?@$&amp;#39;&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;OK&amp;#39;&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;Not OK&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="how-it-works">How it works &lt;a href="#how-it-works">¶&lt;/a>&lt;/h2>
&lt;p>When installing any package through &lt;em>pamac&lt;/em> or &lt;em>yay&lt;/em>, timeshift automatically kicks in if &lt;code>etc/timeshift-autosnap.conf&lt;/code> doesn&amp;rsquo;t include its skip.&lt;/p>
&lt;script id="asciicast-547865" src="https://asciinema.org/a/547865.js" async>&lt;/script>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/timeshift/timeshift-after-install.webp"
width="820"
height="655"
srcset="https://vlasov.pro/ru/p/timeshift/timeshift-after-install_hu11808219343456374573.webp 480w, https://vlasov.pro/ru/p/timeshift/timeshift-after-install_hu1277256472034217943.webp 1024w"
loading="lazy"
alt="And now I have two backups too"
class="gallery-image"
data-flex-grow="125"
data-flex-basis="300px"
>&lt;/p></description></item><item><title>Convenient and Colorful ZSH with p10k</title><link>https://vlasov.pro/en/p/zsh-p10k/</link><pubDate>Sun, 25 Dec 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/zsh-p10k/</guid><description>&lt;img src="https://vlasov.pro/ru/p/zsh-p10k/logo.webp" alt="Featured image of post Convenient and Colorful ZSH with p10k" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>Previously, I described my experience with ZSH &lt;a class="link" href="../shells" >here&lt;/a>. Now, things are a bit different; I have fully switched to &lt;a class="link" href="https://github.com/romkatv/powerlevel10k" target="_blank" rel="noopener"
>Powerlevel10k&lt;/a>.&lt;/p>
&lt;p>It&amp;rsquo;s a very beautiful and convenient shell prompt that is easy to install and configure on the fly.&lt;/p>
&lt;h2 id="configuring-p10k">Configuring p10k &lt;a href="#configuring-p10k">¶&lt;/a>&lt;/h2>
&lt;p>You can configure p10k very easily, right on the go, even ten times a day.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">p10k configure
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I have embedded the installation of p10k directly in my .zshrc, so you don&amp;rsquo;t even have to follow the official instructions on the website. Well, almost. There are recommended fonts to ensure everything looks good, which are described &lt;a class="link" href="https://github.com/romkatv/powerlevel10k#fonts" target="_blank" rel="noopener"
>here&lt;/a>. Below, I recorded and showed what the configuration of p10k looks like. Unfortunately, the asciinema recording shows the beautiful elements as squares since these symbols are not supported in the recording. So, here’s a screenshot of the terminal window.&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/zsh-p10k/tilix-screenshot.webp"
width="872"
height="658"
srcset="https://vlasov.pro/ru/p/zsh-p10k/tilix-screenshot_hu9219161931832726404.webp 480w, https://vlasov.pro/ru/p/zsh-p10k/tilix-screenshot_hu10273949202985261343.webp 1024w"
loading="lazy"
alt="(Click the image to enlarge)"
class="gallery-image"
data-flex-grow="132"
data-flex-basis="318px"
>&lt;/p>
&lt;p>While the recording didn&amp;rsquo;t turn out very well, at least I can show you the menus.&lt;/p>
&lt;script id="asciicast-547818" src="https://asciinema.org/a/547818.js" async>&lt;/script>
&lt;h2 id="explanation-of-my-zshrc">Explanation of my .zshrc &lt;a href="#explanation-of-my-zshrc">¶&lt;/a>&lt;/h2>
&lt;p>Everything written below consists of snippets from my .zshrc, which you can download at the end of the article. For your convenience, I will duplicate the link &lt;a class="link" href="files/dot.zshrc" >here&lt;/a>.&lt;/p>
&lt;h3 id="installing-p10k">Installing p10k &lt;a href="#installing-p10k">¶&lt;/a>&lt;/h3>
&lt;p>This is done with a simple condition and direct cloning from GitHub. If we have Git and p10k is not yet installed, we can clone it.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="nb">command&lt;/span> -v git &amp;gt;/dev/null &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="o">[&lt;/span> ! -d ~/powerlevel10k &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;info: installing p10k&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> git clone --depth &lt;span class="m">1&lt;/span> --single-branch https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="plugins">Plugins &lt;a href="#plugins">¶&lt;/a>&lt;/h3>
&lt;p>I install plugins simply by cloning them from GitHub. I added comments directly in the code for clarification.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># if we have git installed&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="nb">command&lt;/span> -v git &amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># and folder with plugins is absent&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -d /usr/share/zsh/plugins &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># let&amp;#39;s create it with sudo&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sudo mkdir -p /usr/share/zsh/plugins
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># and jump in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">cd&lt;/span> /usr/share/zsh/plugins
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># now, let&amp;#39;s read every line between &amp;lt;&amp;lt;EOF and EOF lines below&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="nv">IFS&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="nb">read&lt;/span> -r REPO&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># and for every line, which will be available in variable named REPO&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># let&amp;#39;s cut only last part of the url (ex: zsh-autosuggestions.git) and save to BASENAME var&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">BASENAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>basename &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$REPO&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># now, we will remove .git from the end of BASENAME and check either such folder exists&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -d &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">BASENAME&lt;/span>&lt;span class="p">%.git&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># if not, let&amp;#39;s print an info message&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">REPO&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: Cloning to &lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">pwd&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">/&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">BASENAME&lt;/span>&lt;span class="p">%.git&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># and finally clone that plugin&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sudo git clone --depth &lt;span class="m">1&lt;/span> --single-branch &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$REPO&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">done&lt;/span> &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">https://github.com/zsh-users/zsh-history-substring-search.git
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">https://github.com/zsh-users/zsh-syntax-highlighting.git
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">https://github.com/zsh-users/zsh-autosuggestions.git
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># after all plugins cloned, we cd back to the location we were&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">cd&lt;/span> - &amp;gt;/dev/null
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># okay, now we assume that all plugins are cloned and we have to include them&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># once again, for every hardcoded path to .zsh file&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">while&lt;/span> &lt;span class="nv">IFS&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="nb">read&lt;/span> -r SOURCE&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># we skip the plugin if it starts with &amp;#39;#&amp;#39; (commented out)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SOURCE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> grep -qE &lt;span class="s1">&amp;#39;^#&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="o">[&lt;/span> -s &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SOURCE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># if it is enabled, we just include it in current shell session with source command&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">source&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>realpath &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SOURCE&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span> &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/usr/share/zsh/plugins/zsh-history-substring-search/zsh-history-substring-search.zsh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="adding-paths-to-path">Adding Paths to PATH &lt;a href="#adding-paths-to-path">¶&lt;/a>&lt;/h3>
&lt;p>Often, we install additional binaries in non-standard folders. For example, I use &lt;em>~/.local/bin&lt;/em> for various tools like kubectl, helm, k9s, and others. Here, we check each folder, if it exists, and add it to the &lt;em>PATH&lt;/em> variable.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="k">while&lt;/span> &lt;span class="nv">IFS&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="nb">read&lt;/span> -r P&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -d &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$P&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">export&lt;/span> &lt;span class="nv">PATH&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">P&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">PATH&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span> &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">${HOME}/.local/share/gem/ruby/3.0.0/bin
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">${HOME}/projects/stm32/gcc-arm-none-eabi-10.3-2021.10/bin
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">${HOME}/.local/bin
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="aliases">Aliases &lt;a href="#aliases">¶&lt;/a>&lt;/h3>
&lt;p>Here everything is straightforward, with lots of different aliases.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> ..&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;cd .. &amp;amp;&amp;amp; ls -lhA --color=auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">d&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;sudo -E docker&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">dc&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;docker-compose&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">e&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;exit&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">j&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo journalctl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">l&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ls -lh --color=always&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">la&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ls -lhA --color=always&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">p&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ping 8.8.8.8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">please&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;sudo&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">reborn&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo shutdown -r now&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;sudo&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">sctl&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo systemctl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">svi&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo vim&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">svim&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo vim&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">t&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;terraform&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubectl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">kd&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubectl describe&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">kg&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubectl get&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">ky&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubectl get -o yaml&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">ke&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;kubectl exec -it&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">vi&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;vim&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">g&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;git&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">b&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo btrfs&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">c&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;code .&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> ansible-time&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;time ansible-playbook&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="git-config">Git Config &lt;a href="#git-config">¶&lt;/a>&lt;/h3>
&lt;p>By the way, I also have a Git config. The link is &lt;a class="link" href="files/dot.gitconfig" >here&lt;/a> or the same at the end of the page. Two interesting commands here:&lt;/p>
&lt;ol>
&lt;li>&lt;code>git ps&lt;/code> - pushes the branch, and if it doesn&amp;rsquo;t exist yet, it catches the message from the Git error log and pushes with &amp;ndash;set-upstream.&lt;/li>
&lt;li>&lt;code>git dpush&lt;/code> (dummy push) - adds all files and folders to the commit, writes a standard commit message, and pushes.&lt;/li>
&lt;li>&lt;code>git cc&lt;/code> - simply makes a commit with a standard message.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ruby" data-lang="ruby">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>&lt;span class="k">alias&lt;/span>&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">co&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">checkout&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">add&lt;/span> &lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ci&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">commit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">cc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">commit&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">m&lt;/span> &lt;span class="s1">&amp;#39;Nothing special. Just regular commit.&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ps&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">!&lt;/span> &lt;span class="n">sh&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">c&lt;/span> &lt;span class="s1">&amp;#39;git push &amp;gt;/tmp/git-ps 2&amp;gt;&amp;amp;1 || grep -- &amp;#34;git push --set-upstream&amp;#34; /tmp/git-ps | sh&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">pt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">push&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">tags&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">pts&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">!&lt;/span> &lt;span class="n">sh&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">c&lt;/span> &lt;span class="s1">&amp;#39;git push &amp;amp;&amp;amp; git push --tags&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">pl&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pull&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">st&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">status&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">br&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">branch&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">hist&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">log&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">pretty&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nb">format&lt;/span>&lt;span class="ss">:&amp;#39;%h %ad | %s%d [%an]&amp;#39;&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">graph&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">date&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">short&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">type&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">cat&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">file&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">dump&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">cat&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">file&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="nb">p&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">dpush&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">!&lt;/span> &lt;span class="n">sh&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">c&lt;/span> &lt;span class="s1">&amp;#39;git add . &amp;amp;&amp;amp; git commit -m &amp;#34;Nothing special. Just regular commit.&amp;#34;&amp;#39;&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">git&lt;/span> &lt;span class="n">push&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="kubeconfig">KUBECONFIG &lt;a href="#kubeconfig">¶&lt;/a>&lt;/h3>
&lt;p>Here, we look for the standard kubeconfig for &lt;a class="link" href="https://k3s.io" target="_blank" rel="noopener"
>k3s&lt;/a> or &lt;a class="link" href="https://docs.rke2.io" target="_blank" rel="noopener"
>rke2&lt;/a> and set it in KUBECONFIG.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># if there is no file at the path that is already being set in KUBECONFIG var&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -z &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$KUBECONFIG&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># for every filepath from the list below&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="nv">IFS&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="nb">read&lt;/span> -r K&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># check if file exists and it is not empty&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -s &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$K&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># change owner and group to current user&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> ! stat -c &lt;span class="s1">&amp;#39;%u:%g&amp;#39;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$K&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> grep -qF &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>id -u&lt;span class="k">)&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="k">$(&lt;/span>id -g&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sudo chown &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">USER&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">USER&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$K&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;info
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">: chown &lt;/span>&lt;span class="nv">$K&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># assign it to the KUBECONFIG variable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">export&lt;/span> &lt;span class="nv">KUBECONFIG&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">K&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">KUBECONFIG&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">done&lt;/span> &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/etc/rancher/rke2/rke2.yaml
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">~/.kube/config
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">~/.kube/k3s.yaml
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Here’s the translated content of your Hugo page section into English, formatted in valid Markdown:&lt;/p>
&lt;h3 id="automatic-utility-downloads">Automatic Utility Downloads &lt;a href="#automatic-utility-downloads">¶&lt;/a>&lt;/h3>
&lt;p>Here&amp;rsquo;s what&amp;rsquo;s happening: &lt;code>.zshrc&lt;/code> automatically checks to ensure that we have the binaries of the utilities we use installed. If the utility is missing, it downloads it; if not, it does nothing. However, I can manually update k9s by executing &lt;code>_update_k9s&lt;/code>. This section installs the following utilities:&lt;/p>
&lt;ol>
&lt;li>&lt;a class="link" href="https://k9scli.io" target="_blank" rel="noopener"
>k9s&lt;/a> - more details &lt;a class="link" href="../k9s" >in my article&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/rikatz/kubepug" target="_blank" rel="noopener"
>kubepug&lt;/a> - a tool for checking deprecated APIs in the cluster before upgrading the Kubernetes version&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/hidetatz/kubecolor" target="_blank" rel="noopener"
>kubecolor&lt;/a> - a wrapper around kubectl for colorful output&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">_update_kubepug&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mkdir -p ~/.local/bin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LOCATION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>curl --connect-timeout &lt;span class="m">1&lt;/span> -sS https://github.com/rikatz/kubepug/releases/latest -D- &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;/^location:/{print $2}&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LATEST_VERSION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LOCATION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> awk -F/ &lt;span class="s1">&amp;#39;{print $NF}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;[0-9a-zA-Z_.-]+&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> ! k9s version --short &lt;span class="p">|&lt;/span> grep -qF &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s2">&amp;#34;Updating kubepug to %s\n&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;https://github.com/rikatz/kubepug/releases/download/%s/kubepug_linux_%s.tar.gz&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>uname -p &lt;span class="p">|&lt;/span> sed &lt;span class="s1">&amp;#39;s/unknown/amd64/g&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> tr -d &lt;span class="s1">&amp;#39;[[:space:]]&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> xargs curl -sSL &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> tar -xpzf - kubepug
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> install kubepug ~/.local/bin/kubepug -m &lt;span class="m">0755&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f kubepug
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! &lt;span class="nb">command&lt;/span> -v kubepug &lt;span class="p">&amp;amp;&lt;/span>&amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> _update_kubepug
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">_update_k9s&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mkdir -p ~/.local/bin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LOCATION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>curl --connect-timeout &lt;span class="m">1&lt;/span> -sS https://github.com/derailed/k9s/releases/latest -D- &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;/^location:/{print $2}&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LATEST_VERSION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LOCATION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> awk -F/ &lt;span class="s1">&amp;#39;{print $NF}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;[0-9a-zA-Z_.-]+&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> ! k9s version --short &lt;span class="p">|&lt;/span> grep -qF &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s2">&amp;#34;Updating k9s to %s\n&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;https://github.com/derailed/k9s/releases/download/%s/k9s_Linux_%s.tar.gz&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>uname -p &lt;span class="p">|&lt;/span> sed &lt;span class="s1">&amp;#39;s/unknown/x86_64/g&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> tr -d &lt;span class="s1">&amp;#39;[[:space:]]&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> xargs curl -sSL &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> tar -xpzf - k9s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> install k9s ~/.local/bin/k9s -m &lt;span class="m">0755&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f k9s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! &lt;span class="nb">command&lt;/span> -v k9s &lt;span class="p">&amp;amp;&lt;/span>&amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> _update_k9s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">_update_kubecolor&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mkdir -p ~/.local/bin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LOCATION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>curl --connect-timeout &lt;span class="m">1&lt;/span> -sS https://github.com/hidetatz/kubecolor/releases/latest -D- &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;/^location:/{print $2}&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">LATEST_VERSION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LOCATION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> awk -F/ &lt;span class="s1">&amp;#39;{print $NF}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;[0-9a-zA-Z_.-]+&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> sed &lt;span class="s1">&amp;#39;s/^v//g&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> ! kubecolor --kubecolor-version &lt;span class="p">|&lt;/span> grep -qF &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s2">&amp;#34;Updating kubecolor to %s\n&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;https://github.com/hidetatz/kubecolor/releases/download/%s/kubecolor_%s_Linux_%s.tar.gz&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="s2">&amp;#34;v&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LATEST_VERSION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>uname -p &lt;span class="p">|&lt;/span> sed &lt;span class="s1">&amp;#39;s/unknown/x86_64/g&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> tr -d &lt;span class="s1">&amp;#39;[[:space:]]&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> xargs curl -sSL &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> tar -xpzf - kubecolor
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> install kubecolor ~/.local/bin/kubecolor -m &lt;span class="m">0755&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f kubecolor
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! &lt;span class="nb">command&lt;/span> -v kubecolor &lt;span class="p">&amp;amp;&lt;/span>&amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> _update_kubecolor
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">alias&lt;/span> &lt;span class="nv">kubectl&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubecolor&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">typeset&lt;/span> -g &lt;span class="nv">POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">|kubecolor&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Additionally, for several commands, if they exist, automatic loading of completion scripts is performed so that zsh knows what to suggest.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Completions for 3rd-party binaries&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> COMMAND in kubectl helm k3d flux kubepug&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">command&lt;/span> -v &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$COMMAND&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &amp;gt;/dev/null&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">source&lt;/span> &amp;lt;&lt;span class="o">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$COMMAND&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> completion zsh&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="separate-environments">Separate Environments &lt;a href="#separate-environments">¶&lt;/a>&lt;/h3>
&lt;p>This is the smartest and at the same time simplest trick in my arsenal. The most valuable thing in work is that when you work on different projects/environments, the scariest thing you can do is to break something. The easiest way to do that is &lt;strong>forgetting to switch&lt;/strong> to the desired environment and apply something where you didn&amp;rsquo;t intend.&lt;/p>
&lt;p>This snippet of code prevents exactly that.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> -f env.sh &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">source&lt;/span> ./env.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>It&amp;rsquo;s that simple. What actually happens? When zsh starts, it checks the directory it was launched from, and if there’s a file named exactly &lt;code>env.sh&lt;/code>, it includes it in the context. Let me explain.&lt;/p>
&lt;p>I use &lt;a class="link" href="https://github.com/ranger/ranger" target="_blank" rel="noopener"
>Ranger&lt;/a> for navigation through folders from the terminal. Let&amp;rsquo;s say I&amp;rsquo;m working on a project and also have a blog. I created the following directories for my projects.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plaintext" data-lang="plaintext">&lt;span class="line">&lt;span class="cl">.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── MyBlog
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   ├── env.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   └── kubeconfig.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── SuperWorkProject
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── development
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │   ├── env.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> │   └── kubeconfig.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── production
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── env.sh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── kubeconfig.yaml
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">4 directories, 6 files
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>In my production project, I have two environments, all running Kubernetes, each with its &lt;strong>separate&lt;/strong> &lt;code>kubeconfig.yaml&lt;/code>. Let&amp;rsquo;s say I need to work on production. In its &lt;code>env.sh&lt;/code>, I will write the following.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">KUBECONFIG&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;~/projects/SuperWorkProject/production/kubeconfig.yaml&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">AWS_PROFILE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;production&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pf&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nohup sh -c &lt;span class="s1">&amp;#39;kubectl get po -n monitoring -l app.kubernetes.io/name=grafana -o name | xargs -I{} kubectl port-forward {} 3000&amp;#39;&lt;/span> 1&amp;gt;/dev/null &lt;span class="p">&amp;amp;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now, I just open zsh in this folder or run &lt;code>source ./env.sh&lt;/code>. That&amp;rsquo;s it; now I&amp;rsquo;m sure I&amp;rsquo;m working with production. Additionally, I declared a function for port-forwarding.&lt;/p></description></item><item><title>Kubernetes Authorization via OIDC</title><link>https://vlasov.pro/en/p/kubernetes-oidc/</link><pubDate>Thu, 01 Dec 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/kubernetes-oidc/</guid><description>&lt;img src="https://vlasov.pro/ru/p/kubernetes-oidc/kubernetes-oidc.webp" alt="Featured image of post Kubernetes Authorization via OIDC" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>To authenticate in Kubernetes through kubeconfig for access via &lt;a class="link" href="https://kubernetes.io/docs/tasks/tools/" target="_blank" rel="noopener"
>kubectl&lt;/a>, ServiceAccounts are generally used. They are simply easier to create, but this is not the right approach. Tokens from ServiceAccounts are accessible to anyone who can read secrets in the namespace where the ServiceAccount was created, which means that actions can be taken on your behalf. Not secure&amp;hellip;&lt;/p>
&lt;p>You can create a certificate, sign it in the cluster, and operate as a User. This is much better; no one can do anything on your behalf because we generated the private part locally and did not share it. I’ll explain how to do this since I&amp;rsquo;ve figured it out.&lt;/p>
&lt;p>Recently, I finally tried &lt;a class="link" href="https://goauthentik.io" target="_blank" rel="noopener"
>Authentik&lt;/a> and also attempted to link it to the cluster via &lt;a class="link" href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens" target="_blank" rel="noopener"
>API server configuration&lt;/a>. It turned out to be even simpler in some aspects than dealing with certificates for users. This is what I will talk about.&lt;/p>
&lt;h2 id="access-via-serviceaccount">Access via ServiceAccount &lt;a href="#access-via-serviceaccount">¶&lt;/a>&lt;/h2>
&lt;p>Let’s create a ServiceAccount.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl create serviceaccount &lt;span class="nb">test&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Previously, before Kubernetes 1.22, a token was automatically generated; now it needs to be created separately. You can generate a temporary one.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl create token &lt;span class="nb">test&lt;/span> --duration&lt;span class="o">=&lt;/span>10m
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Alternatively, you can obtain a permanent token by creating a secret for it.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl apply -f - &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">apiVersion: v1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kind: Secret
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> name: test-sa-secret
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> annotations:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> kubernetes.io/service-account.name: test
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">type: kubernetes.io/service-account-token
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SA_TOKEN&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>kubectl get -o yaml secret test-sa-secret -o &lt;span class="nv">jsonpath&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;{.data.token}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> base64 -d&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now we can write it in kubeconfig and use it.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl config current-context &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>xargs kubectl config get-contexts --no-headers &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>awk &lt;span class="s1">&amp;#39;{print $4}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>xargs kubectl config set-credentials &lt;span class="s2">&amp;#34;--token=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">SA_TOKEN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="creating-a-user">Creating a User &lt;a href="#creating-a-user">¶&lt;/a>&lt;/h2>
&lt;p>This part is a bit more complicated. You need to create a certificate, a signing request, sign it, retrieve the public part, and only then are we ready to proceed. I’m attaching my script, but I don&amp;rsquo;t want to describe all of this. I’m focusing on OIDC, so consider this as a nice bonus &amp;#x1f604;&lt;/p>
&lt;p>How to use it:&lt;/p>
&lt;ol>
&lt;li>Write your name in the variable &lt;em>NAME&lt;/em>&lt;/li>
&lt;li>Write your company name in the variable &lt;em>GROUP&lt;/em>&lt;/li>
&lt;li>Change &lt;em>CLUSTERROLE&lt;/em> if you really want to&lt;/li>
&lt;li>Run the script and read the instructions on the screen&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">NAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;john-johnson&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">GROUP&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;asdfqwer&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CLUSTERROLE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;cluster-admin&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">openssl ecparam -genkey -name prime256v1 &lt;span class="p">|&lt;/span> openssl ec -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">KEY_BASE64&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>base64 -w0 &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">openssl req -new -key &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span> -subj &lt;span class="s2">&amp;#34;/CN=&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">/O=&lt;/span>&lt;span class="nv">$GROUP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CSR_BASE64&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>base64 -w0 &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rm -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NAME&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># ┬ ┐┐─┐┬─┐┬─┐ ┌─┐┬─┐┬─┐┬─┐┌┐┐o┌─┐┌┐┐
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># │ │└─┐├─ │┬┘ │ │┬┘├─ │─┤ │ ││ ││││
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># ┘─┘──┘┴─┘┘└┘ └─┘┘└┘┴─┘┘ ┘ ┘ ┘┘─┘┘└┘
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">1. Please, execute the following code using kubectl that has access to the cluster (using default admin credentials, for example)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl apply -f - &amp;lt;&amp;lt;EOT
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">apiVersion: certificates.k8s.io/v1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kind: CertificateSigningRequest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> name: $GROUP:$NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">spec:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> expirationSeconds: 31536000 # 1 year
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> signerName: kubernetes.io/kube-apiserver-client
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> usages: [&amp;#34;client auth&amp;#34;]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> username: $NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> request: $CSR_BASE64
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOT
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl certificate approve &amp;#39;$GROUP:$NAME&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl apply -f - &amp;lt;&amp;lt;EOT
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">apiVersion: rbac.authorization.k8s.io/v1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kind: ClusterRoleBinding
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">metadata:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> name: user:${NAME}:${CLUSTERROLE}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">roleRef:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> apiGroup: rbac.authorization.k8s.io
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> kind: ClusterRole
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> name: $CLUSTERROLE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">subjects:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">- apiGroup: rbac.authorization.k8s.io
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> kind: User
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> name: $NAME
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOT
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl get -o jsonpath=&amp;#39;{.status.certificate}&amp;#39; csr &amp;#39;$GROUP:$NAME&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">echo
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">2. Please, execute the following code locally, on your PC, where you want to have those credentials inserted
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl config set &amp;#34;users.$GROUP:$NAME.client-key-data&amp;#34; &amp;#34;$KEY_BASE64&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">kubectl config set &amp;#34;users.$GROUP:$NAME.client-certificate-data&amp;#34; &amp;#34;-&amp;#34; --set-raw-bytes=true
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">3. Now place the certificate that has been printed during step #1 in your kubeconfig client-certificate-data for user $GROUP:$NAME marker
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">4. Specify $GROUP:$NAME user in the context you want to use
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="google-oidc">Google OIDC &lt;a href="#google-oidc">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>Configure the &lt;a class="link" href="https://console.cloud.google.com/apis/credentials/consent" target="_blank" rel="noopener"
>&lt;strong>OAuth consent screen&lt;/strong>&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Create &lt;a class="link" href="https://console.cloud.google.com/apis/credentials/oauthclient" target="_blank" rel="noopener"
>OAuth2 credentials&lt;/a> of type Web application, Authorized redirect URIs - in the list below.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plaintext" data-lang="plaintext">&lt;span class="line">&lt;span class="cl">http://127.0.0.1:18000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">http://127.0.0.1:8000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">http://localhost:18000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">http://localhost:8000
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>
&lt;p>As a result, you will get the Client ID and Client Secret.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Great, now you need to install the &lt;a class="link" href="https://github.com/int128/kubelogin" target="_blank" rel="noopener"
>kubectl oidc-login plugin&lt;/a>.&lt;/p>
&lt;p>After installation, try to ensure everything works.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl oidc-login setup &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-issuer-url&lt;span class="o">=&lt;/span>https://accounts.google.com &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-client-id&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;YOUR CLIENT ID&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-client-secret&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;YOUR CLIENT SECRET&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>If everything is fine, your browser should open, you log in as someone, and a big beautiful instruction will appear in the console. Something like this.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plaintext" data-lang="plaintext">&lt;span class="line">&lt;span class="cl">authentication in progress...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Opening in existing browser session.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 2. Verify authentication
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">You got a token with the following claims:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;iss&amp;#34;: &amp;#34;https://accounts.google.com&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;azp&amp;#34;: &amp;#34;longalphanum&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;aud&amp;#34;: &amp;#34;longalphanum&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;sub&amp;#34;: &amp;#34;longalphanum&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;at_hash&amp;#34;: &amp;#34;longalphanum&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;nonce&amp;#34;: &amp;#34;longalphanum&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;iat&amp;#34;: longalphanum,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;exp&amp;#34;: longalphanum
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 3. Bind a cluster role
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Run the following command:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> kubectl create clusterrolebinding oidc-cluster-admin --clusterrole=cluster-admin --user=&amp;#39;https://accounts.google.com#12345678901234567890&amp;#39;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 4. Set up the Kubernetes API server
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Add the following options to the kube-apiserver:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --oidc-issuer-url=https://accounts.google.com
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --oidc-client-id=longalphanum
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 5. Set up the kubeconfig
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Run the following command:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> kubectl config set-credentials oidc \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-api-version=client.authentication.k8s.io/v1beta1 \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-command=kubectl \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-arg=oidc-login \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-arg=get-token \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-arg=--oidc-issuer-url=https://accounts.google.com \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-arg=--oidc-client-id=longalphanum \
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --exec-arg=--oidc-client-secret=longalphanum
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">## 6. Verify cluster access
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Make sure you can access the Kubernetes cluster.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> kubectl --user=oidc get nodes
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">You can switch the default context to oidc.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> kubectl config set-context --current
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> --user=oidc
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="authentik">Authentik &lt;a href="#authentik">¶&lt;/a>&lt;/h2>
&lt;p>This tool is great! Among its direct analogs, it&amp;rsquo;s worth mentioning &lt;a class="link" href="https://www.okta.com" target="_blank" rel="noopener"
>Okta&lt;/a> and &lt;a class="link" href="https://www.keycloak.org" target="_blank" rel="noopener"
>Keycloak&lt;/a>. All three products are excellent; Okta is often considered the benchmark. Other options may be better or worse, but they are always compared to Okta. &amp;#x1f604;&lt;/p>
&lt;p>I installed Authentik from the &lt;a class="link" href="https://artifacthub.io/packages/helm/goauthentik/authentik" target="_blank" rel="noopener"
>official chart&lt;/a>. It’s running locally, and I needed a certificate. I obtained one using Certbot with DNS verification. After that, we proceed as follows:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Applications &amp;gt; Providers&lt;/strong>&lt;/p>
&lt;p>Create a &lt;strong>Kubernetes&lt;/strong> provider of type OAuth2/OIDC&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Client type&lt;/strong>: Confidential&lt;/li>
&lt;li>&lt;strong>Client ID&lt;/strong>: remember this&lt;/li>
&lt;li>&lt;strong>Client Secret&lt;/strong>: remember this&lt;/li>
&lt;li>&lt;strong>Redirect URIs&lt;/strong>: &lt;code>http://(127.0.0.1|localhost):1?8000(/.*)?&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Application &amp;gt; Applications&lt;/strong>&lt;/p>
&lt;p>Create an application &lt;strong>Kubernetes&lt;/strong> and select the provider you created in step 1.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>System&lt;/strong>&lt;/p>
&lt;p>Create users (surprise, right?) and also create groups. I made &lt;em>kubernetes:admin&lt;/em> and &lt;em>kubernetes:restricted&lt;/em>. The first group will be assigned the cluster-admin role in Kubernetes, while the second will have read-only access. Don’t forget to add users to the corresponding groups.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>System &amp;gt; Certificates&lt;/strong>&lt;/p>
&lt;p>I’m not sure about this step; I just haven’t checked it without a certificate. I uploaded the certificate obtained via Certbot here, and then selected this certificate in &lt;em>Application &amp;gt; Providers &amp;gt; Kubernetes &amp;gt; Edit &amp;gt; Signing Key&lt;/em>. Kubernetes didn’t complain, so it might be possible to use a self-signed certificate, but I’m not sure; you’ll have to try it yourself.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Customization &amp;gt; Property Mappings&lt;/strong>&lt;/p>
&lt;p>Create a mapping with the following parameters:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Name&lt;/strong>: Kubernetes&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Scope name&lt;/strong>: kubernetes&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Expression&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">all_groups&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;kubernetes:admin&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;kubernetes:restricted&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">return&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">groups&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">group&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">group&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">all_groups&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">ak_is_group_member&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ul>
&lt;p>This way, for those who request this scope, Authentik will append the groups the user belongs to, iterating only through the Kubernetes groups.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Verify kube-oidc-login&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">kubectl oidc-login setup &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-issuer-url&lt;span class="o">=&lt;/span>https://authentik.example.com/application/o/kubernetes/ &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-client-id&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;YOUR CLIENT ID&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-client-secret&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;YOUR CLIENT SECRET&amp;#39;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --oidc-extra-scope&lt;span class="o">=&lt;/span>kubernetes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Everything should work; just follow the instructions.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Grant permissions to the group in Kubernetes&lt;/p>
&lt;p>Authentik will pass the group list, and now we need Kubernetes to pay attention to this. Add the following arguments to the API server:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">--oidc-groups-claim&lt;span class="o">=&lt;/span>groups
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">--oidc-groups-prefix&lt;span class="o">=&lt;/span>oidc:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now you can create resources like these:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io/v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ClusterRoleBinding&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">oidc:kubernetes:admin&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">roleRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">apiGroup&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ClusterRole&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">cluster-admin&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">subjects&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">apiGroup&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Group&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">oidc:kubernetes:admin&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">apiVersion&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io/v1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ClusterRoleBinding&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">metadata&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">this-name-is-custom&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">roleRef&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">apiGroup&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ClusterRole&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">view&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">subjects&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="nt">apiGroup&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbac.authorization.k8s.io&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">kind&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Group&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">oidc:kubernetes:restricted&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ol></description></item><item><title>wg-quick network namespace</title><link>https://vlasov.pro/en/p/wg-quick-netns/</link><pubDate>Fri, 25 Nov 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/wg-quick-netns/</guid><description>&lt;img src="https://vlasov.pro/ru/p/wg-quick-netns/wireguard.webp" alt="Featured image of post wg-quick network namespace" />&lt;h2 id="tldr">TL;DR &lt;a href="#tldr">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="na">PreUp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">ip netns list | grep -qF -- %i &amp;amp;&amp;amp; ip netns delete %i || true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">PostUp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">(ip netns list | grep -qF -- %i || ip netns add %i) &amp;amp;&amp;amp; ip -n %i link set up lo &amp;amp;&amp;amp; IPS=&amp;#34;$(ip address save dev %i | base64)&amp;#34; &amp;amp;&amp;amp; ip link set %i netns %i &amp;amp;&amp;amp; echo &amp;#34;$IPS&amp;#34; | base64 -d | ip -n %i address restore dev %i &amp;amp;&amp;amp; ip -n %i link set up %i &amp;amp;&amp;amp; (ip -n %i route show default | grep -qF default || ip -n %i route add default dev %i) &amp;amp;&amp;amp; echo &amp;#39;IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCgpuZXRucz0nJXMnCgpjYXQgPDxFT0YgfCB4YXJncyAtMCBzdWRvIC1FIG5zZW50ZXIgIi0tbmV0PS92YXIvcnVuL25ldG5zLyRuZXRucyIgdW5zaGFyZSAtLW1vdW50IHNoIC1jCmZvciBjb25mIGluICIkbmV0bnMiICJ0dW4uJG5ldG5zIjsgZG8KICBpZiBbIC1mICIvdmFyL3J1bi9yZXNvbHZjb25mL2ludGVyZmFjZXMvXCRjb25mIiBdOyB0aGVuCiAgICBtb3VudCAtLWJpbmQgIi92YXIvcnVuL3Jlc29sdmNvbmYvaW50ZXJmYWNlcy9cJGNvbmYiIC9ldGMvcmVzb2x2LmNvbmYKICBmaQpkb25lCmV4cG9ydCBEQlVTX1NFU1NJT05fQlVTX0FERFJFU1M9dW5peDpwYXRoPS9kZXYvbnVsbApzdWRvIC1FIC11ICcjJHtTVURPX1VJRDotJChpZCAtdSl9JyAtZyAnIyR7U1VET19HSUQ6LSQoaWQgLWcpfScgLS0gJEAKRU9GCg==&amp;#39; | base64 -d | xargs -0 -I{} printf {} %i &amp;gt; /usr/local/bin/wg-%i-exec &amp;amp;&amp;amp; echo &amp;#39;IyEvdXNyL2Jpbi9lbnYgc2gKc2V0IC1lCgppZiBbICIkKGlkIC11KSIgLW5lIDAgXTsgdGhlbgogIGVjaG8gImVycm9yOiBydW4gbWUgYXMgcm9vdCIgMT4mMgogIGV4aXQgMQpmaQoKbmV0bnM9JyVzJwppcCBuZXRucyBleGVjICIkbmV0bnMiIGlwIGxpbmsgc2V0ICIkbmV0bnMiIG5ldG5zIDEKaXAgbmV0bnMgZGVsZXRlICIkbmV0bnMiCnN5c3RlbWN0bCBzdG9wICJ3Zy1xdWlja0AkbmV0bnMuc2VydmljZSIK&amp;#39; | base64 -d | xargs -0 -I{} printf {} %i &amp;gt; /usr/local/bin/wg-%i-down &amp;amp;&amp;amp; chmod 0755 /usr/local/bin/wg-%i-* &amp;amp;&amp;amp; chown root:root /usr/local/bin/wg-%i-* &amp;amp;&amp;amp; echo &amp;#39;bmV0bnM9JyVzJwpjYXQgPDxFT0YKIyAg4pSQIOKUrG/ilKzilIDilJDilKzilIDilJDilIzilIDilJDilKwg4pSQ4pSs4pSA4pSQ4pSs4pSA4pSQ4pSs4pSA4pSQICDilIzilJDilJDilKzilIDilJDilIzilJDilJDilIzilJDilJDilJDilIDilJAKIyAg4pSC4pSC4pSC4pSC4pSC4pSs4pSY4pSc4pSAIOKUgiDilKzilIIg4pSC4pSC4pSA4pSk4pSC4pSs4pSY4pSCIOKUgiAg4pSC4pSC4pSC4pSc4pSAICDilIIg4pSC4pSC4pSC4pSU4pSA4pSQCiMgIOKUlOKUtOKUmOKUmOKUmOKUlOKUmOKUtOKUgOKUmOKUmOKUgOKUmOKUmOKUgOKUmOKUmCDilJjilJjilJTilJjilJjilIDilJggIOKUmOKUlOKUmOKUtOKUgOKUmCDilJgg4pSY4pSU4pSY4pSA4pSA4pSYClRoYW5rcyBmb3IgdXNpbmcgbmV0bnMgd2ctcXVpY2sgd3JhcHBlciEKCi91c3IvbG9jYWwvYmluL3dnLSRuZXRucy1leGVjIENPTU1BTkQgICAtIGV4ZWN1dGUgc2hlbGwgY29tbWFuZCBpbiAkbmV0bnMgbmV0d29yayBuYW1lc3BhY2UKL3Vzci9sb2NhbC9iaW4vd2ctJG5ldG5zLWRvd24gICAgICAgICAgIC0gdXNlIGl0IGluc3RlYWQgb2Ygd2ctcXVpY2sgZG93biAkbmV0bnMKRU9G&amp;#39; | base64 -d | xargs -0 -I{} printf {} %i | sh - &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">PostDown&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">rm -f /usr/local/bin/wg-%i-* || true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://www.wireguard.com" target="_blank" rel="noopener"
>Wireguard&lt;/a> is an awesome, simple VPN that is &lt;a class="link" href="https://www.wireguard.com" target="_blank" rel="noopener"
>already included in the kernel&lt;/a>. A very powerful and simple tool. It&amp;rsquo;s much easier to set up than &lt;a class="link" href="https://openvpn.net" target="_blank" rel="noopener"
>OpenVPN&lt;/a>. For its simple configuration, the &lt;a class="link" href="https://www.man7.org/linux/man-pages/man8/wg-quick.8.html" target="_blank" rel="noopener"
>wg-quick&lt;/a> utility is used, which is part of wireguard tools. For better understanding, I&amp;rsquo;ll additionally clarify that from my experience, most solutions like &lt;a class="link" href="https://github.com/donaldzou/WGDashboard" target="_blank" rel="noopener"
>WGDashboard&lt;/a> and &lt;a class="link" href="https://github.com/ngoduykhanh/wireguard-ui" target="_blank" rel="noopener"
>wireguard-ui&lt;/a> generate client configs specifically for wg-quick.&lt;/p>
&lt;h2 id="problem-statement">Problem Statement &lt;a href="#problem-statement">¶&lt;/a>&lt;/h2>
&lt;p>Move the wireguard interface to a separate network namespace so that applications can be run in it. Why do this? This eliminates the need to proxy traffic to blocked sites through Wireguard with some complex solutions. Need to access some restricted place - just launch another browser in the Wireguard namespace and that&amp;rsquo;s it! For example, I rewrote the Exec line in the &lt;a class="link" href="https://www.thunderbird.net/en-US/" target="_blank" rel="noopener"
>Thunderbird&lt;/a> shortcut, which has no equally functional alternative yet, and now it always starts through VPN and can peacefully collect mail from any SMTP.
We need to use vanilla wg-quick without modifications so it works out of the box.&lt;/p>
&lt;h2 id="solution-analysis">Solution Analysis &lt;a href="#solution-analysis">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://www.man7.org/linux/man-pages/man8/wg-quick.8.html" target="_blank" rel="noopener"
>In the documentation&lt;/a>, there are 4 ways for additional wg-quick interface configuration: PreUp, PostUp, PreDown, PostDown. So we need to write scripts that do everything needed. The ready solution is presented at the beginning of the article, and now let&amp;rsquo;s analyze it. I&amp;rsquo;ll transform this compressed code into human-readable form - it looks different but is identical in content. &lt;strong>Note:&lt;/strong> the code contains &lt;code>%i&lt;/code>, this is a wg-quick macro itself, wherever it encounters this macro, it substitutes the name of the interface being created.&lt;/p>
&lt;h3 id="preup">PreUp &lt;a href="#preup">¶&lt;/a>&lt;/h3>
&lt;p>Everything is simple here.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># search for our namespace in the list of network namespaces&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ip netns list &lt;span class="p">|&lt;/span> grep -qF -- %i&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># if found - delete it&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ip netns delete %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="postup">PostUp &lt;a href="#postup">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! ip netns list &lt;span class="p">|&lt;/span> grep -qF -- %i&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># create network namespace if it doesn&amp;#39;t exist yet (and it shouldn&amp;#39;t)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ip netns add %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># start the loopback interface there (the 127.0.0.1 one)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ip -n %i link &lt;span class="nb">set&lt;/span> up lo
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># save the list of network addresses that wg-quick assigned to the interface during creation&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># and encode it in base64, because this is a binary stream in the ip utility format&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">IPS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>ip address save dev %i &lt;span class="p">|&lt;/span> base64&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># move the interface to our special namespace&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ip link &lt;span class="nb">set&lt;/span> %i netns %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># restore the addresses back, decoding them from the variable created earlier&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$IPS&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> base64 -d &lt;span class="p">|&lt;/span> ip -n %i address restore dev %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># start the network interface in that namespace&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ip -n %i link &lt;span class="nb">set&lt;/span> up %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># look for a route to 0.0.0.0/0 in our namespace&amp;#39;s route list&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! ip -n %i route show default &lt;span class="p">|&lt;/span> grep -qF default&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># add it if not found&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ip -n %i route add default dev %i
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># here was a script in base64, I decoded it directly for you in the text to make it clear what&amp;#39;s there&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># this script is decoded and the interface name is inserted into it using printf, which will always&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># work with the script&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOT | xargs -0 -I{} printf {} %i &amp;gt; /usr/local/bin/wg-%i-exec
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">set -e
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># the interface name will land here in the variable
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">netns=&amp;#39;%s&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># and I&amp;#39;ll explain this mess separately
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">cat &amp;lt;&amp;lt;EOF | xargs -0 sudo -E nsenter &amp;#34;--net=/var/run/netns/$netns&amp;#34; unshare --mount sh -c
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">for conf in &amp;#34;$netns&amp;#34; &amp;#34;tun.$netns&amp;#34;; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> if [ -f &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; ]; then
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> mount --bind &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; /etc/resolv.conf
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> fi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">done
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">export DBUS_SESSION_BUS_ADDRESS=unix:path=/dev/null
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">sudo -E -u &amp;#39;#${SUDO_UID:-$(id -u)}&amp;#39; -g &amp;#39;#${SUDO_GID:-$(id -g)}&amp;#39; -- $@
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># same kind of script, but we execute not a user command there, but wg-quick down&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOT | xargs -0 -I{} printf {} %i &amp;gt; /usr/local/bin/wg-%i-down
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">set -e
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># must be run as root
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">if [ &amp;#34;$(id -u)&amp;#34; -ne 0 ]; then
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> echo &amp;#34;error: run me as root&amp;#34; 1&amp;gt;&amp;amp;2
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> exit 1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">fi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">netns=&amp;#39;%s&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># return the interface back to the root netns
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">ip netns exec &amp;#34;$netns&amp;#34; ip link set &amp;#34;$netns&amp;#34; netns 1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># delete our custom netns
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">ip netns delete &amp;#34;$netns&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># and stop via wg-quick, which will remove the interface itself
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">systemctl stop &amp;#34;wg-quick@$netns.service&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># change owner and permissions on files&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">chmod &lt;span class="m">0755&lt;/span> /usr/local/bin/wg-%i-*
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">chown root:root /usr/local/bin/wg-%i-*
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># just output text to screen when bringing up the interface - user help,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># which tells about the two scripts created earlier. This text is decoded and directly&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># thrown to sh, i.e., executed on the fly, and there&amp;#39;s only one cat there&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOT | xargs -0 -I{} printf {} %i | sh -
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">netns=&amp;#39;%s&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">cat &amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># ┐ ┬o┬─┐┬─┐┌─┐┬ ┐┬─┐┬─┐┬─┐ ┌┐┐┬─┐┌┐┐┌┐┐┐─┐
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># │││││┬┘├─ │ ┬│ ││─┤│┬┘│ │ │││├─ │ │││└─┐
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"># └┴┘┘┘└┘┴─┘┘─┘┘─┘┘ ┘┘└┘┘─┘ ┘└┘┴─┘ ┘ ┘└┘──┘
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">Thanks for using netns wg-quick wrapper!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/usr/local/bin/wg-$netns-exec COMMAND - execute shell command in $netns network namespace
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">/usr/local/bin/wg-$netns-down - use it instead of wg-quick down $netns
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOT&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>And here&amp;rsquo;s the real madness. Let me explain the main points.&lt;/p>
&lt;ol>
&lt;li>When you move a network interface to another namespace, unfortunately, all IP addresses are lost from it. Therefore, we save them at the beginning and then restore them after the transfer.&lt;/li>
&lt;li>The loopback interface in the new namespace is disabled by default, so we enable it ourselves&lt;/li>
&lt;li>A route is added only to &lt;code>0.0.0.0/0&lt;/code> because in principle our traffic has nowhere to go except to wireguard, so we send everything there regardless of what&amp;rsquo;s written in AllowedIPs on the interface. This makes the script simpler, works the same way, and creates no vulnerabilities.&lt;/li>
&lt;li>Two scripts are created: &lt;code>wg-%i-exec&lt;/code>, &lt;code>wg-%i-down&lt;/code>. The first is needed to run programs in our network namespace, and the second is needed to simply do &lt;code>wg-quick down&lt;/code>, because just executing &lt;code>wg-quick down&lt;/code> won&amp;rsquo;t stop the interface - you need to execute &lt;em>wg-quick&lt;/em> inside our namespace&lt;/li>
&lt;/ol>
&lt;h3 id="how-wg-i-exec-works">How wg-%i-exec works &lt;a href="#how-wg-i-exec-works">¶&lt;/a>&lt;/h3>
&lt;p>There are several problems that the script solves:&lt;/p>
&lt;ol>
&lt;li>Inside the namespace there&amp;rsquo;s no resolv.conf, or there might not be. wg-quick always creates it for itself through &lt;a class="link" href="https://manpages.ubuntu.com/manpages/trusty/man8/resolvconf.8.html" target="_blank" rel="noopener"
>resolvconf&lt;/a>, even without all our tricks. That is, it&amp;rsquo;s created for the interface. This is needed for DNS name resolution.&lt;/li>
&lt;li>We need to make it so that even when running exec as a user, they don&amp;rsquo;t get root privileges as a bonus, but remain with their own privileges.&lt;/li>
&lt;/ol>
&lt;p>I&amp;rsquo;ll break down the script line by line into possibly even non-working shell code, but it will be more convenient to comment this way.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># the interface name will land here in the variable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">netns&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;%s&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># and I&amp;#39;ll explain this mess separately&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF | xargs -0 sudo -E nsenter &amp;#34;--net=/var/run/netns/$netns&amp;#34; unshare --mount sh -c
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">for conf in &amp;#34;$netns&amp;#34; &amp;#34;tun.$netns&amp;#34;; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> if [ -f &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; ]; then
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> mount --bind &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; /etc/resolv.conf
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> fi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">done
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">export DBUS_SESSION_BUS_ADDRESS=unix:path=/dev/null
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">sudo -E -u &amp;#39;#${SUDO_UID:-$(id -u)}&amp;#39; -g &amp;#39;#${SUDO_GID:-$(id -g)}&amp;#39; -- $@
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># execute on behalf of sudo, preserving the current user&amp;#39;s env, this will still be with root privileges&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo -E
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># nsenter will run us in this namespace&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">nsenter &lt;span class="s2">&amp;#34;--net=/var/run/netns/&lt;/span>&lt;span class="nv">$NETNS&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># and then unmount everything that was mounted&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">unshare --mount
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># shell command that will execute the script&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sh -c
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"># where we mount resolv.conf created by wg-quick, if such exists at all
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"># on Ubuntu and Fedora this is needed, on Manjaro - /etc/resolv.conf is already in place
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">for conf in &amp;#34;$netns&amp;#34; &amp;#34;tun.$netns&amp;#34;; do
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> if [ -f &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; ]; then
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> mount --bind &amp;#34;/var/run/resolvconf/interfaces/\$conf&amp;#34; /etc/resolv.conf
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> fi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">done
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"># browsers won&amp;#39;&lt;/span>t start without this
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">DBUS_SESSION_BUS_ADDRESS&lt;/span>&lt;span class="o">=&lt;/span>unix:path&lt;span class="o">=&lt;/span>/dev/null
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># and using sudo preserving the same current user&amp;#39;s env&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo -E
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># not on behalf of root, but already on behalf of the user who ran the exec script&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-u &lt;span class="s1">&amp;#39;#${SUDO_UID:-$(id -u)}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-g &lt;span class="s1">&amp;#39;#${SUDO_GID:-$(id -g)}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># execute what they requested&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-- &lt;span class="nv">$@&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="conclusion">Conclusion &lt;a href="#conclusion">¶&lt;/a>&lt;/h2>
&lt;p>Just insert these 3 lines into the config and that&amp;rsquo;s it! No Ansible, dancing with tambourines, complex setup and maintenance.&lt;/p></description></item><item><title>GPT (UEFI) for Btrfs (/ and /boot) over dm-crypt</title><link>https://vlasov.pro/en/p/gpt-btrfs-gnome/</link><pubDate>Sun, 20 Mar 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/gpt-btrfs-gnome/</guid><description>&lt;img src="https://vlasov.pro/ru/p/gpt-btrfs-gnome/gparted.png" alt="Featured image of post GPT (UEFI) for Btrfs (/ and /boot) over dm-crypt" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>The program in the article&amp;rsquo;s photo is &lt;a class="link" href="https://gparted.org" target="_blank" rel="noopener"
>GParted&lt;/a>. I love and practice it. It&amp;rsquo;s convenient and simple to do whatever you want with partitions. I couldn&amp;rsquo;t decide what to use as the main image for the article. Let it be my current partitioning scheme &amp;#x1f604;&lt;br>
I reinstall systems fairly often, a couple of times a year. The reasons vary: I built a small server, swapped my work PC for a laptop, or upgraded my parents&amp;rsquo; computer with a larger drive&amp;hellip; Just little things, really. I believe I have extensive experience with both Windows and various Linux distributions. This article is mostly just chit-chat, so please don&amp;rsquo;t take offense. If someone happens to discover that comments have been allowed on the site for half a year, I would be sincerely glad &amp;#x1f604;&lt;/p>
&lt;h2 id="partition-table-type">Partition Table Type &lt;a href="#partition-table-type">¶&lt;/a>&lt;/h2>
&lt;p>I used to think: &amp;ldquo;Well, there&amp;rsquo;s the old good MBR, and GPT was invented with their cursed UEFIs to run on laptops and prevent people from installing other operating systems! The 4-partition limitation - so what? If you want more, use logical partitions.&amp;rdquo;
I thought this way until January 2022, when I received a &lt;a class="link" href="https://www.lenovo.com/ua/uk/laptops/ideapad/5-series/IdeaPad-5-14ARE05/p/88IPS501392" target="_blank" rel="noopener"
>laptop&lt;/a> for work, and of course, I started thinking about how to set it up. &amp;ldquo;I&amp;rsquo;ll try GPT; I’ve never used it before. Let’s see if it works, what’s the difference?&amp;rdquo; The result: &lt;em>GPT UEFI forever!&lt;/em> Why&amp;hellip;&lt;/p>
&lt;ol>
&lt;li>There’s no limit on the number of partitions.&lt;/li>
&lt;li>There’s no bootloader area at the beginning of the disk, meaning that the BIOS doesn’t load the disk by following a link at the start, &lt;em>but rather a specific program found on one of however many FAT32 partitions&lt;/em>.&lt;/li>
&lt;li>&lt;a class="link" href="https://www.gnu.org/software/grub/" target="_blank" rel="noopener"
>GRUB&lt;/a> sees all the neighbors on the disk, and so does &lt;strong>the BIOS&lt;/strong>, as it turns out that the entry point is exactly the same UEFI program. You can access the BIOS from the bootloader menu, then back to the bootloader, then again to the BIOS, you get the idea&amp;hellip;&lt;/li>
&lt;li>When you install Windows and it wipes the MBR without asking you (I won’t express my eloquent, uncensored opinion about Microsoft&amp;rsquo;s respect for products not developed by them), and then you need to restore GRUB from a LiveUSB, or maybe some system update failed. It doesn&amp;rsquo;t matter what happened. You just boot another OS straight from the BIOS! I really liked that.&lt;/li>
&lt;li>A downside, but really just a minor one, is that UEFI programs can only be on FAT32 partitions. Well, that&amp;rsquo;s okay. I created it and forgot about it.&lt;/li>
&lt;li>Windows wasn&amp;rsquo;t initially planned, but when it appeared, it turned out that it could be installed on any partitions in order, not just the first one as in the case of MBR, which is a huge plus.&lt;/li>
&lt;/ol>
&lt;h2 id="file-systems">File Systems &lt;a href="#file-systems">¶&lt;/a>&lt;/h2>
&lt;p>I switched to BTRFS everywhere, on my work machine, server, and even the archive partition (auto, moto, photo &amp;hellip;) is also on BTRFS. I really love and respect it; I tried it recently as well. I looked for various &lt;a class="link" href="https://www.phoronix.com/scan.php?page=news_item&amp;amp;px=Linux-5.14-File-Systems" target="_blank" rel="noopener"
>performance benchmarks&lt;/a> and realized that on average, BTRFS is about the same as EXT4 but slower than XFS. &amp;ldquo;To take it or not to take it?&amp;rdquo; I wondered. So I took it for one simple and clear reason: my machines are not high-load servers, and I wouldn’t feel the performance difference &amp;#x1f604; I’m satisfied with my choice.&lt;/p>
&lt;ol>
&lt;li>I have BTRFS RAID1 on two 1TB Barracuda HDDs on my home server - a software RAID, with no problems and at the first attempt.&lt;/li>
&lt;li>Built-in features: compression, defragmentation, error checking (which can indicate when drives are dying), snapshots. It&amp;rsquo;s a dream!&lt;/li>
&lt;li>It turns out GRUB loads BTRFS and boots from BTRFS without any issues!&lt;/li>
&lt;li>It’s a pity there’s no built-in encryption. I had to layer dm-crypt on top - and no worries, everything is excellent.&lt;/li>
&lt;li>BTRFS is like a logical partition with rubber partitions inside, which aren&amp;rsquo;t arranged sequentially as we are used to, but simply exist, all at once &amp;#x1f604; No need to add space if it runs out or think about what will consume how much.&lt;/li>
&lt;/ol>
&lt;p>Interestingly, I had to migrate the OS from one hardware to another. Here&amp;rsquo;s how it looked with BTRFS.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># mount the root btrfs on the old machine&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount /dev/sda1 -o &lt;span class="nv">subvol&lt;/span>&lt;span class="o">=&lt;/span>/ /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># do the same on the new machine&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh user@new-pc mount /dev/sda1 -o &lt;span class="nv">subvol&lt;/span>&lt;span class="o">=&lt;/span>/ /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># create a readonly snapshot of the system partition&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">btrfs subvolume snapshot -r /mnt/@manjaro /mnt/@manjaro-ro
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># send it via SSH! simply amazing...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">btrfs send /mnt/@manjaro-ro &lt;span class="p">|&lt;/span> ssh user@new-pc btrfs receive /mnt/@manjaro-ro
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># on the new machine, create a readwrite snapshot from the received readonly one&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh user@new-pc btrfs subvolume snapshot /mnt/@manjaro-ro /mnt/@manjaro
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># delete the readonly snapshot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh user@new-pc btrfs subvolume del /mnt/@manjaro-ro
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># unmount everything&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh user@new-pc umount /mnt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I have never migrated so easily and simply. Just remember to do the following manually later:&lt;/p>
&lt;ol>
&lt;li>Fix UUIDs in &lt;code>/etc/fstab&lt;/code>&lt;/li>
&lt;li>Update &lt;code>/etc/hostname&lt;/code>&lt;/li>
&lt;li>&lt;code>grub-install ... &amp;amp;&amp;amp; grub-mkconfig ...&lt;/code>&lt;/li>
&lt;/ol>
&lt;h2 id="gpt-partitions">GPT Partitions &lt;a href="#gpt-partitions">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>If Windows needs more space, I&amp;rsquo;ll shrink Manjaro from the end.&lt;/li>
&lt;li>If I need another Linux, it will also need an EFI partition, but the boot partition isn’t necessary! Because multiple Linux systems can boot from one BTRFS boot - just different (subvolume) partitions.&lt;/li>
&lt;/ol>
&lt;h2 id="operating-systems">Operating Systems &lt;a href="#operating-systems">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>It&amp;rsquo;s hard to imagine anything better than Manjaro. I really like everything - &lt;a class="link" href="https://wiki.manjaro.org/index.php/Main_Page" target="_blank" rel="noopener"
>documentation&lt;/a>, utilities, &lt;a class="link" href="https://wiki.manjaro.org/index.php/Manjaro_Kernels" target="_blank" rel="noopener"
>ease of kernel update control with mhwd-kernel&lt;/a>, compatibility with all Vanilla Arch documentation. Fresh software, but not as bleeding-edge as Fedora, which is also nice! &lt;a class="link" href="https://stabyourself.net/mari0/" target="_blank" rel="noopener"
>There’s mari0&lt;/a>&lt;/li>
&lt;li>Windows 10, just for games and Steam.&lt;/li>
&lt;/ol>
&lt;h2 id="important-notes">Important Notes &lt;a href="#important-notes">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Windows does not ask anyone and formats partitions with the &lt;code>boot,esp&lt;/code> flags in FAT32 and puts its EFI there. This was resolved by manually creating the EFI-Windows partition and setting these flags. Linux doesn’t care where they are - it doesn’t affect booting, but the Windows installation fit in the space I needed.&lt;/li>
&lt;li>Initially, I didn’t separate boot, and it was also encrypted! It works perfectly! One downside: GRUB does not pull drivers and uses software-implemented algorithms for decryption, without leveraging CPU hardware capabilities. The initial decryption took me 5-7 seconds. People online complained about tens of seconds&amp;hellip; For me, those 5-7 seconds were not critical, especially since it doesn’t affect work later, just at the beginning of the boot. However, I decided to remove that delay; I also don’t need paranoid security.&lt;/li>
&lt;li>To restore the bootloader, you also need to mount &lt;em>efivars&lt;/em> before chrooting.&lt;/li>
&lt;li>&lt;a class="link" href="https://wiki.manjaro.org/index.php/GRUB/Restore_the_GRUB_Bootloader#EFI_System" target="_blank" rel="noopener"
>Here&amp;rsquo;s excellent documentation&lt;/a> on bootloader recovery.&lt;/li>
&lt;li>It&amp;rsquo;s hard to find better &lt;a class="link" href="https://wiki.archlinux.org/title/Dm-crypt/Encrypting_an_entire_system#Configuring_mkinitcpio" target="_blank" rel="noopener"
>documentation on system installation than this&lt;/a> for an encrypted partition.&lt;/li>
&lt;li>UUIDs in &lt;code>/etc/fstab&lt;/code> must match those you need from the output of &lt;code>blkid&lt;/code>.&lt;/li>
&lt;/ol>
&lt;h2 id="unimportant-notes">Unimportant Notes &lt;a href="#unimportant-notes">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>This is what my boot screen looks like thanks to &lt;a class="link" href="https://wiki.archlinux.org/title/plymouth" target="_blank" rel="noopener"
>plymouth&lt;/a>. &lt;a class="link" href="https://github.com/adi1090x/plymouth-themes" target="_blank" rel="noopener"
>Theme Pack 2 - Flame&lt;/a>. (the image flickering only occurs in the browser; during boot, it’s smooth)&lt;/li>
&lt;li>I chose a theme for Grub &lt;a class="link" href="https://www.gnome-look.org/browse?cat=109" target="_blank" rel="noopener"
>here&lt;/a>. &lt;a class="link" href="https://www.gnome-look.org/p/1603282" target="_blank" rel="noopener"
>This is the one I took.&lt;/a>&lt;/li>
&lt;li>dm-crypt can be patched to create a &lt;a class="link" href="https://www.kali.org/tools/cryptsetup-nuke-password/" target="_blank" rel="noopener"
>nuke password&lt;/a>. If entered, it destroys all keys, and the partition can no longer be decrypted. No matter who steals it, they will never be able to use it.&lt;/li>
&lt;/ol>
&lt;h3 id="grub-recovery-script">Grub recovery script &lt;a href="#grub-recovery-script">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># расшивровуем раздел с системой&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cryptsetup luksOpen /dev/nvme0n1p1 cryptroot
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем систему&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount /dev/mapper/cryptroot -o &lt;span class="nv">subvol&lt;/span>&lt;span class="o">=&lt;/span>@root /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем boot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount /dev/nvme0n1p2 -o &lt;span class="nv">subvol&lt;/span>&lt;span class="o">=&lt;/span>@boot /mnt/boot
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># создаём папку efi если нет&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mkdir -p /mnt/boot/efi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем efi в boot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount /dev/nvme0n1p3 /mnt/boot/efi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем кучу всего для chroot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> i in dev proc sys &lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span> mount --bind /&lt;span class="nv">$i&lt;/span> /mnt/&lt;span class="nv">$i&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># монтируем efivars а то grub не встанет&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount --bind /sys/firmware/efi/efivars /mnt/sys/firmware/efi/efivars
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># запрыгиваем в нашу систему&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">chroot /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ставим grub. тут нужны пояснения&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. в случае с mbr мы привыкли указывать диск, куда прописать загрузчик&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># в случае с efi он ничего никуда не прописывает, а просто наполняет /boot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. bootloader-id это просто для красоты - именно так BIOS будет подписывать нашу ось в списке&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># можно и не писать, там по умолчанию будет manjaro&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">grub-install --bootloader-id&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Manjaro&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># если профукал весь раздел /boot вместе с образами ядра, то вот так они перегенерятся&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pacman -S linux
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># собираем initramfs образы&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mkinitcpio -P
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># собираем меню grub&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">grub-mkconfig -o /boot/grub/grub.cfg
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># выходим из chroot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">exit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># размонтируем и закрываем всё в обратном порядке&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /mnt/sys/firmware/efi/efivars
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> i in dev proc sys&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span> umount /mnt/&lt;span class="nv">$i&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /mnt/boot/efi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /mnt/boot
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /mnt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cryptsetup luksClose cryptroot
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="simple-explanation-of-os-booting-efi">Simple Explanation of OS Booting (EFI) &lt;a href="#simple-explanation-of-os-booting-efi">¶&lt;/a>&lt;/h3>
&lt;ol>
&lt;li>The BIOS starts up and finds all FAT32 partitions that contain an EFI folder and the familiar files. It loads one of the programs it finds, as requested.&lt;/li>
&lt;li>The EFI program is not as limited as MBR; it can do pretty much anything. In our case, it accesses the &lt;code>/boot&lt;/code> partition with GRUB, discovers BTRFS, and loads the GRUB menu. This is where the theme we chose for GRUB is displayed.&lt;/li>
&lt;li>Now, we select what to boot from the GRUB menu.&lt;/li>
&lt;li>GRUB loads the entire initramfs of the selected operating system into RAM. This is what we generated with the &lt;a class="link" href="https://wiki.archlinux.org/title/mkinitcpio" target="_blank" rel="noopener"
>mkinitcpio&lt;/a> command. Initcpio is a program similar to EFI, but when it was created, EFI didn’t exist yet; only the limited MBR was around. I have a feeling that you could boot the system directly from EFI without the extra layer, but that’s another story&amp;hellip; Also, along with initramfs, the kernel is loaded here since it’s also stored on &lt;code>/boot&lt;/code>.&lt;/li>
&lt;li>Initcpio is a layered cake of &lt;a class="link" href="https://wiki.archlinux.org/title/mkinitcpio#HOOKS" target="_blank" rel="noopener"
>hooks&lt;/a> that are executed sequentially. Each one does something important and necessary. If we installed Plymouth, then right here, in one of the very first hooks, some beautiful graphics are drawn on the screen to hide a bunch of loading logs.&lt;/li>
&lt;li>One of the hooks is &lt;em>encrypt&lt;/em> or &lt;em>plymouth-encrypt&lt;/em>. This particular piece of the initramfs cake asks us for the password for the encrypted root. Up to this point, it hasn’t been accessed at all &amp;#x1f604;&lt;/li>
&lt;li>Decryption, creating the first process, starting services, drivers, the graphical shell, and the whole process of booting up.&lt;/li>
&lt;/ol>
&lt;h2 id="conclusion">Conclusion &lt;a href="#conclusion">¶&lt;/a>&lt;/h2>
&lt;p>I hope the article helped someone or provided some information. If you have suggestions or ideas, feel free to contact me!&lt;/p></description></item><item><title>Overview of k9s</title><link>https://vlasov.pro/en/p/k9s/</link><pubDate>Mon, 17 Jan 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/k9s/</guid><description>&lt;img src="https://vlasov.pro/ru/p/k9s/k9s.webp" alt="Featured image of post Overview of k9s" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://github.com/derailed/k9s" target="_blank" rel="noopener"
>k9s&lt;/a> - my favorite tool for working with Kubernetes clusters. I really like this tool, there are quite good analogues and even much prettier ones, but exactly here, hotkeys work well and it&amp;rsquo;s very convenient to use from the terminal.&lt;/p>
&lt;p>Everything you can read in the repository page is also indicated what&amp;rsquo;s fresh in memory, only that which I constantly use.&lt;/p>
&lt;h2 id="overview">Overview &lt;a href="#overview">¶&lt;/a>&lt;/h2>
&lt;h3 id="viewing-logs">Viewing logs &lt;a href="#viewing-logs">¶&lt;/a>&lt;/h3>
&lt;p>Just by pressing &lt;code>L&lt;/code> you can view the logs of a separate pod, there too you can quickly choose a range of time for which these logs should be shown.&lt;/p>
&lt;h3 id="copying-to-clipboard-buffer">Copying to clipboard buffer &lt;a href="#copying-to-clipboard-buffer">¶&lt;/a>&lt;/h3>
&lt;p>By pressing &lt;code>C&lt;/code> in the mode of viewing logs or manifest object, the screen content (the entire file or log, not only what is visible) is copied into the clipboard buffer. You need to have &lt;code>xsel&lt;/code> installed as well.&lt;/p>
&lt;h3 id="port-forwarding">Port forwarding &lt;a href="#port-forwarding">¶&lt;/a>&lt;/h3>
&lt;p>Pressing &lt;code>Shift + F&lt;/code> allows you to choose which ports to forward to your local machine so that you can access any service.&lt;/p>
&lt;h3 id="viewing-problematic-pods">Viewing problematic pods &lt;a href="#viewing-problematic-pods">¶&lt;/a>&lt;/h3>
&lt;p>By pressing &lt;code>Ctrl + Z&lt;/code> in the list of pods, only those remain that are not Running.&lt;/p>
&lt;h3 id="searching-by-substring">Searching by substring &lt;a href="#searching-by-substring">¶&lt;/a>&lt;/h3>
&lt;p>Just press the backslash and write a substring that needs to be searched in the name or tags of object objects from the list. It&amp;rsquo;s convenient when there are many objects.&lt;/p>
&lt;h2 id="demonstration">Demonstration &lt;a href="#demonstration">¶&lt;/a>&lt;/h2>
&lt;script id="asciicast-462297" src="https://asciinema.org/a/462297.js" async>&lt;/script></description></item><item><title>Notes on Terraform</title><link>https://vlasov.pro/en/p/terraform-notes/</link><pubDate>Sun, 16 Jan 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/terraform-notes/</guid><description>&lt;img src="https://vlasov.pro/ru/p/terraform-notes/terraform.webp" alt="Featured image of post Notes on Terraform" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://www.terraform.io" target="_blank" rel="noopener"
>Terraform&lt;/a> is a fantastic tool for automating resource creation in clouds like AWS, Azure, GCP, Hetzner, and many others. It&amp;rsquo;s really cool. With &lt;a class="link" href="https://github.com/tfutils/tfenv" target="_blank" rel="noopener"
>tfenv&lt;/a>, you can easily and conveniently update Terraform locally and choose the desired version. You can &lt;a class="link" href="https://github.com/tfutils/tfenv#terraform-version-file" target="_blank" rel="noopener"
>create a file in the project&amp;rsquo;s root&lt;/a> to specify the required version, allowing tfenv to automatically use the correct Terraform version for your project.&lt;br>
There are several practical recommendations I&amp;rsquo;ve developed from reading the official documentation, which is excellent, as well as the modules and code written by AWS.&lt;/p>
&lt;h2 id="recommendations">Recommendations &lt;a href="#recommendations">¶&lt;/a>&lt;/h2>
&lt;p>Study the &lt;a class="link" href="https://www.terraform-best-practices.com" target="_blank" rel="noopener"
>official recommendations&lt;/a>. Below are my own notes.&lt;/p>
&lt;h3 id="1-do-not-duplicate-resource-type-in-the-name">1. Do not duplicate resource type in the name &lt;a href="#1-do-not-duplicate-resource-type-in-the-name">¶&lt;/a>&lt;/h3>
&lt;p>Incorrect&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_vpc&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;production_vpc&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">cidr_block&lt;/span> = &lt;span class="s2">&amp;#34;172.16.0.0/16&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">tags&lt;/span> = &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Name&lt;/span> = &lt;span class="s2">&amp;#34;Production VPC&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Correct&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_vpc&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;production&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">cidr_block&lt;/span> = &lt;span class="s2">&amp;#34;172.16.0.0/16&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">tags&lt;/span> = &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Name&lt;/span> = &lt;span class="s2">&amp;#34;Production&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Explanation&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>In the code, you&amp;rsquo;ll still reference the resource as &lt;code>${aws_vpc.production.id}&lt;/code>—it’s already clear that this is a VPC, so there’s no need to waste characters on what’s already written.&lt;/li>
&lt;li>The same goes for the resource name; you&amp;rsquo;ll always see the VPC in the list on the VPC page in the AWS Console, and there won’t be anything else. Again, why duplicate?&lt;/li>
&lt;/ol>
&lt;h3 id="2-use-this-as-a-name-but-only-in-modules">2. Use &lt;code>this&lt;/code> as a name, but only in modules &lt;a href="#2-use-this-as-a-name-but-only-in-modules">¶&lt;/a>&lt;/h3>
&lt;p>Suppose you have a module that creates a virtual machine and minimal attachments. Within the module, the virtual machine is unique.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_instance&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;this&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">ami&lt;/span> = &lt;span class="nb">data&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">aws_ami&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">id&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">instance_type&lt;/span> = &lt;span class="nb">var&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">instance_type&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Why come up with names for resources if it&amp;rsquo;s the only one within the module? There’s no need. It’s also important to understand that this is the object name within the Terraform code. It&amp;rsquo;s convenient when any resource type is simply &lt;code>this&lt;/code>, but you should only do this within a single module that creates a logical unit. A virtual machine without its Security Group, which opens the ports, doesn’t make sense; thus, logically, it’s one piece.&lt;/p>
&lt;h3 id="3-create-standard-files-for-modules">3. Create standard files for modules &lt;a href="#3-create-standard-files-for-modules">¶&lt;/a>&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>File&lt;/th>
&lt;th>Content&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>vars.tf&lt;/td>
&lt;td>All variables&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>outputs.tf&lt;/td>
&lt;td>Output parameters&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>versions.tf&lt;/td>
&lt;td>Section with &lt;a class="link" href="https://www.terraform.io/language/settings#specifying-provider-requirements" target="_blank" rel="noopener"
>provider requirements&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>main.tf&lt;/td>
&lt;td>File with the root content&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="4-do-not-declare-providers-in-modules">4. Do not declare providers in modules &lt;a href="#4-do-not-declare-providers-in-modules">¶&lt;/a>&lt;/h3>
&lt;p>Specify &lt;a class="link" href="https://www.terraform.io/language/settings#specifying-provider-requirements" target="_blank" rel="noopener"
>version constraints&lt;/a>, but leave initialization to the discretion of the user of your module.&lt;/p>
&lt;h3 id="5-tags-variable">5. Tags variable &lt;a href="#5-tags-variable">¶&lt;/a>&lt;/h3>
&lt;p>Add a variable that will apply tags to all resources in the module.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">variable&lt;/span> &lt;span class="s2">&amp;#34;tags&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">type&lt;/span> =&lt;span class="nb"> map&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">string&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">description&lt;/span> = &lt;span class="s2">&amp;#34;Extra tags.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">default&lt;/span> = &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">locals&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">default_tags&lt;/span> = &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Custom&lt;/span> = &lt;span class="s2">&amp;#34;Some default tags&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Terraform&lt;/span> = &lt;span class="s2">&amp;#34;Path to module folder in your Git repo - helps to find code in the repo fast&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">tags&lt;/span> =&lt;span class="nb"> merge&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">local&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">default_tags&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">var&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">tags&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_vpc&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;production&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">cidr_block&lt;/span> = &lt;span class="s2">&amp;#34;172.16.0.0/16&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">tags&lt;/span> =&lt;span class="nb"> merge&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">local&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">tags&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">Name&lt;/span> = &lt;span class="s2">&amp;#34;Production&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>In the &lt;code>local.tags&lt;/code> variable, we first collect the final dictionary and then use it where needed within the module.&lt;/p>
&lt;h3 id="6-resource-naming-with-name_prefix">6. Resource naming with &lt;code>name_prefix&lt;/code> &lt;a href="#6-resource-naming-with-name_prefix">¶&lt;/a>&lt;/h3>
&lt;p>Always, without exception, use a name prefix for creating resources. By changing just this variable, the code should create exactly the same infrastructure in the same account without any conflicts—this is a good module that can be reused.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">variable&lt;/span> &lt;span class="s2">&amp;#34;name_prefix&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">type&lt;/span> = &lt;span class="nx">string&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">description&lt;/span> = &lt;span class="s2">&amp;#34;Name prefix for all resources (required).&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">validation&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">condition&lt;/span> = &lt;span class="nb">can&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">regex&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;^[a-z][a-z0-9-]+[a-z]$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">var&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">name_prefix&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;tls_private_key&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;this&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">algorithm&lt;/span> = &lt;span class="s2">&amp;#34;RSA&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">rsa_bits&lt;/span> = &lt;span class="m">4096&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_key_pair&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;this&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">key_name&lt;/span> = &lt;span class="nb">var&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">name_prefix&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">public_key&lt;/span> = &lt;span class="nx">tls_private_key&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">public_key_openssh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>And there’s no point in adding anything to the name if there&amp;rsquo;s only one resource. Suppose this code is part of the same module for creating a virtual machine; it will be used like this.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">module&lt;/span> &lt;span class="s2">&amp;#34;ec2_backend&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">source&lt;/span> = &lt;span class="s2">&amp;#34;./ec2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">name_prefix&lt;/span> = &lt;span class="s2">&amp;#34;production-backend&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">instance_type&lt;/span> = &lt;span class="s2">&amp;#34;t3a.small&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This way, it will be clear from the prefix to which virtual machine the EC2 Key Pair belongs in the list. If there were two, then the name in the code would be &lt;code>&amp;quot;${var.name_prefix}-some-suffix&amp;quot;&lt;/code>.&lt;/p>
&lt;h3 id="7-no-hyphens-in-resource-names">7. No hyphens in resource names &lt;a href="#7-no-hyphens-in-resource-names">¶&lt;/a>&lt;/h3>
&lt;p>Forget about using hyphens in resource names. It breaks the code analyzer in the IDE, and it causes issues in various situations.&lt;/p>
&lt;p>Incorrect&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">module&lt;/span> &lt;span class="s2">&amp;#34;ec2-backend&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">source&lt;/span> = &lt;span class="s2">&amp;#34;./ec2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">name_prefix&lt;/span> = &lt;span class="s2">&amp;#34;production-backend&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">instance_type&lt;/span> = &lt;span class="s2">&amp;#34;t3a.small&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">output&lt;/span> &lt;span class="s2">&amp;#34;backend-ip&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">value&lt;/span> &lt;span class="nb">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ec2&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nx">backend&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">private&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nx">ipv4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Correct&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-terraform" data-lang="terraform">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">module&lt;/span> &lt;span class="s2">&amp;#34;ec2_backend&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">source&lt;/span> = &lt;span class="s2">&amp;#34;./ec2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">name_prefix&lt;/span> = &lt;span class="s2">&amp;#34;production-backend&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">instance_type&lt;/span> = &lt;span class="s2">&amp;#34;t3a.small&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">output&lt;/span> &lt;span class="s2">&amp;#34;backend_ip&amp;#34;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">value&lt;/span> &lt;span class="nb">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">ec2_backend&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">private_ipv4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I would like to emphasize that for the name of the resource in the cloud, I recommend using hyphens as much as possible—it looks nicer—but in Terraform, never.&lt;/p></description></item><item><title>Figlet ASCII Graphics</title><link>https://vlasov.pro/en/p/figlet/</link><pubDate>Fri, 07 Jan 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/figlet/</guid><description>&lt;img src="https://vlasov.pro/ru/p/figlet/bomberman.webp" alt="Featured image of post Figlet ASCII Graphics" />&lt;blockquote>
&lt;p>&lt;a class="link" href="https://www.asciiart.eu/video-games/atomic-bomberman" target="_blank" rel="noopener"
>&lt;em>Bomberman from here.&lt;/em>&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl"># ┬ ┬┬─┐┬ ┬ ┌─┐ # ┳━┓┳━┓┏┓┓┳━┓┳━┓┳━┓┓━┓┳━┓┓━┓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># │─┤├─ │ │ │ │ # ┃ ┃┃━┫ ┃ ┃━┫┃━┃┃━┫┗━┓┣━ ┗━┓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># ┘ ┴┴─┘┘─┘┘─┘┘─┘ # ┇━┛┛ ┇ ┇ ┛ ┇┇━┛┛ ┇━━┛┻━┛━━┛
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># ┳━┓┓ ┳┓━┓ ┳━┓┏━┓┏━┓ # ┌┐┐┬─┐┌┐┐┐ ┬┌─┐┬─┐┬┌
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># ┃━┫┃┃┃┗━┓ ┣━ ┃ ┏━┛ # │││├─ │ ││││ ││┬┘├┴┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># ┛ ┇┗┻┇━━┛ ┻━┛┗━┛┗━━ # ┘└┘┴─┘ ┘ └┴┘┘─┘┘└┘┘ ┘
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I insert such captions in the source codes to visually separate chunks. In Terraform, for example.&lt;/p>
&lt;h2 id="installation">Installation &lt;a href="#installation">¶&lt;/a>&lt;/h2>
&lt;p>Install &lt;a class="link" href="https://www.google.com/search?q=figlet%20install" target="_blank" rel="noopener"
>figlet&lt;/a> in any way suitable for your distribution.&lt;br>
Download additional fonts.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">curl -Lo- &lt;span class="s1">&amp;#39;https://github.com/vlasov-y/figlet-fonts/archive/refs/tags/v1.1.tar.gz&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>sudo tar -C &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>figlet -I2&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> --strip-components &lt;span class="m">1&lt;/span> -xpzvf -
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="viewing-all-fonts">Viewing All Fonts &lt;a href="#viewing-all-fonts">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">find &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>figlet -I2&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -type f -name &lt;span class="s1">&amp;#39;*.*f&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="k">while&lt;/span> &lt;span class="nb">read&lt;/span> -r i&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&amp;gt; &lt;/span>&lt;span class="nv">$i&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> figlet -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$i&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>basename &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$i&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span> &lt;span class="p">|&lt;/span> less
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="function-for-bashrc">Function for .bashrc &lt;a href="#function-for-bashrc">¶&lt;/a>&lt;/h2>
&lt;p>Be careful here. In the overwhelming majority of fonts, there are characters that won&amp;rsquo;t display at all or will be shown incorrectly (as rectangles) for your colleagues who pulled the same code from Git. Through trial and error, I found a universal and beautiful font for myself - &lt;em>Rusto&lt;/em>. There’s also &lt;em>RustoFat&lt;/em>, which I actually like more, but it has its problems. &amp;#x1f622;&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┬─┐┬ ┐┐─┐┌┐┐┌─┐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># │┬┘│ │└─┐ │ │ │&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┘└┘┘─┘──┘ ┘ ┘─┘&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┳━┓┳ ┓┓━┓┏┓┓┏━┓┳━┓┳━┓┏┓┓&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┃┳┛┃ ┃┗━┓ ┃ ┃ ┃┣━ ┃━┫ ┃ &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┇┗┛┇━┛━━┛ ┇ ┛━┛┇ ┛ ┇ ┇ &lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The captions above were generated using my function, so your Rusto will differ slightly. Add this function to your &lt;code>.bashrc&lt;/code> or &lt;code>.zshrc&lt;/code>, and you can use it. Also, you&amp;rsquo;ll need to install &lt;code>xsel&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">rusto &lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> figlet -f rusto &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$*&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> sed &lt;span class="s2">&amp;#34;s@^@&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">P&lt;/span>&lt;span class="k">:-&lt;/span>&lt;span class="p"># &lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">@g; s@┆@┘@g&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> tee /tmp/tt &lt;span class="p">|&lt;/span> xsel -i -b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> cat /tmp/tt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f /tmp/tt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rustofat &lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> figlet -f rustofat &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$*&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> sed &lt;span class="s2">&amp;#34;s@^@&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">P&lt;/span>&lt;span class="k">:-&lt;/span>&lt;span class="p"># &lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">@g&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> tee /tmp/tt &lt;span class="p">|&lt;/span> xsel -i -b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> cat /tmp/tt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f /tmp/tt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>What happens here? When you execute the command in the console &lt;code>rusto&lt;/code> or &lt;code>rustofat&lt;/code>, the text passed as arguments to the commands will be transformed, displayed on the screen, and immediately copied to the clipboard. Also, the symbol &lt;code>┆&lt;/code> is replaced with &lt;code>┘&lt;/code> to make &lt;em>Rusto&lt;/em> completely problem-free. Additionally, &lt;code># &lt;/code> is prepended to the start of each line, allowing you to paste it directly into the source code. You can replace the hash by setting the variable &lt;code>P&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">❯ rusto hello world
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┬ ┬┬─┐┬ ┬ ┌─┐ ┐ ┬┌─┐┬─┐┬ ┬─┐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># │─┤├─ │ │ │ │ ││││ ││┬┘│ │ │&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ┘ ┴┴─┘┘─┘┘─┘┘─┘ └┴┘┘─┘┘└┘┘─┘┘─┘&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❯ &lt;span class="nv">P&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;// &amp;#39;&lt;/span> rustofat changed comment char
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">// ┏━┓┳ ┳┳━┓┏┓┓┏━┓┳━┓┳━┓ ┏━┓┏━┓┏┏┓┏┏┓┳━┓┏┓┓┏┓┓ ┏━┓┳ ┳┳━┓┳━┓
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">// ┃ ┃━┫┃━┫┃┃┃┃ ┳┣━ ┃ ┃ ┃ ┃ ┃┃┃┃┃┃┃┣━ ┃┃┃ ┃ ┃ ┃━┫┃━┫┃┳┛
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">// ┗━┛┇ ┻┛ ┇┇┗┛┇━┛┻━┛┇━┛ ┗━┛┛━┛┛ ┇┛ ┇┻━┛┇┗┛ ┇ ┗━┛┇ ┻┛ ┇┇┗┛
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="bonus">Bonus &lt;a href="#bonus">¶&lt;/a>&lt;/h2>
&lt;p>I generate the daily report form like this.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">LC_ALL&lt;/span>&lt;span class="o">=&lt;/span>C.POSIX date &lt;span class="s1">&amp;#39;+%d %B&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>figlet &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>xargs -0 &lt;span class="nb">printf&lt;/span> &lt;span class="s1">&amp;#39;```\n%s```\nNo blocks\nNo questions\nDone\\Doing:\n&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span>xsel -ib
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>It produces something like this.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="l">```&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">___ __ _ &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">/ _ \ / /_ | | __ _ _ __ _ _ __ _ _ __ _ _ &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">| | | | &amp;#39;_ \ _ | |/ _` | &amp;#39;_ \| | | |/ _` | &amp;#39;__| | | |&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">| |_| | (_) | | |_| | (_| | | | | |_| | (_| | | | |_| |&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">\___/ \___/ \___/ \__,_|_| |_|\__,_|\__,_|_| \__, |&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="l">|___/ &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">```&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="kc">No&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">blocks&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="kc">No&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">questions&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">Done\Doing&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="l">Drinking tea&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="l">Sleeping&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="l">Writing evening report&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>- &lt;span class="l">Emulating work&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Then I add what I did and send it to Slack.&lt;/p></description></item><item><title>Safe Update of Manjaro</title><link>https://vlasov.pro/en/p/manjaro-update/</link><pubDate>Thu, 06 Jan 2022 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/manjaro-update/</guid><description>&lt;img src="https://vlasov.pro/ru/p/manjaro-update/manjaro.webp" alt="Featured image of post Safe Update of Manjaro" />&lt;h2 id="history">History &lt;a href="#history">¶&lt;/a>&lt;/h2>
&lt;p>It somehow happened that I updated my system fully, and both of my machines - the work machine and the personal server - broke. The Python 3.10 library crashed with a segfault, which caused the Kodi media server to malfunction. The Python Pip package also failed. It was quite frustrating in general. Fortunately, I had a backup.
I really love &lt;a class="link" href="https://manjaro.org" target="_blank" rel="noopener"
>Manjaro&lt;/a> - it&amp;rsquo;s the best operating system for professional use, and I never had any problems with updating except maybe New Year&amp;rsquo;s Eve &amp;#x1f604; This is my second time, and both times were on New Year&amp;rsquo;s Eve.
&lt;strong>December 31, 2020&lt;/strong>, I made a full update of the system, but when I woke up to the new year, I found that X11 would not start because the drivers for Nvidia had expired. And then I thought: &amp;ldquo;Well, I fixed it in 5 minutes, how about others? Are they DevOps or ordinary users?&amp;rdquo; It seems like there was a transfer of drivers to the distribution&amp;rsquo;s repository, a simple renaming, but that was enough.
And again New Year&amp;rsquo;s Eve! I install an update and Python3 crashes at the level of .so libraries &amp;#x1f604; The system works overall, but it needs something in many places and some software can fail. Right away the &lt;a class="link" href="https://github.com/ranger/ranger" target="_blank" rel="noopener"
>ranger&lt;/a> stopped working, so I had to reinstall it again.
This is what happened, and here&amp;rsquo;s the script below.&lt;/p>
&lt;h2 id="script">Script &lt;a href="#script">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="c1">## Making root BTRFS subvolume snapshot before making full Manjaro update&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">PARTITION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mount &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;$3~/^\/$/{print $1}&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SUBVOL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>mount &lt;span class="p">|&lt;/span> awk &lt;span class="s1">&amp;#39;$3~/^\/$/{print $6}&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;subvol=[^,)]+&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> cut -d&lt;span class="o">=&lt;/span> -f2- &lt;span class="p">|&lt;/span> sed -r &lt;span class="s1">&amp;#39;s/^\///g&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">MOUNTPOINT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;/mnt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">BACKUP&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>date +%Y-%m-%d &lt;span class="p">|&lt;/span> xargs &lt;span class="nb">printf&lt;/span> &lt;span class="s2">&amp;#34;backup/%s-%s&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SUBVOL&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">main&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> backup
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">backup&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Mounting &lt;/span>&lt;span class="nv">$PARTITION&lt;/span>&lt;span class="s2"> to &lt;/span>&lt;span class="nv">$MOUNTPOINT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mount &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$PARTITION&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MOUNTPOINT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -o &lt;span class="nv">subvol&lt;/span>&lt;span class="o">=&lt;/span>/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">cd&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MOUNTPOINT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> dirname &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$BACKUP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> xargs mkdir -p
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -d &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$BACKUP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Backing up &lt;/span>&lt;span class="nv">$SUBVOL&lt;/span>&lt;span class="s2"> to &lt;/span>&lt;span class="nv">$BACKUP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> btrfs sub snap -r &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SUBVOL&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$BACKUP&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$BACKUP&lt;/span>&lt;span class="s2"> exists already&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">cd&lt;/span> /
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Unmounting &lt;/span>&lt;span class="nv">$MOUNTPOINT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> umount &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$MOUNTPOINT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">update&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Running update&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> yay -Syu
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">main &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$@&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="example-usage">Example Usage &lt;a href="#example-usage">¶&lt;/a>&lt;/h2>
&lt;script id="asciicast-460238" src="https://asciinema.org/a/460238.js" async>&lt;/script>
&lt;p>And here&amp;rsquo;s what happens if the backup is made today already.&lt;/p>
&lt;script id="asciicast-460241" src="https://asciinema.org/a/460241.js" async>&lt;/script></description></item><item><title>PulseAudio over TCP</title><link>https://vlasov.pro/en/p/pulseaudio-tcp/</link><pubDate>Wed, 17 Nov 2021 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/pulseaudio-tcp/</guid><description>&lt;img src="https://vlasov.pro/ru/p/pulseaudio-tcp/pulseaudio.webp" alt="Featured image of post PulseAudio over TCP" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://www.freedesktop.org/wiki/Software/PulseAudio/" target="_blank" rel="noopener"
>PulseAudio&lt;/a> is a sound server, in my understanding. It runs on any Linux PC. Microphones, speakers, virtual devices - everything goes through PulseAudio and is controlled by it.&lt;/p>
&lt;h2 id="task">Task &lt;a href="#task">¶&lt;/a>&lt;/h2>
&lt;p>There’s a small server connected to a wall-mounted TV. I’m working on a PC with &lt;a class="link" href="https://manjaro.org" target="_blank" rel="noopener"
>Manjaro&lt;/a> and, to be honest, the headphones aren&amp;rsquo;t great. They’ll do for work, but I want to listen to music through the TV.&lt;/p>
&lt;h2 id="sources">Sources &lt;a href="#sources">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>&lt;a class="link" href="https://wiki.archlinux.org/title/PulseAudio/Examples#Selecting_the_server_with_Zeroconf" target="_blank" rel="noopener"
>Arch Wiki PulseAudio Examples&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://medium.com/@joao.paulo.silvasouza/how-to-configure-pulseaudio-for-multiple-devices-at-the-same-time-in-ubuntu-4943ef0c16db" target="_blank" rel="noopener"
>Joao Paulo Silva de Souza&amp;rsquo;s article on Medium&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://unix.stackexchange.com/a/443064" target="_blank" rel="noopener"
>A good answer on Unix Overflow&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://unix.stackexchange.com/questions/443013/pulseaudio-simultanious-add-two-devices" target="_blank" rel="noopener"
>And another one&lt;/a>&lt;/li>
&lt;/ol>
&lt;h2 id="solution">Solution &lt;a href="#solution">¶&lt;/a>&lt;/h2>
&lt;p>The traffic will be sent over TCP from the PC to the server (for simplicity, I’ll just refer to it as TV in the text, but it&amp;rsquo;s actually a server on Manjaro).&lt;/p>
&lt;p>On both devices, we install the Zeroconf module so that the computers can find each other without issues.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">yay -S pulseaudio-zeroconf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now, let&amp;rsquo;s take the cookie file from one and copy it to the other so they are the same. I found it in my home directory on the PC.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">scp ~/.config/pulse/cookie server:/etc/pulse/cookie
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo cp -f ~/.config/pulse/cookie /etc/pulse/cookie
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now we configure:&lt;/p>
&lt;ol>
&lt;li>The TV will be the PulseAudio &lt;strong>server&lt;/strong>, as it &lt;strong>receives&lt;/strong> the audio stream.&lt;/li>
&lt;li>The PC will be the PulseAudio &lt;strong>client&lt;/strong>, as it &lt;strong>sends&lt;/strong> the stream.&lt;/li>
&lt;/ol>
&lt;p>On the TV, we run it as a regular user because there’s no need to start &lt;code>pulseaudio --kill/--start&lt;/code> as root.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SUBNET&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;192.168.0.0/24&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo mkdir -p /etc/pulse/default.pa.d/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF | sudo tee /etc/pulse/default.pa.d/zeroconf.pa
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;${SUBNET}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">load-module module-zeroconf-publish
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> --now avahi-daemon.service
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --kill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --start
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>On the PC, it&amp;rsquo;s almost the same.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SUBNET&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;192.168.0.0/24&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo mkdir -p /etc/pulse/default.pa.d/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF | sudo tee /etc/pulse/default.pa.d/zeroconf.pa
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;${SUBNET}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">load-module module-zeroconf-discover
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> --now avahi-daemon.service
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --kill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --start
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>That&amp;rsquo;s it. Now in pavucontrol, you can direct some application through the tunnel to the PC!&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/pulseaudio-tcp/pavucontrol.png"
width="814"
height="502"
srcset="https://vlasov.pro/ru/p/pulseaudio-tcp/pavucontrol_hu15804026729683766190.png 480w, https://vlasov.pro/ru/p/pulseaudio-tcp/pavucontrol_hu1219485386400571975.png 1024w"
loading="lazy"
alt="Pavucontrol where Chrome streams directly to the TV via the server&amp;rsquo;s HDMI"
class="gallery-image"
data-flex-grow="162"
data-flex-basis="389px"
>&lt;/p>
&lt;h2 id="bonus-that-doesnt-work">Bonus that doesn’t work &lt;a href="#bonus-that-doesnt-work">¶&lt;/a>&lt;/h2>
&lt;p>What would be nice next? Right, something that won&amp;rsquo;t be useful but is interesting. I want both the PC and the TV to play the same stream.&lt;/p>
&lt;p>On the PC, let’s check what outputs we have and get their names.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># pacmd list-sinks | grep name:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">name: &amp;lt;alsa_output.pci-0000_00_1b.0.analog-stereo&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">name: &amp;lt;tunnel.aurelius.local.auto_null&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">name: &amp;lt;tunnel.aurelius.local.auto_null.2&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">name: &amp;lt;tunnel.aurelius.local.alsa_output.pci-0000_00_0e.0.hdmi-stereo&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Here we can see that the first one seems to be the headphones, while the others have come through the network. The 2nd and 3rd are likely the rear and front outputs on the case, while the last one is definitely the HDMI from the computer - which is what we need. So we need to combine the 1st and 4th.&lt;/p>
&lt;p>Still on the PC:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SLAVE_1&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;alsa_output.pci-0000_00_1b.0.analog-stereo&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">SLAVE_2&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;tunnel.aurelius.local.alsa_output.pci-0000_00_0e.0.hdmi-stereo&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEFAULT_SLAVE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$SLAVE_1&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF | sudo tee -a /etc/pulse/default.pa.d/zeroconf.pa
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">load-module module-combine-sink sink_name=combined sink_properties=&amp;#34;device.description=&amp;#39;Combined TV and PC&amp;#39; slaves=${SLAVE_1},${SLAVE_2}&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">set-default-sink ${DEFAULT_SLAVE}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --kill
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pulseaudio --start
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>That&amp;rsquo;s it &amp;#x1f604; &amp;hellip; Except it doesn&amp;rsquo;t work. I don’t know why. The device has been added, it can be selected, and there are no errors in the logs, but the sound only goes to the headphones and not to the TV. At the same time, when I simply select the TV, it works. So it seems this module cannot combine tunnel and simple devices. I decided to write this anyway; maybe it will be useful to someone.&lt;/p></description></item><item><title>Wireguard Ansible</title><link>https://vlasov.pro/en/p/wireguard-ansible/</link><pubDate>Tue, 16 Nov 2021 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/wireguard-ansible/</guid><description>&lt;img src="https://vlasov.pro/ru/p/wireguard-ansible/wireguard.webp" alt="Featured image of post Wireguard Ansible" />&lt;p>&lt;a class="link" href="https://github.com/vlasov-y/wireguard-ansible" target="_blank" rel="noopener"
>&lt;strong>GitHub&lt;/strong>&lt;/a>&lt;/p>
&lt;h2 id="update-from-november-25-2022">Update from November 25, 2022 &lt;a href="#update-from-november-25-2022">¶&lt;/a>&lt;/h2>
&lt;p>I switched to classic wg-quick from this Ansible setup. The solution turned out to be technically much simpler, and it meets my functional needs.&lt;/p>
&lt;h2 id="update-from-march-21-2022">Update from March 21, 2022 &lt;a href="#update-from-march-21-2022">¶&lt;/a>&lt;/h2>
&lt;p>I removed automatic key generation due to excessive implementation complexity and the inability to configure servers individually; it could only be done collectively. Now it’s different. Configuration changes are incompatible with the old version; please check the examples in the repository, as I have added documentation there.&lt;/p>
&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://www.wireguard.com" target="_blank" rel="noopener"
>Wireguard&lt;/a> is an amazing, simple VPN that is &lt;a class="link" href="https://www.wireguard.com" target="_blank" rel="noopener"
>already included in the kernel&lt;/a>. It’s a very powerful and straightforward tool. It installs much more easily than &lt;a class="link" href="https://openvpn.net" target="_blank" rel="noopener"
>OpenVPN&lt;/a>.&lt;/p>
&lt;h2 id="problem-statement">Problem Statement &lt;a href="#problem-statement">¶&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>I live in Ukraine, and unfortunately, some internet resources are blocked, and access is sometimes necessary.&lt;/li>
&lt;li>I want to be able to remotely connect from my phone or someone else&amp;rsquo;s computer to my home server.&lt;/li>
&lt;li>I want traffic to be proxied on the PC only for domains on the list, not everything.&lt;/li>
&lt;/ul>
&lt;p>With these requests, I started working. For myself, all for myself. No one else needs it for now, although I posted it on &lt;a class="link" href="https://github.com/vlasov-y/wireguard-ansible" target="_blank" rel="noopener"
>GitHub&lt;/a>. Posted is a strong word. No documentation, nothing! Yes! Just lazy to write&amp;hellip; Oh well.&lt;/p>
&lt;h2 id="solution-overview">Solution Overview &lt;a href="#solution-overview">¶&lt;/a>&lt;/h2>
&lt;p>I used Ansible, which can configure the network immediately. What it can do:&lt;/p>
&lt;ol>
&lt;li>Use a constant preshared key for all connections.&lt;/li>
&lt;li>Ability to specify your AllowedIPs.&lt;/li>
&lt;li>Ability to add peers with statically defined keys (since Ansible can&amp;rsquo;t be run on the phone).&lt;/li>
&lt;li>Automatic selection of free rt_table IDs and fwmarks.&lt;/li>
&lt;li>Ability to set up more than one network on the same machines with a single run!&lt;/li>
&lt;/ol>
&lt;p>What it can&amp;rsquo;t do:&lt;/p>
&lt;ol>
&lt;li>Separate runs on one or a subgroup of hosts. Only all at once.&lt;/li>
&lt;/ol>
&lt;h2 id="understanding-ansible-variables">Understanding Ansible Variables &lt;a href="#understanding-ansible-variables">¶&lt;/a>&lt;/h2>
&lt;blockquote>
&lt;p>all.yml&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># CIDR networks&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">192.168.99.0&lt;/span>&lt;span class="l">/24&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.0.0&lt;/span>&lt;span class="l">/24&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># marks for routing - each network has its own&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_fwmarks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># preshared key for the network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_preshared_keys&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># keys for each server in each network where it exists&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_keys&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public_host&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">private&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home_server&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">private&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">laptop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">private&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public_host&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">private&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">laptop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">private&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">smartphone&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># only public key for the phone, as the private is not needed here&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">longalphanum&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_addresses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># addresses for each server in each network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public_host&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">192.168.99.1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">laptop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">192.168.99.2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home_server&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">192.168.99.3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">public_host&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.0.1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">laptop&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.0.2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">smartphone&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">10.0.0.3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>We have a server with a public IP, and it will serve as the connection point for everyone. The topology is a star.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># these are variables for a specific host - the server&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">yes&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># wireguard-tools have already been installed, so we turn this off&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_install_tools&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">no&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># list of peers&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_peers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># for the home network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># the first peer is our laptop, where we run Ansible&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">laptop&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># the second has inventory_hostname home_server&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">home_server&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># and keep the network so that it can always be reached,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># because the server is behind NAT&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">keepalive_seconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">25&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># the second network will only be used from the phone and PC&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">laptop&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># and here is the phone&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">smartphone&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># now we&amp;#39;ll choose the ports it should listen on&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># for the others, it doesn&amp;#39;t matter, but&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># for the server, it&amp;#39;s better to specify everything statically&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># so nothing is regenerated if anything happens&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># and all clients don&amp;#39;t need to be reconfigured&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># with new server credentials&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">3000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># enable masquerading so that the server can&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># release peer traffic to the Internet as a gateway&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_masquarade&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">auto&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now, let’s specify variables for the laptop we are working on.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># and again explicitly enable the role&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">yes&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_peers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># in the VPN network peers, only our public server&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">hostname&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">public_host&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># we have a domain pointing to the server so we don’t need to remember the address&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">endpoint&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">vpn.example.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># routing all traffic through the VPN, and it&amp;#39;s important to understand&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># that we are not sending all system traffic through Wireguard&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># we are telling Wireguard on the host to allow&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># everything that specifically comes to you on the output and does not match&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># in other networks by more narrow rules&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">allowed_ips&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="m">0.0.0.0&lt;/span>&lt;span class="l">/0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="p">::&lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">keepalive_seconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">25&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># the contact point for the home network is the same&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">hostname&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">public_host&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">endpoint&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">vpn.example.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">keepalive_seconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">25&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">allowed_ips&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># and in the paths, we specify only the subnet of the home network&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;{{ wireguard_networks.home }}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># and enable proxying specific domains through the VPN&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_proxy_domains&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">vpn&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">list&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">site.we.want.access&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">another.one&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>And the home server just needs to be accessible. It doesn’t need to be in the VPN.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># here I hope everything is already clear&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">yes&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">wireguard_peers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">home&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">hostname&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">public_host&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">endpoint&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">vpn.example.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">allowed_ips&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;{{ wireguard_networks.home }}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">keepalive_seconds&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">25&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="conclusion">Conclusion &lt;a href="#conclusion">¶&lt;/a>&lt;/h2>
&lt;p>From any peer, there is access to any within the network. Traffic finds its way through the public server. Everything works. I measured with iperf; out of 80 Mbps, Wireguard delivers ~60 - to me, that’s an excellent result!&lt;/p></description></item><item><title>Age Encryption</title><link>https://vlasov.pro/en/p/age/</link><pubDate>Sun, 12 Sep 2021 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/age/</guid><description>&lt;img src="https://vlasov.pro/ru/p/age/age.webp" alt="Featured image of post Age Encryption" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://age-encryption.org" target="_blank" rel="noopener"
>Age&lt;/a> – a new utility, written in Go, that supposedly performs excellent asymmetric encryption and more. Indeed, it looks simple and somewhat reminds me of &lt;a class="link" href="https://www.wireguard.com" target="_blank" rel="noopener"
>Wireguard&lt;/a> (utility wg).
It encrypts the input stream to the output stream. Simple and understandable. Among its distinguishing features is the ability to encrypt for a group of recipients, so each can decrypt.
Today&amp;rsquo;s task was to create backups btrfs disk partitions with home photos/video somewhere in the cloud, e.g., &lt;a class="link" href="https://www.backblaze.com" target="_blank" rel="noopener"
>Backblaze&lt;/a>, to save money. This is just not good enough (no trust in clouds). Data needs to be encrypted.&lt;/p>
&lt;p>A 300 GiB partition and loading it in one piece, then storing it as a whole is very uninteresting. &lt;a class="link" href="https://man7.org/linux/man-pages/man1/split.1.html" target="_blank" rel="noopener"
>Split&lt;/a> will help divide the file into chunks.&lt;/p>
&lt;h2 id="generating-key">Generating Key &lt;a href="#generating-key">¶&lt;/a>&lt;/h2>
&lt;p>It&amp;rsquo;s claimed that you can use a simple SSH public key instead of Age keys. Let&amp;rsquo;s try both ways.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ssh-keygen -t ed25519 -o -a &lt;span class="m">150&lt;/span> -qN &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span> -f id_ed25519
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">age-keygen -o age.key
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">age-keygen -y age.key &amp;gt; recipients.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat id_ed25519.pub &amp;gt;&amp;gt; recipients.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>We get such keys.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">age1qrcn5glms66thfv9cj5pzdwl3z87t9evzaqlxdj9ksravmw3mypswawuag
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIObk2OuhYlrr3ezvf5gAWXgUdcLn4XQFa8B8GCRpBr9q user@host
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="encryption">Encryption &lt;a href="#encryption">¶&lt;/a>&lt;/h2>
&lt;p>For simplicity, let&amp;rsquo;s generate 10 MiB of random data and immediately compare the hash sums.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">dd &lt;span class="k">if&lt;/span>&lt;span class="o">=&lt;/span>/dev/urandom &lt;span class="nv">of&lt;/span>&lt;span class="o">=&lt;/span>data &lt;span class="nv">bs&lt;/span>&lt;span class="o">=&lt;/span>1M &lt;span class="nv">count&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cp data data.orig
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now we can encrypt. Using both archiving and splitting.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">tar -cz data &lt;span class="p">|&lt;/span> age -R recipients.txt &lt;span class="p">|&lt;/span> split -b 1MiB -d - chunk-
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>We get 10 files from chunk-00 to chunk-10.&lt;/p>
&lt;h2 id="decryption">Decryption &lt;a href="#decryption">¶&lt;/a>&lt;/h2>
&lt;p>Decrypting using SSH key.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">cat chunk-* &lt;span class="p">|&lt;/span> age -d -i id_ed25519 &lt;span class="p">|&lt;/span> tar xz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mv data data.ssh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Decrypting using Age key.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">cat chunk-* &lt;span class="p">|&lt;/span> age -d -i age.key &lt;span class="p">|&lt;/span> tar xz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mv data data.age
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="verification">Verification &lt;a href="#verification">¶&lt;/a>&lt;/h2>
&lt;p>Checking the hash sums.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># sha256sum data*&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">5ebc271a22cfb9af0430253c2d8f3b83d1c3f5fdd062dd0ecc6c1f2d7925b828 data.age
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">5ebc271a22cfb9af0430253c2d8f3b83d1c3f5fdd062dd0ecc6c1f2d7925b828 data.orig
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">5ebc271a22cfb9af0430253c2d8f3b83d1c3f5fdd062dd0ecc6c1f2d7925b828 data.ssh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>It works. As always, later we&amp;rsquo;ll find vulnerabilities, but you can use it.&lt;/p></description></item><item><title>Installing Python Packages Offline</title><link>https://vlasov.pro/en/p/python3-pip-air-gap/</link><pubDate>Sun, 29 Aug 2021 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/python3-pip-air-gap/</guid><description>&lt;img src="https://vlasov.pro/ru/p/python3-pip-air-gap/python.webp" alt="Featured image of post Installing Python Packages Offline" />&lt;p>Suppose we want to install &lt;a class="link" href="https://www.ansible.com" target="_blank" rel="noopener"
>Ansible&lt;/a> offline.&lt;/p>
&lt;h2 id="creating-a-virtualenv">Creating a Virtualenv &lt;a href="#creating-a-virtualenv">¶&lt;/a>&lt;/h2>
&lt;p>We will create a virtual environment to download all dependencies without accidentally including unnecessary ones. First, let’s install &lt;code>virtualenv&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">python3 -m pip install --upgrade --user virtualenv
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 -m virtualenv venv
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now we can activate it.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">. ./venv/bin/activate
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now, for the duration of the terminal session, we are in an isolated Python virtual environment.&lt;/p>
&lt;h2 id="preparing-required-packages">Preparing Required Packages &lt;a href="#preparing-required-packages">¶&lt;/a>&lt;/h2>
&lt;p>By installing only what is needed in a clean environment, we will also pull in all dependencies. Additionally, &lt;strong>make sure to include &lt;code>setuptools&lt;/code> and &lt;code>pip&lt;/code>&lt;/strong>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">python3 -m pip install --upgrade pip setuptools ansible
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now we can create a list of what we have.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">python3 -m pip freeze &amp;gt; requirements.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;blockquote>
&lt;p>You can simply add &lt;code>pip&lt;/code> and &lt;code>setuptools&lt;/code> to &lt;code>requirements.txt&lt;/code> without specifying versions (if they aren&amp;rsquo;t already in the list).&lt;/p>
&lt;/blockquote>
&lt;p>Example &lt;code>requirements.txt&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plaintext" data-lang="plaintext">&lt;span class="line">&lt;span class="cl">ansible==3.4.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ansible-base==2.10.11
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cryptography==2.8
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">jinja2==2.11.3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">netaddr==0.7.19
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pbr==5.4.4
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">jmespath==0.9.5
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ruamel.yaml==0.16.10
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ruamel.yaml.clib==0.2.2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">MarkupSafe==1.1.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pip
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">setuptools
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Having the list of packages with dependencies, we can download them &lt;strong>even without &lt;code>venv&lt;/code>&lt;/strong>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">python3 -m pip download --dest my-pip-packages -r requirements.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>For convenience, let’s pack everything into an archive.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">tar -cpvzf pips.tgz my-pip-packages requirements.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="installing-in-an-offline-environment">Installing in an Offline Environment &lt;a href="#installing-in-an-offline-environment">¶&lt;/a>&lt;/h2>
&lt;blockquote>
&lt;p>Python should already be installed in advance.&lt;/p>
&lt;/blockquote>
&lt;p>Unpack your archive and install everything you brought. &lt;strong>Pip&lt;/strong> and &lt;strong>setuptools&lt;/strong> should be installed separately at the beginning, followed by everything else. If the command is not run as a superuser, you need to either:&lt;/p>
&lt;ol>
&lt;li>Add &lt;code>sudo&lt;/code> at the beginning&lt;/li>
&lt;li>Add the &lt;code>--user&lt;/code> argument to pip to install packages only for the user running the command&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">tar -xpzvf pips.tgz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 -m pip install --upgrade --no-index --find-links python-packages pip setuptools
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 -m pip install --upgrade --no-index --find-links my-pip-packages -r requirements.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now you can run Ansible!&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">root@289f34a67cbd:/host# ansible --version
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ansible 2.10.11
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> config &lt;span class="nv">file&lt;/span> &lt;span class="o">=&lt;/span> None
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> configured module search &lt;span class="nv">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">[&lt;/span>&lt;span class="s1">&amp;#39;/root/.ansible/plugins/modules&amp;#39;&lt;/span>, &lt;span class="s1">&amp;#39;/usr/share/ansible/plugins/modules&amp;#39;&lt;/span>&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ansible python module &lt;span class="nv">location&lt;/span> &lt;span class="o">=&lt;/span> /usr/local/lib/python3.6/dist-packages/ansible
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> executable &lt;span class="nv">location&lt;/span> &lt;span class="o">=&lt;/span> /usr/local/bin/ansible
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> python &lt;span class="nv">version&lt;/span> &lt;span class="o">=&lt;/span> 3.6.9 &lt;span class="o">(&lt;/span>default, Jan &lt;span class="m">26&lt;/span> 2021, 15:33:00&lt;span class="o">)&lt;/span> &lt;span class="o">[&lt;/span>GCC 8.4.0&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="locales">Locales &lt;a href="#locales">¶&lt;/a>&lt;/h2>
&lt;p>There have been cases where in a severely stripped-down environment, like Docker Ubuntu 18.04, the package installation fails with the following error.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plaintext" data-lang="plaintext">&lt;span class="line">&lt;span class="cl">ERROR: Exception:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> File &amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/cli/base_command.py&amp;#34;, line 173, in _main
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> status = self.run(options, args)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> File &amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/cli/req_command.py&amp;#34;, line 203, in wrapper
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> return func(self, options, args)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> File &amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/commands/install.py&amp;#34;, line 316, in run
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> reqs, check_supported_wheels=not options.target_dir
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> File &amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/operations/prepare.py&amp;#34;, line 249, in unpack_url
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> unpack_file(file.path, location, file.content_type)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> File &amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/utils/unpacking.py&amp;#34;, line 256, in unpack_file
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> untar_file(filename, location)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> File &amp;#34;/usr/local/lib/python3.6/dist-packages/pip/_internal/utils/unpacking.py&amp;#34;, line 226, in untar_file
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> with open(path, &amp;#34;wb&amp;#34;) as destfp:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">UnicodeEncodeError: &amp;#39;ascii&amp;#39; codec can&amp;#39;t encode character &amp;#39;\xe9&amp;#39; in position 117: ordinal not in range(128)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This can be resolved by setting environment variables before installing packages.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LANGUAGE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LANG&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_CTYPE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_NUMERIC&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_TIME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_COLLATE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_MONETARY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_MESSAGES&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_PAPER&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_NAME&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_ADDRESS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_TELEPHONE&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_MEASUREMENT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_IDENTIFICATION&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">export&lt;/span> &lt;span class="nv">LC_ALL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;C.UTF-8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Creating a Virtual Camera for Conferences</title><link>https://vlasov.pro/en/p/v4l2loopback/</link><pubDate>Thu, 22 Jul 2021 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/v4l2loopback/</guid><description>&lt;img src="https://github.com/umlaeute/v4l2loopback/blob/main/images/icon.png?raw=true" alt="Featured image of post Creating a Virtual Camera for Conferences" />&lt;p>We don&amp;rsquo;t always want to include a camera during the conference, so we found a way to display video or static images instead. The means of OS or browser doesn&amp;rsquo;t provide this out of the box. I found &lt;a class="link" href="https://github.com/umlaeute/v4l2loopback" target="_blank" rel="noopener"
>this article&lt;/a> and, indeed, created a virtual camera module that is recognized by browsers as an ordinary camera &amp;#x1f604;&lt;/p>
&lt;p>Below is a script with detailed comments. The only argument to it is the path to the file or image that should be transmitted in the stream.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># label for the new webcam as it will be seen in browser&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">LABEL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;VirtualCam #0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># module insertion in case if it was not inserted during this boot&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> ! lsmod &lt;span class="p">|&lt;/span> grep -qE &lt;span class="s1">&amp;#39;^v4l2loopback&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># camera is being created during the module loading&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sudo modprobe v4l2loopback &lt;span class="nv">devices&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> &lt;span class="nv">exclusive_caps&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> &lt;span class="nv">max_buffers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">2&lt;/span> &lt;span class="nv">card_label&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LABEL&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># wait for a while to finish module initialization&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sleep &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># path to media file&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">F&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">1&lt;/span>&lt;span class="p">:?File is not passed&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># getting path to newly created camera device&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEV&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>v4l2-ctl --list-devices 2&amp;gt;/dev/null &lt;span class="p">|&lt;/span> grep -A1 &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$LABEL&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;/dev/video[0-9]+&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$F&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># check in case if media file path does not exists&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;error: file &lt;/span>&lt;span class="nv">$F&lt;/span>&lt;span class="s2"> does not exists&amp;#34;&lt;/span> &amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># get file type and use proper streaming command&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">case&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>file --mime-type --brief &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$F&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> cut -d/ -f1&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> in
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> video&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># in case if file is video&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ffmpeg -re -i &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$F&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -f v4l2 -vcodec rawvideo -pix_fmt yuv420p &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$DEV&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> image&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># in case if file is picture&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ffmpeg -loop &lt;span class="m">1&lt;/span> -re -i &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$F&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -f v4l2 -vcodec rawvideo -pix_fmt yuv420p &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$DEV&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> *&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># in case if file is something else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;error: unknown mime type&amp;#39;&lt;/span> &amp;gt;&lt;span class="p">&amp;amp;&lt;/span>&lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">exit&lt;/span> &lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">esac&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>So, in the end, we were able to stream Rick Ashley - Never Gonna Give You Up.&lt;/p>
&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
&lt;p>One notable drawback is that FFmpeg consumes almost an entire core. Additionally, we are, of course, only transmitting the image, without any sound.&lt;/p></description></item><item><title>CEPH Upgrade</title><link>https://vlasov.pro/en/p/ceph-upgrade/</link><pubDate>Mon, 16 Nov 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/ceph-upgrade/</guid><description>&lt;img src="https://vlasov.pro/ru/p/ceph-upgrade/ceph.webp" alt="Featured image of post CEPH Upgrade" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>We have the following cluster:&lt;/p>
&lt;ul>
&lt;li>Ceph 15.2.1 installed with cephadm&lt;/li>
&lt;li>14 OSD&lt;/li>
&lt;li>3 MON&lt;/li>
&lt;li>3 RGW&lt;/li>
&lt;li>3 MDS&lt;/li>
&lt;li>3 CRUSH&lt;/li>
&lt;/ul>
&lt;p>Version &lt;em>15.2.4&lt;/em> has been released, and we want to upgrade.&lt;/p>
&lt;h2 id="getting-started">Getting Started &lt;a href="#getting-started">¶&lt;/a>&lt;/h2>
&lt;p>Cephadm provides a mechanism for upgrading, but it didn&amp;rsquo;t work for me right away, so I had to &lt;strong>assist&lt;/strong> it. Let&amp;rsquo;s see what exactly needs to be upgraded.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ceph orch upgrade check ceph/ceph 15.2.4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>A JSON file appears with a list of daemons that have already been upgraded and those that differ from the requested version, i.e., all of them at the moment. Time to get started.&lt;br>
So, the procedure has been launched, and now there are some commands worth running to get a summary.&lt;/p>
&lt;ol>
&lt;li>&lt;code>ceph status&lt;/code> - for general information about the cluster&amp;rsquo;s state. You can run it in a separate terminal like this: &lt;code>watch -n 10 ceph status&lt;/code>&lt;/li>
&lt;li>&lt;code>ceph status -W cephadm&lt;/code> - definitely run this command in the terminal to monitor the orchestrator&amp;rsquo;s log.&lt;/li>
&lt;/ol>
&lt;h2 id="temporary-difficulties">Temporary Difficulties &lt;a href="#temporary-difficulties">¶&lt;/a>&lt;/h2>
&lt;p>We call &lt;code>ceph orch ps&lt;/code> and see that all &lt;em>monitors&lt;/em> and &lt;em>managers&lt;/em> are upgraded, good, but now we&amp;rsquo;re in &lt;strong>HEALTH_ERROR&lt;/strong> with the error shown below.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">module &amp;#39;cephadm&amp;#39; has failed: auth get failed: failed to find client.crash.01 in keyring retval: -2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>It turns out that some keys are missing. You need to create one for each crash and restart the orchestration.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> i in &lt;span class="k">$(&lt;/span>ceph orch ps &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;crash.[0-9]+&amp;#39;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ceph auth get-or-create &lt;span class="s2">&amp;#34;client.&lt;/span>&lt;span class="nv">$i&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> mgr &lt;span class="s2">&amp;#34;profile crash&amp;#34;&lt;/span> mon &lt;span class="s2">&amp;#34;profile crash&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph orch upgrade stop
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph mgr module disable cephadm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph mgr module &lt;span class="nb">enable&lt;/span> cephadm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph orch upgrade start ceph/ceph 15.2.4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Now we see that the &lt;em>crashes&lt;/em> are ready too, good, but then everything seems to be stuck. Yes, HEALTH_OK, but &lt;code>ceph orch ps&lt;/code> shows that all &lt;em>OSDs&lt;/em> are still on the old version. The logs show the following.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">Upgrade: It is NOT safe to stop osd.0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Aha, the orchestrator is afraid to stop OSD daemons with data. Let&amp;rsquo;s help. Here is my situation.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ceph osd tree&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-1 14.00000 root default
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-3 5.00000 host &lt;span class="m">01&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">0&lt;/span> hdd 1.00000 osd.0 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">1&lt;/span> hdd 1.00000 osd.1 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">2&lt;/span> hdd 1.00000 osd.2 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">3&lt;/span> hdd 1.00000 osd.3 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">4&lt;/span> hdd 1.00000 osd.4 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-5 5.00000 host &lt;span class="m">02&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">5&lt;/span> hdd 1.00000 osd.5 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">6&lt;/span> hdd 1.00000 osd.6 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">7&lt;/span> hdd 1.00000 osd.7 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">8&lt;/span> hdd 1.00000 osd.8 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">9&lt;/span> hdd 1.00000 osd.9 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-7 4.00000 host &lt;span class="m">03&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">10&lt;/span> hdd 1.00000 osd.10 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">11&lt;/span> hdd 1.00000 osd.11 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">12&lt;/span> hdd 1.00000 osd.12 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">13&lt;/span> hdd 1.00000 osd.13 up 1.00000 1.00000
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>At first, I stopped OSDs one by one.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ceph osd out osd.0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Then I relaxed and began to decommission a whole server sequentially. When we decommission osd.0, after some time, when rebalancing finishes, &lt;code>ceph status -W cephadm&lt;/code> complains about osd.1, and &lt;code>ceph orch ps&lt;/code> shows that osd.0 is upgraded. The idea is clear; just don&amp;rsquo;t forget to reintegrate it.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ceph osd in osd.0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>In short, we decommission the OSDs of the first server, wait until cephadm complains about the next ones, and then reintegrate them. Further, &lt;strong>wait for HEALTH_OK before decommissioning the next server&amp;rsquo;s OSD&lt;/strong>, or you could lose data&amp;hellip;&lt;br>
&lt;strong>Based on your OSD tree&lt;/strong>, the plan, if done from scratch, is as follows:&lt;/p>
&lt;ol>
&lt;li>out 0, 1, 2, 3, 4&lt;/li>
&lt;li>wait for complaints about 5&lt;/li>
&lt;li>in 0, 1, 2, 3, 4&lt;/li>
&lt;li>wait for HEALTH_OK&lt;/li>
&lt;li>out 5, 6, 7, 8, 9&lt;/li>
&lt;li>wait for complaints about 10&lt;/li>
&lt;li>in 5, 6, 7, 8, 9&lt;/li>
&lt;li>wait for HEALTH_OK&lt;/li>
&lt;li>out 10, 11, 12, 13&lt;/li>
&lt;li>check that everything is upgraded with &lt;code>ceph orch ps&lt;/code>&lt;/li>
&lt;li>in 10, 11, 12, 13&lt;/li>
&lt;li>wait for HEALTH_OK&lt;/li>
&lt;/ol>
&lt;div class="ascii-art">
```plain
╔═╗╔═╗╔═╗╦ ╦ ╦ ╦╔═╗╔═╗╦═╗╔═╗╔╦╗╔═╗╔╦╗┬
║ ║╣ ╠═╝╠═╣ ║ ║╠═╝║ ╦╠╦╝╠═╣ ║║║╣ ║║│
╚═╝╚═╝╩ ╩ ╩ ╚═╝╩ ╚═╝╩╚═╩ ╩═╩╝╚═╝═╩╝o
```
&lt;/div>
&lt;h2 id="notes">Notes &lt;a href="#notes">¶&lt;/a>&lt;/h2>
&lt;p>The cluster is &lt;em>half-empty&lt;/em>, so it was quick. If it were otherwise, it would have taken days&amp;hellip;&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">% sudo ceph osd df &lt;span class="o">[&lt;/span>22&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ID CLASS WEIGHT REWEIGHT SIZE RAW USE DATA OMAP META AVAIL %USE VAR PGS STATUS
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">0&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.4 GiB &lt;span class="m">438&lt;/span> MiB &lt;span class="m">39&lt;/span> KiB &lt;span class="m">1024&lt;/span> MiB 5.5 TiB 0.03 1.11 &lt;span class="m">37&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">1&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.4 GiB &lt;span class="m">454&lt;/span> MiB 2.2 MiB &lt;span class="m">1022&lt;/span> MiB 5.5 TiB 0.03 1.12 &lt;span class="m">46&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">2&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.3 GiB &lt;span class="m">314&lt;/span> MiB 1.0 MiB &lt;span class="m">1023&lt;/span> MiB 5.5 TiB 0.02 1.01 &lt;span class="m">24&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">3&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.2 GiB &lt;span class="m">161&lt;/span> MiB 2.5 MiB &lt;span class="m">1022&lt;/span> MiB 5.5 TiB 0.02 0.90 &lt;span class="m">34&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">4&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.2 GiB &lt;span class="m">242&lt;/span> MiB &lt;span class="m">21&lt;/span> KiB &lt;span class="m">1024&lt;/span> MiB 5.5 TiB 0.02 0.96 &lt;span class="m">34&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">5&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.2 GiB &lt;span class="m">212&lt;/span> MiB 3.0 MiB &lt;span class="m">1021&lt;/span> MiB 5.5 TiB 0.02 0.93 &lt;span class="m">34&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">6&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.5 GiB &lt;span class="m">485&lt;/span> MiB &lt;span class="m">533&lt;/span> KiB &lt;span class="m">1023&lt;/span> MiB 5.5 TiB 0.03 1.14 &lt;span class="m">35&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">7&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.3 GiB &lt;span class="m">280&lt;/span> MiB 1.8 MiB &lt;span class="m">1022&lt;/span> MiB 5.5 TiB 0.02 0.99 &lt;span class="m">41&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">8&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.3 GiB &lt;span class="m">265&lt;/span> MiB &lt;span class="m">19&lt;/span> MiB &lt;span class="m">1005&lt;/span> MiB 5.5 TiB 0.02 0.97 &lt;span class="m">38&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">9&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.4 GiB &lt;span class="m">359&lt;/span> MiB &lt;span class="m">949&lt;/span> KiB &lt;span class="m">1023&lt;/span> MiB 5.5 TiB 0.02 1.05 &lt;span class="m">28&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">10&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.2 GiB &lt;span class="m">179&lt;/span> MiB &lt;span class="m">467&lt;/span> KiB &lt;span class="m">1024&lt;/span> MiB 5.5 TiB 0.02 0.91 &lt;span class="m">33&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">11&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.1 GiB &lt;span class="m">132&lt;/span> MiB 2.8 MiB &lt;span class="m">1021&lt;/span> MiB 5.5 TiB 0.02 0.87 &lt;span class="m">23&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">12&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.3 GiB &lt;span class="m">358&lt;/span> MiB &lt;span class="m">19&lt;/span> MiB &lt;span class="m">1005&lt;/span> MiB 5.5 TiB 0.02 1.04 &lt;span class="m">36&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="m">13&lt;/span> hdd 1.00000 1.00000 5.5 TiB 1.3 GiB &lt;span class="m">301&lt;/span> MiB &lt;span class="m">734&lt;/span> KiB &lt;span class="m">1023&lt;/span> MiB 5.5 TiB 0.02 1.00 &lt;span class="m">39&lt;/span> up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> TOTAL &lt;span class="m">76&lt;/span> TiB &lt;span class="m">18&lt;/span> GiB 4.1 GiB &lt;span class="m">54&lt;/span> MiB &lt;span class="m">14&lt;/span> GiB &lt;span class="m">76&lt;/span> TiB 0.02
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">MIN/MAX VAR: 0.87/1.14 STDDEV: 0.00
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Introduction to Docker</title><link>https://vlasov.pro/en/p/docker/</link><pubDate>Fri, 21 Aug 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/docker/</guid><description>&lt;img src="https://vlasov.pro/ru/p/docker/docker.webp" alt="Featured image of post Introduction to Docker" />&lt;blockquote>
&lt;p>Written in collaboration with &lt;a class="link" href="https://rebrainme.com/blog/docker/docker-ustanovka-nastrojka-i-pervye-shagi-v-sisteme/" target="_blank" rel="noopener"
>ReBrainMe&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>&lt;a class="link" href="https://www.docker.com/" target="_blank" rel="noopener"
>Docker&lt;/a> is the de facto standard containerization engine, widely used for running applications in both development environments and high-load production environments. You can learn more about terminology &lt;a class="link" href="https://rebrainme.com/blog/docker/terminologiya-v-docker/" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>The purpose of this article is to install and run Docker locally, start getting acquainted with this fascinating system, and grasp the basics.&lt;/p>
&lt;h2 id="installing-docker">Installing Docker &lt;a href="#installing-docker">¶&lt;/a>&lt;/h2>
&lt;p>Docker has &lt;a class="link" href="https://docs.docker.com/get-docker/" target="_blank" rel="noopener"
>official instructions&lt;/a> for installation. In practice, I used the installation script (for Linux):&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">curl -LO get.docker.com &lt;span class="p">|&lt;/span> sudo sh -
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>If the &lt;code>curl&lt;/code> utility is not installed, &lt;a class="link" href="https://get.docker.com/" target="_blank" rel="noopener"
>download the script&lt;/a> and run it manually:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sh /path/to/downloaded/script.sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>If you want to install a specific version of Docker, you can use the installation scripts from &lt;a class="link" href="https://rancher.com/docs/rancher/v2.x/en/installation/requirements/installing-docker/" target="_blank" rel="noopener"
>Rancher&lt;/a>, which you can &lt;a class="link" href="https://github.com/rancher/install-docker" target="_blank" rel="noopener"
>find and download here&lt;/a>. The script is run in the same way, you can change the URL in the &lt;code>curl&lt;/code> command, and it will work.&lt;/p>
&lt;h2 id="configuring-docker">Configuring Docker &lt;a href="#configuring-docker">¶&lt;/a>&lt;/h2>
&lt;p>It works out of the box, but there are a couple of things I would recommend adjusting right away based on personal experience.&lt;/p>
&lt;h3 id="configure-the-logging-driver">Configure the logging driver &lt;a href="#configure-the-logging-driver">¶&lt;/a>&lt;/h3>
&lt;p>By default, the &lt;a class="link" href="https://docs.docker.com/config/containers/logging/json-file/" target="_blank" rel="noopener"
>json-file&lt;/a> driver is used, which does not limit the size of the &lt;a class="link" href="https://en.wikipedia.org/wiki/JSON" target="_blank" rel="noopener"
>JSON&lt;/a> file where logs for the corresponding container are stored. You can adjust this on Linux by editing the &lt;em>/etc/docker/daemon.json&lt;/em> file. If the file does not exist, create it. The content to add:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;log-driver&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;json-file&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;log-opts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;max-size&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;100m&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;max-file&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This configures the json-file driver to not create more than one log file per container, with the file size not exceeding &lt;code>100 MB&lt;/code>. This can be overridden when starting the container, but having these defaults saves you from wondering, &lt;em>&amp;ldquo;Where did 6 GB go in one day?&amp;rdquo;&lt;/em>&lt;/p>
&lt;h3 id="start-the-docker-service">Start the Docker service &lt;a href="#start-the-docker-service">¶&lt;/a>&lt;/h3>
&lt;p>Sometimes it does not start automatically after installation. You can fix this on Linux with:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo systemctl &lt;span class="nb">enable&lt;/span> --now docker.service
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Here, we used &lt;a class="link" href="https://wiki.archlinux.org/index.php/Systemd" target="_blank" rel="noopener"
>systemctl&lt;/a> to start the Docker Engine and enable it to start on boot.&lt;/p>
&lt;h3 id="add-the-user-to-the-docker-group">Add the user to the Docker group &lt;a href="#add-the-user-to-the-docker-group">¶&lt;/a>&lt;/h3>
&lt;p>To be able to interact with the Docker Engine as a &lt;em>non-privileged user&lt;/em> (without &lt;code>sudo&lt;/code>), you need to add the user to the Docker group.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo usermod -aG docker &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$USER&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>For the changes to take effect, you need to reboot or use &lt;a class="link" href="https://wiki.archlinux.org/index.php/Access_Control_Lists" target="_blank" rel="noopener"
>ACL&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo setfacl -m &lt;span class="s2">&amp;#34;u:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">USER&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:rwx&amp;#34;&lt;/span> /var/run/docker.sock
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="getting-acquainted-with-dockerhub">Getting acquainted with DockerHub &lt;a href="#getting-acquainted-with-dockerhub">¶&lt;/a>&lt;/h2>
&lt;p>&lt;em>Containers&lt;/em> are created from &lt;em>images&lt;/em>. An image is an ordered set of filesystem layers that were created during the build process. People share images by uploading them to a Docker Registry. The most popular one is &lt;a class="link" href="https://hub.docker.com/" target="_blank" rel="noopener"
>DockerHub&lt;/a>. Many software products are published here and supported &lt;strong>officially&lt;/strong>, and there are many tools created by individuals or small communities that are as good as the official ones. &lt;strong>It is important&lt;/strong> to check what you are downloading and running – whether it’s an unknown source with no documentation or an official build that is regularly updated and comes with clear documentation. There have been rumors of miners in unknown images&amp;hellip; but that’s more of a rarity than a rule (in my experience).&lt;/p>
&lt;p>Here are some links to official images: &lt;a class="link" href="https://hub.docker.com/_/haproxy" target="_blank" rel="noopener"
>HaProxy&lt;/a>, &lt;a class="link" href="https://hub.docker.com/_/nginx" target="_blank" rel="noopener"
>Nginx&lt;/a>, &lt;a class="link" href="https://hub.docker.com/_/postgres" target="_blank" rel="noopener"
>PostgreSQL&lt;/a>, &lt;a class="link" href="https://hub.docker.com/_/mysql" target="_blank" rel="noopener"
>MySQL&lt;/a>, &lt;a class="link" href="https://hub.docker.com/r/grafana/grafana" target="_blank" rel="noopener"
>Grafana&lt;/a>, &lt;a class="link" href="https://hub.docker.com/r/prom/prometheus" target="_blank" rel="noopener"
>Prometheus&lt;/a>.&lt;/p>
&lt;h2 id="running-the-first-container">Running the first container &lt;a href="#running-the-first-container">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker run --rm -it -p 8080:80 nginx:stable-alpine
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Opening &lt;a class="link" href="http://localhost:8080" target="_blank" rel="noopener"
>http://localhost:8080&lt;/a> shows:&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/docker/nginx-welcome.png"
width="549"
height="205"
srcset="https://vlasov.pro/ru/p/docker/nginx-welcome_hu17821898986438557257.png 480w, https://vlasov.pro/ru/p/docker/nginx-welcome_hu8976578484894536805.png 1024w"
loading="lazy"
alt="Nginx welcome page"
class="gallery-image"
data-flex-grow="267"
data-flex-basis="642px"
>&lt;/p>
&lt;p>What did we do? Let’s break down the command step by step.&lt;/p>
&lt;p>&lt;em>&lt;code>sudo&lt;/code>&lt;/em> – run the following command as another user, defaulting to the superuser &lt;code>root&lt;/code>.&lt;br>
&lt;em>&lt;code>docker&lt;/code>&lt;/em> – run the Docker executable, found in one of the paths specified in the &lt;code>PATH&lt;/code> environment variable.&lt;br>
&lt;em>&lt;code>run&lt;/code>&lt;/em> – create and start a new container.&lt;br>
&lt;em>&lt;code>--rm&lt;/code>&lt;/em> – remove it after it finishes running, so it doesn’t take up space.&lt;br>
&lt;em>&lt;code>-i&lt;/code>&lt;/em> – attach stdin/out/err from the shell to the container; run in interactive mode.&lt;br>
&lt;em>&lt;code>-t&lt;/code>&lt;/em> – create a TTY for the container.&lt;br>
&lt;em>&lt;code>-p 8080:80&lt;/code>&lt;/em> – forward port 8080 from the host to port 80 inside the container.&lt;br>
&lt;em>&lt;code>nginx:stable-alpine&lt;/code>&lt;/em> – use the nginx image with the tag stable-alpine to create the container. Other tags can be found on the &lt;a class="link" href="https://hub.docker.com/_/nginx" target="_blank" rel="noopener"
>Nginx DockerHub page&lt;/a>.&lt;/p>
&lt;h2 id="mounting">Mounting &lt;a href="#mounting">¶&lt;/a>&lt;/h2>
&lt;p>It’s often necessary to attach some data to the container or take it out so that it’s not lost when the container is recreated. More details can be found &lt;a class="link" href="https://docs.docker.com/storage/volumes/" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;Hello world! Date: &lt;/span>&lt;span class="k">$(&lt;/span>date&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &amp;gt; /tmp/my_file.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo docker run --rm -it -p 8080:80 -v /tmp/my_file.txt:/usr/share/nginx/html/index.html:ro nginx:stable-alpine
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Here we created the file &lt;em>/tmp/my_file.txt&lt;/em> and mounted it to &lt;em>/usr/share/nginx/html/index.html&lt;/em>. According to the container description, and by empirical means, we can determine that the web server&amp;rsquo;s file path in the default configuration file is &lt;em>/usr/share/nginx/html&lt;/em>, and the default file to open as the main page is index.html. Thus, we mount from the host to the container at the found path.&lt;/p>
&lt;p>When mounting, be careful. &lt;strong>If mounting a file&lt;/strong>, it must already exist on the host at startup, otherwise, a directory will be created. When mounting, &lt;strong>the path on the host must be absolute&lt;/strong>. When mounting a directory, the contents of the target path inside the container will &lt;strong>disappear&lt;/strong> and be replaced by the contents of the host folder.&lt;/p>
&lt;h2 id="running-in-background-mode">Running in background mode &lt;a href="#running-in-background-mode">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker run -d --name my1 -p 3000:3000 grafana/grafana
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Here, a couple of new flags appeared. &lt;em>&lt;code>-d&lt;/code>&lt;/em> – run in the background. &lt;em>&lt;code>--name my1&lt;/code>&lt;/em> – set the container name to &amp;ldquo;my1&amp;rdquo;, as a random one is generated by default, but we want to assign our own. Check the container status.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker ps
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo docker stats
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The first command displays information about all running containers, and the second provides a brief summary of resource consumption. &lt;a class="link" href="https://localhost:3000" target="_blank" rel="noopener"
>Open Grafana&lt;/a>.&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/docker/grafana-login.webp"
width="562"
height="570"
srcset="https://vlasov.pro/ru/p/docker/grafana-login_hu3519326263104635802.webp 480w, https://vlasov.pro/ru/p/docker/grafana-login_hu5812811221392077487.webp 1024w"
loading="lazy"
alt="Grafana login page"
class="gallery-image"
data-flex-grow="98"
data-flex-basis="236px"
>&lt;/p>
&lt;p>We can log in, explore (login: admin, password: admin), and then stop the container.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker stop my1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo docker ps -a
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>As you can see, the container is stopped but not deleted. We can start it again or remove it.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker start my1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo docker rm -f my1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="conclusion">Conclusion &lt;a href="#conclusion">¶&lt;/a>&lt;/h2>
&lt;p>We installed Docker, got acquainted with DockerHub, launched a couple of containers, and tried basic commands for running applications with Docker Community Edition.&lt;/p></description></item><item><title>Plans</title><link>https://vlasov.pro/en/plan/</link><pubDate>Wed, 22 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/plan/</guid><description>&lt;h2 id="articles-to-write">Articles to Write &lt;a href="#articles-to-write">¶&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> &lt;strong>Reverse SSH Tunneling&lt;/strong>. There was an article that got lost. How to forward a port from a remote host using SSH.&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> &lt;strong>Migrating from &lt;a class="link" href="https://ghost.org" target="_blank" rel="noopener"
>Ghost&lt;/a> to &lt;a class="link" href="https://gohugo.io" target="_blank" rel="noopener"
>Hugo&lt;/a>&lt;/strong>. Why I decided to switch to Hugo and how it went.&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> &lt;strong>The &lt;a class="link" href="https://github.com/derailed/k9s" target="_blank" rel="noopener"
>k9s&lt;/a> Utility&lt;/strong>. A great tool that I use daily for working with Kubernetes.&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> &lt;strong>Terraform Tips and Tricks&lt;/strong>. Examples, tricks, and useful links for working with Terraform.&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> &lt;strong>Boltology: The 20\80 Rule in IT&lt;/strong>. Who knows the 80/20 rule? It&amp;rsquo;s true that 80% of efforts give 80% results, but you need to put 100% effort into the remaining 20%.&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> &lt;strong>Wireguard Ansible&lt;/strong>. An article about my development - Ansible playbooks for setting up and configuring Wireguard.&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> &lt;strong>Healthcheck.io&lt;/strong> (&lt;a class="link" href="https://healthcheck.io" target="_blank" rel="noopener"
>https://healthcheck.io&lt;/a>). A great service that can be sure of successful backups.&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> How to search and work with Helm charts.&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> My experience with &lt;a class="link" href="https://argo-cd.readthedocs.io/en/stable/" target="_blank" rel="noopener"
>ArgoCD&lt;/a>. &lt;em>(Stable, automated, flexible, but not without flaws. I use it on a large production with clean hands. Recommend)&lt;/em>&lt;/li>
&lt;/ul></description></item><item><title>Resume</title><link>https://vlasov.pro/en/resume/</link><pubDate>Wed, 22 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/resume/</guid><description>&lt;div class="resume">
&lt;iframe class="resume" src="https://vlasov.pro/Resume Yurii Vlasov.pdf"> &lt;/embed>
&lt;/div></description></item><item><title>xFreeRDP</title><link>https://vlasov.pro/en/p/xfreerdp/</link><pubDate>Tue, 07 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/xfreerdp/</guid><description>&lt;img src="https://vlasov.pro/ru/p/xfreerdp/xfreerdp.webp" alt="Featured image of post xFreeRDP" />&lt;p>&lt;a class="link" href="http://www.freerdp.com/" target="_blank" rel="noopener"
>xFreeRDP&lt;/a> – a tool for connecting to RDP from Linux. After moving to &lt;a class="link" href="https://manjaro.org/" target="_blank" rel="noopener"
>Manjaro&lt;/a> I was unable to install &lt;a class="link" href="https://vlasov.pro/en/p/remmina/" >Remmina&lt;/a>, so I had to look for an alternative. This option pleased me. You can create a one-line script for hosts that you often connect to and use like a catalog.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>xfreerdp /v:1.2.3.4 /u:username /p:password /w:1360 /h:730 /drive:tmp,/tmp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Here I explicitly set the display size for connection and mount &lt;em>/tmp&lt;/em> from local machine to remote one, so you can get some files.&lt;/p></description></item><item><title>About Me</title><link>https://vlasov.pro/en/about/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/about/</guid><description>&lt;h2 id="about-me">About Me &lt;a href="#about-me">¶&lt;/a>&lt;/h2>
&lt;p>I work as a system engineer &lt;em>(DevOps)&lt;/em>, and I am studying and trying to do my best. In the process of working, I understood how much everything is lacking in terms of understanding systems at various stages of the &lt;em>life cycle of software development&lt;/em>.&lt;br>
I studied at &lt;a class="link" href="https://csn.khai.edu/" target="_blank" rel="noopener"
>KhAI&lt;/a> as a computer engineer and received a master&amp;rsquo;s degree in May 2020.
You should take what is written on this site critically - do not believe everything you hear. I am sometimes uneducated in many questions, but in any case, I try to write about what I am sure of.
Please, keep in mind, that english version of the site is autotranslated with AI&amp;rsquo;s, so errors are possible &amp;#x1f604;&lt;/p>
&lt;h2 id="my-goals">My Goals &lt;a href="#my-goals">¶&lt;/a>&lt;/h2>
&lt;p>The list contains the goals that I pursue while keeping this blog afloat. They are ordered by priority according to importance, in descending order:&lt;/p>
&lt;ol>
&lt;li>Do not write nonsense.&lt;/li>
&lt;li>Write and maintain a set of materials that cover at least the minimum knowledge required for every IT professional working in the industry.&lt;/li>
&lt;li>Publish articles based on interesting and unusual solutions. These solutions should be interesting but should not standardize them as necessary to study.&lt;/li>
&lt;li>Support feedback and adjust the course of this blog.&lt;/li>
&lt;li>Use this resource as a &amp;ldquo;CV&amp;rdquo; when transitioning to any other company.&lt;/li>
&lt;/ol></description></item><item><title>Archive</title><link>https://vlasov.pro/en/archives/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/archives/</guid><description/></item><item><title>Search</title><link>https://vlasov.pro/en/search/</link><pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/search/</guid><description/></item><item><title>Rsnapshot</title><link>https://vlasov.pro/en/p/rsnapshot/</link><pubDate>Tue, 12 May 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/rsnapshot/</guid><description>&lt;img src="https://vlasov.pro/ru/p/rsnapshot/rsnapshot.webp" alt="Featured image of post Rsnapshot" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://wiki.archlinux.org/index.php/Rsnapshot" target="_blank" rel="noopener"
>Rsnapshot&lt;/a> is a great utility that can:&lt;/p>
&lt;ol>
&lt;li>Backup folders in the local system and store them in a backup storage (a designated folder somewhere nearby).&lt;/li>
&lt;li>Run scripts that create backups, store them locally, and rsnapshot takes these files and puts them in the same backup folder.&lt;/li>
&lt;li>Send backups via sftp somewhere.&lt;/li>
&lt;li>Store only diffs between backups, saving space.&lt;/li>
&lt;/ol>
&lt;h2 id="retention">Retention &lt;a href="#retention">¶&lt;/a>&lt;/h2>
&lt;p>Rsnapshot has Retention Policies (I might not be calling it exactly right), which in the configuration start with &lt;em>retain&lt;/em>. These are descriptions of &lt;em>abstract plans&lt;/em> about how many recent backup copies to keep. &lt;em>I struggled for a while until I realized that their names don&amp;rsquo;t affect anything.&lt;/em> So if a plan is called &lt;em>daily&lt;/em>, rsnapshot won&amp;rsquo;t necessarily run it every day—you can run it monthly in cron if you want. I find it convenient to use names like daily, weekly, and monthly for configuration (for easier reading and maintenance).&lt;/p>
&lt;p>Retention policies written lower in the config are considered to be executed less frequently than those higher up, so the number for those should be smaller. Rsnapshot uses the content from the higher retention &lt;code>i+1&lt;/code> to create the next lower retention &lt;code>i&lt;/code>. Example:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ date
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>Tue May 12 05:58:33 UTC 2020
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ rsnapshot daily
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ ls -la /data/backups
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>total 48
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxrwxr-x. 11 y.vlasov y.vlasov 4096 May 12 05:57 .
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxrwxr-x+ 6 root root 4096 Apr 27 09:43 ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 12 05:57 daily.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 12 00:00 daily.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 11 00:00 daily.2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 10 00:00 daily.3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 9 00:00 daily.4
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 8 00:00 daily.5
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 7 00:00 daily.6
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 4 00:00 weekly.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 2 00:00 weekly.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ rsnapshot weekly
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ ls -la /data/backups
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>total 48
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxrwxr-x. 11 y.vlasov y.vlasov 4096 May 12 05:57 .
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxrwxr-x+ 6 root root 4096 Apr 27 09:43 ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 12 05:57 daily.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 12 00:00 daily.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 11 00:00 daily.2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 10 00:00 daily.3
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 9 00:00 daily.4
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 8 00:00 daily.5
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 7 00:00 weekly.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 4 00:00 weekly.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">drwxr-xr-x. 6 root root 4096 May 2 00:00 weekly.2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="backup-backup_script">Backup, backup_script &lt;a href="#backup-backup_script">¶&lt;/a>&lt;/h2>
&lt;p>So how does it perform a backup? Rsnapshot backs up &lt;strong>all the steps&lt;/strong> listed in the configuration &lt;strong>each time it is called&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>&lt;em>backup&lt;/em> - you specify a folder path to be backed up, and it copies it completely to the storage.&lt;/li>
&lt;li>&lt;em>backup_script&lt;/em> - you specify the path to a shell script that performs the backup itself, and places the resulting files/folders nearby, then rsnapshot moves them to the storage.&lt;/li>
&lt;li>&lt;em>other options&lt;/em> - &lt;code>man rsnapshot&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h2 id="plan">Plan &lt;a href="#plan">¶&lt;/a>&lt;/h2>
&lt;ol start="0">
&lt;li>Create a folder at the &lt;em>snapshot_root&lt;/em> path.&lt;/li>
&lt;li>Write the rsnapshot.conf file (by default located at &lt;em>/etc/rsnapshot.conf&lt;/em>).&lt;/li>
&lt;li>Add rsnapshot calls to the scheduler - cron.&lt;/li>
&lt;/ol>
&lt;h2 id="example">Example &lt;a href="#example">¶&lt;/a>&lt;/h2>
&lt;p>Let&amp;rsquo;s create the snapshot_root folder: &lt;code>mkdir -p /data/backups&lt;/code>.&lt;/p>
&lt;h3 id="contents-of-etcrsnapshotconf">Contents of /etc/rsnapshot.conf &lt;a href="#contents-of-etcrsnapshotconf">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Note 1: You must use tabs to separate arguments on a line&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">config_version 1.2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">snapshot_root /data/backups
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">no_create_root &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Note 2: Paths may vary between OSes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmd_rm /usr/bin/rm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmd_rsync /usr/bin/rsync
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmd_logger /usr/bin/logger
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Retention configuration&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">retain daily &lt;span class="m">7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">retain weekly &lt;span class="m">4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Logging settings&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">verbose &lt;span class="m">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">loglevel &lt;span class="m">3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">lockfile /var/run/rsnapshot.pid
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## Describing the actions&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">backup /data/ghost ghost/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">backup_script /srv/my_soft/backup.sh my_soft/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="contents-of-crontab">Contents of crontab &lt;a href="#contents-of-crontab">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">0 0 * * * /usr/bin/rsnapshot daily 2&amp;gt;&amp;amp;1 | systemd-cat -t rsnapshot-daily
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">10 0 * * 0 /usr/bin/rsnapshot weekly 2&amp;gt;&amp;amp;1 | systemd-cat -t rsnapshot-weekly
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="contents-of-srvmy_softbackupsh">Contents of /srv/my_soft/backup.sh &lt;a href="#contents-of-srvmy_softbackupsh">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CMD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">rm -rf backup; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">pg_basebackup -U my_user -X stream -F plain -D backup 1&amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;&amp;amp; \
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">tar -C backup -czf - $(ls backup)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">&amp;#39;&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker &lt;span class="nb">exec&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -w /tmp &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> my_soft.postgres &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> /bin/sh -c &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CMD&lt;/span>&lt;span class="s2"> 1&amp;gt;pg_basebackup.tgz
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="contents-of-daily0">Contents of daily.0 &lt;a href="#contents-of-daily0">¶&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-plain" data-lang="plain">&lt;span class="line">&lt;span class="cl">/data/backups/daily.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── ghost
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   └── data
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── my_soft
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   └── pg_basebackup.tgz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── proxy
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   ├── certificates.tgz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│   └── haproxy.tgz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── another_one
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── another_backup_from_backup_script.tgz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">5 directories, 4 files
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>RPM2PKG</title><link>https://vlasov.pro/en/p/rpm2pkg/</link><pubDate>Mon, 27 Apr 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/rpm2pkg/</guid><description>&lt;img src="https://vlasov.pro/ru/p/rpm2pkg/rpm2pkg.webp" alt="Featured image of post RPM2PKG" />&lt;blockquote>
&lt;p>It turned out that Skype and Slack can be installed from AUR with one command&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">yay -S slack-desktop skype
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I left the article just for history&lt;/p>
&lt;/blockquote>
&lt;p>I switched to &lt;a class="link" href="https://manjaro.org/" target="_blank" rel="noopener"
>Manjaro&lt;/a> and encountered the fact that Skype and Viber are packaged in RPM and DEB. What to do with Arch?
On &lt;a class="link" href="https://gitlab.com/vlasov-y/rpm2pkg" target="_blank" rel="noopener"
>GitLab&lt;/a> I placed a simple script that converts rpm to pkg.&lt;/p>
&lt;h2 id="using-the-script">Using the Script &lt;a href="#using-the-script">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Install dependencies&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo pacman -S rpm rpm2cpio cpio git
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 -m pip install --upgrade --user pip pyyaml jinja2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="2">
&lt;li>Clone repository&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git clone --depth &lt;span class="m">1&lt;/span> --single-branch git@gitlab.com:vlasov-y/rpm2pkg.git
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> rpm2pkg
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>Convert&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">curl -fLO https://repo.skype.com/latest/skypeforlinux-64.rpm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python3 rpm2pkg skypeforlinux-64.rpm
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># or add --install to install package automatically (interactive mode, will prompt you for confirmation)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># python3 rpm2pkg --install skypeforlinux-64.rpm&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="4">
&lt;li>Install&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo pacman -U skype*.pkg.tar.gz
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="5">
&lt;li>Remove&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo pacman -R skype
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Nextcloud</title><link>https://vlasov.pro/en/p/nextcloud/</link><pubDate>Sat, 25 Apr 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/nextcloud/</guid><description>&lt;img src="https://vlasov.pro/ru/p/nextcloud/nextcloud.webp" alt="Featured image of post Nextcloud" />&lt;h2 id="launching-the-stack">Launching the Stack &lt;a href="#launching-the-stack">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://nextcloud.com/" target="_blank" rel="noopener"
>&lt;strong>Nextcloud&lt;/strong>&lt;/a> - personal cloud with gallery, email checking, online document editing, audio and radio listening, etc. A demo can be seen &lt;a class="link" href="https://try.nextcloud.com/" target="_blank" rel="noopener"
>here&lt;/a>. A clone of &lt;a class="link" href="https://owncloud.org/" target="_blank" rel="noopener"
>OwnCloud&lt;/a>, I tried initially and didn&amp;rsquo;t find any issues, but there are slightly more applications than what I saw.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.7&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">nextcloud&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nextcloud:18.0.3-apache&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">nextcloud&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unless-stopped&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">depends_on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">postgres&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s1">&amp;#39;8080:80&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">./nextcloud:/var/www/html:rw&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">logging&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">json-file&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">options&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">max-size&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">100m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">postgres&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">postgres:11.7-alpine&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">postgres&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unless-stopped&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">networks&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">nextcloud&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">./postgres:/var/lib/postgresql/data:rw&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">POSTGRES_DB=nextcloud&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">POSTGRES_USER=nextcloud&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">POSTGRES_PASSWORD=94dbd6b2-bd9f-4867-99af-37f8e4444640&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># gitleaks:allow&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">logging&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">json-file&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">options&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">max-size&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">100m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="notes">Notes &lt;a href="#notes">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Tried updating from 16.0.4.1 to 18.0.3 through 17.0.5 - everything failed. Reinstalled and restored files beforehand by downloading them myself from &lt;code>./nextcloud/data/username/files&lt;/code>. Went back using file synchronization via &lt;a class="link" href="https://nextcloud.com/install/#install-clients" target="_blank" rel="noopener"
>client application&lt;/a>.&lt;/li>
&lt;li>The Admin account cannot be deleted through the UI. I created my own account, then tried to delete the standard one as I believe all accounts should always be unique, no fuss. You can delete it like this:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo docker-compose &lt;span class="nb">exec&lt;/span> -u www-data nextcloud php occ user:delete admin
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>For WebDAV and CalDAV to work properly, add the following configuration to your haproxy configuration file:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">global
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> log 127.0.0.1 local0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> stats socket /var/run/haproxy.sock mode &lt;span class="m">660&lt;/span> level admin expose-fd listeners
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> stats timeout 30s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> user root
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> group root
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> daemon
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> maxconn &lt;span class="m">4096&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> nbproc &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Default SSL material locations&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ca-base /etc/ssl/certs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> crt-base /etc/ssl/private
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># general SSL config&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tlsv12 no-tls-tickets
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> tune.ssl.default-dh-param &lt;span class="m">4096&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tlsv12 no-tls-tickets
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">defaults
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> log global
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> mode http
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> option http-buffer-request
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> option httplog
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> option dontlognull
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> option forwardfor
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> timeout connect 5s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> timeout client 25s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> timeout server 25s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> timeout tunnel 3600s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> timeout http-keep-alive 1s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> timeout http-request 15s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> timeout queue 30s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> timeout tarpit 60s
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> compression algo gzip
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> compression &lt;span class="nb">type&lt;/span> text/plain text/css text/xml text/javascript application/javascript application/x-javascript application/xml application/json
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> errorfile &lt;span class="m">400&lt;/span> /usr/local/etc/haproxy/errors/400.http
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> errorfile &lt;span class="m">403&lt;/span> /usr/local/etc/haproxy/errors/403.http
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> errorfile &lt;span class="m">408&lt;/span> /usr/local/etc/haproxy/errors/408.http
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> errorfile &lt;span class="m">500&lt;/span> /usr/local/etc/haproxy/errors/500.http
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> errorfile &lt;span class="m">502&lt;/span> /usr/local/etc/haproxy/errors/502.http
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> errorfile &lt;span class="m">503&lt;/span> /usr/local/etc/haproxy/errors/503.http
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> errorfile &lt;span class="m">504&lt;/span> /usr/local/etc/haproxy/errors/504.http
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">frontend http_https
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">bind&lt;/span> :80
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">bind&lt;/span> :443 ssl crt /certificates/cloudflare.haproxy alpn h2,http/1.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># acls&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> acl dav path_reg -i ^/.well-known/&lt;span class="o">(&lt;/span>carddav&lt;span class="p">|&lt;/span>caldav&lt;span class="o">)&lt;/span>.*$
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> acl webfinger path_reg -i ^/.well-known/&lt;span class="o">(&lt;/span>carddav&lt;span class="p">|&lt;/span>caldav&lt;span class="o">)&lt;/span>.*$
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># proxy headers&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> http-request set-header X-Forwarded-Port %&lt;span class="o">[&lt;/span>dst_port&lt;span class="o">]&lt;/span> &lt;span class="k">if&lt;/span> forwarded_port
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># http-response set-header Access-Control-Allow-Credentials &amp;#34;true&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> http-request add-header X-Forwarded-Proto https &lt;span class="k">if&lt;/span> https forwarded_proto
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> http-request replace-path &lt;span class="o">(&lt;/span>.*&lt;span class="o">)&lt;/span> /remote.php/dav &lt;span class="k">if&lt;/span> dav
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> http-request replace-path &lt;span class="o">(&lt;/span>.*&lt;span class="o">)&lt;/span> /public.php?service&lt;span class="o">=&lt;/span>webfinger &lt;span class="k">if&lt;/span> webfinger
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> default_backend cloud
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">backend nextcloud
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> http-response set-header Strict-Transport-Security &lt;span class="s2">&amp;#34;max-age=63072000; includeSubDomains; preload;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> server default nextcloud:80 check
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="4">
&lt;li>Authorization was rotating endlessly and only F5 allowed access. On the PC, the problem disappeared, but how about with a client for Android? &lt;a class="link" href="https://github.com/nextcloud/android/issues/3623#issuecomment-568992424" target="_blank" rel="noopener"
>Here&lt;/a>, it turned out that you can simply add a magic word to your config and you&amp;rsquo;ll be able to log in forever.&lt;/li>
&lt;/ol></description></item><item><title>Command Line Setup</title><link>https://vlasov.pro/en/p/shells/</link><pubDate>Wed, 22 Apr 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/shells/</guid><description>&lt;img src="https://vlasov.pro/ru/p/shells/bash.webp" alt="Featured image of post Command Line Setup" />&lt;blockquote>
&lt;p>Written together with &lt;a class="link" href="https://rebrainme.com/blog/" target="_blank" rel="noopener"
>ReBrainMe&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>The command-line shell is used for any server manipulation. There are many ways to configure servers. It&amp;rsquo;s important that it&amp;rsquo;s comfortable for the administrator, but the &lt;strong>main thing&lt;/strong> is that it&amp;rsquo;s &lt;strong>efficient&lt;/strong> in terms of time, effort, and cost. The command line can be colorful, with arrows of different colors showing the path to the current directory, time, CPU load, and other stuff. Here&amp;rsquo;s an example from &lt;a class="link" href="https://github.com/ohmyzsh/ohmyzsh/" target="_blank" rel="noopener"
>here&lt;/a>:&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/shells/ohmyzsh.webp"
width="633"
height="346"
srcset="https://vlasov.pro/ru/p/shells/ohmyzsh_hu14244436401278716114.webp 480w, https://vlasov.pro/ru/p/shells/ohmyzsh_hu6890038653941497772.webp 1024w"
loading="lazy"
alt="ohmyzsh"
class="gallery-image"
data-flex-grow="182"
data-flex-basis="439px"
>&lt;/p>
&lt;p>It&amp;rsquo;s beautiful, yes, but too many colors distract from the essence. Also, the Git repository branch is displayed, taking up vital space on the left, though it could be moved to the right.&lt;/p>
&lt;h2 id="command-line-shells">Command Line Shells &lt;a href="#command-line-shells">¶&lt;/a>&lt;/h2>
&lt;p>Shells come in different types, though they solve the same problems in very similar ways, they are configured differently and have different functionality. &lt;em>Try different ones and find your own! &amp;hellip; or write one yourself&lt;/em>.&lt;/p>
&lt;ul>
&lt;li>&lt;em>bash&lt;/em> – the de facto standard shell, with basic autocompletion and path completion, included in most distributions by default, often used as a script shell.&lt;/li>
&lt;li>&lt;em>fish&lt;/em> and &lt;em>zsh&lt;/em> – two different shells that greatly surpass bash in functionality, often heard of.&lt;/li>
&lt;li>&lt;em>ksh, tsh, csh &amp;hellip;&lt;/em> other shells, which may be just as good or even better, but are slightly less common.&lt;/li>
&lt;/ul>
&lt;p>The goal of this article is to &lt;strong>subjectively&lt;/strong> figure out what really needs to be in the terminal window and &lt;em>suggest a solution&lt;/em> based on &lt;strong>zsh&lt;/strong>.&lt;/p>
&lt;p>What is needed for the command line to be effective?&lt;/p>
&lt;h2 id="shell-requirements">Shell Requirements &lt;a href="#shell-requirements">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>&lt;em>Path autocompletion&lt;/em>. This is undeniably the main feature needed for navigating directory trees. It may seem that Bash has path autocompletion by default by pressing Tab twice. Try Zsh – you only need to press Tab once, a small thing, right? Now go back to Bash :) Additionally, Zsh can be configured to display a list of files matching the given prefix, which &lt;em>eliminates the need to interrupt input and run ls -la, you can even select the option with arrow keys&lt;/em>. This is not used often, but it&amp;rsquo;s convenient.&lt;/li>
&lt;li>&lt;em>Command history search&lt;/em>. If you’ve already switched to &lt;a class="link" href="https://github.com/ranger/ranger" target="_blank" rel="noopener"
>ranger&lt;/a>, this might become the most important requirement for you. At first, we learn about &lt;strong>Ctrl+R&lt;/strong> to search for a command in the history of typed commands. Convenient, but not perfect. In Zsh, you can just type a piece of the command and use the arrow keys to select the one you need from the autosuggestions. Subjectively more convenient, and here’s why: to show the next command from history, you need to press Ctrl+R again, which is not very comfortable, especially when you skip over the one you need.&lt;/li>
&lt;li>&lt;em>Highlighting the command prompt&lt;/em>. When scrolling through a large number of logs in the terminal from different commands, you start to lose track and spend extra time distinguishing which block of logs belongs to which command, where the command itself is, etc. Highlighting the command prompt is really necessary, but not in a way that overshadows everything. Often, the first thing a beginner changes in a non-standard shell is the contents of the &lt;strong>PS1&lt;/strong> variable. &lt;a class="link" href="https://linoxide.com/how-tos/change-bash-prompt-variable-ps1/" target="_blank" rel="noopener"
>Here’s a good description of PS1-4 variables&lt;/a>.&lt;/li>
&lt;li>&lt;em>Lightweight&lt;/em>. Briefly: when you&amp;rsquo;re on a server where the loadavg is tens of times exceeded, you’ll regret setting up resource-intensive code in motd or the beginning of .zshrc (.bashrc) that outputs extensive CPU, memory, network, disk usage statistics, etc.&lt;/li>
&lt;li>&lt;em>Uncluttered&lt;/em>. Even if zsh is chosen for daily use, I write all scripts with a shebang for classic sh because it’s practically everywhere, and the syntax is standardized. In other words, it’s not recommended to write scripts using the non-standard syntaxes of advanced shells, as it will be a hassle to install them on every server.&lt;/li>
&lt;li>&lt;em>Comfort&lt;/em>. Efficiency and comfort are closely related. Setting a semi-transparent image as the background or picking fonts to your liking is also very important when you find yourself thinking that ugly fonts and a clunky interface kill your motivation to work completely. &lt;em>Just don’t overdo it&lt;/em>.&lt;/li>
&lt;/ol>
&lt;h2 id="aliases">Aliases &lt;a href="#aliases">¶&lt;/a>&lt;/h2>
&lt;p>It’s very convenient to declare aliases to speed up command typing.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> ..&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;cd .. &amp;amp;&amp;amp; ls -lhA --color=auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">a&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ls -lhA --color=auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">d&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo docker&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">dc&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo docker-compose&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">die&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo shutdown now&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">e&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;exit&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">g&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;git&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">j&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo journalctl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;kubectl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">l&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ls -lh --color=auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">la&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ls -lhA --color=auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">p&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ping 8.8.8.8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">r&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ranger&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">reborn&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo shutdown -r now&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">s&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">sctl&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo systemctl&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">sr&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;screen -R&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">svi&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo vim&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">svim&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;sudo vim&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">alias&lt;/span> &lt;span class="nv">t&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;terraform&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>And a little humor: &lt;em>alias please=&amp;lsquo;sudo&amp;rsquo;&lt;/em> will make your interaction with the computer much smoother.&lt;/p>
&lt;h2 id="zsh-configuration">Zsh Configuration &lt;a href="#zsh-configuration">¶&lt;/a>&lt;/h2>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/shells/my-zsh.png"
width="676"
height="276"
srcset="https://vlasov.pro/ru/p/shells/my-zsh_hu5659858168636195027.png 480w, https://vlasov.pro/ru/p/shells/my-zsh_hu10784998609317191711.png 1024w"
loading="lazy"
alt="Example of a custom zsh configuration"
class="gallery-image"
data-flex-grow="244"
data-flex-basis="587px"
>&lt;/p>
&lt;p>As you can see, each command is highlighted between separators like &lt;code>; &amp;amp;&amp;amp; |&lt;/code>, and the command is entered on the second line, after the prompt indicating the current directory and username with host. This makes long commands more readable and manageable. On the right, honestly &lt;em>borrowed&lt;/em> from the standard settings shipped with zsh in &lt;a class="link" href="https://manjaro.org/" target="_blank" rel="noopener"
>Manjaro&lt;/a>, is the current Git repository branch. If there are changes, deletions, or additions, yellow, green, and red circles appear. Since it didn&amp;rsquo;t take up much space, it was decided to keep it. Why not.
When typing a command, the last one that matches the prefix is suggested. You can confirm the selection by pressing the right arrow key. The terminal emulator window is &lt;a class="link" href="https://terminator-gtk3.readthedocs.io/en/latest/" target="_blank" rel="noopener"
>Terminator&lt;/a>.&lt;/p>
&lt;p>To set up and configure the terminal window as in the example, follow these steps:&lt;/p>
&lt;ol>
&lt;li>&lt;a class="link" href="https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH" target="_blank" rel="noopener"
>Install&lt;/a> ohmyzsh&lt;/li>
&lt;li>Copy &lt;a class="link" href="files/dot.zshrc" >.zshrc&lt;/a> to your home directory&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">install -o &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>id -u&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -g &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>id -g&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -m &lt;span class="m">0644&lt;/span> .zshrc ~/.zshrc
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="3">
&lt;li>Unpack the &lt;a class="link" href="files/plugins.tgz" >plugins&lt;/a>&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo tar -xpzvf plugins.tgz /
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo usermod -s &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">command&lt;/span> -v zsh&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$USER&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="4">
&lt;li>Set zsh as the default shell&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo usermod -s &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>&lt;span class="nb">command&lt;/span> -v zsh&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$USER&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Introduction to CEPH</title><link>https://vlasov.pro/en/p/ceph-intro/</link><pubDate>Wed, 22 Apr 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/ceph-intro/</guid><description>&lt;img src="https://vlasov.pro/ru/p/ceph-intro/ceph.webp" alt="Featured image of post Introduction to CEPH" />&lt;h2 id="installation">Installation &lt;a href="#installation">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://ceph.io/" target="_blank" rel="noopener"
>&lt;strong>CEPH&lt;/strong>&lt;/a> is a distributed network storage system that supports S3, iSCSI, RBD, etc. It’s a great solution, with plenty of documentation available, but it can be tricky to figure out the correct installation method at first.&lt;/p>
&lt;h3 id="rook">Rook &lt;a href="#rook">¶&lt;/a>&lt;/h3>
&lt;p>The officially recommended way to install CEPH on Kubernetes. You can read about the experience of the team at &lt;a class="link" href="https://flant.com/" target="_blank" rel="noopener"
>Flant&lt;/a> &lt;a class="link" href="https://habr.com/en/company/flant/blog/451818/" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;h3 id="cephadm">Cephadm &lt;a href="#cephadm">¶&lt;/a>&lt;/h3>
&lt;p>Based on this, I wrote some Ansible playbooks and successfully managed a cluster deployed on a host. It accepted 40 GiB over the local network in 2 minutes and remained stable :)&lt;/p>
&lt;h3 id="deprecated--not-recommended">Deprecated / Not Recommended &lt;a href="#deprecated--not-recommended">¶&lt;/a>&lt;/h3>
&lt;p>The methods I tried that turned out to be either non-working or deprecated:&lt;/p>
&lt;ul>
&lt;li>&lt;a class="link" href="https://docs.ceph.com/docs/master/rados/deployment/" target="_blank" rel="noopener"
>&lt;strong>ceph-deploy&lt;/strong>&lt;/a>: somewhere in the documentation, I found that this method is not recommended. Unfortunately, I had already spent a couple of days on it. I can’t provide a link since their SSL certificate expired, and I’m blocked from accessing the site due to HSTS.&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/ceph/ceph-ansible" target="_blank" rel="noopener"
>&lt;strong>ceph ansible&lt;/strong>&lt;/a>: comprehensive and feature-rich, but CentOS 7 is no longer supported on the master branch, and the monitors didn’t synchronize. I couldn’t find a way to install the dashboard without monitoring, so I implemented it myself. I gained experience with Ansible, but then new issues arose, prompting me to switch to &lt;em>cephadm&lt;/em>, which I’m glad I did.&lt;/li>
&lt;/ul>
&lt;h2 id="useful-commands">Useful Commands &lt;a href="#useful-commands">¶&lt;/a>&lt;/h2>
&lt;p>Here&amp;rsquo;s a &lt;a class="link" href="https://sabaini.at/pages/ceph-cheatsheet.html" target="_blank" rel="noopener"
>cheatsheet&lt;/a> I found helpful.&lt;br>
To view the list of disks in use on the servers:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ceph orch device ls
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph device ls
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph device ls-by-host ceph-server-0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>To check the space usage summary:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ceph osd df
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph df
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph df &lt;span class="p">|&lt;/span> grep -oE &lt;span class="s1">&amp;#39;[0-9.]+\s*[a-zA-Z]+$&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> uniq &lt;span class="p">|&lt;/span> sort -n
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>To view the cluster status:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ceph status
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph -w
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>To see the infrastructure, including which services/containers are running and where:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ceph orch ls
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph orch ps
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="replacing-an-osd">Replacing an OSD &lt;a href="#replacing-an-osd">¶&lt;/a>&lt;/h2>
&lt;p>&lt;a class="link" href="https://m.habr.com/en/company/flant/blog/495870/" target="_blank" rel="noopener"
>Here’s a good article&lt;/a> from the same Flant team, along with a &lt;a class="link" href="https://m.habr.com/en/company/flant/blog/495870/comments/#comment_21477582" target="_blank" rel="noopener"
>useful comment&lt;/a> that complements it well. I recreated the OSD when I expanded the block device on the server (virtual machine) to add space to the cluster. I followed this process:&lt;/p>
&lt;ol>
&lt;li>The cluster must be in HEALTH_OK state.&lt;/li>
&lt;li>Remove the OSD from the cluster.&lt;/li>
&lt;li>Delete the daemon (container) holding this OSD.&lt;/li>
&lt;li>Purge the OSD.&lt;/li>
&lt;li>Clear the partition.&lt;/li>
&lt;li>Reconnect it.&lt;/li>
&lt;li>Wait for HEALTH_OK.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># The OSD we want to recreate&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">OSD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;osd.0&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Find the host&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">HOST&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>ceph device ls &lt;span class="p">|&lt;/span> awk &lt;span class="s2">&amp;#34;/&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">OSD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/{print \$2}&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> cut -d: -f1&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Get the name of the block device allocated to the OSD&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DEV&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;/dev/&lt;/span>&lt;span class="k">$(&lt;/span>ceph device ls &lt;span class="p">|&lt;/span> awk &lt;span class="s2">&amp;#34;/&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">OSD&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/{print \$2}&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> cut -d: -f2&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph health &lt;span class="p">|&lt;/span> grep -q &lt;span class="s1">&amp;#39;HEALTH_OK&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph osd out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$OSD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph orch daemon rm &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$OSD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> --force
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph osd purge &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$OSD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> --force
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph orch device zap &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">HOST&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEV&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> --force
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">NEW_ID&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;osd.&lt;/span>&lt;span class="k">$(&lt;/span>ceph orch daemon add osd &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">HOST&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DEV&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#39; | awk &amp;#39;{print &lt;/span>&lt;span class="nv">$3&lt;/span>&lt;span class="s2">}&amp;#39;)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sleep &lt;span class="m">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph osd crush reweight &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$NEW_ID&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="m">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">while&lt;/span> ! ceph health &lt;span class="p">|&lt;/span> grep -q &lt;span class="s1">&amp;#39;HEALTH_OK&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">do&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> sleep &lt;span class="m">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>In my experience, replacing an OSD with 15 GiB of data took about 30 minutes. This was tested on three &lt;a class="link" href="https://www.hetzner.com/cloud#pricing" target="_blank" rel="noopener"
>CX21 Hetzner&lt;/a> instances.&lt;/p>
&lt;h2 id="rbd-and-docker">RBD and Docker &lt;a href="#rbd-and-docker">¶&lt;/a>&lt;/h2>
&lt;p>Setting up RBD and integrating it with Docker:&lt;/p>
&lt;ol>
&lt;li>Create a pool.&lt;/li>
&lt;li>Initialize the pool.&lt;/li>
&lt;li>Create a user for the setup.&lt;/li>
&lt;li>Disable unnecessary features. Some RBD features aren’t supported in Linux kernels before 4.17, so they had to be disabled. You can check the options with:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ceph config &lt;span class="nb">help&lt;/span> rbd_default_features
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ol start="5">
&lt;li>Install the Docker volume plugin.&lt;/li>
&lt;li>Test on the container.&lt;/li>
&lt;li>Mount the volume and verify the file.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph osd pool create rbd
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rbd pool init rbd
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph auth get-or-create client.rbd mon &lt;span class="s1">&amp;#39;profile rbd&amp;#39;&lt;/span> osd &lt;span class="s1">&amp;#39;profile rbd pool=rbd&amp;#39;&lt;/span> mgr &lt;span class="s1">&amp;#39;profile rbd pool=rbd&amp;#39;&lt;/span> &amp;gt; /etc/ceph/ceph.client.rbd.keyring
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ceph config &lt;span class="nb">set&lt;/span> global rbd_default_features &lt;span class="m">7&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>I used this &lt;a class="link" href="https://github.com/wetopi/docker-volume-rbd" target="_blank" rel="noopener"
>volume driver&lt;/a>. Other options I found hadn’t been updated in 3-4 years and seemed abandoned. This driver doesn’t require anything to run on the side and &lt;a class="link" href="https://docs.docker.com/engine/extend/" target="_blank" rel="noopener"
>integrates directly into Docker&lt;/a>. Install it like this:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker plugin install wetopi/rbd &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --alias&lt;span class="o">=&lt;/span>rbd &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --grant-all-permissions &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">LOG_LEVEL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">RBD_CONF_POOL&lt;/span>&lt;span class="o">=&lt;/span>rbd &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">RBD_CONF_CLUSTER&lt;/span>&lt;span class="o">=&lt;/span>ceph &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">RBD_CONF_KEYRING_USER&lt;/span>&lt;span class="o">=&lt;/span>client.rbd &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nv">MOUNT_OPTIONS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;--options=noatime,discard&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Run a simple Docker Compose stack and mount the image:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;3.8&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">test&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">alpine&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">command&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">sh -c &amp;#39;cat /vol/test; date | tee /vol/test&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">data-volume:/vol&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">data-volume&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">vol1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">rbd&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver_opts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">size&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">123&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># MiB&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Run and verify:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo docker-compose up
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Step 7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rbd map vol1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mkdir /tmp/vol1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mount /dev/rbd0 /tmp/vol1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> /tmp/vol1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ls -la
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="nb">test&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> /
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">umount /tmp/vol1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rbd unmap /dev/rbd0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>Remmina</title><link>https://vlasov.pro/en/p/remmina/</link><pubDate>Wed, 22 Apr 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/remmina/</guid><description>&lt;img src="https://vlasov.pro/ru/p/remmina/remmina.webp" alt="Featured image of post Remmina" />&lt;p>Great client application for connecting by RDP/VNC/etc. I installed it on Ubuntu 18.04 like this:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo add-apt-repository ppa:remmina-ppa-team/remmina-next
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo apt install remmina &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-exec &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-kwallet &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-nx &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-rdp &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-secret &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-spice &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-vnc &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-www &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> remmina-plugin-xdmcp &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> libfreerdp-plugins-standard
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo ln -s /usr/lib/x86_64-linux-gnu/libssh.so.4 /usr/lib/x86_64-linux-gnu/libssh_threads.so.4
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>More information is available on their &lt;a class="link" href="https://remmina.org/" target="_blank" rel="noopener"
>page&lt;/a>.&lt;/p></description></item><item><title>Basics of SSH</title><link>https://vlasov.pro/en/p/ssh-intro/</link><pubDate>Mon, 09 Mar 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/ssh-intro/</guid><description>&lt;img src="https://vlasov.pro/ru/p/ssh-intro/openssh.webp" alt="Featured image of post Basics of SSH" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>&lt;strong>S&lt;/strong>ecure &lt;strong>Sh&lt;/strong>ell - de facto standard way to get access to a remote terminal on an virtual server. On the computer where you need to get access, &lt;strong>SSH server&lt;/strong> is installed, and on the computer where the operator works, &lt;strong>SSH client&lt;/strong> is installed. Through SSH we can:&lt;/p>
&lt;ol>
&lt;li>Transfer files&lt;/li>
&lt;li>Execute commands on the target server&lt;/li>
&lt;li>Get information about the target system and perform simple automation&lt;/li>
&lt;/ol>
&lt;p>On Linux and MacOS, we have a terminal - SSH, which is usually set up by default. For Windows, I used the following options:&lt;/p>
&lt;ol>
&lt;li>&lt;a class="link" href="https://mobaxterm.mobatek.net/" target="_blank" rel="noopener"
>MobaXTerm&lt;/a> - convenient, but paid. Suitable for non-commercial use, but you&amp;rsquo;ll need to buy a license if you want to use it in a company. Advantages:
&lt;ul>
&lt;li>Immediately provides a file manager with drag-n-drop files to the target system&lt;/li>
&lt;li>Normal keyboard support and RSA key support&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a class="link" href="https://git-scm.com/" target="_blank" rel="noopener"
>Git&lt;/a> - when setting up Git, it includes Git Bash and an SSH client. Very close to the usual &lt;a class="link" href="https://ru.wikipedia.org/wiki/Bash" target="_blank" rel="noopener"
>Bash&lt;/a>.&lt;/li>
&lt;/ol>
&lt;h2 id="connecting">Connecting &lt;a href="#connecting">¶&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ssh &lt;span class="o">[&lt;/span>-p &amp;lt;ssh порт&amp;gt;&lt;span class="o">]&lt;/span> &amp;lt;пользователь&amp;gt;@&amp;lt;ip целевого хоста&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The port is optional, defaulting to &lt;strong>22&lt;/strong>, but &lt;em>it&amp;rsquo;s highly recommended&lt;/em> not to run the SSH server on the standard port, as the world is full of automated bots that scan networks and find virtual machines with SSH on the standard port and simple passwords, trying to add them to some botnet. I once fell for this, but it&amp;rsquo;s a different story&amp;hellip;&lt;/p>
&lt;h2 id="copying-files">Copying Files &lt;a href="#copying-files">¶&lt;/a>&lt;/h2>
&lt;p>To copy files to the target host, you can use scp.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">scp &lt;span class="o">[&lt;/span>-P &amp;lt;ssh порт&amp;gt;&lt;span class="o">]&lt;/span> /path/to/local/file &amp;lt;пользователь&amp;gt;@&amp;lt;ip целевого хоста&amp;gt;:&amp;lt;путь на сервере назначения&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Note:&lt;/p>
&lt;ol>
&lt;li>The port for scp is specified using &lt;code>-P&lt;/code>, whereas for ordinary SSH - &lt;code>-p&lt;/code>.&lt;/li>
&lt;li>The folder on the target machine should belong to the user you&amp;rsquo;re connecting with, or you&amp;rsquo;ll need permission to write to that folder\file.&lt;/li>
&lt;/ol></description></item><item><title>First Post on Ghost</title><link>https://vlasov.pro/en/p/ghost/</link><pubDate>Sun, 08 Mar 2020 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/ghost/</guid><description>&lt;img src="https://vlasov.pro/ru/p/ghost/ghost-logo.webp" alt="Featured image of post First Post on Ghost" />&lt;blockquote>
&lt;p>&lt;em>Now the blog is written on &lt;a class="link" href="https://docs.stack.jimmycai.com" target="_blank" rel="noopener"
>Hugo&lt;/a>. This article is the first post from the old blog, which, just like that, was on Ghost.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;ul>
&lt;li>&lt;a class="link" href="#notes" >Notes&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>First article. Reminded me of Isaac Asimov&amp;rsquo;s &amp;ldquo;&lt;a class="link" href="https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B8%D0%B9_%D0%B2%D0%BE%D0%BF%D1%80%D0%BE%D1%81" target="_blank" rel="noopener"
>The Last Question&lt;/a>&amp;rdquo;, listened to on the way to work one of those ordinary days. A good thing - recommend it.
Writing a good article, which will be a worthwhile read, is not as easy as it seemed at first. There are two reasons for this:&lt;/p>
&lt;ol>
&lt;li>Thoughts must be &lt;em>useful&lt;/em>.&lt;/li>
&lt;li>The text should be &lt;em>systematized&lt;/em>.&lt;/li>
&lt;/ol>
&lt;p>The system is launched on &lt;a class="link" href="https://ghost.org" target="_blank" rel="noopener"
>Ghost&lt;/a> - the server is good, fast, and started easily, there&amp;rsquo;s enough tooling for such a pseudo-blogger like me. There&amp;rsquo;s a built-in plugin for choosing images from &lt;a class="link" href="https://unsplash.com/" target="_blank" rel="noopener"
>Unsplash&lt;/a> - images that can be published without fear of being sued for copyright infringement.
docker-compose.yml file, which makes this whole thing easy to set up, is presented below.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.7&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">services&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ghost&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ghost:3.9.0-alpine&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">container_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ghost&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">restart&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">unless-stopped&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">port&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s1">&amp;#39;80:2368&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">volumes&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">/data/ghost:/var/lib/ghost/content:rw&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">url=http://example.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">logging&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">driver&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">json-file&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">options&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">max-size&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">100m&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="notes">Notes &lt;a href="#notes">¶&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Always &lt;em>keep the version&lt;/em> of the image, from which the container will be started. This helps avoid problems with the stack restarting later on. If you use &lt;code>latest&lt;/code>, it&amp;rsquo;s possible that when you recreate the stack, &lt;code>up -&amp;gt; down&lt;/code> might start again a newer version, which won&amp;rsquo;t be compatible with the current data and settings etc. Moreover, it&amp;rsquo;s impossible to quickly and easily remember &lt;em>which version was exactly launched at the moment of startup?&lt;/em>&lt;/li>
&lt;li>&lt;strong>Always&lt;/strong> control the logging process. If using the standard Docker logging driver - json-file, then by default, the Docker daemon will receive logs and write them to a file for this container until &lt;em>the disk runs out&lt;/em>. By default, the file is always one, but its location can be limited by setting the &lt;code>max-size: 100m&lt;/code> option (I just took 100 MB, it&amp;rsquo;s unlikely that anyone would read more than that). &lt;a class="link" href="https://docs.docker.com/config/containers/logging/json-file/" target="_blank" rel="noopener"
>More information about the json-file Docker logging driver&lt;/a>.&lt;/li>
&lt;li>I recommend always specifying &lt;code>container_name&lt;/code> - it&amp;rsquo;s easier to read &lt;code>docker ps&lt;/code>.&lt;/li>
&lt;/ol></description></item><item><title>Reverse SSH Tunnels</title><link>https://vlasov.pro/en/p/reverse-ssh/</link><pubDate>Sun, 20 Oct 2019 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/reverse-ssh/</guid><description>&lt;img src="https://vlasov.pro/ru/p/reverse-ssh/ssh.png" alt="Featured image of post Reverse SSH Tunnels" />&lt;h2 id="introduction">Introduction &lt;a href="#introduction">¶&lt;/a>&lt;/h2>
&lt;p>When needing to access a server located behind &lt;a class="link" href="https://www.webopedia.com/definitions/nat/" target="_blank" rel="noopener"
>NAT&lt;/a>, direct connection cannot be made. Instead, we need to come up with alternative methods. We&amp;rsquo;ll explore how to use both direct and reverse SSH tunnels for these purposes.&lt;/p>
&lt;h2 id="tunnels">Tunnels &lt;a href="#tunnels">¶&lt;/a>&lt;/h2>
&lt;h3 id="reverse-tunnel">Reverse Tunnel &lt;a href="#reverse-tunnel">¶&lt;/a>&lt;/h3>
&lt;ul>
&lt;li>Created from the target server (CS) to a intermediate (PS).&lt;/li>
&lt;li>Socket created on PS.&lt;/li>
&lt;li>Direct tunnel - created from the initial server (NS) to PS.&lt;/li>
&lt;li>Socket located on NS.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/reverse-ssh/diagram.png"
width="542"
height="317"
srcset="https://vlasov.pro/ru/p/reverse-ssh/diagram_hu17955256524260640580.png 480w, https://vlasov.pro/ru/p/reverse-ssh/diagram_hu3505688432812524674.png 1024w"
loading="lazy"
alt="Schematic diagram of the proposed method"
class="gallery-image"
data-flex-grow="170"
data-flex-basis="410px"
>&lt;/p>
&lt;p>Using two tunnels, we can access CS. Ports for any website or even just SSH server in CS can be cast and gain access into the system. SOCKS5 proxy can also be used to exit the network through CS.&lt;/p>
&lt;blockquote>
&lt;p>Intermediate Server must be accessible from both CS and NS&lt;/p>
&lt;/blockquote>
&lt;h3 id="creating-user-on-ps">Creating User on PS &lt;a href="#creating-user-on-ps">¶&lt;/a>&lt;/h3>
&lt;p>Using a user that can only create tunnels is recommended for security purposes. Below code creates a new user with no home directory or interpreter:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sudo adduser -s /bin/false -M -N tunnel
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo usermod -d / tunnel
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;tunnel:tunnel&amp;#39;&lt;/span> &lt;span class="p">|&lt;/span> sudo chpasswd
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF | sudo tee -a /etc/ssh/sshd_config
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">Match User tunnel
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> PasswordAuthentication yes
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> AuthenticationMethods &amp;#34;password&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sudo systemctl restart sshd
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="reverse-tunnel-1">Reverse Tunnel &lt;a href="#reverse-tunnel-1">¶&lt;/a>&lt;/h3>
&lt;p>Now let&amp;rsquo;s move on to creating tunnels. We&amp;rsquo;ll need a reverse tunnel from PS to CS.&lt;/p>
&lt;p>Below is &lt;code>sshpass&lt;/code> command, which is necessary for automatically entering passwords when connecting via SSH:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">mkdir -p ~/.ssh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh-keyscan -H jump-host &amp;gt;&amp;gt; ~/.ssh/known_hosts
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Creating the reverse tunnel on CS:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">sshpass -p &lt;span class="s1">&amp;#39;password&amp;#39;&lt;/span> ssh -fNR 2222:localhost:22 tunnel@jump-host
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ul>
&lt;li>&lt;code>ssh-keyscan -H jump-host&lt;/code> adds SSH Server&amp;rsquo;s key to PS&amp;rsquo;s known hosts.&lt;/li>
&lt;li>&lt;code>-fN&lt;/code> executes command and doesn&amp;rsquo;t create a tty session.&lt;/li>
&lt;li>&lt;code>-R&lt;/code> creates the reverse tunnel.&lt;/li>
&lt;li>&lt;code>2222:localhost:22&lt;/code> translates into: proxying 127.0.0.1:2222 (default localhost) to PS at 127.0.0.1:22 on CS. So, it does exactly this: proxies 127.0.0.1:2222 from NS&amp;rsquo;s default address &lt;code>localhost&lt;/code> to PS&amp;rsquo;s address &lt;code>127.0.0.1&lt;/code>. Now we can access CS via PS.&lt;/li>
&lt;li>Checking the tunnel can be done with:&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ssh -p &lt;span class="m">2222&lt;/span> localhost hostname
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="direct-tunnel">Direct Tunnel &lt;a href="#direct-tunnel">¶&lt;/a>&lt;/h3>
&lt;p>To get into reverse tunnel on PS, a direct tunnel from NS needs to be created:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">mkdir -p ~/.ssh
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ssh-keyscan -H jump-host &amp;gt;&amp;gt; ~/.ssh/known_hosts
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">sshpass -p &lt;span class="s1">&amp;#39;password&amp;#39;&lt;/span> ssh -fNL 1234:localhost:2222 tunnel@jump-host
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;ul>
&lt;li>&lt;code>1234:localhost:2222&lt;/code> translates into: proxying 127.0.0.1:1234 from NS to PS at 127.0.0.1:2222 on CS, which means proxying from NS&amp;rsquo;s address &lt;code>localhost&lt;/code> at port &lt;code>1234&lt;/code> to PS&amp;rsquo;s address &lt;code>127.0.0.1&lt;/code> at port &lt;code>2222&lt;/code>. So, now we can access reverse tunnel on PS using direct tunnel.&lt;/li>
&lt;li>To access the tunnel:&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ssh -fND &lt;span class="m">1329&lt;/span> -p &lt;span class="m">1234&lt;/span> user-on-th@localhost
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="socks5-proxy">SOCKS5 Proxy &lt;a href="#socks5-proxy">¶&lt;/a>&lt;/h3>
&lt;p>We can set up any browser to use a SOCKS5 proxy for directing all traffic. This is convenient when trying to access resources in local network CS from NS. After creating tunnels, the following command needs to be executed on NS:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ssh -fND &lt;span class="m">1329&lt;/span> -p &lt;span class="m">1234&lt;/span> user-on-th@localhost
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>And to configure a browser&amp;rsquo;s SOCKS5 proxy settings, look at this screenshot.&lt;/p>
&lt;p>&lt;img src="https://vlasov.pro/ru/p/reverse-ssh/proxy-settings.webp"
width="1020"
height="700"
srcset="https://vlasov.pro/ru/p/reverse-ssh/proxy-settings_hu6932171806291270442.webp 480w, https://vlasov.pro/ru/p/reverse-ssh/proxy-settings_hu17882682458861990530.webp 1024w"
loading="lazy"
alt="KDE Plasma Proxy Settings"
class="gallery-image"
data-flex-grow="145"
data-flex-basis="349px"
>&lt;/p></description></item><item><title>OpenSSL Snippet</title><link>https://vlasov.pro/en/p/openssl-snippet/</link><pubDate>Thu, 25 Apr 2019 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/openssl-snippet/</guid><description>&lt;img src="https://vlasov.pro/ru/p/openssl-snippet/https.webp" alt="Featured image of post OpenSSL Snippet" />&lt;p>Here is the translated text:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;span class="lnt">87
&lt;/span>&lt;span class="lnt">88
&lt;/span>&lt;span class="lnt">89
&lt;/span>&lt;span class="lnt">90
&lt;/span>&lt;span class="lnt">91
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/usr/bin/env sh
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="nb">set&lt;/span> -e
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># path to private part of CA (PEM encoded)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CA_KEY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;ca.key&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># path to public part of CA (PEM encoded)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CA_CRT&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;ca.crt&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># password to use CA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">CA_PASSWORD&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;longalphanum&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Country&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">C&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;UA&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># State&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">ST&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;Kiev&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Location&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">L&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;Kiev&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Organization&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">O&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;No organization&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Organization unit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">OU&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;No unit&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Domain to issue final cert for&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;vlasov.pro&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Days while the certificate will be valid&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">DAYS&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;365&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">subj&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;/C=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">C&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/ST=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">ST&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/L=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">L&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/O=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">O&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/OU=&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">OU&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">/CN=&lt;/span>&lt;span class="nv">$1&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="o">[&lt;/span> ! -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_KEY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">]&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="o">[&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$1&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;-ca&amp;#39;&lt;/span> &lt;span class="o">]&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;basicConstraints=CA:true&amp;#39;&lt;/span> &amp;gt; extfile.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># CA - used for signing of both server and client certs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># generate private key&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl ecparam -genkey -name prime256v1 &lt;span class="p">|&lt;/span> openssl ec -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_KEY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># generate signing request&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl req -new -key &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_KEY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -out ca.csr -subj &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>subj &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$O&lt;/span>&lt;span class="s2"> CA&amp;#34;&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># csr + key = crt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl x509 -req -days &lt;span class="m">3650&lt;/span> -in ca.csr -signkey &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_KEY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -extfile extfile.txt -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> rm -f ca.csr
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># convert crt to DER format&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> openssl x509 -inform PEM -outform DER -in &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">.der&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">echo&lt;/span> &lt;span class="s1">&amp;#39;Generated CA&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># generate and sign certificate&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s">&amp;lt;&amp;lt;EOF &amp;gt;extfile.txt
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">[ req ]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">req_extensions = req_ext
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">distinguished_name = req_distinguished_name
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">[req_distinguished_name]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">[ req_ext ]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">basicConstraints = CA:FALSE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">keyUsage = nonRepudiation, digitalSignature, keyEncipherment
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">subjectAltName = @alt_names
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">[alt_names]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">DNS.1 = $DOMAIN
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">DNS.2 = *.$DOMAIN
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># issue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">openssl ecparam -genkey -name prime256v1 &lt;span class="p">|&lt;/span> openssl ec -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span> &lt;span class="c1"># key&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">openssl req -new -key &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span> -config extfile.txt -subj &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="k">$(&lt;/span>subj &lt;span class="nv">$DOMAIN&lt;/span>&lt;span class="k">)&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="c1"># csr&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">openssl x509 -req &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -days &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$DAYS&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -in &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -CA &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.crt&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -CAkey &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_KEY&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -CAcreateserial &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -passin &lt;span class="s2">&amp;#34;pass:&lt;/span>&lt;span class="nv">$CA_PASSWORD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -extensions req_ext -extfile extfile.txt &lt;span class="c1"># csr + rootCA.crt = crt &lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rm -f &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.csr&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># convert DER -&amp;gt; PEM&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">openssl x509 -inform PEM -outform DER -in &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.crt&amp;#34;&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.der.crt&amp;#34;&lt;/span> &lt;span class="c1"># convert&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># convert PEM -&amp;gt; pkcs12&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">openssl pkcs12 -export &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -inkey &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.key&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -in &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.crt&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -out &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.pfx&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -password &lt;span class="s2">&amp;#34;pass:&lt;/span>&lt;span class="nv">$JKS_PASSWORD&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> -name &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$DOMAIN&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># create fullchain&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cat &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.crt&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &amp;gt; &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.full&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># verify&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">openssl verify -CAfile &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$CA_CRT&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">DOMAIN&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.crt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># info&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">log_info &lt;span class="s2">&amp;#34;Generated &lt;/span>&lt;span class="nv">$DOMAIN&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">done&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">rm -f extfile.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title/><link>https://vlasov.pro/en/p/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://vlasov.pro/en/p/</guid><description>&lt;h1 id="how-to-set-up-commit-and-tag-signing-in-git-using-gpg-and-ssh">How to Set Up Commit and Tag Signing in Git Using GPG and SSH &lt;a href="#how-to-set-up-commit-and-tag-signing-in-git-using-gpg-and-ssh">¶&lt;/a>&lt;/h1>
&lt;p>Signing commits and tags ensures that the changes are genuinely made by you. This is an essential step for project security and transparency. In this article, I will guide you through configuring automatic commit and tag signing in Git and show you how to separate configurations for personal and work projects.&lt;/p>
&lt;hr>
&lt;h2 id="main-git-configuration-file">Main Git Configuration File &lt;a href="#main-git-configuration-file">¶&lt;/a>&lt;/h2>
&lt;p>The main configuration file, &lt;code>~/.gitconfig&lt;/code>, defines general settings for all repositories. Here, you can specify your username, enable mandatory signing for commits and tags, and include additional configuration files for specific project groups.&lt;/p>
&lt;p>Here’s an example of a basic configuration file:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ~/.gitconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[user]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">John Smith&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[commit]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">gpgsign&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[tag]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">gpgSign&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[includeIf &amp;#34;gitdir:~/Personal/&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">~/Personal/.gitconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[includeIf &amp;#34;gitdir:~/Work/&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">~/Work/.gitconfig&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>With the &lt;code>[includeIf]&lt;/code> directives, Git will automatically apply the appropriate configuration based on the repository’s location.&lt;/p>
&lt;hr>
&lt;h2 id="configuration-for-personal-projects">Configuration for Personal Projects &lt;a href="#configuration-for-personal-projects">¶&lt;/a>&lt;/h2>
&lt;p>If you use SSH for signing in personal projects, the setup looks like this. In the configuration file &lt;code>~/Personal/.gitconfig&lt;/code>, you specify your personal email, set the signing format to &lt;code>ssh&lt;/code>, and provide a command that allows Git to find the appropriate key in the &lt;code>ssh-agent&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ~/Personal/.gitconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[user]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">email&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">personal@a.com&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[gpg]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">format&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">ssh&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[gpg &amp;#34;ssh&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">defaultKeyCommand&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">sh -c &amp;#34;ssh-add -L | awk &amp;#39;$3~/^personal@a\\.com$/{print \&amp;#34;key::\&amp;#34;$0}&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This configuration ensures that Git uses the key already added to the &lt;code>ssh-agent&lt;/code>, simplifying the signing process.&lt;/p>
&lt;hr>
&lt;h2 id="configuration-for-work-projects">Configuration for Work Projects &lt;a href="#configuration-for-work-projects">¶&lt;/a>&lt;/h2>
&lt;p>For work projects, GPG is often used. In the configuration file &lt;code>~/Work/.gitconfig&lt;/code>, you define your work email and the GPG key ID to be used for signing.&lt;/p>
&lt;p>If you don’t have a GPG key yet, you can create one using the following command:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">gpg --full-gen-key
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>To get the key ID, run:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">gpg --list-keys
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Here’s an example configuration file for work projects:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ~/Work/.gitconfig&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[user]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">email&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">company@b.com
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> signingKey = 35C1A64CD7FC0AB6EB66756B2445463C3234ECE1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[gpg]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">format&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">openpgp&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This configuration ensures that commits and tags in work repositories are signed using the specified GPG key.&lt;/p>
&lt;hr>
&lt;p>With these configurations, Git will automatically use the appropriate signing key depending on the repository. This helps maintain order and transparency when working with commits and tags.&lt;/p></description></item></channel></rss>