<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Victor&#x27;s Blog</title>
    <link rel="self" type="application/atom+xml" href="https://www.victorsavu.eu/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://www.victorsavu.eu"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-05-14T09:54:00+00:00</updated>
    <id>https://www.victorsavu.eu/atom.xml</id>
    <entry xml:lang="en">
        <title>I built a Rust CLI tool without writing a single line of code</title>
        <published>2026-05-14T09:54:00+00:00</published>
        <updated>2026-05-14T09:54:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/blog/subsonic-shuffler/"/>
        <id>https://www.victorsavu.eu/blog/subsonic-shuffler/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/blog/subsonic-shuffler/">&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
&lt;p&gt;This blog post was written by Claude. Like the project itself, not a single word was typed by hand.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I&#x27;ve been self-hosting my music with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.navidrome.org&#x2F;&quot;&gt;Navidrome&lt;&#x2F;a&gt; for a while now, and one thing that always bothered me was the lack of a good way to shuffle a playlist in place. Subsonic clients can shuffle playback, but the playlist order on the server stays fixed — so if I want a fresh random order I had to do it manually.&lt;&#x2F;p&gt;
&lt;p&gt;So I built &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.victorsavu.eu&#x2F;victor&#x2F;subsonic_shuffle&quot;&gt;subsonic-shuffler&lt;&#x2F;a&gt;: a small Rust CLI that shuffles a Subsonic playlist. It can shuffle in place, write the result to a different playlist, or create a new one. It reads credentials from environment variables and runs as a one-shot Podman container on my CoreOS server, triggered nightly at 3 AM by a systemd timer.&lt;&#x2F;p&gt;
&lt;p&gt;The interesting part: I didn&#x27;t write a single line of code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-experiment&quot;&gt;The experiment&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve been using Claude Code for a while for smaller tasks, but this time I wanted to see how far I could push it on a greenfield project with no existing codebase to guide it. The rules I set for myself: describe what I want, answer clarifying questions, review what gets produced — but never touch the keyboard to write code myself.&lt;&#x2F;p&gt;
&lt;p&gt;The result is a fully working Rust project with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A CLI built with &lt;code&gt;clap&lt;&#x2F;code&gt;, using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;opensubsonic&quot;&gt;&lt;code&gt;opensubsonic&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate for the Subsonic API&lt;&#x2F;li&gt;
&lt;li&gt;Flexible source&#x2F;destination options (&lt;code&gt;--source&lt;&#x2F;code&gt;, &lt;code&gt;--source-id&lt;&#x2F;code&gt;, &lt;code&gt;--output&lt;&#x2F;code&gt;, &lt;code&gt;--output-id&lt;&#x2F;code&gt;, &lt;code&gt;--create&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;Helpful error messages that list matching playlists with their IDs when a name is ambiguous&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;code&gt;Justfile&lt;&#x2F;code&gt; for local development&lt;&#x2F;li&gt;
&lt;li&gt;A multi-stage &lt;code&gt;Containerfile&lt;&#x2F;code&gt; producing a minimal Alpine image&lt;&#x2F;li&gt;
&lt;li&gt;The image published to my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.victorsavu.eu&#x2F;victor&#x2F;-&#x2F;packages&#x2F;container&#x2F;subsonic-shuffler&#x2F;latest&quot;&gt;Forgejo container registry&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The crate published to my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.victorsavu.eu&#x2F;victor&#x2F;-&#x2F;packages&#x2F;cargo&#x2F;subsonic-shuffler&#x2F;1.0.0&quot;&gt;Forgejo cargo registry&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;A Quadlet &lt;code&gt;.container&lt;&#x2F;code&gt; file for systemd integration on CoreOS&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All of it committed in a git repository with meaningful commit messages — also written by Claude.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-worked-well&quot;&gt;What worked well&lt;&#x2F;h2&gt;
&lt;p&gt;The back-and-forth felt natural. I&#x27;d describe a feature, Claude would ask clarifying questions when the design wasn&#x27;t obvious (shuffle in place vs. create new? what happens on ambiguous names?), implement it, verify it compiled, then commit. When I asked for changes — removing a redundant flag, changing error message formatting, adjusting the &lt;code&gt;--create&lt;&#x2F;code&gt; semantics — they landed correctly on the first try.&lt;&#x2F;p&gt;
&lt;p&gt;The knowledge of the ecosystem was solid. It looked up the &lt;code&gt;opensubsonic&lt;&#x2F;code&gt; crate&#x27;s actual API on docs.rs before writing code rather than guessing, which meant the implementation was correct from the start.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-still-required-my-input&quot;&gt;What still required my input&lt;&#x2F;h2&gt;
&lt;p&gt;Judgment calls that needed context I held: which registry to publish to, what the container image path should be, how the systemd unit should be structured, what &lt;code&gt;OnCalendar=&lt;&#x2F;code&gt; value to use for the timer. These aren&#x27;t things an AI can know — they&#x27;re decisions about my infrastructure. But once I supplied the answer, execution was immediate and correct.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;For a self-contained tool with a clear spec, AI-assisted development is genuinely useful — not as autocomplete, but as a collaborator that can take a description and produce a working, well-structured result. The limiting factor wasn&#x27;t the code; it was me articulating what I actually wanted.&lt;&#x2F;p&gt;
&lt;p&gt;The source is at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.victorsavu.eu&#x2F;victor&#x2F;subsonic_shuffle&quot;&gt;forgejo.victorsavu.eu&#x2F;victor&#x2F;subsonic_shuffle&lt;&#x2F;a&gt; if you want to use it or read through what was generated.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Backup Radicale to git</title>
        <published>2026-05-10T20:00:00+00:00</published>
        <updated>2026-05-10T20:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/radicale-git/"/>
        <id>https://www.victorsavu.eu/tips/radicale-git/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/radicale-git/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;radicale.org&#x2F;v3.html&quot;&gt;Radicale&lt;&#x2F;a&gt; allows for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;radicale.org&#x2F;v3.html#versioning-collections-with-git&quot;&gt;storage hooks&lt;&#x2F;a&gt; to record changes in git. Getting it working in a container is a bit more involved though. You need:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;code&gt;.gitconfig&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Access to the repository&lt;&#x2F;li&gt;
