<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Issei.space</title><link>https://issei.space/</link><description>Recent content on Issei.space</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Wed, 24 Jun 2026 08:17:41 +0200</lastBuildDate><atom:link href="https://issei.space/index.xml" rel="self" type="application/rss+xml"/><item><title>1Password Linux: fatal: cannot exec '/opt/1Password/op-ssh-sign': No such file or directory</title><link>https://issei.space/blog/1password-linux-unable-to-git-sign/</link><pubDate>Wed, 24 Jun 2026 08:17:41 +0200</pubDate><guid>https://issei.space/blog/1password-linux-unable-to-git-sign/</guid><description>&lt;p&gt;I&amp;rsquo;m using 1Password to store my SSH keys - recently i noticed that the git sign process started to fail&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;❯ git commit -m &amp;#34;very important change&amp;#34;
fatal: cannot exec &amp;#39;/opt/1Password/op-ssh-sign&amp;#39;: No such file or directory
error:
fatal: failed to write commit object
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It turns out, that the op-ssh-sign has been moved from &lt;code&gt;/opt/1Password/op-ssh-sign&lt;/code&gt; to &lt;code&gt;/usr/share/1password/op-ssh-sign&lt;/code&gt;. After editing the &lt;code&gt;~/.gitconfig&lt;/code&gt; to use the new path, it started working again. What&amp;rsquo;s weird, is that in the &amp;ldquo;Configure Commit Signing&amp;hellip;&amp;rdquo; popup, the automatic setup still uses the &lt;code&gt;/opt&lt;/code&gt; directory. Not sure on which version precisely i got broken, but it is still broken on &lt;code&gt;1Password for Linux 8.12.24 (81224034)&lt;/code&gt;&lt;/p&gt;</description><content>&lt;p&gt;I&amp;rsquo;m using 1Password to store my SSH keys - recently i noticed that the git sign process started to fail&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;❯ git commit -m &amp;#34;very important change&amp;#34;
fatal: cannot exec &amp;#39;/opt/1Password/op-ssh-sign&amp;#39;: No such file or directory
error:
fatal: failed to write commit object
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It turns out, that the op-ssh-sign has been moved from &lt;code&gt;/opt/1Password/op-ssh-sign&lt;/code&gt; to &lt;code&gt;/usr/share/1password/op-ssh-sign&lt;/code&gt;. After editing the &lt;code&gt;~/.gitconfig&lt;/code&gt; to use the new path, it started working again. What&amp;rsquo;s weird, is that in the &amp;ldquo;Configure Commit Signing&amp;hellip;&amp;rdquo; popup, the automatic setup still uses the &lt;code&gt;/opt&lt;/code&gt; directory. Not sure on which version precisely i got broken, but it is still broken on &lt;code&gt;1Password for Linux 8.12.24 (81224034)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2026-06-24-1password/git-signing-popup_hu_9b04a168af0816e9.webp"
alt="Screenshot showing 1Password window, with opened &amp;lsquo;configure commit signing&amp;rsquo; popup, showcasing that the automatic default config is still using the old /opt path instead of the new one"
loading="lazy"
/&gt;
&lt;/p&gt;</content></item><item><title>High kworker CPU usage on idle linux system</title><link>https://issei.space/blog/kworker-pve-high-cpu-usage/</link><pubDate>Sun, 22 Mar 2026 18:46:48 +0100</pubDate><guid>https://issei.space/blog/kworker-pve-high-cpu-usage/</guid><description>&lt;p&gt;I&amp;rsquo;m running an HP Z230 SFF as my little homeserver for the last 5 years. It is not the most powerful, but it was energy-efficient enough, and was doing great for the things I&amp;rsquo;m running on it, so I kept using it. Recently I noticed that despite being idle, the power usage was higher than normal. Normally the power usage with idle workload oscillates around 25-30W, but it was at nearly 60W.
On Proxmox I didn&amp;rsquo;t see that any VM was using much CPU, so I dug deeper. In &lt;code&gt;top&lt;/code&gt; on the host, I noticed that only one core was maxed out, and the process &lt;code&gt;kworker/1:3+usb_hub_wq&lt;/code&gt; was using a lot of CPU.&lt;/p&gt;</description><content>&lt;p&gt;I&amp;rsquo;m running an HP Z230 SFF as my little homeserver for the last 5 years. It is not the most powerful, but it was energy-efficient enough, and was doing great for the things I&amp;rsquo;m running on it, so I kept using it. Recently I noticed that despite being idle, the power usage was higher than normal. Normally the power usage with idle workload oscillates around 25-30W, but it was at nearly 60W.
On Proxmox I didn&amp;rsquo;t see that any VM was using much CPU, so I dug deeper. In &lt;code&gt;top&lt;/code&gt; on the host, I noticed that only one core was maxed out, and the process &lt;code&gt;kworker/1:3+usb_hub_wq&lt;/code&gt; was using a lot of CPU.&lt;/p&gt;
&lt;p&gt;After some research on the internet, I first found a suggestion to disable some interrupts:
&lt;a href="https://unix.stackexchange.com/questions/588018/kworker-thread-kacpid-notify-kacpid-hogging-60-70-of-cpu"&gt;https://unix.stackexchange.com/questions/588018/kworker-thread-kacpid-notify-kacpid-hogging-60-70-of-cpu&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But that didn&amp;rsquo;t fix the issue for me. I didn&amp;rsquo;t see any high values in the list, and even after disabling the highest one (which had a value of about &amp;ldquo;120&amp;rdquo;), it didn&amp;rsquo;t change anything.&lt;/p&gt;
&lt;p&gt;The thing that fixed it for me was unloading the &lt;code&gt;xhci_pci&lt;/code&gt; driver using &lt;code&gt;modprobe&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ modprobe -r xhci_pci
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ dmesg
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; 183.933736&lt;span style="color:#f92672"&gt;]&lt;/span&gt; xhci_hcd 0000:00:14.0: remove, state &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; 183.933749&lt;span style="color:#f92672"&gt;]&lt;/span&gt; usb usb2: USB disconnect, device number &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; 183.934564&lt;span style="color:#f92672"&gt;]&lt;/span&gt; xhci_hcd 0000:00:14.0: USB bus &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; deregistered
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; 183.934586&lt;span style="color:#f92672"&gt;]&lt;/span&gt; xhci_hcd 0000:00:14.0: remove, state &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; 183.934590&lt;span style="color:#f92672"&gt;]&lt;/span&gt; usb usb1: USB disconnect, device number &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; 183.939166&lt;span style="color:#f92672"&gt;]&lt;/span&gt; xhci_hcd 0000:00:14.0: USB bus &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; deregistered
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After that, I took a look at &lt;code&gt;top&lt;/code&gt; and I didn&amp;rsquo;t see the &lt;code&gt;kworker&lt;/code&gt; again in the list of top CPU usage processes, so I added the driver to the blacklist, as I&amp;rsquo;m not using USB 3.0 devices on this host.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;blacklist xhci_pci&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; /etc/modprobe.d/pve-blacklist.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Please note that this behaviour is probably caused by some kind of hardware failure. As this is my test/home server, I&amp;rsquo;m accepting that fact, but in today&amp;rsquo;s market, it is pretty hard to find a good deal for a replacement, newer homeserver due to the memory pricing, so good ol&amp;rsquo; Haswell with DDR3 will need to live for even longer.&lt;/p&gt;
&lt;p&gt;Ref: &lt;a href="https://community.frame.work/t/tracking-kworker-stuck-at-near-100-cpu-usage-with-ubuntu-22-04/23053/52"&gt;https://community.frame.work/t/tracking-kworker-stuck-at-near-100-cpu-usage-with-ubuntu-22-04/23053/52&lt;/a&gt;&lt;/p&gt;</content></item><item><title>Backblaze B2 Operator for Kubernetes</title><link>https://issei.space/blog/backblaze-b2-kubernetes-operator/</link><pubDate>Sat, 27 Dec 2025 14:32:39 +0100</pubDate><guid>https://issei.space/blog/backblaze-b2-kubernetes-operator/</guid><description>&lt;p&gt;As you might guess by some of my older entries, I&amp;rsquo;m a fan of Backblaze B2 object storage.&lt;/p&gt;
&lt;p&gt;Some time ago I created my first Kubernetes operator using Operator-SDK in Golang. Before that, I had some experience with python pykube/kopf, but these libraries are pretty much abandoned, so I decided to take a look at the &amp;ldquo;first party&amp;rdquo; solution.&lt;/p&gt;
&lt;p&gt;I wanted to create Backblaze B2 buckets and keys in the cluster, but I noticed that at the time, there weren&amp;rsquo;t any operators available, so I created my own. It supports creating buckets and keys with ACL. I know - what a diversity of feature from a storage operator&lt;/p&gt;</description><content>&lt;p&gt;As you might guess by some of my older entries, I&amp;rsquo;m a fan of Backblaze B2 object storage.&lt;/p&gt;
&lt;p&gt;Some time ago I created my first Kubernetes operator using Operator-SDK in Golang. Before that, I had some experience with python pykube/kopf, but these libraries are pretty much abandoned, so I decided to take a look at the &amp;ldquo;first party&amp;rdquo; solution.&lt;/p&gt;
&lt;p&gt;I wanted to create Backblaze B2 buckets and keys in the cluster, but I noticed that at the time, there weren&amp;rsquo;t any operators available, so I created my own. It supports creating buckets and keys with ACL. I know - what a diversity of feature from a storage operator&lt;/p&gt;
&lt;p&gt;The operator is open-source and can be found on &lt;a href="https://github.com/mgruszkiewicz/backblaze-operator"&gt;github.com/mgruszkiewicz/backblaze-operator&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="how-to-setup"&gt;How to setup?&lt;/h2&gt;
&lt;p&gt;Setup should be relatively straightforward, you need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;create application key in your b2 account with correct permissions or use master application key&lt;/li&gt;
&lt;li&gt;helm&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="creating-keys"&gt;Creating keys&lt;/h2&gt;
&lt;p&gt;Creating application keys with specific capabilities/permissions is a bit tricky on Backblaze B2, as it is not possible from the web interface - you need to use the B2 CLI to do that.&lt;/p&gt;
&lt;p&gt;First, you need to install the b2 cli, that will depend on the platform you are using.
Refer to the &lt;a href="https://www.backblaze.com/docs/cloud-storage-command-line-tools"&gt;official Backblaze documentation&lt;/a&gt; on how to do that&lt;/p&gt;
&lt;p&gt;then authenticate to your account&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;b2 account authorize
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and finally, we can create a key for operator&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;b2 key create operator-blog writeKeys,deleteKeys,listBuckets,listAllBucketNames,readBuckets,writeBuckets,deleteBuckets
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output will contain two values, separated by space - the first one will be the application id, the second application key&lt;/p&gt;
&lt;h2 id="setup-operator-using-helm"&gt;Setup operator using Helm&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm upgrade --install backblaze-operator backblaze-operator &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set credentials.b2ApplicationId&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;your-application-id&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set credentials.b2ApplicationKey&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;your-application-key&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --set credentials.b2Region&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;us-west-004&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --namespace backblaze-operator --create-namespace &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --repo https://mgruszkiewicz.github.io/helm-charts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="setup-operator-in-fluxcd-repository"&gt;Setup operator in FluxCD repository&lt;/h2&gt;
&lt;p&gt;If you are using GitOps (and you probably should!) to manage your cluster, you can also easily install the operator using FluxCD HelmReleases. As we will need to pass the Backblaze keys, you will need a way to pass securely the keys to the cluster. In my case I prefer to store the secrets in Vault, and I passed them out to cluster via ExternalSecrets, but the method doesn&amp;rsquo;t matter - you can use variable substitution or create a secret manually and reference it in values.&lt;/p&gt;
&lt;p&gt;First, create the secret with your Backblaze credentials:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl create secret generic backblaze-credentials &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --from-literal&lt;span style="color:#f92672"&gt;=&lt;/span&gt;B2_APPLICATION_ID&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;your-application-id&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --from-literal&lt;span style="color:#f92672"&gt;=&lt;/span&gt;B2_APPLICATION_KEY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;your-application-key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --from-literal&lt;span style="color:#f92672"&gt;=&lt;/span&gt;B2_REGION&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;your-b2-region&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --namespace backblaze-operator
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then apply the following FluxCD configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;source.toolkit.fluxcd.io/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;HelmRepository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;isseispace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;flux-system&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;interval&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;url&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;https://mgruszkiewicz.github.io/helm-charts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;helm.toolkit.fluxcd.io/v2beta1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;HelmRelease&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;backblaze-operator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;backblaze-operator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;interval&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;5m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;chart&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;chart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;backblaze-operator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;sourceRef&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;HelmRepository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;isseispace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;flux-system&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;values&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;credentials&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;secret&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;useSecret&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;backblaze-credential&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="creating-an-example-bucket"&gt;Creating an example bucket&lt;/h1&gt;
&lt;p&gt;After a successful operator installation, we can try to create a new Backblaze B2 bucket from our Kubernetes cluster using CRD.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;b2.issei.space/v1alpha2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-b2-bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;atProvider&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;acl&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;metadata.name&lt;/code&gt; will be used as a bucket name.&lt;br&gt;
Note - to create a bucket with &lt;code&gt;acl: public&lt;/code&gt;, you first need to add a payment method to your Backblaze account, otherwise the creation process will fail.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s check the status:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;❯ kubectl describe buckets.b2.issei.space my-b2-bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;Name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-b2-bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;Namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;Labels&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;&amp;lt;none&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;Annotations&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;&amp;lt;none&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;API Version&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;b2.issei.space/v1alpha2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;Kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;Metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;Creation Timestamp&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;2025-12-27T15:55:11Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;Finalizers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;bucket.b2.issei.space/finalizer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;Generation&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;Resource Version&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;762&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;UID&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3ed908df-373a-452a-825c-b6215ec9d2a0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;Spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;At Provider&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;Acl&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;Status&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;At Provider&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;Acl&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;Reconciled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;Events&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;Type Reason Age From Message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ---- ------ ---- ---- -------
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;Normal BucketCreated 2m42s bucket-controller Successfully created bucket my-b2-bucket with ACL private&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s create a new application key that has only access to our new bucket&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;b2.issei.space/v1alpha2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-b2-key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;atProvider&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;bucketName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-b2-bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;capabilities&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;deleteFiles&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;listAllBucketNames&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;listBuckets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;listFiles&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;readBucketEncryption&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;readBucketReplications&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;readBuckets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;readFiles&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;shareFiles&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;writeBucketEncryption&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;writeBucketReplications&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;writeFiles&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;writeConnectionSecretToRef&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;new-key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and let&amp;rsquo;s check the status:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;❯ kubectl describe secret new-key
Name: new-key
Namespace: default
Labels: &amp;lt;none&amp;gt;
Annotations: &amp;lt;none&amp;gt;
Type: Opaque
Data
====
AWS_ACCESS_KEY_ID: 25 bytes
AWS_SECRET_ACCESS_KEY: 31 bytes
bucketName: 21 bytes
endpoint: 30 bytes
keyName: 9 bytes
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you can connect your application to new Backblaze B2 object storage bucket!&lt;/p&gt;
&lt;p&gt;For compatibility with apps that expect S3 object storage, the secret is created with AWS S3 named keys.&lt;/p&gt;</content></item><item><title>Exposing service from Runpod.io (and others) to netbird network</title><link>https://issei.space/blog/expose-service-to-netbird-from-docker/</link><pubDate>Sun, 05 Oct 2025 18:31:27 +0200</pubDate><guid>https://issei.space/blog/expose-service-to-netbird-from-docker/</guid><description>&lt;p&gt;Sometimes you need a better GPU for testing - service offerings like runpod.io or salad cloud is cool, for setup a quick docker container for testing, however currently both runpod and salad are missing the ability to setup some kind of sidecar, which would allow user to setup for example a vpn connection to internal network, so you can access the external container from your secure network and not just directly throught the internet.&lt;/p&gt;</description><content>&lt;p&gt;Sometimes you need a better GPU for testing - service offerings like runpod.io or salad cloud is cool, for setup a quick docker container for testing, however currently both runpod and salad are missing the ability to setup some kind of sidecar, which would allow user to setup for example a vpn connection to internal network, so you can access the external container from your secure network and not just directly throught the internet.&lt;/p&gt;
&lt;p&gt;Both services are offering a public ingress that will automatically route traffic to your containers, however, at least in the case of salad.com, you can only enable authentication by salad API key, which is pretty clunky while working with stuff like comfyui.&lt;/p&gt;
&lt;p&gt;As a workaround to missing sidecar feature, you can do something, that is disgureged by pretty much anyone - run multiple processes in one container!
This solution is not perfect, and if you can, i would stick to sidecars, however, sometimes you do what you need to do.&lt;/p&gt;
&lt;p&gt;In the beginning i mentioned two services - runpod.io and salad.com, however, that method should work everywhere, that you can run your own docker container and define some environmental variables.&lt;/p&gt;
&lt;h2 id="okay-so-how-to-do-it"&gt;Okay, so how to do it?&lt;/h2&gt;
&lt;p&gt;The modification needed for docker image are not that big. We will be using &lt;code&gt;userspace&lt;/code&gt; implementation in the netbird, instead of default kernel one.
As a example, i will be using &lt;code&gt;nginx&lt;/code&gt; image, however you can use any other image as a base - you just need to define the correct startup command in the &lt;code&gt;start.sh&lt;/code&gt; script.
&lt;div class="collapsable-code"&gt;
&lt;input id="827913546" type="checkbox" /&gt;
&lt;label for="827913546"&gt;
&lt;span class="collapsable-code__language"&gt;docker&lt;/span&gt;
&lt;span class="collapsable-code__title"&gt;Dockerfile&lt;/span&gt;
&lt;span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"&gt;&lt;/span&gt;
&lt;/label&gt;
&lt;pre class="language-docker" &gt;&lt;code&gt;
FROM nginx:latest
# Netbird envs
ENV NB_FOREGROUND_MODE=true
ENV NB_USE_NETSTACK_MODE=true
ENV NB_ENABLE_NETSTACK_LOCAL_FORWARDING=true
ENV NB_DAEMON_ADDR=unix://netbird.sock
# Setup netbird
ADD https://github.com/netbirdio/netbird/releases/download/v0.59.2/netbird_0.59.2_linux_amd64.tar.gz /tmp/netbird.tar.gz
RUN cd /tmp/ &amp;amp;&amp;amp; tar -xvzf /tmp/netbird.tar.gz &amp;amp;&amp;amp; mv netbird /bin/ &amp;amp;&amp;amp; chmod &amp;#43;x /bin/netbird
EXPOSE 80
WORKDIR /app
COPY start.sh .
RUN chmod &amp;#43;x /app/start.sh
CMD /app/start.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;div class="collapsable-code"&gt;
&lt;input id="524138679" type="checkbox" /&gt;
&lt;label for="524138679"&gt;
&lt;span class="collapsable-code__language"&gt;bash&lt;/span&gt;
&lt;span class="collapsable-code__title"&gt;start.sh&lt;/span&gt;
&lt;span class="collapsable-code__toggle" data-label-expand="△" data-label-collapse="▽"&gt;&lt;/span&gt;
&lt;/label&gt;
&lt;pre class="language-bash" &gt;&lt;code&gt;
#!/bin/bash
netbird up --setup-key=$NB_SETUP_KEY --extra-dns-labels $NB_EXTRA_DNS_LABEL &amp;amp;
nginx -g &amp;#34;daemon off;&amp;#34;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id="whats-going-on-here"&gt;What&amp;rsquo;s going on here?&lt;/h2&gt;
&lt;p&gt;The trick is pretty simple - we&amp;rsquo;re running netbird in userspace mode, which doesn&amp;rsquo;t require kernel modules or special privileges. The &lt;code&gt;NB_USE_NETSTACK_MODE&lt;/code&gt; flag tells netbird to use userspace networking instead of trying to create kernel interfaces, which is perfect for restricted container environments.&lt;/p&gt;
&lt;p&gt;In the startup script, we launch netbird in the background with the &lt;code&gt;&amp;amp;&lt;/code&gt; operator, then start nginx in foreground mode. The netbird process will connect to your netbird network using the setup key you provide, and from that point your container is accessible from other machines in your netbird network.&lt;/p&gt;
&lt;h2 id="setting-it-up"&gt;Setting it up&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ll need to set two environment variables when launching your container:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NB_SETUP_KEY&lt;/code&gt; - your netbird setup key (get it from your netbird dashboard)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NB_EXTRA_DNS_LABEL&lt;/code&gt; - optional, but useful for giving your container a nice hostname in the network&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For runpod, you can set these in the environment variables section when creating your pod. For salad, add them in the container configuration.&lt;/p&gt;
&lt;p&gt;Once the container starts, give it a few seconds for netbird to establish the connection, then you should be able to access your service directly from any other machine in your netbird network - no public internet exposure needed!&lt;/p&gt;
&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;Is this the cleanest solution? Nope. Does it work? Absolutely. Sometimes you just need to get stuff done, and this workaround lets you securely access your GPU workloads without exposing them to the entire internet or dealing with API key authentication in places where it doesn&amp;rsquo;t make sense.&lt;/p&gt;
&lt;p&gt;Just remember - if the platform adds proper sidecar support in the future, migrate to that. But until then, this gets the job done.&lt;/p&gt;</content></item><item><title>ChatGPT on feature phone</title><link>https://issei.space/blog/chatgpt-on-a-featurephone/</link><pubDate>Fri, 12 Sep 2025 11:08:01 +0200</pubDate><guid>https://issei.space/blog/chatgpt-on-a-featurephone/</guid><description>&lt;p&gt;Last weekend, I was wondering, how hard it would be to create a app for a &lt;em&gt;featurephone&lt;/em&gt;/&lt;em&gt;dumbphone&lt;/em&gt;/&lt;em&gt;brick&lt;/em&gt; however you want to name it.
I never made any application for pre-android era phones and did not have the opportunity. All i know that it can be done in Java. I never actually programmed in java either, but I decided to give it a shot.&lt;/p&gt;
&lt;h2 id="setting-up-the-ide"&gt;Setting up the IDE&lt;/h2&gt;
&lt;p&gt;I thought that this would take much longer, and I will probably need to create a VM with something like windows xp, however i found a easy to follow tutorial with working download links that helped me setup the environment in less than 30 minutes. I was suprised that it worked without issue even on windows 10.
If you also want to setup J2ME environment &lt;a href="https://youtu.be/QI5v6Wa6hvw"&gt;here is the link to youtube&lt;/a&gt; (author disallows playback on external sites :/)&lt;/p&gt;</description><content>&lt;p&gt;Last weekend, I was wondering, how hard it would be to create a app for a &lt;em&gt;featurephone&lt;/em&gt;/&lt;em&gt;dumbphone&lt;/em&gt;/&lt;em&gt;brick&lt;/em&gt; however you want to name it.
I never made any application for pre-android era phones and did not have the opportunity. All i know that it can be done in Java. I never actually programmed in java either, but I decided to give it a shot.&lt;/p&gt;
&lt;h2 id="setting-up-the-ide"&gt;Setting up the IDE&lt;/h2&gt;
&lt;p&gt;I thought that this would take much longer, and I will probably need to create a VM with something like windows xp, however i found a easy to follow tutorial with working download links that helped me setup the environment in less than 30 minutes. I was suprised that it worked without issue even on windows 10.
If you also want to setup J2ME environment &lt;a href="https://youtu.be/QI5v6Wa6hvw"&gt;here is the link to youtube&lt;/a&gt; (author disallows playback on external sites :/)&lt;/p&gt;
&lt;p&gt;Not sure if all the software in that pack is clean, so for safety reasons i decided to run a VM anyway.
Is there a way to setup a environemnt on linux? Probably yes, but personally i just wanted to get going and don&amp;rsquo;t tinker with 32bit libraries.
While researching i found this guide - &lt;a href="https://github.com/ading2210/setup-j2me-sdk"&gt;https://github.com/ading2210/setup-j2me-sdk&lt;/a&gt; - maybe it can be useful for someone&lt;/p&gt;
&lt;h2 id="now-what"&gt;Now what?&lt;/h2&gt;
&lt;p&gt;Okay, so i had a idea that sounded funny to me - what if we could interact with &lt;strong&gt;AI&lt;/strong&gt; on that brick? Nowadays you have phones and computers certified &lt;em&gt;(ekgh copilot plus pc egkh)&lt;/em&gt; to run &lt;strong&gt;AI&lt;/strong&gt;, so?
Sorry about the clickbait, we actually won&amp;rsquo;t be inferencing AI model on the device itself, but just using the API. I don&amp;rsquo;t even want to attempt something like that - i wasn&amp;rsquo;t even able to find a chipset name for the nokia phones i have in my drawer.&lt;/p&gt;
&lt;p&gt;As i never created a app in J2ME, i did some checkup online - it seems like i can just do HTTP request no problem, so let&amp;rsquo;s try to cook something!&lt;/p&gt;
&lt;p&gt;For now, i won&amp;rsquo;t be building fully fledged GPT chat, just a single message and response.&lt;/p&gt;
&lt;h2 id="issue-with-networking"&gt;Issue with networking&lt;/h2&gt;
&lt;p&gt;as you might expect, the old bricks phone with OS from nearly 20 years ago, will not support modern SSL/TLS protocols - so for the quick demo, i just skipped encryption, as i won&amp;rsquo;t be transmitting any sensitive informations and will tear it down soon after. I&amp;rsquo;m sure it is possible to establish a TLS connection, but i just didn&amp;rsquo;t bother with that.&lt;/p&gt;
&lt;p&gt;Instead of crafting my own proxy, i decided to utilize &lt;a href="https://github.com/BerriAI/litellm"&gt;LiteLLM&lt;/a&gt; as a gateway - it allows me to connect pretty much any LLM with openai compatible api, create a virtual keys, log requests and responses from underlaying llm models.&lt;/p&gt;
&lt;p&gt;Also LiteLLM was helpful for debugging, as i can enable logging of each request and easily validate why it might failed&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2025-09-12-nokia/litellmresponse_hu_e9580fad24eaa153.webp"
alt="screenshot showing litellm dashboard - showing request body from nokia and response from chatgpt API"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;My next issue was that - of course most of this old phones don&amp;rsquo;t have WiFi - and i needed to use cellular connection - in Poland the 2G/Edge is still available so that was not a issue, one prepaid sim card later i had internet connection on my phone.&lt;/p&gt;
&lt;h2 id="building-the-application"&gt;Building the application&lt;/h2&gt;
&lt;p&gt;Overall, as i mentioned before, i want to keep it as barebones as possible, so we will have just a simple form, and will be crafting json by combining the strings and escape the characters manually. Brutal, but we just want to have some fun :)&lt;/p&gt;
&lt;p&gt;I also asked Claude Sonnet 4 about some of this things, and was suprised that it returned me a non-halucinated responses and things that actually worked.&lt;/p&gt;
&lt;p&gt;In the end, i was suprised how easy it was to build a simple form based app in J2ME. I&amp;rsquo;m sure that back in the days, when open source and knowledge sharing on the internet was not that popular (e.g most of the things you will probably learn from a book)&lt;/p&gt;
&lt;p&gt;I did published the code in github repository - &lt;a href="https://github.com/mgruszkiewicz/j2me-tinyllm"&gt;https://github.com/mgruszkiewicz/j2me-tinyllm&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="demo-time"&gt;Demo time!&lt;/h2&gt;
&lt;video preload="metadata" controls&gt;
&lt;source
src="https://i.issei.space/3lv76V0D.mov"
type="video/mp4"
&gt;
Your browser does not support the video element.
&lt;/video&gt;
&lt;p&gt;I did speedup the typing part, it was a while since using T9 for daily texting 😅&lt;/p&gt;</content></item><item><title>FYI: My HTTP routes are not visible after migrating from regular docker to docker swarm!!</title><link>https://issei.space/blog/traefik-migrate-to-swarm/</link><pubDate>Sat, 21 Jun 2025 13:19:19 +0200</pubDate><guid>https://issei.space/blog/traefik-migrate-to-swarm/</guid><description>&lt;p&gt;Recently, during migration from one host to another, we had a idea to run the docker in swarm mode, so i future, when we needed more capacity, we could just add more nodes &amp;ldquo;without the complexity of kubernetes&amp;rdquo;. However, after starting the working docker-compose in the docker swarm mode, i noticed that the traefik was not picking up the labels from the containers and i couldn&amp;rsquo;t really figure out why.&lt;/p&gt;</description><content>&lt;p&gt;Recently, during migration from one host to another, we had a idea to run the docker in swarm mode, so i future, when we needed more capacity, we could just add more nodes &amp;ldquo;without the complexity of kubernetes&amp;rdquo;. However, after starting the working docker-compose in the docker swarm mode, i noticed that the traefik was not picking up the labels from the containers and i couldn&amp;rsquo;t really figure out why.&lt;/p&gt;
&lt;p&gt;The docker provider was replaced in config file with docker swarm, but it still wasn&amp;rsquo;t working.&lt;/p&gt;
&lt;p&gt;In the end, it was a pretty silly mistake on my part - in regular Docker, you add labels to the containers like that&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;services:
laravel:
image: mylaravelapp:latest
labels:
- &amp;#34;traefik.enable=true&amp;#34;
- &amp;#34;traefik.http.routers.laravel.rule=Host(`api.my-app.local`)&amp;#34;
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However, in Docker Swarm, labels are defined under &lt;code&gt;deploy&lt;/code&gt; section&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;services:
laravel:
image: mylaravelapp:latest
deploy:
placement:
constraints:
- node.role == manager
labels:
- &amp;#34;traefik.enable=true&amp;#34;
- &amp;#34;traefik.http.routers.laravel.rule=Host(`api.my-app.local`)&amp;#34;
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This took me too long to solve, I hope this blog entry will help someone out&lt;/p&gt;</content></item><item><title>Podłączenie własnego routera Netia ETTH</title><link>https://issei.space/blog/wlasny-router-netia-etth/</link><pubDate>Sun, 30 Mar 2025 13:38:41 +0200</pubDate><guid>https://issei.space/blog/wlasny-router-netia-etth/</guid><description>&lt;p&gt;Ostatnio zmieniłem operatora na Netie, ze względu na oferowanie internetu po ETTH, co pozwala wyeliminować totalnie urządzenie od dostawcy (a nie jak w przypadku np. UPC/Play po DOCSIS gdzie trzeba przestawić ich wspaniałego connectboxa w tryb bridge). Według instrukcji na internecie, również powinienem bez problemu otrzymać dane PPPoE.&lt;/p&gt;
&lt;p&gt;W moim przypadku (prawdopodobnie że jest to sieć &lt;code&gt;internetia&lt;/code&gt;?), w portalu netiaonline nie miałem podanych danych logowania PPPoE (tak jak to powinno być według instrukcji). Instalator również nie miał przy sobie na umowie tych danych, oraz po sprawdzeniu przez siebie w portalu, również nie mógł uzyskać tych danych. Po kontakcie na infolinii, jedyne co dostałem SMSem, to nieprzydatne dla mnie informacje co do ustawień ADSL, nadal bez danych do logowania.&lt;/p&gt;</description><content>&lt;p&gt;Ostatnio zmieniłem operatora na Netie, ze względu na oferowanie internetu po ETTH, co pozwala wyeliminować totalnie urządzenie od dostawcy (a nie jak w przypadku np. UPC/Play po DOCSIS gdzie trzeba przestawić ich wspaniałego connectboxa w tryb bridge). Według instrukcji na internecie, również powinienem bez problemu otrzymać dane PPPoE.&lt;/p&gt;
&lt;p&gt;W moim przypadku (prawdopodobnie że jest to sieć &lt;code&gt;internetia&lt;/code&gt;?), w portalu netiaonline nie miałem podanych danych logowania PPPoE (tak jak to powinno być według instrukcji). Instalator również nie miał przy sobie na umowie tych danych, oraz po sprawdzeniu przez siebie w portalu, również nie mógł uzyskać tych danych. Po kontakcie na infolinii, jedyne co dostałem SMSem, to nieprzydatne dla mnie informacje co do ustawień ADSL, nadal bez danych do logowania.&lt;/p&gt;
&lt;p&gt;Zastanawiało mnie że instalator, jedyne co zrobił po przyjściu, to podłączył router i już internet śmigał, co podpowiadało mi, że występuje jedynie filtrowanie po adresie MAC&lt;/p&gt;
&lt;p&gt;Metodą prób i błędów, doszedłem do tego, że aby podpiąć swój router do sieci ETTH w takim wypadku należy&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;sklonować adres MAC WANu z routera który dostaliśmy od operatora (w przypadku Huawei DN8245X6-10, znajduje się od na naklejce od spodu urządzenia)&lt;/li&gt;
&lt;li&gt;ustawić dane logowania PPPoE na WAN na:&lt;br&gt;
login: internet&lt;br&gt;
hasło: internet&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Po tej operacji, mój mikrotik dostał adres z DHCP - niestety przez ostatnie zmiany w sieci Netii, adres IP zza CGNAT zamist publiczny :(&lt;/p&gt;</content></item><item><title>Plesk default page instead of domain content after enabling Cloudflare proxy</title><link>https://issei.space/blog/cloudflare-proxy-default-plesk-page/</link><pubDate>Mon, 24 Feb 2025 17:13:47 +0100</pubDate><guid>https://issei.space/blog/cloudflare-proxy-default-plesk-page/</guid><description>&lt;p&gt;Recently i faced an interesting issue - after enabling Cloudflare proxy on domain hosted on Plesk (with Litespeed webserver, but that is not important), the domain returned Plesk default page instead of the domain, even through in domain logs i could see the requests.&lt;/p&gt;</description><content>&lt;p&gt;Recently i faced an interesting issue - after enabling Cloudflare proxy on domain hosted on Plesk (with Litespeed webserver, but that is not important), the domain returned Plesk default page instead of the domain, even through in domain logs i could see the requests.&lt;/p&gt;
&lt;p&gt;The solution was to enable &amp;ldquo;Full&amp;rdquo; SSL/TLS encryption in domain settings on Cloudflare. (on that domain at first it was set to &amp;lsquo;Flexible&amp;rsquo;)
&lt;img
src="https://issei.space/images/2025-02-24-cloudflare-proxy-plesk/Screenshot_20250224_171838_hu_bf254c3987253e98.webp"
alt="screenshot showing cloudflare dashboard, with &amp;lsquo;SSL/TLS Overview&amp;rsquo; section highlighted"
loading="lazy"
/&gt;
&lt;/p&gt;</content></item><item><title>How NOT to setup a RWX storage for Kubernetes cluster - SMB share on Mikrotik router</title><link>https://issei.space/blog/cursed-kubernetes-storage-experiment/</link><pubDate>Fri, 17 Jan 2025 21:53:32 +0100</pubDate><guid>https://issei.space/blog/cursed-kubernetes-storage-experiment/</guid><description>&lt;p&gt;Some time ago I decided to setup seperate homelab network in my house, as my previous &lt;em&gt;homelab&lt;/em&gt; server is more like a production homeserver which I don&amp;rsquo;t want to disrupt. It is not much, but I wanted to build something small, energy-efficient and from the parts I already had.&lt;/p&gt;
&lt;p&gt;But back to the topic that made me curious - I kinda needed some persistent storage for pods in lab. Then I remembered that the Mikrotik (RB951G-2HnD) router i&amp;rsquo;m using have a USB port and I saw an option in winbox to create SMB share. I think you can image where it is going.&lt;/p&gt;</description><content>&lt;p&gt;Some time ago I decided to setup seperate homelab network in my house, as my previous &lt;em&gt;homelab&lt;/em&gt; server is more like a production homeserver which I don&amp;rsquo;t want to disrupt. It is not much, but I wanted to build something small, energy-efficient and from the parts I already had.&lt;/p&gt;
&lt;p&gt;But back to the topic that made me curious - I kinda needed some persistent storage for pods in lab. Then I remembered that the Mikrotik (RB951G-2HnD) router i&amp;rsquo;m using have a USB port and I saw an option in winbox to create SMB share. I think you can image where it is going.&lt;/p&gt;
&lt;h1 id="setup-kubernetes-cluster"&gt;Setup Kubernetes cluster&lt;/h1&gt;
&lt;p&gt;For Kubernetes I will be using single-node Talos Linux. Didn&amp;rsquo;t even used Terraform or anything fancy to deploy it, just created a virtual machine on Proxmox with nocloud image.&lt;br&gt;
What is a Talos Linux? Talos Linux is a minimal, immutable linux distribution that is designed for Kubernetes - it doesn&amp;rsquo;t even have a SSH, and you do all the configuration over API.&lt;/p&gt;
&lt;p&gt;As this writeup is not a tutorial, I will skip setup of Talos Linux, but if i got you interested, take a look on &lt;a href="https://www.talos.dev/v1.9/introduction/getting-started/"&gt;Talos Linux Getting Started guide&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="setup-samba-share-on-mikrotik"&gt;Setup Samba share on Mikrotik&lt;/h1&gt;
&lt;p&gt;The cover picture was kinda a clickbait - for storage I will be using a slow microSD card, as at the time of writing, i didn&amp;rsquo;t had any USB-powered storage that was stable on my mikrotik (i guess 2,5&amp;quot; SSDs or HDDs might be a bit too power hungry, or my adapters were not compatible with ROS)&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not a RouterOS expert, additionally the forum.mikrotik.com at the time of writing was down&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2025-01-15-cursed-storage/Screenshot_20250115_221834_hu_57e26ee730ae1f52.webp"
alt="nginx error page showing 504 gateway timeout on mikrotik forum"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;but this &lt;em&gt;minor inconvenience&lt;/em&gt; will not prevent me from trying anyway.&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s see if our USB drive is detected&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[admin@MikroTik] &amp;gt; disk print
Flags: B - BLOCK-DEVICE; M, F - FORMATTING; p - PARTITION
Columns: SLOT, MODEL, SERIAL, INTERFACE, SIZE, FREE, FS
# SLOT MODEL SERIAL INTERFACE SIZE FREE FS
0 B usb1 MXTronics MXT USB Device 130818v01 USB 2.00 480Mbps 7 744 782 336
1 BMp usb1-part1 @1&amp;#39;048&amp;#39;576-7&amp;#39;744&amp;#39;782&amp;#39;336 7 743 733 760 7 518 978 048 ext4
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cool, there is my USB. I pre-formatted this card on my PC to ext4.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[admin@MikroTik] /ip/smb/shares&amp;gt; add name=kube directory=/usb1-part1
[admin@MikroTik] /ip/smb/shares&amp;gt; print
Flags: * - DEFAULT
Columns: NAME, DIRECTORY, MAX-SESSIONS
# NAME DIRECTORY MAX-SESSIONS
;;; default share
0 * pub /pub 10
1 kube /usb-part1 10
[admin@MikroTik] &amp;gt; /ip/smb/shares/enable numbers=1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Next i enabled the SMB and added user&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[admin@MikroTik] &amp;gt; /ip/smb/set enabled=yes
[admin@MikroTik] &amp;gt; /ip/smb/set interfaces=bridge
[admin@MikroTik] &amp;gt; /ip/smb/users/add name=&amp;#34;cluster&amp;#34; password=&amp;#34;pleasedontlook&amp;#34; read-only=no
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And i tried to connect to share from my desktop
&lt;img
src="https://issei.space/images/2025-01-15-cursed-storage/Screenshot_20250115_230537_hu_cfe530839ec720ab.webp"
alt=""
loading="lazy"
/&gt;
Success!&lt;/p&gt;
&lt;h1 id="setup-smb-csi-on-kubernetes"&gt;Setup SMB CSI on Kubernetes&lt;/h1&gt;
&lt;p&gt;As of CSI driver setup, I just installed the driver using kubectl, following &lt;a href="https://github.com/kubernetes-csi/csi-driver-smb/blob/master/docs/install-csi-driver-v1.16.0.md"&gt;official documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Created the StorageClass, statefulset and persistent volume for testing aaand&amp;hellip;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;csi-provisioner Mounting command: mount
csi-provisioner Mounting arguments: -t cifs -o dir_mode=0777,file_mode=0777,uid=1001,gid=1001,&amp;lt;masked&amp;gt; //192.168.200.1/kube /tmp/pvc-873655b4-c46b-4ef8-95db-7fa00a603be6
csi-provisioner Output: mount error(95): Operation not supported
csi-provisioner Refer to the mount.cifs(8) manual page (e.g. man mount.cifs) and kernel log messages (dmesg)
csi-provisioner &amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;oh. In Talos console i can see, more specific error&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kern: info: [2025-01-15T22:18:38.016242704Z]: CIFS: Attempting to mount \\192.168.200.1\kube
kern: err: [2025-01-15T22:18:38.026805704Z]: CIFS: VFS: \\192.168.200.1 Dialect not supported by server. Consider specifying vers=1.0 or vers=2.0 on mount for accessing
older servers
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So in smb StorageClass I added&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mountOptions:
- vers=2.0
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and look!&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;❯ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
storage-test-0 Bound pvc-873655b4-c46b-4ef8-95db-7fa00a603be6 2Gi RWO smb &amp;lt;unset&amp;gt; 18m
❯ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pvc-873655b4-c46b-4ef8-95db-7fa00a603be6 2Gi RWO Delete Bound default/storage-test-0 smb &amp;lt;unset&amp;gt; 2m41s
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;we got our PV on smb share provisioned!&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s enter the pod and do some basic tests. As i never used SMB CSI driver before, i was surprised that in &lt;code&gt;mount&lt;/code&gt; i can see the whole path to smb server, but that makes sense.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/ # mount
[...]
//192.168.200.1/kube/pvc-873655b4-c46b-4ef8-95db-7fa00a603be6 on /mnt type cifs (rw,relatime,vers=2.0,cache=strict,username=cluster,uid=1001,noforceuid,gid=1001,noforcegid,addr=192.168.200.1,file_mode=0777,dir_mode=0777,soft,nounix,serverino,mapposix,rsize=65536,wsize=65536,bsize=1048576,echo_interval=60,actimeo=1,closetimeo=1)
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="testing-out-our-monstrosity"&gt;Testing out our monstrosity&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s at first point out all the bottlenecks&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using MicroSD card (class 4) in USB adapter&lt;/li&gt;
&lt;li&gt;Using not that powerful routerboard&lt;/li&gt;
&lt;li&gt;Using CIFS (+on linux)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="random-read"&gt;Random Read&lt;/h2&gt;
&lt;p&gt;As the first test, i used &lt;code&gt;fio&lt;/code&gt; to perform random read&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/mnt # fio --name=randread --ioengine=libaio --iodepth=16 --rw=randread --bs=4k --direct=0 --size=100M --numjobs=4 --runtime=240 --group_reporting
randread: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=16
...
fio-3.38
Starting 4 processes
randread: Laying out IO file (1 file / 100MiB)
randread: Laying out IO file (1 file / 100MiB)
randread: Laying out IO file (1 file / 100MiB)
randread: Laying out IO file (1 file / 100MiB)
Jobs: 4 (f=4): [r(4)][100.0%][r=1893KiB/s][r=473 IOPS][eta 00m:00s]
randread: (groupid=0, jobs=4): err= 0: pid=26: Wed Jan 15 22:38:23 2025
read: IOPS=382, BW=1531KiB/s (1567kB/s)(359MiB/240006msec)
slat (usec): min=1159, max=600406, avg=8302.61, stdev=5622.61
clat (usec): min=8, max=905809, avg=124681.33, stdev=28987.76
lat (msec): min=6, max=912, avg=132.98, stdev=30.01
clat percentiles (msec):
| 1.00th=[ 106], 5.00th=[ 110], 10.00th=[ 112], 20.00th=[ 115],
| 30.00th=[ 117], 40.00th=[ 120], 50.00th=[ 122], 60.00th=[ 125],
| 70.00th=[ 128], 80.00th=[ 132], 90.00th=[ 138], 95.00th=[ 144],
| 99.00th=[ 159], 99.50th=[ 186], 99.90th=[ 684], 99.95th=[ 869],
| 99.99th=[ 894]
bw ( KiB/s): min= 56, max= 2408, per=100.00%, avg=1926.10, stdev=42.95, samples=1526
iops : min= 14, max= 602, avg=481.48, stdev=10.73, samples=1526
lat (usec) : 10=0.01%, 20=0.01%, 50=0.01%
lat (msec) : 10=0.01%, 20=0.01%, 50=0.02%, 100=0.10%, 250=99.59%
lat (msec) : 500=0.15%, 750=0.03%, 1000=0.09%
cpu : usr=0.13%, sys=0.65%, ctx=103998, majf=0, minf=102
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=99.9%, 32=0.0%, &amp;gt;=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, &amp;gt;=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.1%, 32=0.0%, 64=0.0%, &amp;gt;=64=0.0%
issued rwts: total=91847,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=16
Run status group 0 (all jobs):
READ: bw=1531KiB/s (1567kB/s), 1531KiB/s-1531KiB/s (1567kB/s-1567kB/s), io=359MiB (376MB), run=240006-240006msec
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;During the test, i saw around 60% of CPU utilization on router, so actually we might not be yet bottlenecked by router.
I&amp;rsquo;m actually quite suprised by the IOPS number&lt;/p&gt;
&lt;h2 id="random-readwrite"&gt;Random Read/Write&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/mnt # fio --randrepeat=1 --ioengine=libaio --gtod_reduce=1 --name=test --filename=random_read_write.fio --bs=4k --iodepth=64 --size=100M --readwrite=randrw --rwmixread=75
test: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=64
fio-3.38
Starting 1 process
Jobs: 1 (f=1): [f(1)][100.0%][eta 00m:00s]
test: (groupid=0, jobs=1): err= 0: pid=35: Wed Jan 15 22:43:11 2025
read: IOPS=180, BW=722KiB/s (739kB/s)(75.1MiB/106574msec)
bw ( KiB/s): min= 8, max= 2280, per=100.00%, avg=1046.69, stdev=887.64, samples=147
iops : min= 2, max= 570, avg=261.67, stdev=221.92, samples=147
write: IOPS=59, BW=239KiB/s (245kB/s)(24.9MiB/106574msec); 0 zone resets
bw ( KiB/s): min= 7, max= 824, per=100.00%, avg=407.48, stdev=284.06, samples=125
iops : min= 1, max= 206, avg=101.86, stdev=71.02, samples=125
cpu : usr=0.18%, sys=1.80%, ctx=21840, majf=0, minf=7
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, &amp;gt;=64=99.8%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, &amp;gt;=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, &amp;gt;=64=0.0%
issued rwts: total=19233,6367,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=64
Run status group 0 (all jobs):
READ: bw=722KiB/s (739kB/s), 722KiB/s-722KiB/s (739kB/s-739kB/s), io=75.1MiB (78.8MB), run=106574-106574msec
WRITE: bw=239KiB/s (245kB/s), 239KiB/s-239KiB/s (245kB/s-245kB/s), io=24.9MiB (26.1MB), run=106574-106574msec
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;yeah, not that surprising.&lt;/p&gt;
&lt;h2 id="real-world-application-test"&gt;Real-world application test?&lt;/h2&gt;
&lt;p&gt;I really wanted to make a benchmark using Postgres &lt;code&gt;pgbench&lt;/code&gt;, but Postgres will just hang on creating initial data, so i gave up. I think we already know how good it would perform with the current setup.&lt;/p&gt;
&lt;h2 id="end-words"&gt;End words&lt;/h2&gt;
&lt;p&gt;Actually, the setup process on both RouterOS and Kubernetes part was pretty painless and i didn&amp;rsquo;t even need to spend multiple hours on troubleshooting. Would I recommended that setup for file storage on PVC? Definitely not, but in a pinch, it might actually be useful as a shared storage for e.g. small configuration files that need R/W access (otherwise just use configmaps).&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://learningbytutz.blogspot.com/2019/12/adding-hard-drive-to-mikrotik_25.html"&gt;https://learningbytutz.blogspot.com/2019/12/adding-hard-drive-to-mikrotik_25.html&lt;/a&gt;
&lt;a href="https://dotlayer.com/how-to-use-fio-to-measure-disk-performance-in-linux/"&gt;https://dotlayer.com/how-to-use-fio-to-measure-disk-performance-in-linux/&lt;/a&gt;&lt;/p&gt;</content></item><item><title>MicroSD Card not visible on boot in linux</title><link>https://issei.space/blog/linux-chromebook-sd-card-on-boot/</link><pubDate>Fri, 23 Aug 2024 19:37:07 +0200</pubDate><guid>https://issei.space/blog/linux-chromebook-sd-card-on-boot/</guid><description>&lt;p&gt;I&amp;rsquo;m still using my chromebook with coreboot as a portable thinclient. Due to small built-in storage (only 16GB), i&amp;rsquo;m also using microSD card as a secondary storage for larger files and project. However i was strugeling with microSD card not being mounted at boot (waiting for device), my solution was to just physically eject and insert the card at boot, but it is pretty inconvient and is probably destroying the card pins.&lt;/p&gt;</description><content>&lt;p&gt;I&amp;rsquo;m still using my chromebook with coreboot as a portable thinclient. Due to small built-in storage (only 16GB), i&amp;rsquo;m also using microSD card as a secondary storage for larger files and project. However i was strugeling with microSD card not being mounted at boot (waiting for device), my solution was to just physically eject and insert the card at boot, but it is pretty inconvient and is probably destroying the card pins.&lt;/p&gt;
&lt;h2 id="the-solution"&gt;The solution&lt;/h2&gt;
&lt;p&gt;The solution was to create a systemd unit, that will run on boot before &lt;code&gt;local-fs.target&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# /etc/systemd/system/rescan-sd-card.service
[Unit]
Description=Remove and rescan MMC and PCI devices before mounting filesystems
DefaultDependencies=no
Before=local-fs.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c &amp;#39;echo 1 &amp;gt; /sys/class/mmc_host/mmc0/device/remove&amp;#39;
ExecStartPost=/bin/sh -c &amp;#39;echo 1 &amp;gt; /sys/class/pci_bus/0000:00/rescan&amp;#39;
RemainAfterExit=yes
[Install]
WantedBy=local-fs.target
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note: check if on your device the sdcard is also &lt;code&gt;mmc0&lt;/code&gt; - you can check it just by looking at &lt;code&gt;lsblk&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After creating the file at &lt;code&gt;/etc/systemd/system/rescan-sd-card.service&lt;/code&gt;, we need to enable it&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo systemctl enable rescan-sd-card.service
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now, on boot, the system will &amp;lsquo;remove&amp;rsquo; the mmc device, and rescan pci bus. That solved the issue and now my OS is booting without user intervention.&lt;/p&gt;
&lt;h2 id="reference"&gt;Reference&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://unix.stackexchange.com/questions/710377/microsd-card-not-found-at-boot-time-works-when-ejected-and-reinserted"&gt;https://unix.stackexchange.com/questions/710377/microsd-card-not-found-at-boot-time-works-when-ejected-and-reinserted&lt;/a&gt;&lt;/p&gt;</content></item><item><title>Solving issue with K3s System Upgrade exec /bin/upgrade.sh: exec format error</title><link>https://issei.space/blog/k3s-system-upgrade-issue/</link><pubDate>Fri, 02 Aug 2024 22:37:07 +0200</pubDate><guid>https://issei.space/blog/k3s-system-upgrade-issue/</guid><description>&lt;p&gt;Recently, I was trying to upgrade my toy K3s cluster using System Upgrade Plans operator. Applied example manifest, control-plane upgraded without issues, but pod for upgrading worker node was constantly restarting with error in logs &lt;code&gt;exec /bin/upgrade.sh: exec format error&lt;/code&gt;.
I would &lt;em&gt;kinda&lt;/em&gt; expect that issue on ARM system (although we come a long way in the last couple of years!), but my nodes are running on x86 CPU, so what is happening?&lt;/p&gt;</description><content>&lt;p&gt;Recently, I was trying to upgrade my toy K3s cluster using System Upgrade Plans operator. Applied example manifest, control-plane upgraded without issues, but pod for upgrading worker node was constantly restarting with error in logs &lt;code&gt;exec /bin/upgrade.sh: exec format error&lt;/code&gt;.
I would &lt;em&gt;kinda&lt;/em&gt; expect that issue on ARM system (although we come a long way in the last couple of years!), but my nodes are running on x86 CPU, so what is happening?&lt;/p&gt;
&lt;h1 id="my-troubleshooting-steps"&gt;My troubleshooting steps&lt;/h1&gt;
&lt;h3 id="try-to-define-image-version-with-correct-architecture"&gt;Try to define image version with correct architecture&lt;/h3&gt;
&lt;p&gt;Looking at image manifest, it is a multi-arch image, so maybe we are pulling the wrong image (or there was an error on release)? I noticed that rancher is pushing single-arch images as well, so just in case I tried to define image for specific architecture (amd64)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: plan-k3s-agent-upgrade
namespace: system-upgrade
spec:
[...]
upgrade:
image: rancher/k3s-upgrade:v1.30.3-k3s1-amd64
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The issue still persisted.&lt;/p&gt;
&lt;h3 id="restarting-node"&gt;Restarting node&lt;/h3&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2024-08-02-k3s/have-you-tried-turning-it-off-and-on-again_hu_991955ddb2377ffd.webp"
alt="have you tried turning it off and on again?"
loading="lazy"
/&gt;
&lt;br&gt;
In my case, my K3s nodes are virtual machines running on Proxmox hosts, so I just tried to reboot the VM, but it didn&amp;rsquo;t change anything.
I had a couple of PVC on that node which were using openebs-hostpath storage, so I didn&amp;rsquo;t want to go straight to nuclear option (but kinda recommended option) to just delete old node and replace it with brand new one.&lt;/p&gt;
&lt;h3 id="prune-images-on-node"&gt;Prune images on node&lt;/h3&gt;
&lt;p&gt;Maybe at first we pulled an image for a wrong architecture? Decided to prune unused images from that node, just to be safe.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;root@k3s-2:~# crictl rmi --prune
Deleted: docker.io/rancher/k3s-upgrade:v1.30.3-k3s1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And after restarting the system upgrade operator, the update proceeded without issues, and both of my nodes were happily on v1.30.3.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;➜ kg nodes
NAME STATUS ROLES AGE VERSION
k3s-1 Ready control-plane,etcd,master 138d v1.30.3+k3s1
k3s-2 Ready &amp;lt;none&amp;gt; 138d v1.30.3+k3s1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The fix in this case was pretty straight-forward, but maybe my troubleshooting steps will help someone in the future.&lt;/p&gt;</content></item><item><title>Własny zdecentralizowany Reddit, czyli jak stworzyć własną instancje Lemmy używając Dockera</title><link>https://issei.space/blog/instalacja-lemmy/</link><pubDate>Tue, 16 Apr 2024 20:00:00 +0200</pubDate><guid>https://issei.space/blog/instalacja-lemmy/</guid><description>&lt;p&gt;W tym wpisie postaram się przybliżyć proces instalacji własnej instancji Lemmiego oraz opisać czym jest ten cały fediverse.&lt;/p&gt;
&lt;h2 id="czym-jest-lemmy"&gt;Czym jest Lemmy?&lt;/h2&gt;
&lt;p&gt;Lemmy to zdecentralizowany odpowiednik Reddita/agregatora linków/forum. Istnieje podział na community, możliwość upvote/downvote oraz komentowania postów.&lt;/p&gt;
&lt;h2 id="czym-jest-ten-fediverse"&gt;Czym jest ten fediverse?&lt;/h2&gt;
&lt;p&gt;Fediverse (Fediwersum) to w skrócie zbiór zdecentralizowanych serwisów społecznościowych które korzystają z ustandaryzowanego protokołu do komunikacji z sobą. Działaniem bardzo przypomina email - czyli przykładowo posiadając skrzynkę pocztową na gmailu, możemy bez problemu pisać i odbierać maile od użytkownika o2 - tak samo jest tutaj, np. jeżeli ktoś opublikuje wpis na Lemmy, to inny użytkownik który np. używa Mastodon, zobaczy ten post oraz może z nim prowadzić interakcje.
Plusem fediverse jest to, że nie ma jednego centralnego serwera.&lt;/p&gt;</description><content>&lt;p&gt;W tym wpisie postaram się przybliżyć proces instalacji własnej instancji Lemmiego oraz opisać czym jest ten cały fediverse.&lt;/p&gt;
&lt;h2 id="czym-jest-lemmy"&gt;Czym jest Lemmy?&lt;/h2&gt;
&lt;p&gt;Lemmy to zdecentralizowany odpowiednik Reddita/agregatora linków/forum. Istnieje podział na community, możliwość upvote/downvote oraz komentowania postów.&lt;/p&gt;
&lt;h2 id="czym-jest-ten-fediverse"&gt;Czym jest ten fediverse?&lt;/h2&gt;
&lt;p&gt;Fediverse (Fediwersum) to w skrócie zbiór zdecentralizowanych serwisów społecznościowych które korzystają z ustandaryzowanego protokołu do komunikacji z sobą. Działaniem bardzo przypomina email - czyli przykładowo posiadając skrzynkę pocztową na gmailu, możemy bez problemu pisać i odbierać maile od użytkownika o2 - tak samo jest tutaj, np. jeżeli ktoś opublikuje wpis na Lemmy, to inny użytkownik który np. używa Mastodon, zobaczy ten post oraz może z nim prowadzić interakcje.
Plusem fediverse jest to, że nie ma jednego centralnego serwera.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;&lt;img
src="https://issei.space/images/2024-04-09-lemmy/Screenshot_20240409_234719_hu_a9df83bd8537fdd7.webp"
alt="screenshot showing the same post on lemmy.ml and sh.itjust.works"
loading="lazy"
/&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Ten sam post z community !linux@lemmy.ml widoczny na lemmy.ml oraz sh.itjust.works&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="po-co-tworzyć-własną-instancje"&gt;Po co tworzyć własną instancje?&lt;/h2&gt;
&lt;p&gt;Jeżeli chcesz tylko spróbować fediverse, nie musisz tworzyć własnej instancji - najlepiej znaleźć instancje która ma otwartą rejestrację lub poprosić o dostęp. Jest wiele list instancji np. &lt;a href="https://joinfediverse.wiki/Instances"&gt;joinfediverse.wiki&lt;/a&gt; lub &lt;a href="https://www.fediverse.to/"&gt;fediverse.to&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Tworzenie własnej instancji ma sens, jeżeli:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;chcesz prowadzić większe community i mieć nad nim pełną kontrolę&lt;/li&gt;
&lt;li&gt;chcesz mieć niezależną, prywatną instancje, za którą odpowiadasz tylko Ty&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="co-jest-potrzebne-do-stworzenia-własnej-instancji"&gt;Co jest potrzebne do stworzenia własnej instancji?&lt;/h2&gt;
&lt;p&gt;Do stworzenia własnej instancji nie potrzeba dużo - potrzebujesz tylko domeny (lub subdomeny) oraz serwer z wyjściem na świat (otwartym portem 80/443). Lemmy nie wymaga dużo zasobów, ja moją małą instancje hostuje na serwerze z 2vCPU, 2GB RAM oraz 20GB dysku.
Łącze nie ma dużego znaczenia, dla paru osób nawet 5Mb/s uploadu prawdopodobnie wystaczą.&lt;/p&gt;
&lt;h2 id="instalacja-lemmy"&gt;Instalacja Lemmy&lt;/h2&gt;
&lt;p&gt;Do stworzenia instancji Lemmy wykorzystam Dockera, ponieważ to najprostsza metoda instalacji oraz aktualizacji, dodatkowo nie ma większego znaczenia z jakiego systemu operacyjnego korzystasz na hoście. Ten tutorial będzie przedstawiał kroki na Debianie.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Zainstaluj Dockera
W zależności od systemu operacyjnego, będzie się to trochę różniło. Najlepiej będzie przejrzeć oficjalną dokumentacje Dockera &lt;a href="https://docs.docker.com/engine/install/"&gt;jak zainstalować Docker Engine&lt;/a&gt; na systemie który wybrałeś.&lt;/p&gt;
&lt;p&gt;Przykład na Debianie/Ubuntu&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt update
sudo apt install docker docker-compose
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utwórz folder pod pliki
Aby zachować porządek, utworzymy folder w katalogu domowym gdzie będziemy trzymać wszystkie elementy lemmy - w zależności od konfiguracji dysków lub preferencji, możesz go również utworzyć w innym miejscu.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mkdir ~/lemmy
mkdir ~/lemmy/volumes
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utwórz docker-compose
Lemmy dzieli się na pięć (lub cztery jeżeli chcemy wykorzystać oddzielne reverse proxy) elementy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lemmy - główna aplikacja która serwuje API oraz obsługuje wymianę informacji&lt;/li&gt;
&lt;li&gt;Lemmy-ui - kontener z interfejsem webui do interakcji z instancją&lt;/li&gt;
&lt;li&gt;pict-rs - usługa do przechowywania obrazków na instancji&lt;/li&gt;
&lt;li&gt;Postgres - baza danych&lt;/li&gt;
&lt;li&gt;Nginx - jako reverse proxy które kieruje ruch do odpowiednich kontenerów - jest on opcjonalny jeżeli mamy już inne reverse proxy wystawione w sieci.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Na czas pisania tego poradnika, najnowsza stabilna wersja Lemmy to &lt;code&gt;0.19.3&lt;/code&gt; - sprawdź czy na &lt;a href="https://github.com/LemmyNet/lemmy/releases"&gt;Githubie&lt;/a&gt; nie ma dostępnej nowszej wersji.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# docker-compose.yml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;version&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;3.7&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;x-logging&lt;/span&gt;: &lt;span style="color:#75715e"&gt;&amp;amp;default-logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;driver&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;json-file&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;options&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;max-size&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;50m&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;max-file&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;4&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;proxy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;nginx:1-alpine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# You could use port 80 if you won&amp;#39;t use a reverse proxy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;8536:8536&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;./nginx.conf:/etc/nginx/nginx.conf:ro,Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;unless-stopped&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;depends_on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;pictrs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;lemmy-ui&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;logging&lt;/span&gt;: &lt;span style="color:#75715e"&gt;*default-logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;lemmy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;dessalines/lemmy:0.19.3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hostname&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;lemmy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;logging&lt;/span&gt;: &lt;span style="color:#75715e"&gt;*default-logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;./lemmy.hjson:/config/config.hjson:Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;depends_on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;postgres&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;pictrs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;lemmy-ui&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;dessalines/lemmy-ui:0.19.3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;LEMMY_UI_LEMMY_INTERNAL_HOST=lemmy:8536&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;LEMMY_UI_LEMMY_EXTERNAL_HOST=your-domain.tld&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;LEMMY_UI_HTTPS=true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;./volumes/lemmy-ui/extra_themes:/app/extra_themes:Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;depends_on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;lemmy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;logging&lt;/span&gt;: &lt;span style="color:#75715e"&gt;*default-logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;pictrs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;docker.io/asonix/pictrs:0.5.4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# this needs to match the pictrs url in lemmy.hjson&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hostname&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;pictrs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# we can set options to pictrs like this, here we set max. image size and forced format for conversion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# entrypoint: /sbin/tini -- /usr/local/bin/pict-rs -p /mnt -m 4 --image-format webp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;user&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;991&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;991&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;./volumes/pictrs:/mnt:Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;logging&lt;/span&gt;: &lt;span style="color:#75715e"&gt;*default-logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;deploy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;limits&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;memory&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;690m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;postgres&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;docker.io/postgres:15-alpine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hostname&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;postgres&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;POSTGRES_USER=lemmy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;POSTGRES_PASSWORD=password&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;POSTGRES_DB=lemmy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;./volumes/postgres:/var/lib/postgresql/data:Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;shm_size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1g&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;logging&lt;/span&gt;: &lt;span style="color:#75715e"&gt;*default-logging&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Podmień &lt;code&gt;your-domain.tld&lt;/code&gt; we wszystkich miejscach na prawdziwą domenę.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utwórz plik konfiguracyjny lemmy oraz nginx
W folderze w którym utworzyłeś &lt;code&gt;docker-compose.yml&lt;/code&gt;, utwórz plik &lt;code&gt;lemmy.hjson&lt;/code&gt; - jest to główny plik konfiguracyjny lemmy, gdzie skonfigurujemy dane dostępowe do bazy danych, pict-rs, hostname oraz opcjonalne dane SMTP.&lt;/p&gt;
&lt;p&gt;W podstawowej konfiguracji, jedyną rzeczą jaką należy tutaj zmienić, jest &lt;code&gt;hostname&lt;/code&gt; (powinien odpowiadać domenie pod którą chcesz wystawić instancję) oraz &lt;code&gt;pictrs.api_key&lt;/code&gt; (powinien się pokrywać z api_key zdefiniowanym w &lt;code&gt;docker-compose&lt;/code&gt;)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;lemmy.hjson&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;for&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;more&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;info&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;about&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;the&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;config,&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;check&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;out&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;the&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;documentation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;https:&lt;/span&gt;&lt;span style="color:#75715e"&gt;//join-lemmy.org/docs/en/administration/configuration.html
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;database:&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;name&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;of&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;the&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;postgres&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;database&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;for&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;lemmy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;database:&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;lemmy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;username&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;to&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;connect&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;to&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;postgres&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;user&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;lemmy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;password&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;to&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;connect&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;to&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;postgres&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;host&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;where&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;postgres&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;is&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;running&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;host&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;postgres&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;port&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;where&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;postgres&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;can&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;be&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;accessed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;5432&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;maximum&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;number&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;of&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;active&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;sql&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;connections&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;pool_size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;hostname:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;your-domain.tld&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;pictrs:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;url:&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;http://pictrs:8080/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;api_key&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;randomApiToken&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;If&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;you&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;have&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;a&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;instance&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;only&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;for&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;couple&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;of&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;people&lt;/span&gt;, &lt;span style="color:#960050;background-color:#1e0010"&gt;you&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;might&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;want&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;to&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;disable&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;image&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;caching&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;#&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;from&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;other&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;instances&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;cache_external_link_previews:&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Dla bezpieczeństwa, sugeruję zmienić domyślne dane, np. hasło do bazy postgres oraz apiKey do pictrs.&lt;br&gt;
Zajrzyj na &lt;a href="https://join-lemmy.org/docs/administration/configuration.html"&gt;join-lemmy.org/docs/administration/configuration.html&lt;/a&gt; aby dowiedzieć się o reszcie dostępnych opcjach konfiguracjnych.&lt;/p&gt;
&lt;p&gt;Pobierz przykładową konfiguracje nginx&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wget https://raw.githubusercontent.com/LemmyNet/lemmy/1596aee724339c7112d5efa42fa37e838e87d93c/docker/nginx.conf -O ~/lemmy/nginx.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Jeżeli masz inne reverse proxy, możesz pozbyć się kontenera proxy z &lt;code&gt;docker-compose&lt;/code&gt; i wykorzystać ten &lt;code&gt;nginx.conf&lt;/code&gt; jako baza.&lt;/p&gt;
&lt;p&gt;Aby federacja działała poprawnie, potrzebujemy mieć SSL, np. za pomocą LetsEncrypt, w zależności od tego jak chcesz wystawić Lemmy (za reverse proxy, wykorzystać nginx w docker-compose jako główny), musisz odpowiednio zmodyfikować konfiguracje nginx.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ustaw poprawne uprawnienia dla volumes&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p ~/lemmy/volumes/pictrs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p ~/lemmy/volumes/postgres
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Set owner to user defined in pictr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo chown -R 991:991 volumes/pictrs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Uruchom &lt;code&gt;docker-compose&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker-compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;&lt;img
src="https://issei.space/images/2024-04-09-lemmy/Screenshot_20240415_231154_hu_8bd3f27c2718d7a7.webp"
alt="scrrenshot of lemmy setup screen"
loading="lazy"
/&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Po chwili interfejs lemmy-ui powinien być dostępny - powineneś mieć opcje aby założyć konto administratora oraz opcje konfiguracyjne site, jak nazwa, opis, czy instancja ma mieć otwartą rejestrację oraz ustawienia federacji.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Domyślnie nie musisz zmieniać żadnych opcji federacji, sugeruję zostawić &lt;em&gt;Registration Mode&lt;/em&gt; na &lt;em&gt;Require registration application&lt;/em&gt;, aby nasza instancja nie została źródłem spamu&lt;/p&gt;
&lt;p&gt;Następnie powinniśmy już mieć możliwość subskrybowania społeczności 🎉
&lt;img
src="https://issei.space/images/2024-04-09-lemmy/Screenshot_20240415_231816_hu_50aede7e1325cd49.webp"
alt="screenshot of empty lemmy instance"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Znajdowanie społeczności&lt;br&gt;
Domyślnie nie będziesz widział żadnych społeczności - musisz je najpierw znaleźć - do znajdowania społeczności Lemmy możesz wykorzystać &lt;a href="https://lemmyverse.net/communities"&gt;&lt;strong&gt;Lemmy Explorer&lt;/strong&gt;&lt;/a&gt;
&lt;img
src="https://issei.space/images/2024-04-09-lemmy/Screenshot_20240415_225802_hu_89bbf51abb0b5f17.webp"
alt="lemmy explorer"
loading="lazy"
/&gt;
Skopiuj link do społeczności (przykładowo &lt;code&gt;!nazwa@instacja.tld&lt;/code&gt;), przejdź do wyszukiwarki na swojej instancji Lemmy i wyszukaj społeczność.
Możliwe że za pierwszym razem od razu twoja instancja nie pokaże wyszukiwanej społeczności, spróbuj ponownie kliknąć na wyszukiwanie.&lt;br&gt;
&lt;img
src="https://issei.space/images/2024-04-09-lemmy/Screenshot_20240415_232056_hu_e84b5ee53d83c691.webp"
alt="screenshot showing search screen of lemmy instance, in search result showing Technology community from lemmy.world instance"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;Następnie przejdź do społeczności i ją zasubskrybuj, po pewnym czasie na twojej instancji powinny się pokazywać posty z danej społeczeności.
&lt;img
src="https://issei.space/images/2024-04-09-lemmy/Screenshot_20240415_232342_hu_c7b6a590b00b8ffa.webp"
alt="community subscribe button"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;Jeżeli po dłuższym czasie nadal nie pojawiają ci się posty z instancji zewnętrznych, sprawdź logi nginx, oraz czy na pewno twoja instancja jest poprawnie dostępna z internetu/posiada poprawnie skonfigurowane HTTPS&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Cover background: &lt;a href="https://unsplash.com/@pawel_czerwinski?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash"&gt;Pawel Czerwinski&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-close-up-of-a-purple-background-with-wavy-lines-hOYHAdgbTr0?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash"&gt;unsplash&lt;/a&gt;&lt;/p&gt;</content></item><item><title>Setup proxmox-csi-driver in K3S Kubernetes Cluster using FluxCD</title><link>https://issei.space/blog/kubernetes-proxmox-csi-driver/</link><pubDate>Tue, 16 Jan 2024 21:24:07 +0200</pubDate><guid>https://issei.space/blog/kubernetes-proxmox-csi-driver/</guid><description>&lt;p&gt;Currently, I have small, two-node sandbox k3s cluster on my Proxmox homeserver. It is great for testing new things in Kubernetes ecosystem, but currently i’m missing one thing that is pretty awesome on “real” cloud environments with managed Kubernetes services - additional persistent volumes.
Of course, I can use &lt;code&gt;local-path&lt;/code&gt; to get persistent storage in my cluster, but it would be cool to attach separate virtual disks per pod. That’s when i found proxmox-csi-driver.&lt;/p&gt;</description><content>&lt;p&gt;Currently, I have small, two-node sandbox k3s cluster on my Proxmox homeserver. It is great for testing new things in Kubernetes ecosystem, but currently i’m missing one thing that is pretty awesome on “real” cloud environments with managed Kubernetes services - additional persistent volumes.
Of course, I can use &lt;code&gt;local-path&lt;/code&gt; to get persistent storage in my cluster, but it would be cool to attach separate virtual disks per pod. That’s when i found proxmox-csi-driver.&lt;/p&gt;
&lt;p&gt;Proxmox-csi-driver is developed by Serge Logvinov. It is a opensource CSI driver for Proxmox, you can find it on &lt;a href="https://github.com/sergelogvinov/proxmox-csi-plugin/"&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="create-proxmox-user-for-driver"&gt;Create proxmox user for driver&lt;/h2&gt;
&lt;p&gt;First, login to your Proxmox host via SSH or using WebUI Console, and create seperate user that we will utilize for interacting from Kubernetes&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@ashe:~# pveum role add CSI -privs &lt;span style="color:#e6db74"&gt;&amp;#34;VM.Audit VM.Config.Disk Datastore.Allocate Datastore.AllocateSpace Datastore.Audit&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@ashe:~# pveum user add kubernetes-csi@pve
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@ashe:~# pveum aclmod / -user kubernetes-csi@pve -role CSI
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root@ashe:~# pveum user token add kubernetes-csi@pve csi -privsep &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌──────────────┬──────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ key │ value │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;╞══════════════╪══════════════════════════════════════╡
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ full-tokenid │ kubernetes-csi@pve!csi │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├──────────────┼──────────────────────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ info │ &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;privsep&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├──────────────┼──────────────────────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ value │ 1d22d441-2115-4dx4-9e43-144c1ssdd12e │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└──────────────┴──────────────────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Save the secret token for later. Also make sure, that your Kubernetes nodes have &amp;lsquo;VirtIO SCSI Single&amp;rsquo; as their SCSI Controllers.&lt;/p&gt;
&lt;h2 id="label-kubernetes-nodes"&gt;Label kubernetes nodes&lt;/h2&gt;
&lt;p&gt;For driver to work correctly (attach disks to appropriate k8s node), we need to add labels&lt;/p&gt;
&lt;p&gt;&lt;a href="http://topology.kubernetes.io/region"&gt;topology.kubernetes.io/region&lt;/a&gt; can be arbitrary, but it needs to match with config, i will use default &lt;code&gt;Region-1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://topology.kubernetes.io/zone"&gt;topology.kubernetes.io/zone&lt;/a&gt; should be set to Proxmox node name&lt;/p&gt;
&lt;p&gt;Author suggest utilizing his another tool &lt;a href="https://github.com/sergelogvinov/proxmox-cloud-controller-manager"&gt;https://github.com/sergelogvinov/proxmox-cloud-controller-manager&lt;/a&gt;, but currently, I will just add labels with the non-automatic way&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ k label node/homelab-k3s-1 topology.kubernetes.io/region&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Region-1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;node/homelab-k3s-1 labeled
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ k label node/homelab-k3s-2 topology.kubernetes.io/region&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Region-1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;node/homelab-k3s-2 labeled
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ k label node/homelab-k3s-1 topology.kubernetes.io/zone&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ashe
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;node/homelab-k3s-1 labeled
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ k label node/homelab-k3s-2 topology.kubernetes.io/zone&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ashe
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;node/homelab-k3s-2 labeled
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I also noticed that &lt;a href="http://kubernetes.io/hostname=homelab-k3s-1"&gt;&lt;code&gt;kubernetes.io/hostname=homelab-k3s-1&lt;/code&gt;&lt;/a&gt; should match VM name at Proxmox, despite setting the &lt;code&gt;.spec.ProviderID&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="install-using-fluxcd"&gt;Install using FluxCD&lt;/h2&gt;
&lt;p&gt;I will install proxmox-csi-driver using Helm Chart by FluxCD HelmRelease. We will also create a separate namespace for the driver, so it could run as a privileged user.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/sergelogvinov/proxmox-csi-plugin/blob/main/README.md"&gt;The proxmox-csi-driver README&lt;/a&gt; also explains deploying the driver using plain Kubernetes manifest, Helm and Talos if that’s more your thing&lt;/p&gt;
&lt;p&gt;Note: this is an example of HelmRelease and depends on your repository layout you probably should put that HR in seperate Kustomization&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;source.toolkit.fluxcd.io/v1beta2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;HelmRepository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;sergelogvinov&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;flux-system&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;interval&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;10m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;oci&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;url&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;oci://ghcr.io/sergelogvinov/charts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Namespace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;proxmox-csi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;kustomize.toolkit.fluxcd.io/prune&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;disabled&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;pod-security.kubernetes.io/enforce&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;privileged&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;helm.toolkit.fluxcd.io/v2beta2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;HelmRelease&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;proxmox-csi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;proxmox-csi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;interval&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;chart&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;chart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;proxmox-csi-plugin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;sourceRef&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;HelmRepository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;sergelogvinov&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;flux-system&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;maxHistory&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;install&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;createNamespace&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;remediation&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;retries&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;upgrade&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cleanupOnFail&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;remediation&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;retries&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;uninstall&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;keepHistory&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;values&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;config&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;clusters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;url&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;https://ashe.issei.space:8006/api2/json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;insecure&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; &lt;span style="color:#75715e"&gt;# if you have self-signed SSL certificate, change it to true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;token_id&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;kubernetes-csi@pve!csi&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;token_secret&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;${PROXMOX_KUBERNETES_CSI_SECRET:=notset}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;region&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Region-1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;storageClass&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;proxmox-data-xfs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;storage&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;nvme&lt;/span&gt; &lt;span style="color:#75715e"&gt;# Storage name at proxmox&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;reclaimPolicy&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Delete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;fstype&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;xfs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I also did use Flux substitute (&lt;code&gt;PROXMOX_KUBERNETES_CSI_SECRET&lt;/code&gt;), so before pushing the changes to repo I made sure that secret we generated before was deployed in Flux cluster secrets&lt;/p&gt;
&lt;p&gt;After pushing the changes to git, we can check if the Helm was deployed successfully&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ flux get ks -A
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAMESPACE NAME REVISION SUSPENDED READY MESSAGE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;flux-system cluster-apps-proxmox-csi main@sha1:3f0676cf False True Applied revision: main@sha1:3f0676cf
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;...&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ flux get hr -n proxmox-csi
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME REVISION SUSPENDED READY MESSAGE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;proxmox-csi 0.1.15 False True Helm upgrade succeeded &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; release proxmox-csi/proxmox-csi.v8 with chart proxmox-csi-plugin@0.1.15
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ kubectl get pods -n proxmox-csi
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;proxmox-csi-proxmox-csi-plugin-controller-bd748957b-g2nxc 5/5 Running &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;17m ago&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 19m
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;proxmox-csi-proxmox-csi-plugin-node-9v4x8 3/3 Running &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;17m ago&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 60m
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;proxmox-csi-proxmox-csi-plugin-node-gnn24 3/3 Running &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;18m ago&lt;span style="color:#f92672"&gt;)&lt;/span&gt; 60m
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ k get storageclass
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;local-path cluster.local/local-path-provisioner Delete WaitForFirstConsumer true 19d
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;proxmox-data-xfs csi.proxmox.sinextra.dev Delete WaitForFirstConsumer true 34m
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="test"&gt;Test&lt;/h2&gt;
&lt;p&gt;For testing, I will deploy StatefulSet&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;apps/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;StatefulSet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;alpine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;podManagementPolicy&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Parallel &lt;/span&gt; &lt;span style="color:#75715e"&gt;# default is OrderedReady&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;serviceName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;replicas&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;template&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;labels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;alpine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;terminationGracePeriodSeconds&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;containers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;alpine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;alpine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;command&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;sleep&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;1d&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;securityContext&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;seccompProfile&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;RuntimeDefault&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;capabilities&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;drop&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;ALL&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumeMounts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;storage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;mountPath&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;/mnt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;updateStrategy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;RollingUpdate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;selector&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;matchLabels&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;alpine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumeClaimTemplates&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;storage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;accessModes&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;ReadWriteOnce&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;requests&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;storage&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2Gi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;storageClassName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;proxmox-data-xfs &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure that &lt;code&gt;storageClassName&lt;/code&gt; matches the one we set earlier.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ k get pods
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;test-0 1/1 Running &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 3m24s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let’s start a shell in our new pod&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ k exec -it pod/test-0 ash
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl exec &lt;span style="color:#f92672"&gt;[&lt;/span&gt;POD&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;COMMAND&lt;span style="color:#f92672"&gt;]&lt;/span&gt; is DEPRECATED and will be removed in a future version. Use kubectl exec &lt;span style="color:#f92672"&gt;[&lt;/span&gt;POD&lt;span style="color:#f92672"&gt;]&lt;/span&gt; -- &lt;span style="color:#f92672"&gt;[&lt;/span&gt;COMMAND&lt;span style="color:#f92672"&gt;]&lt;/span&gt; instead.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/ &lt;span style="color:#75715e"&gt;# df -h&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Filesystem Size Used Available Use% Mounted on
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;overlay 14.6G 4.1G 9.8G 30% /
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tmpfs 64.0M &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 64.0M 0% /dev
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/dev/sdb 1.9G 46.1M 1.9G 2% /mnt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/dev/vda1 14.6G 4.1G 9.8G 30% /etc/hosts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/dev/vda1 14.6G 4.1G 9.8G 30% /dev/termination-log
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/dev/vda1 14.6G 4.1G 9.8G 30% /etc/hostname
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/dev/vda1 14.6G 4.1G 9.8G 30% /etc/resolv.conf
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;shm 64.0M &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 64.0M 0% /dev/shm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tmpfs 1.9G 12.0K 1.9G 0% /run/secrets/kubernetes.io/serviceaccount
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tmpfs 985.5M &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 985.5M 0% /proc/acpi
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tmpfs 64.0M &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 64.0M 0% /proc/kcore
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tmpfs 64.0M &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 64.0M 0% /proc/keys
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tmpfs 64.0M &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 64.0M 0% /proc/timer_list
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tmpfs 64.0M &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 64.0M 0% /proc/sched_debug
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tmpfs 985.5M &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 985.5M 0% /sys/firmware
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As we can see, we have &lt;code&gt;/mnt&lt;/code&gt; mounted, let’s now create a file&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/ &lt;span style="color:#75715e"&gt;# cd /mnt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/mnt &lt;span style="color:#75715e"&gt;# ls&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/mnt &lt;span style="color:#75715e"&gt;# echo $(date) &amp;gt; test-file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/mnt &lt;span style="color:#75715e"&gt;# cat test-file &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tue Jan &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; 20:12:16 UTC &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/mnt &lt;span style="color:#75715e"&gt;# exit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let’s exit the pod, delete it, wait for recreate, and check if the file is still there&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ k delete pod/test-0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pod &lt;span style="color:#e6db74"&gt;&amp;#34;test-0&amp;#34;&lt;/span&gt; deleted
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ k get pods
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;test-0 0/1 ContainerCreating &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 5s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ k get pods
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME READY STATUS RESTARTS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;test-0 1/1 Running &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 13s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ k exec -it pod/test-0 ash
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl exec &lt;span style="color:#f92672"&gt;[&lt;/span&gt;POD&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;COMMAND&lt;span style="color:#f92672"&gt;]&lt;/span&gt; is DEPRECATED and will be removed in a future version. Use kubectl exec &lt;span style="color:#f92672"&gt;[&lt;/span&gt;POD&lt;span style="color:#f92672"&gt;]&lt;/span&gt; -- &lt;span style="color:#f92672"&gt;[&lt;/span&gt;COMMAND&lt;span style="color:#f92672"&gt;]&lt;/span&gt; instead.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/ &lt;span style="color:#75715e"&gt;# cd /mnt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/mnt &lt;span style="color:#75715e"&gt;# ls -la&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; Jan &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; 20:12 .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; Jan &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; 20:12 ..
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw-r--r-- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; Jan &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; 20:12 test-file
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/mnt &lt;span style="color:#75715e"&gt;# cat test-file &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tue Jan &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; 20:12:16 UTC &lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bingo! The file is still there. We can also check storage class of our Persistent Volume Claim (PVC) to be sure&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ k get pvc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;storage-test-0 Bound pvc-08fa4889-3749-40a3-85cb-ddf273d9ac21 2Gi RWO proxmox-data-xfs 7m11s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In Proxmox WebUI we can also see that additional virtual disk was also attached
&lt;img
src="https://issei.space/images/2024-01-16-proxmox-csi-driver/Screenshot_20240116_212728_hu_6e4ec8ad3d8e8c5a.webp"
alt="Screenshot of Proxmox WebUI, showing hardware specification of one of kubernetes nodes with PVC attached"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;Note: Make sure that after adding new PVC the VM have corrent boot order. In my case it did change, and after a node reboot the VM did not boot from OS disk
&lt;img
src="https://issei.space/images/2024-01-16-proxmox-csi-driver/Screenshot_20240117_172827_hu_5c0cb127d3ccf1e5.webp"
alt="Screenshot of Proxmox WebUI, showing virtual machine hard drive boot order"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;h2 id="troubleshooting"&gt;Troubleshooting&lt;/h2&gt;
&lt;p&gt;If you get an error like&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Warning FailedScheduling 38s default-scheduler 0/2 nodes are available: 2 node(s) did not have enough free storage. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Make sure that cluster nodes can reach Proxmox WebUI. In my case, the issue was caused by proxmox datacenter-level firewall on a host where I forgot to add a rule which allows access to webui (tcp 8006) from a second internal network.&lt;/p&gt;
&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@miteneva?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash"&gt;Maria Teneva&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/a-body-of-water-surrounded-by-mountains-under-a-cloudy-sky-SXwCyG4FoPk?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;</content></item><item><title>Noob is trying to build Android kernel 4.14.x</title><link>https://issei.space/blog/crosscompile-android-kernel/</link><pubDate>Sun, 16 Jul 2023 14:37:07 +0200</pubDate><guid>https://issei.space/blog/crosscompile-android-kernel/</guid><description>&lt;p&gt;At the beginning of this article, i would like to mention that i&amp;rsquo;m a noob when it comes to android custom kernel or ROM development, so some of these information may be obvious to some of you, but it was relatively hard to find one place with up-to-date information on this topic.&lt;/p&gt;
&lt;h2 id="backstory---why-i-want-to-compile-the-kernel-for-my-phone"&gt;Backstory - why i want to compile the kernel for my phone?&lt;/h2&gt;
&lt;p&gt;My current phone is the Xiaomi Mi 9 - i&amp;rsquo;m very happy with this phone, it is more than fast enough for my everyday needs, and the photo quality (especially on gcam) is also pretty good. My main issue with this phone was under MIUI 12 - it had a couple of annoying bugs that will probably never get fixed:&lt;/p&gt;</description><content>&lt;p&gt;At the beginning of this article, i would like to mention that i&amp;rsquo;m a noob when it comes to android custom kernel or ROM development, so some of these information may be obvious to some of you, but it was relatively hard to find one place with up-to-date information on this topic.&lt;/p&gt;
&lt;h2 id="backstory---why-i-want-to-compile-the-kernel-for-my-phone"&gt;Backstory - why i want to compile the kernel for my phone?&lt;/h2&gt;
&lt;p&gt;My current phone is the Xiaomi Mi 9 - i&amp;rsquo;m very happy with this phone, it is more than fast enough for my everyday needs, and the photo quality (especially on gcam) is also pretty good. My main issue with this phone was under MIUI 12 - it had a couple of annoying bugs that will probably never get fixed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sometimes, despite being muted, when taking a screenshot - the stock android sound and popup will appear.&lt;/li&gt;
&lt;li&gt;The screenshots are a bit darker than on screen (as the screenshot is captured at the first frame of the animation&amp;hellip;)&lt;/li&gt;
&lt;li&gt;Sometimes the MIUI Gallery app is trying to index photos, and it might come across a corrupted image - in that case, it would just drain your battery and peg CPU retrying - solution: factory reset the phone or disallow access to storage/uninstall the app&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I decided that life is too short to bother with buggy software that i don&amp;rsquo;t have a control on, and i didn&amp;rsquo;t want to change phone (..aand probably i just like to mess with stuff), because aside from this, it was working great!
I unlocked the bootloader, and install PixelOS 13 - since then - the phone is running better than on stock MIUI (feels quicker + battery last longer). Huge thanks to the mainteiner of PixelOS for cepheus - &lt;a href="https://forum.xda-developers.com/m/balgxmr.9196567/"&gt;balgxmr&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So - why i want to build the kernel from scratch? Because after the last OTA update, there was no KernelSU-compatible kernel on telegram channel. Yes - i could just ask if he could release flashable zip with KSU, but why not try to build it myself?&lt;/p&gt;
&lt;p&gt;KernelSU is a root solution that works in kernel mode and grant root permission to userspace application directly in kernel space. Compared to Magisk, i didn&amp;rsquo;t had any issues with using mobile banking apps, Google Pay or McDonald&amp;rsquo;s app (which was always the hardest to trick that my device was not rooted&amp;hellip;)&lt;/p&gt;
&lt;h2 id="what-do-i-need-to-build-a-kernel"&gt;What do i need to build a kernel?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Preferably Linux-based OS (but can also be done on Windows or Mac!)&lt;/li&gt;
&lt;li&gt;Kernel source&lt;/li&gt;
&lt;li&gt;anykernel3 (optional - to create a flashable zip)&lt;/li&gt;
&lt;li&gt;aarch64 toolchain&lt;/li&gt;
&lt;li&gt;arm32 toolchain&lt;/li&gt;
&lt;li&gt;patience&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a example for this write up i will be using &lt;a href="https://github.com/balgxmr/kernel_xiaomi_cepheus"&gt;kernel_xiaomi_cepheus&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="file-structure"&gt;File structure&lt;/h2&gt;
&lt;p&gt;using &lt;code&gt;--depth 1&lt;/code&gt; to only download the latest changes, as I only want to compile the kernel without any modifications (as the kernel from balgxmr already has a branch with KernelSU patch).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mkdir -p workdir &amp;amp;&amp;amp; cd workdir
git clone https://github.com/balgxmr/kernel_xiaomi_cepheus --depth 1
git clone https://github.com/balgxmr/anykernel3 anykernel
git clone https://github.com/radcolor/aarch64-linux-gnu --depth 1
git clone https://github.com/radcolor/arm-linux-gnueabi --depth 1
chmod +x -R kernel_xiaomi_cepheus/build.sh kernel_xiaomi_cepheus/scripts/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Before continuing i noticed that the kernel has dos character newline encoding, so to get it working under unix, i needed to use the tool &lt;code&gt;dos2unix&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;find . -type f -print0 | xargs -0 dos2unix
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="https://stackoverflow.com/a/11929475"&gt;source&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At first i had no idea where to get toolchain, as &lt;a href="https://gitlab.com/PixelOS-Devices/playgroundtc"&gt;https://gitlab.com/PixelOS-Devices/playgroundtc&lt;/a&gt; was missing some &lt;code&gt;gcc&lt;/code&gt; binaries - got the idea from &lt;a href="https://github.com/balgxmr/kernel_xiaomi_cepheus/issues/2"&gt;issue #2 in repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why i decided to use another prebuild binaries&lt;/p&gt;
&lt;h2 id="installing-dependencies-on-arch-based-os"&gt;Installing dependencies on Arch-based OS&lt;/h2&gt;
&lt;p&gt;Some packages are named differently in arch repository than in debian/ubuntu, here is a list of what you need to install:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo pacman -S clang gcc bc llvm make ncurses bison flex openssl libelf lld zip
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="alternative-way-using-docker"&gt;Alternative way: Using Docker&lt;/h2&gt;
&lt;p&gt;If you are facing any issues with installing the dependencies, or you are on another OS and want to quickly setup a build environment, you could use Docker for that.&lt;/p&gt;
&lt;p&gt;My &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# workdir/Dockerfile
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
# Installing necessary packages
RUN apt update &amp;amp;&amp;amp; apt upgrade -y &amp;amp;&amp;amp; \
apt install git clang g++-11 bc llvm make \
build-essential libncurses-dev bison flex \
libssl-dev libelf-dev zip lld -y \
&amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/* \
&amp;amp;&amp;amp; mkdir /work
WORKDIR /work
CMD tail -f /dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It is using a Ubuntu 22.04 as a base image, and it just install the necessary build dependencies. Also as a small hack - to keep it from shutting down, it will &lt;code&gt;tail&lt;/code&gt; /dev/null.&lt;/p&gt;
&lt;p&gt;My &lt;code&gt;docker-compose.yaml&lt;/code&gt;&lt;br&gt;
we can also just use &lt;code&gt;docker run&lt;/code&gt;, as there would be only one container, but to keep it simple with volume mounts and building i will use docker-compose&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# workdir/docker-compose.yaml
version: &amp;#39;3.7&amp;#39;
services:
builder:
container_name: builder
build:
context: .
volumes:
- ./:/work/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This &lt;code&gt;docker-compose&lt;/code&gt; will build &lt;code&gt;Dockerfile&lt;/code&gt; from current directory, and mount files we have in our &lt;code&gt;workdir&lt;/code&gt; to &lt;code&gt;/work&lt;/code&gt; inside our Docker container.&lt;/p&gt;
&lt;p&gt;Build and enter the container&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker-compose up -d
docker exec -it builder bash
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="trying-to-build-the-kernel"&gt;Trying to build the kernel&lt;/h2&gt;
&lt;p&gt;Thankfully, the kernel source did contain &lt;a href="https://github.com/balgxmr/kernel_xiaomi_cepheus/blob/fe075fd2f6dd52abc5b728f64c9f9ad3d0c4ff12/build.sh"&gt;build.sh&lt;/a&gt; that helped me to figure out what i need to actually compile the kernel. This script probably can be used also for other kernels (just remember to change &lt;code&gt;DEFCONFIG&lt;/code&gt;)
In &lt;code&gt;build.sh&lt;/code&gt; i needed to change a couple of variables&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;export CLANG_PATH=/work/aarch64-linux-gnu/bin
export CLANG32_PATH=/work/arm-linux-gnueabi/bin
export PATH=${CLANG_PATH}:${CLANG32_PATH}:${PATH}
export CROSS_COMPILE=${CLANG_PATH}/aarch64-linux-gnu-
export CROSS_COMPILE_ARM32=${CLANG32_PATH}/arm-linux-gnueabi-
# Paths
KERNEL_DIR=`pwd`
REPACK_DIR=/work/anykernel
ZIP_MOVE=/work/out
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now in &lt;code&gt;kernel_xiaomi_cepheus&lt;/code&gt; directory, we can try to execute &lt;code&gt;bash build.sh&lt;/code&gt; and see results.
Depends on your hardware, it could take some time - on my AMD Ryzen 5 5600G system it took around 6 minutes.&lt;/p&gt;
&lt;p&gt;If everything went well, you should have a flashable zip in &lt;code&gt;workdir/out&lt;/code&gt; on your host.&lt;/p&gt;</content></item><item><title>Installing Linux on Chromebook (and other Apollo Lake devices)</title><link>https://issei.space/blog/linux-on-apollo-lake/</link><pubDate>Tue, 23 May 2023 00:24:56 +0200</pubDate><guid>https://issei.space/blog/linux-on-apollo-lake/</guid><description>&lt;p&gt;In this post i will focus on replacing the ChromeOS with Linux. Before i was running Eupnea on my chromebook, it was working alright, but the boot splashscreen was quite annoying (and recently i encourage a ‘softbrick’ after kernel update).&lt;/p&gt;
&lt;p&gt;If you want to dualboot linux+chromeos i would sugest to stick with Eupnea on external storage, like fast SD card or USB stick.&lt;/p&gt;
&lt;h2 id="what-do-i-need"&gt;What do i need?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Some patience&lt;/li&gt;
&lt;li&gt;Two USB drives - one with UEFI compatible linux of your choice - I will install EndeavourOS via Ventoy because i’m too lazy to configure a decent looking arch desktop on my own, and a second one to backup stock firmware. Technically you can do that on the same drive, but just to be safe, I recommend two separate ones.&lt;/li&gt;
&lt;li&gt;Enabled Developer mode, and disabled WP&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="step-zero---validate-coreboot-support-for-your-device"&gt;Step zero - validate coreboot support for your device&lt;/h2&gt;
&lt;p&gt;Visit &lt;a href="https://mrchromebox.tech/#devices"&gt;https://mrchromebox.tech/#devices&lt;/a&gt; website and check if your device have support for ‘UEFI Firmware’. You probably can also do the same thing using WP_LEGACY, but i decided to just replace firmware in my chromebook.&lt;/p&gt;</description><content>&lt;p&gt;In this post i will focus on replacing the ChromeOS with Linux. Before i was running Eupnea on my chromebook, it was working alright, but the boot splashscreen was quite annoying (and recently i encourage a ‘softbrick’ after kernel update).&lt;/p&gt;
&lt;p&gt;If you want to dualboot linux+chromeos i would sugest to stick with Eupnea on external storage, like fast SD card or USB stick.&lt;/p&gt;
&lt;h2 id="what-do-i-need"&gt;What do i need?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Some patience&lt;/li&gt;
&lt;li&gt;Two USB drives - one with UEFI compatible linux of your choice - I will install EndeavourOS via Ventoy because i’m too lazy to configure a decent looking arch desktop on my own, and a second one to backup stock firmware. Technically you can do that on the same drive, but just to be safe, I recommend two separate ones.&lt;/li&gt;
&lt;li&gt;Enabled Developer mode, and disabled WP&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="step-zero---validate-coreboot-support-for-your-device"&gt;Step zero - validate coreboot support for your device&lt;/h2&gt;
&lt;p&gt;Visit &lt;a href="https://mrchromebox.tech/#devices"&gt;https://mrchromebox.tech/#devices&lt;/a&gt; website and check if your device have support for ‘UEFI Firmware’. You probably can also do the same thing using WP_LEGACY, but i decided to just replace firmware in my chromebook.&lt;/p&gt;
&lt;h2 id="first-step---installing-coreboot"&gt;First step - installing coreboot&lt;/h2&gt;
&lt;p&gt;To install coreboot you have to disable WP (write protection), on chromebooks with CR50 chip you need to use SuzyQ cable or disconnect the batery and power up the laptop. You also need to have enabled developer mode in ChromeOS.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open terminal (CTRL+ALT+T) in ChromeOS&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;shell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Execute this command&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd; curl -LO mrchromebox.tech/firmware-util.sh &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo bash firmware-util.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It will download and execute the firmware utility script.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Select second option &lt;code&gt;Install/Update UEFI (Full ROM) Firmware&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Utility will inform you about the possible consequences. Read it carefully.&lt;/li&gt;
&lt;li&gt;The utility will also backup your existing firmware if you decided to go back to stock firmware. You need to connect a USB stick as a storage device for backup.&lt;/li&gt;
&lt;li&gt;Proceed with the process.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can find more information on &lt;a href="https://mrchromebox.tech/#fwscript"&gt;mrchromebox website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After a successful flash, you can reboot your machine - you should see coreboot logo. Connect pendrive with OS and press ESC on boot screen. Enter &lt;code&gt;Boot Manager Menu&lt;/code&gt; and select your device. Install your Linux distro as normal.&lt;/p&gt;
&lt;h2 id="dummy-output-where-is-audio"&gt;Dummy output? Where is audio?&lt;/h2&gt;
&lt;p&gt;This is not a case for all chromebooks, but at least with my apollo lake based chromebook (HP Chromebook 13 G6 with Intel Celeron N3040) some audio things are missing from kernel. Not a expert on audio subsystem, but that is very annoying.&lt;/p&gt;
&lt;p&gt;To have working audio on our linuxed chromebook we will use &lt;code&gt;audio-script&lt;/code&gt; from Eupnea Linux Project.&lt;/p&gt;
&lt;p&gt;You need to have &lt;code&gt;git&lt;/code&gt; and Python &amp;lt;3.10 installed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone https://github.com/eupnea-linux-backup/audio-scripts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd audio-scripts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./setup-audio --force-avs-install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;UPDATE 2023-08-07&lt;/strong&gt;: Due to Eupnea Project drama + project abondance you might want to use &lt;a href="https://github.com/WeirdTreeThing/chromebook-linux-audio"&gt;WierdTreeThing audio-scripts fork&lt;/a&gt;. I did not tried it yet, but it should work the same way.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;--force-avs-install&lt;/code&gt; is needed because AVS driver might be unstable and might damage speakers if you set the volume too high.&lt;/p&gt;
&lt;p&gt;Just follow the prompts and install AVS driver. I also recommend installing headphone autoswitch.&lt;/p&gt;
&lt;h3 id="troubleshooting-not-working-speakerheadphones-autoswitch"&gt;Troubleshooting not working speaker/headphones autoswitch&lt;/h3&gt;
&lt;p&gt;Check if &lt;code&gt;avs-auto-switcher&lt;/code&gt; service is running&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;➜ ~ systemctl --machine=$(whoami)@.host --user status avs-auto-switcher
○ avs-auto-switcher.service - Automatically switch between avs headphones and speakers
Loaded: loaded (/usr/lib/systemd/user/avs-auto-switcher.service; enabled; preset: enabled)
Active: inactive (dead)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;if it is inactive, try enabling it using command&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;systemctl --machine=$(whoami)@.host --user enable --now avs-auto-switcher
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and check status once again&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;➜ ~ systemctl --machine=$(whoami)@.host --user status avs-auto-switcher
● avs-auto-switcher.service - Automatically switch between avs headphones and speakers
Loaded: loaded (/usr/lib/systemd/user/avs-auto-switcher.service; enabled; preset: enabled)
Active: active (running) since Fri 2023-05-26 16:02:22 CEST; 27s ago
Main PID: 16402
Tasks: 2 (limit: 4522)
Memory: 772.0K
CPU: 1.092s
CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/avs-auto-switcher.service
├─16402 /bin/bash /usr/local/bin/avs-auto-switcher
└─16403 acpi_listen
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="keyboard-layout"&gt;Keyboard layout&lt;/h2&gt;
&lt;p&gt;EndeavourOS and a couple of other distros have builin layout for chromebook media keys, but if your distro is missing that layout, you can use script from
&lt;a href="https://github.com/fascinatingcaptain"&gt;fascinatingcaptain&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone https://github.com/fascinatingcaptain/CBFixesAndTweaks
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd CBFixesAndTweaks
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# make backup of original pc config file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo cp -n /usr/share/X11/xkb/symbols/pc /usr/share/X11/xkb/symbols/pc.bck
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# copy new pc config file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo cp pc /usr/share/X11/xkb/symbols/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# update config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo rm -rf /var/lib/xkb/*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On my EndeavourOS (xfce4) install out-of-the-box keyboard brightness control was not working despite enabling that option in power management (and working in the battery settings), so i installed &lt;code&gt;light&lt;/code&gt; (using AUR) and just bind these buttons to commands.&lt;/p&gt;
&lt;p&gt;To use &lt;code&gt;light&lt;/code&gt; as a regular user (without sudo), you need to be in &lt;code&gt;video&lt;/code&gt; user group (&lt;code&gt;sudo usermod -aG video $(whoami)&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2023-05-23-linux-on-apollo-lake/keybinding_hu_bc3187864eb2f897.webp"
alt="XFCE keybinding settings"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: &lt;code&gt;light&lt;/code&gt; &lt;a href="https://aur.archlinux.org/packages/light?O=10#comment-957514"&gt;is now orphaned&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="enjoy"&gt;Enjoy?&lt;/h2&gt;
&lt;p&gt;On my Chromebook everything else was working fine OOTB.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sleep (after turning on lid close action in settings)&lt;/li&gt;
&lt;li&gt;HDMI output over USB-C&lt;/li&gt;
&lt;li&gt;SD Card reader&lt;/li&gt;
&lt;li&gt;Wi-Fi, Bluetooth&lt;/li&gt;
&lt;li&gt;Battery life looks on par with ChromeOS one&lt;/li&gt;
&lt;/ul&gt;</content></item><item><title>Project Eupnea - native linux for chromebooks</title><link>https://issei.space/blog/eupnea-linux-chromebook/</link><pubDate>Mon, 15 May 2023 10:40:56 +0200</pubDate><guid>https://issei.space/blog/eupnea-linux-chromebook/</guid><description>&lt;p&gt;&lt;strong&gt;UPDATE 2023-08-07&lt;/strong&gt;: Eupnea Project has been discontinued, new install of Depthboot are not recommended, if you can, just use UEFI + audio fixes. Also their Discord and Github was compromised. If you are currenty using Depthboot it is recommended to remove their repository from package manager list.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Let me start with that - second-hand chromebooks are awesome value for cheap, long-lasting battery, portable Netflix and SSH machine.&lt;/p&gt;
&lt;p&gt;I’ve got my Chromebook about a year ago for 55 USD, it is a HP Chromebook 11a G6. I love how lightweight it is and that i can charge it from literally everything using USB-C ports (for real - it can even take charge from normal 5V USB charger). And the battery is awesome, it lasts a whole working day of moderate use.
I bought a chromebook mostly as an experiment, on how the ChromeOS works for “poweruser” - and to be honest, it isn’t that bad, mostly because of the Linux Debian container, but it is still very limiting.&lt;/p&gt;</description><content>&lt;p&gt;&lt;strong&gt;UPDATE 2023-08-07&lt;/strong&gt;: Eupnea Project has been discontinued, new install of Depthboot are not recommended, if you can, just use UEFI + audio fixes. Also their Discord and Github was compromised. If you are currenty using Depthboot it is recommended to remove their repository from package manager list.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Let me start with that - second-hand chromebooks are awesome value for cheap, long-lasting battery, portable Netflix and SSH machine.&lt;/p&gt;
&lt;p&gt;I’ve got my Chromebook about a year ago for 55 USD, it is a HP Chromebook 11a G6. I love how lightweight it is and that i can charge it from literally everything using USB-C ports (for real - it can even take charge from normal 5V USB charger). And the battery is awesome, it lasts a whole working day of moderate use.
I bought a chromebook mostly as an experiment, on how the ChromeOS works for “poweruser” - and to be honest, it isn’t that bad, mostly because of the Linux Debian container, but it is still very limiting.&lt;/p&gt;
&lt;p&gt;So i went on the search of solutions of installing another OS on it - as i knew that pretty much any x86 chromebook can be flashed with coreboot from &lt;a href="http://mrchromebook.tech"&gt;mrchromebook.tech&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The issue are drivers for hardware. I really wanted to use some Linux distro, as i think it would work the best on hardware with that spec tier. But unfortunately, not all i2c hardware have great support, mostly audio, keyboard and touchpad. Actually on the Windows side things seems to be working a bit better, but i doubt Windows 10 on 16GB emmc would be a pleasant experience.&lt;/p&gt;
&lt;h2 id="breath"&gt;Breath&lt;/h2&gt;
&lt;p&gt;Later i discover &lt;a href="https://github.com/cb-linux/breath"&gt;Breath&lt;/a&gt; - it is a way to natively boot Linux without replacing chromebook firmware. All you need to do, is enable Developer Mode, create bootable USB and you can install it. Additionally, it is using Google ChromeOS kernel, so everything should be supported out-of-the-box. It does support creating bootable USB with&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Debian&lt;/li&gt;
&lt;li&gt;Ubuntu&lt;/li&gt;
&lt;li&gt;Arch&lt;/li&gt;
&lt;li&gt;Fedora&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unfortunately, the project was archived due to lack of active maintenance.&lt;/p&gt;
&lt;h2 id="project-eupnea"&gt;Project Eupnea&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/eupnea-linux-backup"&gt;Eupnea&lt;/a&gt; is a fork of Breath, featuring all the features from Breath.&lt;/p&gt;
&lt;p&gt;I decided to give it a try, first try was with EupneaOS - their own distro with a goal of mimicking ChromeOS look, and even Android emulator (via Waydroid). The distro is using KDE Plasma as a Desktop Environment.
I was pretty amazed on how booting process was painless - all it took was to enable developer mode in chromeOS and enable debugging options (that allow access to ChromeOS root shell), executing command that allow booting from USB unsigned OS, quick reboot, pressing CTRL+U, and in a couple of minutes i was on Linux KDE desktop running live from USB on my chromebook!&lt;/p&gt;
&lt;p&gt;Later i decided to create my own image, based on Arch Linux and KDE Plasma (yeah, kde might not be the best choice for that class of hardware) - the process was pretty easy even on WSL2 environment. It generated a &lt;code&gt;.img&lt;/code&gt; file that i could just &lt;code&gt;dd&lt;/code&gt; onto flash drive.&lt;/p&gt;
&lt;p&gt;Next couple of minutes, and i was on desktop of my image, next i decided to execute &lt;code&gt;install-to-internal&lt;/code&gt; command, which, as you might guess, installs the OS to internal storage.&lt;/p&gt;
&lt;p&gt;The best part of it - because you don’t need to replace the firmware - you can just go back to ChromeOS with recovery media.&lt;/p&gt;
&lt;p&gt;After a reboot, i was on desktop of my arch install, running on chromebook - actually i wasn’t running that bad, considering that my chromebook have only a 6W TDP Celeron N3350. But one thing was missing - the audio.&lt;/p&gt;
&lt;h3 id="audio-setup"&gt;Audio setup&lt;/h3&gt;
&lt;p&gt;As my chromebook is running ‘apollo lake’ line of cpu i needed to use AVS drivers. The &lt;code&gt;setup-audio&lt;/code&gt; script claim they are flaky and can burn out speakers, but personally I haven’t had any issues yet. Both the headphone jack and built-in speakers works.&lt;/p&gt;
&lt;h3 id="general-usability"&gt;General usability&lt;/h3&gt;
&lt;p&gt;The first thing i wanted to do on my Linuxed chromebook was installation Steam. It can be done in Crostini, but on my 16GB EMMC, i was missing space and there aren’t any good ways of mounting external SD card in Crostini environment (there is a “Share for linux” option, but that limits transfer speeds to about 5MB/s…)&lt;/p&gt;
&lt;p&gt;The game i wanted to try the most was Stardew Valley - and it works straight away!
But, i had before played this game via Crostini, and it was also working fine under ChromeOS.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;&lt;img
src="https://issei.space/images/2023-05-15-eupnea/eupnea-sv_hu_ef04cfbe1bee7f9d.webp"
alt="stardew vally running on eupnea linux"
loading="lazy"
/&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;HP Chromebook 13 G6 running Steam and Stardew Valley on Arch Linux with Eupnea kernel + necessary fastfetch&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Next thing was a internet browsing using Firefox, as day-to-day, it is my primary browser. It was also running pretty good, no stutters while playing youtube videos, Discord is also running “ok” - sometimes it takes a couple of seconds to switch serve. Netflix, after installing ‘netflix 1080p’ extension, also work great.&lt;/p&gt;
&lt;p&gt;I’ve been running arch on my chromebook for about a month now, and i’m pretty happy with the result. It really brings up the usability of the laptop for me. The battery is also performing on par with the chromeos.&lt;/p&gt;</content></item><item><title>How to use Backblaze B2 as primary storage in Nextcloud</title><link>https://issei.space/blog/how-to-use-backblaze-b2-as-primary-storage-in-nextcloud/</link><pubDate>Mon, 23 Jan 2023 23:30:56 +0200</pubDate><guid>https://issei.space/blog/how-to-use-backblaze-b2-as-primary-storage-in-nextcloud/</guid><description>&lt;p&gt;To setup B2 as primary storage in Nextcloud you of course need to install NC first. For that, I used &lt;a href="https://download.nextcloud.com/server/installer/setup-nextcloud.php"&gt;setup-nextcloud.php&lt;/a&gt; script - it is a nice, quick way of deploying nextcloud on shared hosting. Normally i would recommend setting it up as a docker container, but that will also work for testing.
While installing Nextcloud just pick default storage place for now.&lt;/p&gt;
&lt;h2 id="creating-bucket-in-backblaze"&gt;Creating bucket in Backblaze&lt;/h2&gt;
&lt;p&gt;If you don’t already have Backblaze account, you can register &lt;a href="https://www.backblaze.com/b2/sign-up.html"&gt;here&lt;/a&gt;. Backblaze gives 10GB of free storage + 1GB traffic per day for every user.&lt;br&gt;
Note: make sure you select correct region, as of right now, accounts can’t be moved between regions&lt;/p&gt;</description><content>&lt;p&gt;To setup B2 as primary storage in Nextcloud you of course need to install NC first. For that, I used &lt;a href="https://download.nextcloud.com/server/installer/setup-nextcloud.php"&gt;setup-nextcloud.php&lt;/a&gt; script - it is a nice, quick way of deploying nextcloud on shared hosting. Normally i would recommend setting it up as a docker container, but that will also work for testing.
While installing Nextcloud just pick default storage place for now.&lt;/p&gt;
&lt;h2 id="creating-bucket-in-backblaze"&gt;Creating bucket in Backblaze&lt;/h2&gt;
&lt;p&gt;If you don’t already have Backblaze account, you can register &lt;a href="https://www.backblaze.com/b2/sign-up.html"&gt;here&lt;/a&gt;. Backblaze gives 10GB of free storage + 1GB traffic per day for every user.&lt;br&gt;
Note: make sure you select correct region, as of right now, accounts can’t be moved between regions&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2023-01-23-nextcloud-b2/nextcloud-b2-1_hu_9d6151cb7fd76527.webp"
alt="register form select region"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;Next, after logging in, click on Buckets → Create a Bucket&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2023-01-23-nextcloud-b2/nextcloud-b2-2_hu_7e95ce4742ffda1a.webp"
alt="create bucket 1"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;Enter unique bucket name, and set “Files in Bucket are” “Private”, as we don’t want to access our files publicly from URL.&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2023-01-23-nextcloud-b2/nextcloud-b2-3_hu_63b32984b8dc0233.webp"
alt="create bucket 2"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;Click on “Create a Bucket”&lt;/p&gt;
&lt;h2 id="creating-application-keys-in-backblaze"&gt;Creating application keys in Backblaze&lt;/h2&gt;
&lt;p&gt;Next, navigate to Account → App Keys&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2023-01-23-nextcloud-b2/nextcloud-b2-4_hu_48c9330227ef77ce.webp"
alt="create key 1"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;On Application Keys page, click on “Add a New Application Key”&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2023-01-23-nextcloud-b2/nextcloud-b2-5_hu_da415206b6cb740.webp"
alt="create key 2"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;In popup, enter name of key, allow access only to the bucket we created, and allow list all bucket names for S3 compatibility.&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2023-01-23-nextcloud-b2/nextcloud-b2-6_hu_5595bfa272b26fc6.webp"
alt="create key 3"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;After clicking on Create New Key, you will see your new keyID and applicationKey. Note - it will be displayed only once.&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2023-01-23-nextcloud-b2/nextcloud-b2-7_hu_3528484cfe7f93d3.webp"
alt="create key 4"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;h2 id="configuring-nextcloud"&gt;Configuring Nextcloud&lt;/h2&gt;
&lt;p&gt;Go to &lt;code&gt;config/config.php&lt;/code&gt;file on your Nextcloud server and to &lt;code&gt;$CONFIG&lt;/code&gt; array add&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;objectstore&amp;#39;&lt;/span&gt; =&amp;gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;class&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;\\OC\\Files\\ObjectStore\\S3&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;arguments&amp;#39;&lt;/span&gt; =&amp;gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;bucket&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;nextcloud-testing&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;autocreate&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;key&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;004e8eebeeeef000000000f&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;secret&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;K00400000000000000000000/zU&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;hostname&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;s3.us-west-004.backblazeb2.com&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;port&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#ae81ff"&gt;443&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;use_ssl&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;region&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;auto&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;use_path_style&amp;#39;&lt;/span&gt;=&amp;gt;&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Replace &lt;code&gt;nextcloud-testing&lt;/code&gt; with the name of your bucket. Hostname should be the endpoint of bucket.&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/2023-01-23-nextcloud-b2/nextcloud-b2-8_hu_2a984ebfb5878607.webp"
alt="nextcloud endpoint config"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;&lt;code&gt;config.php&lt;/code&gt; should look something like that&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;$CONFIG&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;array&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;instanceid&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;...&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;passwordsalt&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;...&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;secret&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;...&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;trusted_domains&amp;#39;&lt;/span&gt; =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;array&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;nc.issei.space&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;datadirectory&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;/home/issei/web/nc.issei.space/public_html/data&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;dbtype&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;mysql&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;version&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;25.0.3.2&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;overwrite.cli.url&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;https://nc.issei.space&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;dbname&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;issei_ncs3&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;dbhost&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;dbport&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;dbtableprefix&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;oc_&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;mysql.utf8mb4&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;dbuser&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;issei_ncs3&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;dbpassword&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;...&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;installed&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;objectstore&amp;#39;&lt;/span&gt; =&amp;gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;class&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;\\OC\\Files\\ObjectStore\\S3&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;arguments&amp;#39;&lt;/span&gt; =&amp;gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;bucket&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;nextcloud-testing&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;autocreate&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;key&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;004e8eebeeeef000000000f&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;secret&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;K00400000000000000000000/zU&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;hostname&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;s3.us-west-004.backblazeb2.com&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;port&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#ae81ff"&gt;443&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;use_ssl&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;region&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;auto&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// required for some non Amazon S3 implementations
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;use_path_style&amp;#39;&lt;/span&gt;=&amp;gt;&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Save the file and visit Nextcloud.&lt;/p&gt;
&lt;p&gt;Note: if you uploaded files prior to setting object store you will no longer see them (but they still exist on local filesystem).&lt;/p&gt;
&lt;p&gt;Try to upload a file, if it succeeds, congratulation, your Nextcloud instance will now use B2 as primary storage!&lt;/p&gt;
&lt;h2 id="basic-troubleshooting-guide"&gt;Basic troubleshooting guide&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Add to config array &lt;code&gt;'debug' =&amp;gt; true,&lt;/code&gt; It will print any errors.&lt;/li&gt;
&lt;li&gt;Try to access bucket with awscli or WinSCP on your local machine.&lt;/li&gt;
&lt;/ol&gt;</content></item><item><title>Password prompt while trying to use 'minikube tunnel' (docker@127.0.0.1's password:)</title><link>https://issei.space/blog/windows-minikube-tunnel-password/</link><pubDate>Thu, 03 Nov 2022 10:40:56 +0200</pubDate><guid>https://issei.space/blog/windows-minikube-tunnel-password/</guid><description>&lt;h2 id="issue"&gt;Issue&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ minikube tunnel
✅ Tunnel successfully started
📌 NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible ...
🏃 Starting tunnel for service balanced.
docker@127.0.0.1&amp;#39;s password:
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="solution"&gt;Solution&lt;/h2&gt;
&lt;p&gt;You need to add minikube&amp;rsquo;s ssh key to your ssh agent&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ssh-add C:\Users\user\.minikube\machines\minikube\id_rsa
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="issues-with-ssh-add"&gt;Issues with ssh-add&lt;/h2&gt;
&lt;h3 id="cannot-use-ssh-add-agent-not-running"&gt;Cannot use ssh-add, agent not running&lt;/h3&gt;
&lt;p&gt;Make sure ssh-agent is running&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="permissions-for-cusersuserminikubemachinesminikubeid_rsa-are-too-open"&gt;Permissions for &amp;lsquo;C:\Users\user.minikube\machines\minikube\id_rsa&amp;rsquo; are too open.&lt;/h3&gt;
&lt;p&gt;In case you get &amp;ldquo;Permissions for &amp;lsquo;C:\Users\user\.minikube\machines\minikube\id_rsa&amp;rsquo; are too open.&amp;rdquo; you might need to copy &lt;code&gt;id_rsa&lt;/code&gt; to desktop and change permissions
&lt;a href="https://superuser.com/a/1296046"&gt;https://superuser.com/a/1296046&lt;/a&gt;&lt;/p&gt;</description><content>&lt;h2 id="issue"&gt;Issue&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ minikube tunnel
✅ Tunnel successfully started
📌 NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible ...
🏃 Starting tunnel for service balanced.
docker@127.0.0.1&amp;#39;s password:
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="solution"&gt;Solution&lt;/h2&gt;
&lt;p&gt;You need to add minikube&amp;rsquo;s ssh key to your ssh agent&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ssh-add C:\Users\user\.minikube\machines\minikube\id_rsa
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="issues-with-ssh-add"&gt;Issues with ssh-add&lt;/h2&gt;
&lt;h3 id="cannot-use-ssh-add-agent-not-running"&gt;Cannot use ssh-add, agent not running&lt;/h3&gt;
&lt;p&gt;Make sure ssh-agent is running&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="permissions-for-cusersuserminikubemachinesminikubeid_rsa-are-too-open"&gt;Permissions for &amp;lsquo;C:\Users\user.minikube\machines\minikube\id_rsa&amp;rsquo; are too open.&lt;/h3&gt;
&lt;p&gt;In case you get &amp;ldquo;Permissions for &amp;lsquo;C:\Users\user\.minikube\machines\minikube\id_rsa&amp;rsquo; are too open.&amp;rdquo; you might need to copy &lt;code&gt;id_rsa&lt;/code&gt; to desktop and change permissions
&lt;a href="https://superuser.com/a/1296046"&gt;https://superuser.com/a/1296046&lt;/a&gt;&lt;/p&gt;</content></item><item><title>Archivit</title><link>https://issei.space/projects/archivit/</link><pubDate>Thu, 13 Oct 2022 00:24:56 +0200</pubDate><guid>https://issei.space/projects/archivit/</guid><description>&lt;h1 id="what-is-archivit"&gt;What is Archivit?&lt;/h1&gt;
&lt;p&gt;Archivit is a application that can archive Reddit subreddits posts with comments.
It is fully open-source and free to use, you can find it on my github - &lt;a href="https://github.com/ihyoudou/archivit"&gt;github.com/ihyoudou/archivit&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="usecase"&gt;Usecase&lt;/h1&gt;
&lt;p&gt;Although i did this project mostly because i wanted to try out Laravel Livewire I do see some usecases.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Archiving history, changes of subreddit&lt;/li&gt;
&lt;li&gt;Using the post data, images from posts for machine learning&lt;/li&gt;
&lt;li&gt;Gathering statistics&lt;/li&gt;
&lt;/ul&gt;</description><content>&lt;h1 id="what-is-archivit"&gt;What is Archivit?&lt;/h1&gt;
&lt;p&gt;Archivit is a application that can archive Reddit subreddits posts with comments.
It is fully open-source and free to use, you can find it on my github - &lt;a href="https://github.com/ihyoudou/archivit"&gt;github.com/ihyoudou/archivit&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="usecase"&gt;Usecase&lt;/h1&gt;
&lt;p&gt;Although i did this project mostly because i wanted to try out Laravel Livewire I do see some usecases.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Archiving history, changes of subreddit&lt;/li&gt;
&lt;li&gt;Using the post data, images from posts for machine learning&lt;/li&gt;
&lt;li&gt;Gathering statistics&lt;/li&gt;
&lt;/ul&gt;</content></item><item><title>Ducopay</title><link>https://issei.space/projects/ducopay/</link><pubDate>Sun, 14 Aug 2022 00:24:56 +0200</pubDate><guid>https://issei.space/projects/ducopay/</guid><description>&lt;h2 id="what-it-is"&gt;What it is?&lt;/h2&gt;
&lt;p&gt;Ducopay is a simple payment gateway for a internet currency called &lt;a href="https://duinocoin.com"&gt;Duinocoin&lt;/a&gt;. It features &amp;ldquo;p2p&amp;rdquo; payment method. In the first version, the coins were send at first to our account, tax was subtracted, and the rest was send to seller, but later it was removed, and the payment goes directly to seller.&lt;/p&gt;
&lt;p&gt;It features very simple API and working mechanism&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You create new transaction (as a result you get a transaction ID)&lt;/li&gt;
&lt;li&gt;Then shop redirect you to Ducopay website for payment&lt;/li&gt;
&lt;li&gt;On Ducopay page after successful payment Duinocoin transaction ID is send to backend for verification&lt;/li&gt;
&lt;li&gt;If Duinocoin transaction is valid, the Ducopay server sends a callback to shop&lt;/li&gt;
&lt;li&gt;Shop mark order as &amp;lsquo;payment successful&amp;rsquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="integrations"&gt;Integrations&lt;/h2&gt;
&lt;p&gt;I created some demo applications in PHP and Python (with Flask), plus Wordpress Woocommerce plugin.&lt;/p&gt;</description><content>&lt;h2 id="what-it-is"&gt;What it is?&lt;/h2&gt;
&lt;p&gt;Ducopay is a simple payment gateway for a internet currency called &lt;a href="https://duinocoin.com"&gt;Duinocoin&lt;/a&gt;. It features &amp;ldquo;p2p&amp;rdquo; payment method. In the first version, the coins were send at first to our account, tax was subtracted, and the rest was send to seller, but later it was removed, and the payment goes directly to seller.&lt;/p&gt;
&lt;p&gt;It features very simple API and working mechanism&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You create new transaction (as a result you get a transaction ID)&lt;/li&gt;
&lt;li&gt;Then shop redirect you to Ducopay website for payment&lt;/li&gt;
&lt;li&gt;On Ducopay page after successful payment Duinocoin transaction ID is send to backend for verification&lt;/li&gt;
&lt;li&gt;If Duinocoin transaction is valid, the Ducopay server sends a callback to shop&lt;/li&gt;
&lt;li&gt;Shop mark order as &amp;lsquo;payment successful&amp;rsquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="integrations"&gt;Integrations&lt;/h2&gt;
&lt;p&gt;I created some demo applications in PHP and Python (with Flask), plus Wordpress Woocommerce plugin.&lt;/p&gt;
&lt;p&gt;Go to Ducopay Docs to learn more: &lt;a href="https://docs.ducopay.com/example/"&gt;https://docs.ducopay.com/example/&lt;/a&gt;&lt;br&gt;
Link to Ducopay: &lt;a href="https://ducopay.com"&gt;https://ducopay.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ducopay was written using PHP framework Symfony&lt;/p&gt;</content></item><item><title>TrueTracker</title><link>https://issei.space/projects/truetracker/</link><pubDate>Sun, 14 Aug 2022 00:24:56 +0200</pubDate><guid>https://issei.space/projects/truetracker/</guid><description>&lt;h2 id="what-it-is"&gt;What it is?&lt;/h2&gt;
&lt;p&gt;TrueTracker is my first PHP project created using Symfony framework. It is a simple RMA portal.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Repair shop register repair request (input serial numbers, customer details)&lt;/li&gt;
&lt;li&gt;Repair shop give customer repair tracking code&lt;/li&gt;
&lt;li&gt;Customer can check status of repair on portal&lt;/li&gt;
&lt;li&gt;Repair shop can add notes, update repair status&lt;/li&gt;
&lt;li&gt;System can send Email notifications about change in status.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Frontend is using Bootstrap 5 + jQuery&lt;/p&gt;
&lt;h2 id="features"&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Display repair status for customer&lt;/li&gt;
&lt;li&gt;Generate QR Code for quick lookup&lt;/li&gt;
&lt;li&gt;Ability to attach pictures and description to status&lt;/li&gt;
&lt;li&gt;Search bar for shop - can filter by customer&lt;/li&gt;
&lt;li&gt;Different permissions level (employee, admin)&lt;/li&gt;
&lt;li&gt;Generate repair raport to PDF&lt;/li&gt;
&lt;li&gt;Status messages can be customized&lt;/li&gt;
&lt;li&gt;Send email notification about status change&lt;/li&gt;
&lt;li&gt;Email notification HTML can be changed from admin page&lt;/li&gt;
&lt;li&gt;Automatic updates&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="screenshots"&gt;Screenshots&lt;/h2&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/truetracker/firefox_8TiVib6zRY_hu_a0aaea3da6ca223d.webp"
alt="user list"
loading="lazy"
/&gt;
List of users&lt;/p&gt;</description><content>&lt;h2 id="what-it-is"&gt;What it is?&lt;/h2&gt;
&lt;p&gt;TrueTracker is my first PHP project created using Symfony framework. It is a simple RMA portal.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Repair shop register repair request (input serial numbers, customer details)&lt;/li&gt;
&lt;li&gt;Repair shop give customer repair tracking code&lt;/li&gt;
&lt;li&gt;Customer can check status of repair on portal&lt;/li&gt;
&lt;li&gt;Repair shop can add notes, update repair status&lt;/li&gt;
&lt;li&gt;System can send Email notifications about change in status.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Frontend is using Bootstrap 5 + jQuery&lt;/p&gt;
&lt;h2 id="features"&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Display repair status for customer&lt;/li&gt;
&lt;li&gt;Generate QR Code for quick lookup&lt;/li&gt;
&lt;li&gt;Ability to attach pictures and description to status&lt;/li&gt;
&lt;li&gt;Search bar for shop - can filter by customer&lt;/li&gt;
&lt;li&gt;Different permissions level (employee, admin)&lt;/li&gt;
&lt;li&gt;Generate repair raport to PDF&lt;/li&gt;
&lt;li&gt;Status messages can be customized&lt;/li&gt;
&lt;li&gt;Send email notification about status change&lt;/li&gt;
&lt;li&gt;Email notification HTML can be changed from admin page&lt;/li&gt;
&lt;li&gt;Automatic updates&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="screenshots"&gt;Screenshots&lt;/h2&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/truetracker/firefox_8TiVib6zRY_hu_a0aaea3da6ca223d.webp"
alt="user list"
loading="lazy"
/&gt;
List of users&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/truetracker/example_email_hu_ac2c0242ed1920a.webp"
alt="example email notification"
loading="lazy"
/&gt;
Example email notification&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/truetracker/example_raport_hu_ecbb09649e30a9cd.webp"
alt="example report"
loading="lazy"
/&gt;
Example of exported status report&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/truetracker/searchbar_hu_60212686491c9f67.webp"
alt="searchbar"
loading="lazy"
/&gt;
Search bar can search by serial number, customer email or phone number, repair order descriptions&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/truetracker/repair_order_hu_1343f7756fbe7dea.webp"
alt="repair orders"
loading="lazy"
/&gt;
List of repair orders&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/truetracker/firefox_oWZE66Z0RX_hu_cfbb56add3248d04.webp"
alt="predefined states"
loading="lazy"
/&gt;
Predefined states&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/truetracker/add_new_status_hu_186cd46e9446a610.webp"
alt="adding new status to repair"
loading="lazy"
/&gt;
Adding new status to repair order. Status can be visible for customer or it can be set to interal (only employees can see them)&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/truetracker/shop_repair_view_hu_d0d61d60f3d8a36f.webp"
alt="repair order view for shop"
loading="lazy"
/&gt;
Repair order view for shop&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/truetracker/repair_view_customer_hu_4d43847f1a9d16b1.webp"
alt="repair view for customer"
loading="lazy"
/&gt;
Repair order view for customer&lt;/p&gt;</content></item><item><title>Bułkowzów</title><link>https://issei.space/projects/bulkowoz/</link><pubDate>Sat, 13 Aug 2022 00:24:56 +0200</pubDate><guid>https://issei.space/projects/bulkowoz/</guid><description>&lt;h2 id="o-projekcie"&gt;O projekcie&lt;/h2&gt;
&lt;p&gt;Aplikacja była moim projektem na zaliczenie praktyk zawodowych w technikum (2020) - miał być to sklep internetowy który umożliwia rezerwacje/zamówienie danego posiłku oraz stworzenie bułki z własnymi składnikami.
Aplikacja została napisana w czystym PHP7, wykorzystuje bazę danych MySQL oraz bibliotekę CSS Bootstrap 4.
&lt;img
src="https://issei.space/images/projects/bulkowoz/pvnSwiJ7Vm_hu_59c199a2bfb4592b.webp"
alt="main"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;h2 id="funkcje-aplikacji"&gt;Funkcje aplikacji&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rejestracja oraz logowanie użytkowników&lt;/li&gt;
&lt;li&gt;Weryfikowanie konta za pomocą wiadomości email&lt;/li&gt;
&lt;li&gt;System uprawnień (użytkownik/administrator)&lt;/li&gt;
&lt;li&gt;Możliwość wygenerowania kodu odbioru zamówień (oraz kodu QR)&lt;/li&gt;
&lt;li&gt;Możliwość wygenerowania &amp;ldquo;tokenu offline&amp;rdquo; który umożliwia sprawdzenie ostatnich zamówień z danego konta&lt;/li&gt;
&lt;li&gt;Możliwość ułożenia własnej bułki z predefiniowanych składników oraz obliczanie ceny&lt;/li&gt;
&lt;li&gt;System ocen oraz komenatrzy pod każdym produktem&lt;/li&gt;
&lt;li&gt;Możliwość zmiany podstawowych informacji z panelu administratora&lt;/li&gt;
&lt;li&gt;Możliwość ustawienia konkretnych godzin w których można zarezerować produkt&lt;/li&gt;
&lt;li&gt;Responsywny design&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/bulkowoz/firefox_aGhm47JLMY_hu_bbf21358b0fe25b1.webp"
alt="edytowanie informacji"
loading="lazy"
/&gt;
&lt;/p&gt;</description><content>&lt;h2 id="o-projekcie"&gt;O projekcie&lt;/h2&gt;
&lt;p&gt;Aplikacja była moim projektem na zaliczenie praktyk zawodowych w technikum (2020) - miał być to sklep internetowy który umożliwia rezerwacje/zamówienie danego posiłku oraz stworzenie bułki z własnymi składnikami.
Aplikacja została napisana w czystym PHP7, wykorzystuje bazę danych MySQL oraz bibliotekę CSS Bootstrap 4.
&lt;img
src="https://issei.space/images/projects/bulkowoz/pvnSwiJ7Vm_hu_59c199a2bfb4592b.webp"
alt="main"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;h2 id="funkcje-aplikacji"&gt;Funkcje aplikacji&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rejestracja oraz logowanie użytkowników&lt;/li&gt;
&lt;li&gt;Weryfikowanie konta za pomocą wiadomości email&lt;/li&gt;
&lt;li&gt;System uprawnień (użytkownik/administrator)&lt;/li&gt;
&lt;li&gt;Możliwość wygenerowania kodu odbioru zamówień (oraz kodu QR)&lt;/li&gt;
&lt;li&gt;Możliwość wygenerowania &amp;ldquo;tokenu offline&amp;rdquo; który umożliwia sprawdzenie ostatnich zamówień z danego konta&lt;/li&gt;
&lt;li&gt;Możliwość ułożenia własnej bułki z predefiniowanych składników oraz obliczanie ceny&lt;/li&gt;
&lt;li&gt;System ocen oraz komenatrzy pod każdym produktem&lt;/li&gt;
&lt;li&gt;Możliwość zmiany podstawowych informacji z panelu administratora&lt;/li&gt;
&lt;li&gt;Możliwość ustawienia konkretnych godzin w których można zarezerować produkt&lt;/li&gt;
&lt;li&gt;Responsywny design&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/bulkowoz/firefox_aGhm47JLMY_hu_bbf21358b0fe25b1.webp"
alt="edytowanie informacji"
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/bulkowoz/firefox_3jixcufuyi_hu_909f68ee41e310c4.webp"
alt=""
loading="lazy"
/&gt;
&lt;img
src="https://issei.space/images/projects/bulkowoz/firefox_gY3SyIgte3_hu_3d63ccd07a376288.webp"
alt=""
loading="lazy"
/&gt;
&lt;img
src="https://issei.space/images/projects/bulkowoz/firefox_oBDazxVfo7_hu_232233556901c65a.webp"
alt=""
loading="lazy"
/&gt;
&lt;img
src="https://issei.space/images/projects/bulkowoz/firefox_OsQnfS3CeB_hu_243d08e6bc8bfb01.webp"
alt=""
loading="lazy"
/&gt;
&lt;img
src="https://issei.space/images/projects/bulkowoz/firefox_UbSpC01yHC_hu_dc64604089e93ccb.webp"
alt=""
loading="lazy"
/&gt;
&lt;/p&gt;</content></item><item><title>Mailevi</title><link>https://issei.space/projects/mailevi/</link><pubDate>Sat, 13 Aug 2022 00:24:56 +0200</pubDate><guid>https://issei.space/projects/mailevi/</guid><description>&lt;h2 id="założenia-projektu"&gt;Założenia projektu&lt;/h2&gt;
&lt;p&gt;MailEvi to prosty system do ewidencji fizycznej korespondecji oraz przesyłek do danej instytucji.
Aplikacja została napisana w czystym PHP7, wykorzystuje bazę danych MySQL oraz bibliotekę CSS Bootstrap 4.&lt;/p&gt;
&lt;h2 id="założenia-projektu-1"&gt;Założenia projektu&lt;/h2&gt;
&lt;p&gt;Projekt powstał na zlecenie instytucji i miał być zastępstwem dla arkusza kalkulacyjnego.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dodawanie poczty przychodzącej i wychodzącej, wraz z danymi nadawcy/odbiorcy, opcjonalnym zdjęciem oraz symbolem.&lt;/li&gt;
&lt;li&gt;Możliwość dodawania, modyfikacji oraz usuwania symboli przez pracowników&lt;/li&gt;
&lt;li&gt;Automatyczne uzupełnianie inicjałów w kreatorze symbolu&lt;/li&gt;
&lt;li&gt;Lista poczty podzielona na pocztę przychodzącą i wychodzącą&lt;/li&gt;
&lt;li&gt;Możliwość sortowania tabeli oraz wyszukiwanie.&lt;/li&gt;
&lt;li&gt;Możliwość eksportu listy do pliku CSV&lt;/li&gt;
&lt;li&gt;Podział na konta administratora oraz pracownika&lt;/li&gt;
&lt;li&gt;Widok dla administratora kto dodał dany rekord, data ostatniego logowania oraz możliwość zmiany haseł użytkowników.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/mailevi/asSLoPNQ2k_hu_846028eecd3dceeb.webp"
alt="login screen"
loading="lazy"
/&gt;
Login screen&lt;/p&gt;</description><content>&lt;h2 id="założenia-projektu"&gt;Założenia projektu&lt;/h2&gt;
&lt;p&gt;MailEvi to prosty system do ewidencji fizycznej korespondecji oraz przesyłek do danej instytucji.
Aplikacja została napisana w czystym PHP7, wykorzystuje bazę danych MySQL oraz bibliotekę CSS Bootstrap 4.&lt;/p&gt;
&lt;h2 id="założenia-projektu-1"&gt;Założenia projektu&lt;/h2&gt;
&lt;p&gt;Projekt powstał na zlecenie instytucji i miał być zastępstwem dla arkusza kalkulacyjnego.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dodawanie poczty przychodzącej i wychodzącej, wraz z danymi nadawcy/odbiorcy, opcjonalnym zdjęciem oraz symbolem.&lt;/li&gt;
&lt;li&gt;Możliwość dodawania, modyfikacji oraz usuwania symboli przez pracowników&lt;/li&gt;
&lt;li&gt;Automatyczne uzupełnianie inicjałów w kreatorze symbolu&lt;/li&gt;
&lt;li&gt;Lista poczty podzielona na pocztę przychodzącą i wychodzącą&lt;/li&gt;
&lt;li&gt;Możliwość sortowania tabeli oraz wyszukiwanie.&lt;/li&gt;
&lt;li&gt;Możliwość eksportu listy do pliku CSV&lt;/li&gt;
&lt;li&gt;Podział na konta administratora oraz pracownika&lt;/li&gt;
&lt;li&gt;Widok dla administratora kto dodał dany rekord, data ostatniego logowania oraz możliwość zmiany haseł użytkowników.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/mailevi/asSLoPNQ2k_hu_846028eecd3dceeb.webp"
alt="login screen"
loading="lazy"
/&gt;
Login screen&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/mailevi/explorer_Y2GltzWAyR_hu_f39439ba681a46b0.webp"
alt="csv export"
loading="lazy"
/&gt;
Eksport do pliku CSV&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://issei.space/images/projects/mailevi/v8V1yj6D8e_hu_4e642957715f5964.webp"
alt="details"
loading="lazy"
/&gt;
Dodatkowe informacje o korespondencji&lt;/p&gt;</content></item><item><title>'Hackowanie' ZOOMki - czyli co można zrobić z ramką na zdjęcia Zoom.me</title><link>https://issei.space/blog/hackowanie-zoomki/</link><pubDate>Tue, 24 Nov 2020 00:24:56 +0200</pubDate><guid>https://issei.space/blog/hackowanie-zoomki/</guid><description>&lt;p&gt;Jakiś czas temu od mojego przyjaciela (dzięki &lt;a href="https://www.instagram.com/oskarhyung/"&gt;Oskar!&lt;/a&gt;) dostałem ramkę &lt;a href="https://zoom.me"&gt;zoom.me&lt;/a&gt; ponieważ nie miał do niej zasilacza, a po szybkim sprawdzeniu w internecie co to w ogóle jest, oboje się zainteresowaliśmy. Tak, jak widać po zdjęciu wyżej, można na niej uruchomić DOOMa ;)&lt;/p&gt;
&lt;h2 id="ale-od-początku---co-to-jest-w-ogóle-ta-ramka-zoomme"&gt;Ale od początku - co to jest w ogóle ta ramka zoom.me?&lt;/h2&gt;
&lt;p&gt;Jak możemy przeczytać na stronie producenta:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ZOOM.ME to nowe podejście do komunikacji z bliskimi. Dzięki ZOOM.ME każdy może dzielić się z przyjaciółmi wspaniałymi chwilami uchwyconymi na zdjęciach.&lt;/p&gt;</description><content>&lt;p&gt;Jakiś czas temu od mojego przyjaciela (dzięki &lt;a href="https://www.instagram.com/oskarhyung/"&gt;Oskar!&lt;/a&gt;) dostałem ramkę &lt;a href="https://zoom.me"&gt;zoom.me&lt;/a&gt; ponieważ nie miał do niej zasilacza, a po szybkim sprawdzeniu w internecie co to w ogóle jest, oboje się zainteresowaliśmy. Tak, jak widać po zdjęciu wyżej, można na niej uruchomić DOOMa ;)&lt;/p&gt;
&lt;h2 id="ale-od-początku---co-to-jest-w-ogóle-ta-ramka-zoomme"&gt;Ale od początku - co to jest w ogóle ta ramka zoom.me?&lt;/h2&gt;
&lt;p&gt;Jak możemy przeczytać na stronie producenta:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ZOOM.ME to nowe podejście do komunikacji z bliskimi. Dzięki ZOOM.ME każdy może dzielić się z przyjaciółmi wspaniałymi chwilami uchwyconymi na zdjęciach.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Czyli w skrócie - jest to cyfrowa ramka na zdjęcia na którą można wysłać zdjęcia z dowolnego miejsca na świecie, korzystając z aplikacji lub wprost z maila. Została wydana w 2014 roku w współpracy z firmą Goclever i niestety nie okazała się takim sukcesem na jaki liczyli jego twórcy, po roku od wydania można było ją kupić za około 200zł. Tutaj pojawia się pierwszy problem, ponieważ jak można zobaczyć w &lt;a href="https://play.google.com/store/apps/details?id=me.zoom.asender"&gt;Sklepie Play&lt;/a&gt; aplikacja ma aż 1.8 gwiazdki, do tego większość opinii wspomina o problemami z połączeniem do serwera&lt;br&gt;
&lt;img
src="https://i.issei.space/LNeGaGHf.png"
alt=""
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;No dobra, ale może już to naprawili, przecież strona jeszcze działa&amp;hellip; Niestety ale próba stworzenia konta przez aplikacje jest niemożliwa, ponieważ nieważne jakiego maila bym tam wpisał, on zawsze jest już zajęty. Z ciekawości spróbowałem wysłać zdjęcie mailem na adres który wyświetla się na ramce, niestety - dostaje wiadomość zwrotną, że mój email nie istnieje w systemie (?!)&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://i.issei.space/36RWEPbI.png"
alt=""
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;Okej, skoro nie mogę w taki sposób skorzystać z ramki to pewnie jest inny sposób? Tak - można kopiować zdjęcia bezpośrednio przez złącze microUSB z komputera. Po podłączeniu do komputera można zauważyć dwa foldery - DCIM oraz Pictures. Aby zdjęcia były widoczne na ramce należy je skopiować do folderu DCIM/ZOOM.ME. I tutaj można zauważyć kolejną ciekawostkę - &lt;strong&gt;mimo przywrócenia ustawień fabrycznych w menu ramki zdjęcia się nie usuwają&lt;/strong&gt;. No dobra, zdjęcia skopiowałem, wyświetlają się, fajnie, ale jednak to trochę mało.&lt;/p&gt;
&lt;h2 id="dostanie-się-do-androida"&gt;Dostanie się do androida&lt;/h2&gt;
&lt;p&gt;Tak, ta ramka na zdjęcia działa pod kontrolą androida w wersji 4.2.2. W środku znajduje się procesor Allwinner A23 wraz z 512MB pamięci ram oraz 4GB pamięci flash. Samo to, że ramka działa na androidzie można samemu dosyć szybko zauważyć - ponieważ podczas wpisywania hasła do sieci WiFi wysuwa się typowa androidowa klawiatura. No to do dzieła - udało mi się w internecie znaleźć instrukcję do ramki, jak i &lt;a href="http://downloadfiles.goclever.com/Tablet/Zoom_me/ZOOM.ME_WiFi_Zmiana_Oprogramowania.pdf"&gt;poradnik od producenta w jaki sposób zaktualizować jej oprogramowanie&lt;/a&gt; oraz &lt;a href="https://forum.xda-developers.com/android/help/goclever-zoom-gapps-t3873801"&gt;post na forum XDA z prośbą o pomoc w wgraniu gapps&lt;/a&gt;. Z instrukcji wynika, że domyślnie powinno być włączone debugowanie USB, więc dostanie się do systemu powinno być bardzo proste. Niestety, ale moja ramka posiadała troszkę nowszą wersje oprogramowania i trik z ośmiokrotnym kliknięciem na wersje oprogramowania aby dostać się do ustawień nie zadziałał a debugowanie USB też nie jest uruchomione.&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://i.issei.space/Eipv7J9R.png"
alt=""
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;W mojej ramce nie ma oryginalnej wersji oprogramowania - oryginalne oprogramowanie zostało wydane 07.10.2014, u mnie jest wersja z 17 grudnia 2014. W instrukcji aktualizacji dostępny jest rom z wersją 17.07.2015 - nie wiem czym się dokładniej różnią.&lt;br&gt;
Na samym początku postanowiłem że skoro mam dostęp do instrukcji aktualizacji softu i pliku z systemem oraz jest to urządzenie z procesorem Allwinner to zmodyfikuję sobie rom i do build.prop dodam opcje aby debugowanie było włączone. Sama ta operacja się powiodła, ale przy głębszym spojrzeniu do instrukcji zauważyłem, że do aktualizacji softu potrzebne jest włączone debugowanie USB (?!). Teoretycznie rozwiązanie tego jest proste - wystarczy wyłączyć urządzenie, przytrzymać przycisk głośności i podłączyć kabel USB. Dlaczego teoretycznie? Ponieważ to jest ramka na zdjęcia która nie ma głośnika oraz przycisków głośności. Zastanawiałem się nad otworzeniem obudowy i poszukaniem na płycie głównej pinów odpowiedzialnych za UART lub/oraz głośności, ale dostałem oświecenia&amp;hellip;&lt;/p&gt;
&lt;h2 id="hm-przecież-to-allwinner"&gt;Hm, przecież to Allwinner&lt;/h2&gt;
&lt;p&gt;&amp;hellip;ciekawe czy obsługuje USB OTG. Wziąłem przejściówkę USB OTG, podłączyłem klawiaturę, i.. Działa! No okej, teraz mogę sterować urządzeniem klawiaturą, ale co mi to daje? Ano właśnie dużo - mogę wykorzystać skrót klawiszowy WIN+spacja aby przejść do wbudowanej przeglądarki - tutaj zauważyłem drobny problem - przeglądarka ma problemy z witrynami korzystającymi z HTTPS, ale jestem już za blisko aby mnie to pokonało - wrzuciłem na prosty serwer www plik APK z &lt;a href="https://github.com/tanujnotes/Olauncher"&gt;Olauncherem&lt;/a&gt; i go pobrałem. Huh - sprawdź pasek powiadomień z postępem pobierania pliku - ale ja nie mam dostępu do paska powiadomień.&lt;/p&gt;
&lt;p&gt;Z ciekawości wszedłem na stronę gdzie można wybrać plik do uploadu i pokazał mi się Open Manager - to było już spore ułatwienie ponieważ znałem ścieżkę do pliku. Próbowałem &amp;ldquo;wydostać się&amp;rdquo; do zwykłego trybu menadżera plików ale nie udało mi się. Przypomniałem sobie, że przecież znam teraz ścieżkę i w przeglądarce mogę wpisać lokalizacje tego pliku, więc wpisałem &lt;code&gt;file://storage/emulated/0/Downloads/launcher.apk&lt;/code&gt; i moim oczom ukazało się okienko z pytaniem, czy na pewno chcę zainstalować tą aplikacje&lt;br&gt;
Po zainstalowaniu launchera wystarczy kliknąć parę razy &amp;ldquo;ESC&amp;rdquo; aby przejść do wyboru programu startowego - ja wybrałem aby domyślnie startował launcher - jeżeli ktoś nadal by chciał korzystać z aplikacji zoom.me może ją po prostu uruchomić z listy.&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://i.issei.space/00f1fFSU.jpg"
alt=""
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;h2 id="jestem-w-androidzie-ale-co-dalej"&gt;Jestem w androidzie ale co dalej?&lt;/h2&gt;
&lt;p&gt;Android który jest w tym urządzeniu jest bez aplikacji google (google-apps gapps) przez co swoją drogą działa lepiej niż się spodziewałem. Nie będę tutaj instalował aplikacji google ponieważ miejsca już jest mało, szkoda dodatkowo zamulać urządzenia, a do tego będą tutaj zbędne. Postanowiłem po prostu skorzystać z stron typu apkmirror oraz ewentualnie instalować aplikacje ze sklepu na moim telefonie a następnie eksportowanie ich apk na to urządzenie.&lt;br&gt;
Swoją drogą - nadal nie mamy przycisków nawigacyjnych - przydały by się aby nie trzeba było podłączać klawiatury. W tym celu potrzebujemy zmodyfikować plik build.prop, a żeby go zmodyfikować musimy mieć roota.&lt;br&gt;
Na szczęście rootowanie androida do wersji 5 na takich prostych konstrukcjach jest banalne, ale nadal potrzebujemy debugowania USB. Teraz kiedy już mamy launcher możemy przejść do ustawień, zjechać w dół -&amp;gt; Opcje programistyczne i zaznaczyć debugowanie USB. Na komputerze powinnyśmy mieć zainstalowane sterowniki ADB - ja zawsze korzystam z &lt;a href="https://forum.xda-developers.com/showthread.php?t=2588979"&gt;tej paczki&lt;/a&gt;. Do rootowania wykorzystam skryptu pod nazwą &amp;ldquo;rootV2&amp;rdquo; &lt;a href="https://www.mediafire.com/download/12b1y3aw0k5dhkx/RootV2.rar"&gt;która jest do pobrania tutaj&lt;/a&gt; - wystarczy wypakować pliki, przejść do folderu, uruchomić skrypt, poczekać chwilę i zaraz powinnyśmy mieć na naszej ramce roota oraz aplikacje SuperSU.&lt;br&gt;
Teraz możemy wykorzystać adb aby zmodyfikować nasz build.prop. W tym celu przechodzimy do wiersza poleceń i wykonujemy komendę &lt;code&gt;adb shell&lt;/code&gt;, a następnie&lt;br&gt;
&lt;code&gt;su echo &amp;quot;qemu.hw.mainkeys=0&amp;quot; &amp;gt;&amp;gt; /system/build.prop&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Po tej operacji należy zrestartować ramkę i powinniśmy już widzieć pasek powiadomień oraz przyciski nawigacyjne&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://i.issei.space/TjqlR0Qq.png"
alt=""
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://i.issei.space/zvhXlQMt.png"
alt=""
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;h2 id="zakończenie"&gt;Zakończenie&lt;/h2&gt;
&lt;p&gt;Teraz kiedy już mamy dostęp do przeglądarki, menadżera plików, ADB, roota oraz normalnego launchera możemy robić wszystko co chcemy na tym urządzeniu.&lt;/p&gt;</content></item><item><title>'Odceglanie' NAS'a Buffalo LS210/LS220</title><link>https://issei.space/blog/odceglanie-buffalo-nas/</link><pubDate>Wed, 06 Nov 2019 00:24:56 +0200</pubDate><guid>https://issei.space/blog/odceglanie-buffalo-nas/</guid><description>&lt;p&gt;Ten poradnik powinien działać dla Buffalo LS210/LS220 i rozwiązać problem z siedmiokrotnym miganiem czerwonej diody podczas rozruchu.&lt;/p&gt;
&lt;p&gt;Na początku informuję że nie odpowiadam za ewentualne uszkodzenia oraz utratę danych! &lt;strong&gt;Przed rozpoczęciem, jeżeli nie mamy kopii zapasowej, należy taką utworzyć&lt;/strong&gt; - więcej informacji jak odczytać dyski z NAS&amp;rsquo;a jest na dole&lt;/p&gt;
&lt;p&gt;W przypadku w którym NAS nie jest w ogóle widoczny w sieci oraz w NAS Navigatorze należy wgrać podstawowy system od początku używając TFTP. Domyślnie NAS nada sobie adres IP 192.168.11.150/24. Adres serwera TFTP (swojego komputera) należy ustawić na 192.168.11.1/24 i upewnić się aby wyłączyć zaporę systemu a następnie podłączyć NAS bezpośrednio do komputera kablem sieciowym.&lt;/p&gt;</description><content>&lt;p&gt;Ten poradnik powinien działać dla Buffalo LS210/LS220 i rozwiązać problem z siedmiokrotnym miganiem czerwonej diody podczas rozruchu.&lt;/p&gt;
&lt;p&gt;Na początku informuję że nie odpowiadam za ewentualne uszkodzenia oraz utratę danych! &lt;strong&gt;Przed rozpoczęciem, jeżeli nie mamy kopii zapasowej, należy taką utworzyć&lt;/strong&gt; - więcej informacji jak odczytać dyski z NAS&amp;rsquo;a jest na dole&lt;/p&gt;
&lt;p&gt;W przypadku w którym NAS nie jest w ogóle widoczny w sieci oraz w NAS Navigatorze należy wgrać podstawowy system od początku używając TFTP. Domyślnie NAS nada sobie adres IP 192.168.11.150/24. Adres serwera TFTP (swojego komputera) należy ustawić na 192.168.11.1/24 i upewnić się aby wyłączyć zaporę systemu a następnie podłączyć NAS bezpośrednio do komputera kablem sieciowym.&lt;/p&gt;
&lt;p&gt;W oknie serwera TFTP powinien pojawić się komunikat &lt;code&gt;listening On: 192.168.11.1:69&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Jeżeli się nie wyświetla, lub wyświetla się inny adres IP należy sprawdzić konfigurację adresów IP (lub spróbować odłączyć i podłączyć przewód sieciowy, może też być konieczne aby przed zmianą IP być podłączonym do obecnej sieci jeżeli adres się nie zmienia na ten który ustawiliśmy)&lt;/p&gt;
&lt;p&gt;Następnie należy przytrzymać czerwony przycisk &amp;ldquo;function&amp;rdquo; z tyłu NAS i podłączyć zasilanie. Należy trzymać przycisk function do czasu kiedy dioda z przodu NAS zacznie migać na biało, następnie puścić przycisk i nadusić go jeszcze raz. W konsoli powinny pokazywać się komunikaty&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Client 192.168.11.150 ... Block Served&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Client 192.168.11.150 ... Block Served&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Teraz NAS powinien być w EM Mode (Emergency mode) i pokazywać się w NAS Navigatorze.&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://i.issei.space/ai389.jpg"
alt=""
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;Następnie należy uruchomić program LSUpdater.exe, poczekać aż wyszuka naszego NAS&amp;rsquo;a i kliknąć przycisk Update.&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://i.issei.space/yp3di.png"
alt=""
loading="lazy"
/&gt;
&lt;/p&gt;
&lt;p&gt;&lt;img
src="https://i.issei.space/8x00q.png"
alt=""
loading="lazy"
/&gt;
&lt;em&gt;&lt;a href="http://commonmanrants.blogspot.com/2014/01/buffalo-linkstation-partition-not-found.html"&gt;źródło&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Proces ten będzie trwał kilka minut, po pomyślnym ukończeniu należy podłączyć NAS do sieci aby dostał adres przez DHCP. Po chwili serwer powinien być widoczny w NAS Navigatorze z jego adresem IP.&lt;/p&gt;
&lt;p&gt;Linki do pobrania wszystkich potrzebnych plików: &lt;a href="https://files.s2.issei.space/blog/Buffalo_ls2xx_recovery.zip"&gt;Download&lt;/a&gt; | &lt;a href="https://mega.nz/#!SRczCaxC!zZGums_mUh5XQUXvyBnLmz7GAaAZKwwJhxtsj87n0Mw"&gt;Mirror [mega.nz]&lt;/a&gt; | &lt;a href="https://drive.google.com/file/d/1jv4Rsm0fKDjrGTUyFFXdOGSFcFRLr43F/view?usp=sharing"&gt;Mirror [GDrive]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Suma kontrolna: &lt;code&gt;SHA1: BA3E87B4C61AAA85D8A58321E35D7B68BEBF97DE&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Dodatkowe informacje:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dane na dyskach są w formacie EXT4 oraz RAID jest tworzony przez MD, więc bez problemu można RAID lub pojedynczy dysk odczytać przez linuxa lub z zastosowaniem przykładowo &lt;a href="http://www.ext2fsd.com/"&gt;Ext2Fsd&lt;/a&gt; pod Windowsem.&lt;/li&gt;
&lt;/ul&gt;</content></item></channel></rss>