&lt;li&gt;Configuring Radicale&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;set-up-gitconfig&quot;&gt;Set up &lt;code&gt;.gitconfig&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;git&lt;&#x2F;code&gt; requires a global &lt;code&gt;.gitconfig&lt;&#x2F;code&gt; containing at least a name and email to be able to create commits:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[user]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        email = &amp;lt;a@email.address&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        name = &amp;lt;Some name&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This needs to be mounted into the container (this example assumes the &lt;code&gt;root&lt;&#x2F;code&gt; user):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Volume=&#x2F;var&#x2F;&amp;lt;somewhere&amp;gt;&amp;gt;&#x2F;.gitconfig:&#x2F;root&#x2F;.gitconfig:Z,ro&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;give-radicale-access-to-the-repository&quot;&gt;Give Radicale access to the repository&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;ssh&lt;&#x2F;code&gt; is not available in the repository, we have to use https. To keep things simple, you can add the user and password to the repository URL itself:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git remote add origin https:&#x2F;&#x2F;&amp;lt;user&amp;gt;:&amp;lt;password&amp;gt;@&amp;lt;repository&amp;gt;.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;&quot;&gt;Forgejo&lt;&#x2F;a&gt; supports &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;docs&#x2F;latest&#x2F;user&#x2F;token-scope&#x2F;#specific-repositories&quot;&gt;repository scoped access tokens&lt;&#x2F;a&gt; that are ideal in this case (added to version 15). The token must be used instead of the password and can be restricted to a single repository.&lt;&#x2F;p&gt;
&lt;p&gt;For other git hosts, check what is available and avoid storing your actual user password in plaintext.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;configure-radicale&quot;&gt;Configure Radicale&lt;&#x2F;h3&gt;
&lt;p&gt;Add a hook to commit and upload changes to your radicale config:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[storage]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hook = git add -A &amp;amp;&amp;amp; (git diff --cached --quiet || git commit -m &amp;quot;Changes by \&amp;quot;%(user)s\&amp;quot;&amp;quot;) &amp;amp;&amp;amp; git push&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Use Proton to send emails from Grafana</title>
        <published>2026-04-22T20:30:00+00:00</published>
        <updated>2026-04-22T20:30:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/grafana-proton-email/"/>
        <id>https://www.victorsavu.eu/tips/grafana-proton-email/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/grafana-proton-email/">&lt;p&gt;To allow &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;&quot;&gt;Grafana&lt;&#x2F;a&gt; to send emails using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;proton.me&quot;&gt;Proton&lt;&#x2F;a&gt;, you need to:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Create an SMTP token in Proton from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;account.proton.me&#x2F;u&#x2F;0&#x2F;mail&#x2F;imap-smtp&quot;&gt;settings&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;docs&#x2F;grafana&#x2F;latest&#x2F;setup-grafana&#x2F;configure-grafana&#x2F;#smtp&quot;&gt;Configure Grafana&lt;&#x2F;a&gt; using &lt;code&gt;grafana.ini&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[smtp]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;enabled=true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;host=smtp.protonmail.ch:587&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;user={{SMTP username}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;from_address={{SMTP username}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;startTLS_policy=MandatoryStartTLS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;password={{SMTP token}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where &lt;code&gt;{{SMTP username}}&lt;&#x2F;code&gt; and &lt;code&gt;{{SMTP token}}&lt;&#x2F;code&gt; should be copied from Proton.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>I&#x27;m switching from Proton Calendar to Radicale</title>
        <published>2026-04-03T19:50:00+00:00</published>
        <updated>2026-04-03T19:50:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/blog/switching-to-radicale/"/>
        <id>https://www.victorsavu.eu/blog/switching-to-radicale/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/blog/switching-to-radicale/">&lt;p&gt;I have given up trying to use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calendar.proton.me&quot;&gt;Proton Calendar&lt;&#x2F;a&gt; as my main calendar application due to three big issues:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Proton does not use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;CalDAV&quot;&gt;CalDAV&lt;&#x2F;a&gt; and on Android, other applications can&#x27;t read calendars from the Proton Calendar app. To synchronize events on my smartwatch I need to export the calendar to a 3rd party service (Google in my case).&lt;&#x2F;li&gt;
&lt;li&gt;To be able to plan things, I need to see my work events in my calendar app. Proton has a quite large &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;protonmail.uservoice.com&#x2F;forums&#x2F;932842-lumo&#x2F;suggestions&#x2F;44698060-decrease-sync-delay&quot;&gt;sync delay&lt;&#x2F;a&gt; for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;proton.me&#x2F;support&#x2F;subscribe-to-external-calendar&quot;&gt;external calendars&lt;&#x2F;a&gt;, large enough for me to make mistakes.&lt;&#x2F;li&gt;
&lt;li&gt;Proton contacts also don&#x27;t sync with Android (you can &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;proton.me&#x2F;support&#x2F;proton-contacts-mobile&quot;&gt;import, but not export&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;To make my life simpler, I&#x27;ve migrated to a self-hosted instance of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;radicale.org&#x2F;v3.html&quot;&gt;Radicale&lt;&#x2F;a&gt;. I lose the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mail.proton.me&quot;&gt;Proton Mail&lt;&#x2F;a&gt; app integration, but I can still use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.thunderbird.net&quot;&gt;Thunderbird&lt;&#x2F;a&gt; to manage everything including contacts. On Android I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.davx5.com&#x2F;&quot;&gt;DAVx5&lt;&#x2F;a&gt; to sync everything with much shorter sync delays. I hope &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bitfireAT&#x2F;webdav-push&quot;&gt;CalDAV Push&lt;&#x2F;a&gt; will make the delay go completely away once Radicale supports it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;see-also&quot;&gt;See also&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;radicale-git&#x2F;&quot;&gt;Backup Radicale to git&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;radicale-podman-user&#x2F;&quot;&gt;Override the radicale user when using docker&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;radicale-link-share-calendar&#x2F;&quot;&gt;Sharing Calendars using Radicale and symlinks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Sharing Calendars using Radicale and symlinks</title>
        <published>2026-04-03T19:00:00+00:00</published>
        <updated>2026-04-03T19:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/radicale-link-share-calendar/"/>
        <id>https://www.victorsavu.eu/tips/radicale-link-share-calendar/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/radicale-link-share-calendar/">&lt;p&gt;While &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;radicale.org&#x2F;v3.html&quot;&gt;Radicale&lt;&#x2F;a&gt; now &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Kozea&#x2F;Radicale&#x2F;wiki&#x2F;Sharing-Collections&quot;&gt;supports sharing&lt;&#x2F;a&gt;, an older and very simple way to make it work is to just use symlinks. Here I assume &lt;code&gt;user1&lt;&#x2F;code&gt; wants to share their &lt;code&gt;planning&lt;&#x2F;code&gt; calendar with &lt;code&gt;user2&lt;&#x2F;code&gt; with full permissions.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd &amp;lt;path to collection-root&amp;gt;&#x2F;user2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ln -s ..&#x2F;user1&#x2F;planning&#x2F; user1_planning&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Override the radicale user when using docker</title>
        <published>2026-04-03T18:40:00+00:00</published>
        <updated>2026-04-03T18:40:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/radicale-podman-user/"/>
        <id>https://www.victorsavu.eu/tips/radicale-podman-user/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/radicale-podman-user/">&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;radicale.org&#x2F;v3.html&quot;&gt;Radicale&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Kozea&#x2F;Radicale&#x2F;blob&#x2F;master&#x2F;Dockerfile&quot;&gt;Dockerfile&lt;&#x2F;a&gt; hardcodes &lt;code&gt;1000&lt;&#x2F;code&gt; as the UID running inside the container. If that user is not available, it can still be overridden. If using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.podman.io&#x2F;en&#x2F;latest&#x2F;markdown&#x2F;podman-quadlet.1.html&quot;&gt;quadlet&lt;&#x2F;a&gt; You can add &lt;code&gt;User=&amp;lt;your choice&amp;gt;&lt;&#x2F;code&gt; to the &lt;code&gt;[Container]&lt;&#x2F;code&gt; section. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;podman.io&#x2F;&quot;&gt;podman&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.docker.com&#x2F;products&#x2F;cli&#x2F;&quot;&gt;docker&lt;&#x2F;a&gt; CLI equivalent is &lt;code&gt;--user &amp;lt;your choice&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Allow Thunderbird to archive proton emails</title>
        <published>2026-04-03T18:30:00+00:00</published>
        <updated>2026-04-03T18:30:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/thunderbird-proton-archive/"/>
        <id>https://www.victorsavu.eu/tips/thunderbird-proton-archive/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/thunderbird-proton-archive/">&lt;p&gt;If you get a &lt;code&gt;Operation Not Allowed&lt;&#x2F;code&gt; error when archiving emails in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.thunderbird.net&quot;&gt;Thunderbird&lt;&#x2F;a&gt; when using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;proton.me&#x2F;mail&#x2F;bridge&quot;&gt;Proton Bridge&lt;&#x2F;a&gt;, try to update your account settings in Thunderbird.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;Settings&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Open &lt;code&gt;Account Settings&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Select your bridge account.&lt;&#x2F;li&gt;
&lt;li&gt;Open &lt;code&gt;Copies &amp;amp; Folders&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Go to the &lt;code&gt;Message Archives&lt;&#x2F;code&gt; section and select your archive folder in Proton.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;a href=&quot;&amp;#x2F;thunderbird-proton-archive&amp;#x2F;settings.png&quot;&gt;
    &lt;img src=&quot;&amp;#x2F;thunderbird-proton-archive&amp;#x2F;settings.png&quot; alt=&quot;Set the archived folder&quot; class=&quot;image&quot;&#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Thank you &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;ProtonMail&#x2F;comments&#x2F;136317m&#x2F;operation_not_allowed_when_attempting_to_archive&#x2F;&quot;&gt;years old reddit question&lt;&#x2F;a&gt; and the reply from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;user&#x2F;ProtonMail&#x2F;&quot;&gt;ProtonMail&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Create a BIMI compatible file from Inkscape</title>
        <published>2026-03-22T21:00:00+00:00</published>
        <updated>2026-03-23T20:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/inkscape-bimi/"/>
        <id>https://www.victorsavu.eu/tips/inkscape-bimi/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/inkscape-bimi/">&lt;h2 id=&quot;background&quot;&gt;Background&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bimigroup.org&#x2F;&quot;&gt;BIMI&lt;&#x2F;a&gt; only supports &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;draft-svg-tiny-ps-abrotman&quot;&gt;SVG Tiny Portable&#x2F;Secure&lt;&#x2F;a&gt;, which is a quite restricted profile. My logo is quite simple, but Adobe Illustrator and Inkscape both create entries that are not compatible with it, mostly by using&lt;code&gt;style&lt;&#x2F;code&gt; attributes. Saving an Optimized SVG and editing the resulting file worked from Inkscape.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;steps&quot;&gt;Steps&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-add-a-title&quot;&gt;1. Add a title&lt;&#x2F;h3&gt;
&lt;p&gt;The document should have a title for the format to be valid for BIMI. Add it in Inkscape:&lt;&#x2F;p&gt;
&lt;a href=&quot;&amp;#x2F;inkscape-bimi&amp;#x2F;metadata.png&quot;&gt;
    &lt;img src=&quot;&amp;#x2F;inkscape-bimi&amp;#x2F;metadata.png&quot; alt=&quot;Document Metadata page&quot; class=&quot;image&quot;&#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;h3 id=&quot;2-save-the-right-format&quot;&gt;2. Save the right format&lt;&#x2F;h3&gt;
&lt;p&gt;Use &lt;code&gt;Optimized SVG&lt;&#x2F;code&gt; in the &lt;code&gt;Save As&lt;&#x2F;code&gt; dialog:&lt;&#x2F;p&gt;
&lt;a href=&quot;&amp;#x2F;inkscape-bimi&amp;#x2F;save.png&quot;&gt;
    &lt;img src=&quot;&amp;#x2F;inkscape-bimi&amp;#x2F;save.png&quot; alt=&quot;Save As Optimized SVG&quot; class=&quot;image&quot;&#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;h3 id=&quot;3-configure-export&quot;&gt;3. Configure export&lt;&#x2F;h3&gt;
&lt;p&gt;The precision of the output must be set to &lt;code&gt;2&lt;&#x2F;code&gt; and &lt;code&gt;Collapse groups&lt;&#x2F;code&gt; should be selected.&lt;&#x2F;p&gt;
&lt;a href=&quot;&amp;#x2F;inkscape-bimi&amp;#x2F;optimized.png&quot;&gt;
    &lt;img src=&quot;&amp;#x2F;inkscape-bimi&amp;#x2F;optimized.png&quot; alt=&quot;Optimize settings&quot; class=&quot;image&quot;&#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;blockquote class=&quot;markdown-alert-warning&quot;&gt;
&lt;p&gt;You are removing precision from the original &lt;code&gt;SVG&lt;&#x2F;code&gt;, review the output, particularly around corners and edges.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;4-edit-the-resulting-svg&quot;&gt;4. Edit the resulting SVG&lt;&#x2F;h3&gt;
&lt;p&gt;Replace the version attribute of the &lt;code&gt;svg&lt;&#x2F;code&gt; node from &lt;code&gt;version=&quot;1.1&quot;&lt;&#x2F;code&gt; to &lt;code&gt;version=&quot;1.2&quot; baseProfile=&quot;tiny-ps&quot;&lt;&#x2F;code&gt;. As a sed one-liner:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sed -e &amp;#39;s|version=&amp;quot;1.1&amp;quot;|version=&amp;quot;1.2&amp;quot; baseProfile=&amp;quot;tiny-ps&amp;quot;|&amp;#39;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You also need to remove the &lt;code&gt;metadata&lt;&#x2F;code&gt; section as Inkscape adds incompatible elements to it (like &lt;code&gt;rdf:RDF&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &amp;lt;metadata&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &amp;lt;&#x2F;metadata&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;5-validate-the-result&quot;&gt;5. Validate the result&lt;&#x2F;h3&gt;
&lt;p&gt;Follow the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bimigroup.org&#x2F;using-the-rnc-schema-to-validate-bimi-svg-images&#x2F;&quot;&gt;official instructions&lt;&#x2F;a&gt; and validate the resulting &lt;code&gt;svg&lt;&#x2F;code&gt; file using &lt;code&gt;jingtrang&lt;&#x2F;code&gt;. I added this to my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.victorsavu.eu&#x2F;victor&#x2F;victorsavu&#x2F;src&#x2F;commit&#x2F;5a9c06b9d4294164e38af9d564f71eda4affc4a3&#x2F;justfile#L33&quot;&gt;justfile&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;illustrator-steps&quot;&gt;Illustrator steps&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-export-correctly&quot;&gt;1. Export correctly&lt;&#x2F;h3&gt;
&lt;a href=&quot;&amp;#x2F;inkscape-bimi&amp;#x2F;illustrator.png&quot;&gt;
    &lt;img src=&quot;&amp;#x2F;inkscape-bimi&amp;#x2F;illustrator.png&quot; alt=&quot;Save As SVG Tiny SVG&quot; class=&quot;image&quot;&#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;blockquote class=&quot;markdown-alert-warning&quot;&gt;
&lt;p&gt;You are removing precision from the orignal &lt;code&gt;SVG&lt;&#x2F;code&gt;, review the output, particularly around corners and edges.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;2-remove-groups&quot;&gt;2. Remove groups&lt;&#x2F;h3&gt;
&lt;p&gt;If your &lt;code&gt;SVG&lt;&#x2F;code&gt; contains groups (&lt;code&gt;&amp;lt;g&amp;gt;&lt;&#x2F;code&gt; elements), they need to be removed. I used &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;svgo.dev&#x2F;&quot;&gt;&lt;code&gt;svgo&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to minify the file and it does it automatically.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-add-a-title&quot;&gt;3. Add a title&lt;&#x2F;h3&gt;
&lt;p&gt;Even when a title is set in Illustrator, it will not be added to the final &lt;code&gt;SVG&lt;&#x2F;code&gt;. Add &lt;code&gt;&amp;lt;title&amp;gt;Your Title&amp;lt;&#x2F;title&amp;gt;&lt;&#x2F;code&gt; as the &lt;strong&gt;first child&lt;&#x2F;strong&gt; of &lt;code&gt;&amp;lt;svg&amp;gt;&lt;&#x2F;code&gt; by hand.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;4-set-the-version&quot;&gt;4. Set the version&lt;&#x2F;h3&gt;
&lt;p&gt;Change &lt;code&gt;baseProfile=&quot;tiny&quot;&lt;&#x2F;code&gt; to &lt;code&gt;baseProfile=&quot;tiny-ps&quot;&lt;&#x2F;code&gt;. If using &lt;code&gt;svgo&lt;&#x2F;code&gt;, the version gets removed, add it back as &lt;code&gt;version=&quot;1.2&quot;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>I have a logo</title>
        <published>2026-03-22T20:00:00+00:00</published>
        <updated>2026-03-22T21:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/blog/first-logo/"/>
        <id>https://www.victorsavu.eu/blog/first-logo/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/blog/first-logo/">&lt;a href=&quot;&amp;#x2F;logo.svg&quot;&gt;
    &lt;img src=&quot;&amp;#x2F;logo.svg&quot; alt=&quot;My new logo&quot; class=&quot;image&quot;&#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;h2 id=&quot;logo&quot;&gt;Logo&lt;&#x2F;h2&gt;
&lt;p&gt;Admire my new glorious logo. It&#x27;s now everywhere on this website (which got a header just to hold it) and should also show up in my emails by using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bimigroup.org&#x2F;&quot;&gt;BIMI&lt;&#x2F;a&gt; after &lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;inkscape-bimi&#x2F;&quot;&gt;fighting tooling a bit&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;thank-you&quot;&gt;Thank you&lt;&#x2F;h2&gt;
&lt;p&gt;Thank you &lt;a href=&quot;mailto:hi@hannesavu.eu&quot;&gt;Hannelore Savu&lt;&#x2F;a&gt; for this logo.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2026-03-23-now-with-more-precision&quot;&gt;2026-03-23 Now with more precision&lt;&#x2F;h2&gt;
&lt;p&gt;After reviewing the files in more detail, the precision loss when exporting to &lt;code&gt;tiny-ps&lt;&#x2F;code&gt; with 2 decimals made the logos look odd. A bit more polishing by Hannelore and the logos look amazing in the minified and standards-compliant form.&lt;&#x2F;p&gt;
&lt;p&gt;See the broken logo &lt;a href=&quot;&#x2F;first-logo&#x2F;bimi-logo-broken.svg&quot;&gt;here&lt;&#x2F;a&gt; and pay attention to the rightmost curve.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Forgejo is now live</title>
        <published>2026-03-07T20:00:00+00:00</published>
        <updated>2026-03-07T20:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/blog/forgejo-live/"/>
        <id>https://www.victorsavu.eu/blog/forgejo-live/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/blog/forgejo-live/">&lt;h3 id=&quot;tl-dr-forgejo-is-live-website-code-here&quot;&gt;TL;DR: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.victorsavu.eu&#x2F;&quot;&gt;Forgejo is live&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.victorsavu.eu&#x2F;victor&#x2F;victorsavu&quot;&gt;Website code here&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;forgejo&quot;&gt;Forgejo&lt;&#x2F;h3&gt;
&lt;p&gt;I like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;&quot;&gt;git&lt;&#x2F;a&gt; and good UIs to review changes, so I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;&quot;&gt;Forgejo&lt;&#x2F;a&gt;. This setup took a while since I got sidetracked with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;docs&#x2F;latest&#x2F;admin&#x2F;installation&#x2F;docker&#x2F;#ssh-passthrough&quot;&gt;SSH passthrough&lt;&#x2F;a&gt;, which I never got working on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fedoraproject.org&#x2F;coreos&#x2F;&quot;&gt;CoreOS&lt;&#x2F;a&gt;. But now, by using the built-in SSH server and a &lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;sshd-port-coreos&#x2F;&quot;&gt;moved sshd port&lt;&#x2F;a&gt; I have a working forgejo instance 🎉.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;this-website&quot;&gt;This website&lt;&#x2F;h3&gt;
&lt;p&gt;This website is built using Zola and completely static. You can now &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.victorsavu.eu&#x2F;victor&#x2F;victorsavu&quot;&gt;read the source code&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.victorsavu.eu&#x2F;victor&#x2F;victorsavu&#x2F;commits&#x2F;branch&#x2F;main&quot;&gt;including all the history&lt;&#x2F;a&gt;. Everything is intended to be public so let&#x27;s show the world how the sausage is made.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;other-projects&quot;&gt;Other projects&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;m slowly migrating from an older Forgejo instance (which started as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;about.gitea.com&#x2F;&quot;&gt;Gitea&lt;&#x2F;a&gt;) to this one, expect more repositories to show up soon. Most of them are private though.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;see-also&quot;&gt;See also&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;forgejo-proton-email&#x2F;&quot;&gt;Use Proton to send emails from Forgejo&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;sshd-port-coreos&#x2F;&quot;&gt;Change the SSHD port in Fedora CoreOS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Change the SSHD port in Fedora CoreOS</title>
        <published>2026-03-07T19:00:00+00:00</published>
        <updated>2026-03-08T08:30:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/sshd-port-coreos/"/>
        <id>https://www.victorsavu.eu/tips/sshd-port-coreos/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/sshd-port-coreos/">&lt;p&gt;Changing the port of sshd in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fedoraproject.org&#x2F;coreos&#x2F;&quot;&gt;CoreOS&lt;&#x2F;a&gt; is not obvious. There are multiple open bugs (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coreos&#x2F;fedora-coreos-tracker&#x2F;issues&#x2F;1022&quot;&gt;1&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coreos&#x2F;fedora-coreos-tracker&#x2F;issues&#x2F;396&quot;&gt;2&lt;&#x2F;a&gt;) for this issue and I believe I have found a new approach that works for my server. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coreos&#x2F;docs&#x2F;blob&#x2F;master&#x2F;os&#x2F;customizing-sshd.md&quot;&gt;old CoreOS instructions&lt;&#x2F;a&gt;, don&#x27;t take SELinux into account, they just update the &lt;code&gt;sshd&lt;&#x2F;code&gt; configuration. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.flatcar.org&#x2F;docs&#x2F;latest&#x2F;setup&#x2F;security&#x2F;customizing-sshd&#x2F;&quot;&gt;Flatcar documentation&lt;&#x2F;a&gt; is almost identical.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-configure-sshd-service-and-sshd-socket&quot;&gt;1. Configure &lt;code&gt;sshd.service&lt;&#x2F;code&gt; and &lt;code&gt;sshd.socket&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;  files&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt; path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &#x2F;etc&#x2F;ssh&#x2F;sshd_config.d&#x2F;port.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;        contents&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;            inline&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; Port 2223&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;        mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0644&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;systemd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;  units&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; sshd.socket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;        dropins&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;        -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; sshd-port.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;            contents&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;            [Socket]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;            ListenStream=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;            ListenStream=2223&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;2-make-selinux-happy&quot;&gt;2. Make selinux happy&lt;&#x2F;h3&gt;
&lt;p&gt;Just updating sshd is not enough, it will not have the permissions to bind to any port besides what is set as &lt;code&gt;ssh_port_t&lt;&#x2F;code&gt;. So, let&#x27;s update that using a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;SELinuxProject&#x2F;cil&#x2F;wiki&#x2F;#network-labeling&quot;&gt;cil policy to update the label&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;systemd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;  units&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; custom-ssh-port-t.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;      enabled&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;      contents&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        [Unit]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        Description=Update ssh_port_t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        Before=sshd.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        [Service]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        Type=oneshot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        ExecStart=&#x2F;usr&#x2F;sbin&#x2F;semodule -i &#x2F;root&#x2F;ssh_port_t.cil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        RemainAfterExit=yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        [Install]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;        WantedBy=multi-user.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;  files&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt; path&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &#x2F;root&#x2F;ssh_port_t.cil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;      mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0644&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;      contents&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;        inline&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;          (portcon tcp 2223 (system_u object_r ssh_port_t ((s0)(s0))))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;alternatives-that-didn-t-work-for-me&quot;&gt;Alternatives that didn&#x27;t work for me&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Adding a custom SELinux policy. It only worked if I installed it with &lt;code&gt;selinux -i&lt;&#x2F;code&gt;.
&lt;ul&gt;
&lt;li&gt;I did manage to deploy a &lt;code&gt;pp&lt;&#x2F;code&gt; file that showed up in &lt;code&gt;semodule --list-modules&lt;&#x2F;code&gt;, but never took effect at both low or high priorities.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Changing &lt;code&gt;ssh_port_t&lt;&#x2F;code&gt; using &lt;code&gt;semanage&lt;&#x2F;code&gt;, but it&#x27;s not installed in CoreOS.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Serve precompressed static files from caddy</title>
        <published>2026-03-07T12:00:00+00:00</published>
        <updated>2026-03-07T12:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/caddy-precompress/"/>
        <id>https://www.victorsavu.eu/tips/caddy-precompress/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/caddy-precompress/">&lt;h2 id=&quot;background&quot;&gt;Background&lt;&#x2F;h2&gt;
&lt;p&gt;While &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt; can &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;docs&#x2F;caddyfile&#x2F;directives&#x2F;encode&quot;&gt;compress files&lt;&#x2F;a&gt; as they are requested, my website is completely static (built using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; )and all of this work can be done once ahead of time. For this purpose I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ryanfowler&#x2F;precompress&quot;&gt;precompress&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To make everything work, Caddy needs to be instructed to look for precompressed files:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;file_server {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    precompressed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To actually precompress, you just need to install and point &lt;code&gt;precompress&lt;&#x2F;code&gt; at the right folder. The default options work well for me.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; install precompress&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.cargo&#x2F;bin&#x2F;precompress &lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;{your site folder}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I use a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;just.systems&#x2F;man&#x2F;en&#x2F;&quot;&gt;justfile&lt;&#x2F;a&gt; to manage building and deploying my website, which lets me do everything in a one-liner:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;build:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rm -rf public&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ~&#x2F;.cargo&#x2F;bin&#x2F;zola build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ~&#x2F;.cargo&#x2F;bin&#x2F;precompress public&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;install-deps:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cargo install --locked --git https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;zola&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cargo install precompress&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;deploy-victorsavu: build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rsync -rzP --delete public&#x2F; victorsavu@victorsavu.eu:victorsavu&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Use Proton to send emails from Forgejo</title>
        <published>2026-02-15T00:00:00+00:00</published>
        <updated>2026-02-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/forgejo-proton-email/"/>
        <id>https://www.victorsavu.eu/tips/forgejo-proton-email/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/forgejo-proton-email/">&lt;p&gt;To allow &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;&quot;&gt;Forgejo&lt;&#x2F;a&gt; to send emails using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;proton.me&quot;&gt;Proton&lt;&#x2F;a&gt;, you need to:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Create an SMTP token in Proton from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;account.proton.me&#x2F;u&#x2F;0&#x2F;mail&#x2F;imap-smtp&quot;&gt;settings&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;docs&#x2F;latest&#x2F;admin&#x2F;setup&#x2F;email&#x2F;&quot;&gt;Configure Forgejo&lt;&#x2F;a&gt; using &lt;code&gt;app.ini&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[mailer]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ENABLED = true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FROM           = {{SMTP username}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PROTOCOL       = smtp+starttls &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SMTP_ADDR      = smtp.protonmail.ch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;SMTP_PORT      = 587&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;USER           = {{SMTP username}}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PASSWD         = `{{SMTP token}}`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where &lt;code&gt;{{SMTP username}}&lt;&#x2F;code&gt; and &lt;code&gt;{{SMTP token}}&lt;&#x2F;code&gt; should be copied from Proton.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Limiting deSEC tokens for DNS-01 and dynDNS</title>
        <published>2026-02-08T00:00:00+00:00</published>
        <updated>2026-02-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/desec-limit-tokens/"/>
        <id>https://www.victorsavu.eu/tips/desec-limit-tokens/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/desec-limit-tokens/">&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;desec.readthedocs.io&#x2F;en&#x2F;latest&#x2F;auth&#x2F;tokens.html#token-scoping-policies&quot;&gt;deSEC documentation&lt;&#x2F;a&gt; documents how to scope tokens using policies. I used this feature to limit my deSEC tokens to what they are responsible for.&lt;&#x2F;p&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
&lt;p&gt;The &lt;code&gt;{{id}}&lt;&#x2F;code&gt; is not the token name and is unfortunately not shown in the UI. See &lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;desec-limit-tokens&#x2F;#useful-commands&quot;&gt;useful commands below&lt;&#x2F;a&gt; for a simple way to query the ids of all your tokens.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;just.systems&#x2F;man&#x2F;en&#x2F;&quot;&gt;just&lt;&#x2F;a&gt; to organize my commands. If you want the commands to work in your shell, just replace &lt;code&gt;{{something}}&lt;&#x2F;code&gt; with &lt;code&gt;${something}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;dyndns&quot;&gt;dynDNS&lt;&#x2F;h4&gt;
&lt;p&gt;I use dynDNS since I don&#x27;t have a static IP at home. This allows updating both A and AAAA records, but only for the intended domain and subdomain. For each domain, I use a different token to keep things safer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;desec-limit-token-dyndns id domain subdomain: &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    curl -sS  https:&#x2F;&#x2F;desec.io&#x2F;api&#x2F;v1&#x2F;auth&#x2F;tokens&#x2F;{{id}}&#x2F;policies&#x2F;rrsets&#x2F; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Authorization: Token ${DESEC_TOKEN}&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Content-Type: application&#x2F;json&amp;quot; --data @- &amp;lt;&amp;lt;&amp;lt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       &amp;#39;{&amp;quot;domain&amp;quot;: null, &amp;quot;subname&amp;quot;: null, &amp;quot;type&amp;quot;: null, &amp;quot;perm_write&amp;quot;: false}&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    curl -sS  https:&#x2F;&#x2F;desec.io&#x2F;api&#x2F;v1&#x2F;auth&#x2F;tokens&#x2F;{{id}}&#x2F;policies&#x2F;rrsets&#x2F; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Authorization: Token ${DESEC_TOKEN}&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Content-Type: application&#x2F;json&amp;quot; --data @- &amp;lt;&amp;lt;&amp;lt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       &amp;#39;{&amp;quot;domain&amp;quot;: &amp;quot;{{domain}}&amp;quot;, &amp;quot;subname&amp;quot;: &amp;quot;{{subdomain}}&amp;quot;, &amp;quot;type&amp;quot;: &amp;quot;AAAA&amp;quot;, &amp;quot;perm_write&amp;quot;: true}&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    curl -sS  https:&#x2F;&#x2F;desec.io&#x2F;api&#x2F;v1&#x2F;auth&#x2F;tokens&#x2F;{{id}}&#x2F;policies&#x2F;rrsets&#x2F; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Authorization: Token ${DESEC_TOKEN}&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Content-Type: application&#x2F;json&amp;quot; --data @- &amp;lt;&amp;lt;&amp;lt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       &amp;#39;{&amp;quot;domain&amp;quot;: &amp;quot;{{domain}}&amp;quot;, &amp;quot;subname&amp;quot;: &amp;quot;{{subdomain}}&amp;quot;, &amp;quot;type&amp;quot;: &amp;quot;A&amp;quot;, &amp;quot;perm_write&amp;quot;: true}&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;acme-dns-01&quot;&gt;ACME DNS-01&lt;&#x2F;h4&gt;
&lt;p&gt;I use wildcard certificates, which can only be issued by using a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;docs&#x2F;challenge-types&#x2F;#dns-01-challenge&quot;&gt;DNS-01 challenge&lt;&#x2F;a&gt;. This only allows updating the &lt;code&gt;_acme-challenge&lt;&#x2F;code&gt; with a &lt;code&gt;TXT&lt;&#x2F;code&gt; record only, which is enough for the challenge.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;desec-limit-token-acme id domain: &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    curl -sS https:&#x2F;&#x2F;desec.io&#x2F;api&#x2F;v1&#x2F;auth&#x2F;tokens&#x2F;{{id}}&#x2F; --header &amp;quot;Authorization: Token ${DESEC_TOKEN}&amp;quot; | jq .name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    curl -sS  https:&#x2F;&#x2F;desec.io&#x2F;api&#x2F;v1&#x2F;auth&#x2F;tokens&#x2F;{{id}}&#x2F;policies&#x2F;rrsets&#x2F; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Authorization: Token ${DESEC_TOKEN}&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Content-Type: application&#x2F;json&amp;quot; --data @- &amp;lt;&amp;lt;&amp;lt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       &amp;#39;{&amp;quot;domain&amp;quot;: null, &amp;quot;subname&amp;quot;: null, &amp;quot;type&amp;quot;: null, &amp;quot;perm_write&amp;quot;: false}&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    curl -sS  https:&#x2F;&#x2F;desec.io&#x2F;api&#x2F;v1&#x2F;auth&#x2F;tokens&#x2F;{{id}}&#x2F;policies&#x2F;rrsets&#x2F; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Authorization: Token ${DESEC_TOKEN}&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Content-Type: application&#x2F;json&amp;quot; --data @- &amp;lt;&amp;lt;&amp;lt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       &amp;#39;{&amp;quot;domain&amp;quot;: &amp;quot;{{domain}}&amp;quot;, &amp;quot;subname&amp;quot;: &amp;quot;_acme-challenge&amp;quot;, &amp;quot;type&amp;quot;: &amp;quot;TXT&amp;quot;, &amp;quot;perm_write&amp;quot;: true}&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;useful-commands&quot;&gt;Useful commands&lt;&#x2F;h4&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;desec-list-tokens:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    curl -sS https:&#x2F;&#x2F;desec.io&#x2F;api&#x2F;v1&#x2F;auth&#x2F;tokens&#x2F; --header &amp;quot;Authorization: Token ${DESEC_TOKEN}&amp;quot; | jq &amp;#39;.[] |{name, id}&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;desec-list-policies id:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    curl -sS https:&#x2F;&#x2F;desec.io&#x2F;api&#x2F;v1&#x2F;auth&#x2F;tokens&#x2F;{{id}}&#x2F;policies&#x2F;rrsets&#x2F; --header &amp;quot;Authorization: Token ${DESEC_TOKEN}&amp;quot; | jq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;desec-delete-policy id policy_id:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    curl -sS  -X DELETE https:&#x2F;&#x2F;desec.io&#x2F;api&#x2F;v1&#x2F;auth&#x2F;tokens&#x2F;{{id}}&#x2F;policies&#x2F;rrsets&#x2F;{{policy_id}}&#x2F; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       --header &amp;quot;Authorization: Token ${DESEC_TOKEN}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Enable ipv6 in a quadlet container</title>
        <published>2026-01-17T16:00:00+00:00</published>
        <updated>2026-01-17T16:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/quadlet-ipv6/"/>
        <id>https://www.victorsavu.eu/tips/quadlet-ipv6/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/quadlet-ipv6/">&lt;p&gt;In podman, the default network has ipv6 disabled. To fix this, create &lt;code&gt;&#x2F;etc&#x2F;containers&#x2F;systemd&#x2F;main.network&lt;&#x2F;code&gt; which just enables ipv6:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;systemd&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[Network]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;IPv6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F38BA8;&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All containers will then need to add a &lt;code&gt;Network&lt;&#x2F;code&gt; entry in their config:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;systemd&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[Container]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;Network&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;main.network&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Enable ipv6 on a Hetzner CoreOS server</title>
        <published>2026-01-17T14:00:00+00:00</published>
        <updated>2026-01-17T14:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/hetzner-ipv6/"/>
        <id>https://www.victorsavu.eu/tips/hetzner-ipv6/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/hetzner-ipv6/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hetzner.com&quot;&gt;Hetzner&lt;&#x2F;a&gt; automatically assigns an ipv6 range to each server, but it does &lt;strong&gt;not&lt;&#x2F;strong&gt; assign an ipv6 address to it. This must be done manually for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fedoraproject.org&#x2F;coreos&#x2F;&quot;&gt;CoreOS&lt;&#x2F;a&gt; by updating the network configuration in &lt;code&gt;&#x2F;etc&#x2F;NetworkManager&#x2F;system-connections&#x2F;enp1s0.nmconnection&lt;&#x2F;code&gt; to:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[connection]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id=enp1s0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type=ethernet&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;interface-name=enp1s0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uuid=f141878f-5566-303c-8231-1c1ab23f2256&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ipv4]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;method=auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dns=8.8.8.8,8.8.4.4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[ipv6]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;method=manual&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;addresses=&amp;lt;your range here&amp;gt;::1&#x2F;64,fe80::1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gateway=fe80::1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dns=2001:4860:4860::8888,2001:4860:4860::8844&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;may-fail=false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For DNS (both ipv4 and ipv6) I picked &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;speed&#x2F;public-dns&#x2F;docs&#x2F;using&quot;&gt;Google DNS&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This configuration was based on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.hetzner.com&#x2F;cloud&#x2F;servers&#x2F;primary-ips&#x2F;primary-ip-configuration&#x2F;&quot;&gt;Hetzner documentation on ipv6&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;See also: &lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;cheat-ipv6&#x2F;&quot;&gt;Use direct ipv6 when possible and a fallback for ipv4&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Add modules to caddy on CoreOS</title>
        <published>2026-01-17T12:00:00+00:00</published>
        <updated>2026-01-17T12:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/custom-caddy/"/>
        <id>https://www.victorsavu.eu/tips/custom-caddy/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/custom-caddy/">&lt;p&gt;Some &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt; modules are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;docs&#x2F;modules&#x2F;&quot;&gt;non-standard&lt;&#x2F;a&gt; and are not included in the official docker image. You can add modules easily using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;caddyserver&#x2F;xcaddy&quot;&gt;&lt;code&gt;xcaddy&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, but you need to create a custom docker image each time. This can be done in CoreOS using &lt;code&gt;.build&lt;&#x2F;code&gt; files.&lt;&#x2F;p&gt;
&lt;p&gt;Create a &lt;code&gt;Containerfile&lt;&#x2F;code&gt; that builds the image. In this example we add &lt;code&gt;caddy-dns&#x2F;desec&lt;&#x2F;code&gt; to the image and we install the file as &lt;code&gt;&#x2F;etc&#x2F;containers&#x2F;systemd&#x2F;Containerfile.caddy&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; docker.io&#x2F;library&#x2F;caddy:2-builder &lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; builder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; xcaddy build \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --with github.com&#x2F;caddy-dns&#x2F;desec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; docker.io&#x2F;library&#x2F;caddy:2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=builder &#x2F;usr&#x2F;bin&#x2F;caddy &#x2F;usr&#x2F;bin&#x2F;caddy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
&lt;p&gt;Use the full image path &lt;code&gt;docker.io&#x2F;library&#x2F;caddy&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;To add the build file to quadlet, you need to create &lt;code&gt;&#x2F;etc&#x2F;containers&#x2F;systemd&#x2F;caddy.build&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;systemd&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[Unit]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Build custom Caddy image with deSEC DNS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[Build]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;SetWorkingDirectory&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;File&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Containerfile.caddy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;ImageTag&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;localhost&#x2F;caddy-desec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote class=&quot;markdown-alert-note&quot;&gt;
&lt;p&gt;Note: &lt;code&gt;SetWorkingDirectory&lt;&#x2F;code&gt; is required and also lets you put the &lt;code&gt;Containerfile&lt;&#x2F;code&gt; somewhere else.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Your &lt;code&gt;caddy.container&lt;&#x2F;code&gt; now needs to reference the &lt;code&gt;caddy.build&lt;&#x2F;code&gt; image by adding&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;systemd&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[Container]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;ContainerName&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;caddy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;&quot;&gt;Image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;caddy.build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Use direct ipv6 when possible and a fallback for ipv4</title>
        <published>2026-01-17T10:00:00+00:00</published>
        <updated>2026-01-17T10:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/tips/cheat-ipv6/"/>
        <id>https://www.victorsavu.eu/tips/cheat-ipv6/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/tips/cheat-ipv6/">&lt;h2 id=&quot;background&quot;&gt;Background&lt;&#x2F;h2&gt;
&lt;p&gt;My network provider only provides me an ipv6 address and uses &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fritz.com&#x2F;en&#x2F;apps&#x2F;knowledge-base&#x2F;FRITZ-Box-7590&#x2F;1611_What-is-DS-Lite-and-how-does-it-work&quot;&gt;DS-Lite&lt;&#x2F;a&gt; for outgoing ipv4 connections. This means I can&#x27;t host something on my home-network and have it accessible from all networks.&lt;&#x2F;p&gt;
&lt;p&gt;To get around this I have a funky setup that allows direct connections over ipv6 and proxies all ipv4 through a server that does have an ipv4 address (I use the cheapest &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hetzner.com&quot;&gt;Hetzner&lt;&#x2F;a&gt; server for this). Most networks support ipv6 and a direct connection is used and I don&#x27;t have to pay for bandwidth. The server is only involved in ipv6 connections.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Home server (called &lt;code&gt;homeserver&lt;&#x2F;code&gt;). The server we want to reach from everywhere.&lt;&#x2F;li&gt;
&lt;li&gt;Cloud server (called &lt;code&gt;cloudserver&lt;&#x2F;code&gt;). A cheap server that has a public ipv4 address.&lt;&#x2F;li&gt;
&lt;li&gt;Client (who wants to connect to &lt;code&gt;homeserver&lt;&#x2F;code&gt;) from a different network.&lt;&#x2F;li&gt;
&lt;li&gt;DynDNS provider
&lt;ul&gt;
&lt;li&gt;Must allow updating only &lt;code&gt;AAAA&lt;&#x2F;code&gt; entries without touching &lt;code&gt;A&lt;&#x2F;code&gt;. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;desec.readthedocs.io&#x2F;en&#x2F;latest&#x2F;dyndns&#x2F;update-api.html#determine-ip-address-es&quot;&gt;DeSEC&lt;&#x2F;a&gt; allows this by passing &lt;code&gt;myipv4=preserve&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;dns-setup&quot;&gt;DNS setup&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;home.victorsavu.eu&lt;&#x2F;code&gt;
&lt;code&gt;A&lt;&#x2F;code&gt; - Cloud server ipv4 address - static
&lt;code&gt;AAAA&lt;&#x2F;code&gt; - Home server ipv6 address - DynDNS&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;home6.victorsavu.eu&lt;&#x2F;code&gt;
&lt;code&gt;AAAA&lt;&#x2F;code&gt; - Home server ipv6 address - DynDNS&lt;&#x2F;p&gt;
&lt;h3 id=&quot;homeserver&quot;&gt;Homeserver&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;homeserver&lt;&#x2F;code&gt; uses curl to periodically update the AAAA DynDNS entries in &lt;code&gt;home6.victorsavu.eu&lt;&#x2F;code&gt; and &lt;code&gt;home.victorsavu.eu&lt;&#x2F;code&gt;. It has no other special restrictions.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;caddy-proxy-running-on-cloudserver&quot;&gt;Caddy proxy running on &lt;code&gt;cloudserver&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;*.victorsavu.com {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        tls {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            dns &amp;lt;your provider&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;provider config&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        @redirected `host(&amp;#39;home.victorsavu.eu&amp;#39;)`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        handle @redirected {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                reverse_proxy home6.victorsavu.eu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        # Fallback for otherwise unhandled domains&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        handle {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                respond 421&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We use Caddy to proxy ipv4 connections from clients connecting over ipv4 to &lt;code&gt;homeserver&lt;&#x2F;code&gt;. Since it can&#x27;t respond to all http requests (All ipv6 requests go directly to &lt;code&gt;homeserver&lt;&#x2F;code&gt;), we can&#x27;t use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;docs&#x2F;challenge-types&#x2F;#http-01-challenge&quot;&gt;&lt;code&gt;http-01&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; challenge here and need to use something like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;docs&#x2F;challenge-types&#x2F;#dns-01-challenge&quot;&gt;&lt;code&gt;dns-01&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; instead. &lt;code&gt;dns-01&lt;&#x2F;code&gt; also allows obtaining a wildcard certificate. You can proxy as many subdomains as you need with this setup (I use 4 for example). Additional domains just need to be added to the &lt;code&gt;@redirected&lt;&#x2F;code&gt;: &lt;code&gt;host(&#x27;home.victorsavu.eu&#x27;, &#x27;second.victorsavu.eu&#x27;)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;See also: &lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;hetzner-ipv6&#x2F;&quot;&gt;Enable ipv6 on a Hetzner CoreOS server&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>This site is now live</title>
        <published>2026-01-17T08:00:00+00:00</published>
        <updated>2026-01-17T08:00:00+00:00</updated>
        
        <author>
          <name>
            
              Victor Gabriel Savu
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.victorsavu.eu/blog/first/"/>
        <id>https://www.victorsavu.eu/blog/first/</id>
        
        <content type="html" xml:base="https://www.victorsavu.eu/blog/first/">&lt;p&gt;My website is now live 🎉. I wanted to share some &lt;a href=&quot;https:&#x2F;&#x2F;www.victorsavu.eu&#x2F;tips&#x2F;&quot;&gt;tips&lt;&#x2F;a&gt; so that is where I added multiple entries.&lt;&#x2F;p&gt;
&lt;p&gt;Expect more content and changes to land soonish.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
