<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us">
  <title>cperrin.xyz</title>
  <subtitle>Sysadmin - Programmer - Computer Friend</subtitle>
  <link href="https://staging.cperrin.xyz/en/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="https://staging.cperrin.xyz/en/" rel="alternate" type="text/html"/>
  <updated>2026-06-19T21:37:05+00:00</updated>
  <id>https://staging.cperrin.xyz/en/</id>
  <author>
    <name>Christopher Perrin</name>
    <email>me@cperrin.xyz</email>
  </author>
  <generator uri="https://gohugo.io/" version="0.160.0">Hugo</generator>
  <entry>
    <title>What can we do about the vibe committer</title>
    <link href="https://staging.cperrin.xyz/en/2026/06/19/what-can-we-do-about-the-vibe-committer/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2026/06/19/what-can-we-do-about-the-vibe-committer/</id>
    <published>2026-06-19T00:00:00+00:00</published>
    <updated>2026-06-19T23:07:43+02:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;I recently had a discussion on Mastodon that was sparked by a post of the Software Freedom Conservancy about the &lt;a href=&#34;https://sfconservancy.org/llm-gen-ai/llm-backed-generative-ai-recommendations.html&#34;&gt;handling of LLM-gen-AI submissions&lt;/a&gt;. There are many people who are very opposed to letting LLM-generated code into their projects. This is an understandable standpoint given concerns like legality, unethical sourcing, resource usage, and concentration of power.&lt;/p&gt;
&lt;p&gt;Apart from that, it is completely reasonable for a maintainer to set rules for submissions. A FOSS license doesn&amp;rsquo;t mean that a maintainer even has to interact with anyone. It just provides the source.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;I recently had a discussion on Mastodon that was sparked by a post of the Software Freedom Conservancy about the &lt;a href=&#34;https://sfconservancy.org/llm-gen-ai/llm-backed-generative-ai-recommendations.html&#34;&gt;handling of LLM-gen-AI submissions&lt;/a&gt;. There are many people who are very opposed to letting LLM-generated code into their projects. This is an understandable standpoint given concerns like legality, unethical sourcing, resource usage, and concentration of power.&lt;/p&gt;
&lt;p&gt;Apart from that, it is completely reasonable for a maintainer to set rules for submissions. A FOSS license doesn&amp;rsquo;t mean that a maintainer even has to interact with anyone. It just provides the source.&lt;/p&gt;
&lt;p&gt;Still, it made me think about the impact these rules might have and in which cases they might turn into a net negative.&lt;/p&gt;
&lt;h2 id=&#34;consent-is-king&#34;&gt;Consent is king&lt;/h2&gt;
&lt;p&gt;Maintainers make the rules. They are entrusted with maintaining a version of the code that others might want to contribute to. Often that is a single person who not only made something they wanted to share, but also took it upon themselves to help others improve it. For this we should be grateful for their work and respect their wishes.&lt;/p&gt;
&lt;p&gt;But that is not how the world works. Through ignorance, entitlement, or malice, maintainers are often confronted with demands or hostility. Their boundaries get ignored, and frustrations rise. LLM-generated code is fertile ground for this. While some see it as the holy grail, others see it as the devil. This strong polarizing effect, combined with ignored boundaries, can easily lead to clashes.&lt;/p&gt;
&lt;h2 id=&#34;solid-snake-and-benny-hill&#34;&gt;Solid Snake and Benny Hill&lt;/h2&gt;
&lt;p&gt;Every clash can be very stressful for all sides. This is especially true if innocent people get caught in the crossfire. In my years as a software developer I have seen a lot of bad code. More recently, some code has triggered my vibe code sensor, but it was written by a human.&lt;/p&gt;
&lt;p&gt;On the other hand, I believe I could probably hide the origin of a code submission. I would never do that, especially not to deceive. This makes me think that many people out there have the same knowledge and no problem with deception.&lt;/p&gt;
&lt;p&gt;This could lead to some people sneaking their LLM code in like Solid Snake into a secret base, and others being chased away by an angry maintainer like in a Benny Hill sketch.&lt;/p&gt;
&lt;h2 id=&#34;distrust-leads-to-anger-anger-leads-to-a-bad-time-for-everyone&#34;&gt;Distrust leads to anger, anger leads to a bad time for everyone&lt;/h2&gt;
&lt;p&gt;I am, of course, not the first person to think about nefarious actors trying to sneak past defenses. I am sure the most passionate maintainers are constantly aware of this, constantly on the lookout for the slightest hint of LLM involvement, always vigilant.&lt;/p&gt;
&lt;p&gt;Or constantly concerned with the source of a submission in addition to the quality, always suspicious. From my observations, this can be coupled with anger - maybe anger about LLMs, about disregard of boundaries, or about the extra work they have to put in.&lt;/p&gt;
&lt;p&gt;At this point, it begs the question of who is winning anything here. Even more, some people are definitely losing. The maintainers, new programmers, and the FOSS community as a whole are negatively affected, while vibe coders and LLM companies still get what they want a lot of the time.&lt;/p&gt;
&lt;h2 id=&#34;pragmatic-principles&#34;&gt;Pragmatic principles&lt;/h2&gt;
&lt;p&gt;This all sounds very bad for people who have principles. Standing by principles might hurt someone innocent and even the maintainer, but abandoning principles might hurt just as much. My personal way out: pragmatic principles.&lt;/p&gt;
&lt;p&gt;What I mean by that is searching specifically for the fights I can win and that are a net positive. Some of my guiding principles are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don&amp;rsquo;t search for signs of LLM-generated code in a submission, but don&amp;rsquo;t ignore them&lt;/li&gt;
&lt;li&gt;If in doubt, either assume it&amp;rsquo;s human or communicate doubts&lt;/li&gt;
&lt;li&gt;Evaluate submissions primarily on code quality&lt;/li&gt;
&lt;li&gt;Assume people want to help&lt;/li&gt;
&lt;li&gt;Remember that we all make mistakes&lt;/li&gt;
&lt;li&gt;Concentrate on the positives&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;afterword&#34;&gt;Afterword&lt;/h2&gt;
&lt;p&gt;I want to make it clear that I want everyone to set boundaries as they think right, and that everyone should respect those boundaries. I wish for a world where it is a given that the principles of others are respected.&lt;/p&gt;
&lt;p&gt;The pragmatic approach is only my way to cope when I can&amp;rsquo;t protect my principles in a way that is healthy or even successful. I am aware that this is not easy if a project is run over by slop. It&amp;rsquo;s not a complete solution and not for everyone.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Triggering Veeam Backups on Linux with SystemD</title>
    <link href="https://staging.cperrin.xyz/en/2026/01/28/triggering-veeam-backups-on-linux-with-systemd/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2026/01/28/triggering-veeam-backups-on-linux-with-systemd/</id>
    <published>2026-01-28T00:00:00+00:00</published>
    <updated>2026-01-28T22:44:24+01:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;Veeam Backup is, in my opinion, one of the best free backup solutions available. The Linux version particularly shines with its ability to create snapshot backups of Ext4 partitions.&lt;/p&gt;
&lt;p&gt;Unfortunately, the Linux version has a major drawback compared to its Windows counterpart: backup scheduling is extremely limited. You can only specify the day and hour for when backups should run. If the computer is asleep or powered off at that time, the backup won&amp;rsquo;t execute and, more importantly, won&amp;rsquo;t be rescheduled.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;Veeam Backup is, in my opinion, one of the best free backup solutions available. The Linux version particularly shines with its ability to create snapshot backups of Ext4 partitions.&lt;/p&gt;
&lt;p&gt;Unfortunately, the Linux version has a major drawback compared to its Windows counterpart: backup scheduling is extremely limited. You can only specify the day and hour for when backups should run. If the computer is asleep or powered off at that time, the backup won&amp;rsquo;t execute and, more importantly, won&amp;rsquo;t be rescheduled.&lt;/p&gt;
&lt;p&gt;To work around this limitation, I had to get creative and combine SystemD timers, SystemD services, and some scripting.&lt;/p&gt;
&lt;h2 id=&#34;veeam-cli&#34;&gt;Veeam CLI&lt;/h2&gt;
&lt;p&gt;You can also control Veeam jobs from outside the Terminal UI using the &lt;code&gt;veeamconfig&lt;/code&gt; tool.&lt;/p&gt;
&lt;p&gt;For example, you can start a backup with the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;veeamconfig job run --name &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;JOBNAME&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The catch is that this command is non-blocking and returns immediately. To check if the backup has completed and its status, you need to run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;veeamconfig job status --name &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;JOBNAME&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since this command is also non-blocking, the only solution is polling. We need to repeatedly check if the job is still running until it either completes successfully or fails.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the key part of the polling script that handles the job monitoring:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Extract session ID from job start output&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;SESSION_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$OUTPUT&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep -oP &lt;span class=&#34;s1&#34;&gt;&amp;#39;Session ID: \[\{\K[^}]+&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Poll session status until completion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; true&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;STATUS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;/usr/bin/veeamconfig session info --id &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SESSION_ID&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep &lt;span class=&#34;s2&#34;&gt;&amp;#34;State:&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;STATE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$STATUS&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep -oP &lt;span class=&#34;s1&#34;&gt;&amp;#39;State:\s+\K\w+&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$STATE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Success&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$STATE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Warning&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Job completed with state: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$STATE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;elif&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$STATE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Failed&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Job failed!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Job still running... State: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$STATE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    sleep &lt;span class=&#34;nv&#34;&gt;$POLL_INTERVAL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The script also includes signal handling to gracefully stop backups if needed.&lt;/p&gt;
&lt;h2 id=&#34;systemd&#34;&gt;SystemD&lt;/h2&gt;
&lt;p&gt;The SystemD side was much more straightforward. SystemD timers allow me to wake the computer from sleep mode to start the backup. For this, you only need to set the option &lt;code&gt;WakeSystem=true&lt;/code&gt; in the &lt;code&gt;[Timer]&lt;/code&gt; block.&lt;/p&gt;
&lt;p&gt;The service unit was just as little of a problem with the script. I only had to prevent the computer from going back to sleep while the backup is running. For this, I used &lt;code&gt;systemd-inhibit&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;systemd-service&#34;&gt;SystemD Service&lt;/h3&gt;
&lt;p&gt;The service unit runs our script while preventing the system from sleeping during backups:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;Veeam Backup Job %i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;network.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;simple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;systemd-inhibit --what &amp;#34;sleep:idle:shutdown&amp;#34; --why &amp;#34;Veeam Backup %i&amp;#34; --who &amp;#34;Veeam Job&amp;#34; --mode &amp;#34;block-weak&amp;#34; /usr/local/bin/veeam-run-polling %i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Restart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;systemd-timer&#34;&gt;SystemD Timer&lt;/h3&gt;
&lt;p&gt;This timer wakes your system and runs the backup every other day at 10:30 AM:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;Veeam Backup Timer for Job %i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Timer]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;OnCalendar&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;*-*-1/2 10:30:00&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Persistent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WakeSystem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DeferReactivation&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Unit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;veeam-run@%i.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WantedBy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;timers.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All unit files and the script can be found at &lt;a href=&#34;https://git.screebo.net/cperrin/veeam-systemd-timers&#34;&gt;https://git.screebo.net/cperrin/veeam-systemd-timers&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>2026: The Year Windows Annoyed Us Too Much</title>
    <link href="https://staging.cperrin.xyz/en/2026/01/03/2026-the-year-windows-annoyed-us-too-much/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2026/01/03/2026-the-year-windows-annoyed-us-too-much/</id>
    <published>2026-01-03T00:00:00+00:00</published>
    <updated>2026-01-28T19:48:56+01:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;In the last few days, I&amp;rsquo;ve read several blog posts talking about how 2026 is the year of the Linux desktop, and that&amp;rsquo;s a great thing. However, I think many of the headlines and posts on this topic should have a different title: &amp;ldquo;The Year Windows Annoyed Us Too Much.&amp;rdquo;&lt;/p&gt;
&lt;h2 id=&#34;a-history-of-verschlimmbesserung&#34;&gt;A History of &amp;ldquo;&lt;a href=&#34;https://en.wiktionary.org/wiki/verschlimmbessern&#34;&gt;Verschlimmbesserung&lt;/a&gt;&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;For years now, Microsoft has been steadily making its operating system worse through supposed &amp;ldquo;improvements&amp;rdquo; (&lt;em&gt;Verschlimmbesserung&lt;/em&gt;). Windows Vista was a difficult step because many computers weren&amp;rsquo;t ready for it yet, but there was at least technical progress that was successfully concluded with Windows 7.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;In the last few days, I&amp;rsquo;ve read several blog posts talking about how 2026 is the year of the Linux desktop, and that&amp;rsquo;s a great thing. However, I think many of the headlines and posts on this topic should have a different title: &amp;ldquo;The Year Windows Annoyed Us Too Much.&amp;rdquo;&lt;/p&gt;
&lt;h2 id=&#34;a-history-of-verschlimmbesserung&#34;&gt;A History of &amp;ldquo;&lt;a href=&#34;https://en.wiktionary.org/wiki/verschlimmbessern&#34;&gt;Verschlimmbesserung&lt;/a&gt;&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;For years now, Microsoft has been steadily making its operating system worse through supposed &amp;ldquo;improvements&amp;rdquo; (&lt;em&gt;Verschlimmbesserung&lt;/em&gt;). Windows Vista was a difficult step because many computers weren&amp;rsquo;t ready for it yet, but there was at least technical progress that was successfully concluded with Windows 7.&lt;/p&gt;
&lt;p&gt;One step that many couldn&amp;rsquo;t follow was the switch to Windows 8. Then-CEO of Microsoft, Steve Ballmer, was convinced of making Windows a universally applicable operating system. Whether on a tablet, a phone, a desktop, or an entirely new device, Windows should be the right choice. In doing so, he created a system that served almost no one well. On the desktop, the full-screen interface constantly got in the way and changed the workflow. There were few tablets, and those that existed struggled with the fact that all worthwhile programs weren&amp;rsquo;t adapted for touch, and the system was way too heavy. On phones, the system never gained traction because no one developed apps for it, making it unattractive. Other unwelcome innovations of Windows 8 included the Microsoft account login, where users were forced to log in with an online Microsoft account instead of a local one.&lt;/p&gt;
&lt;p&gt;Some of the design decisions of Windows 8 were then &amp;ldquo;partially reversed&amp;rdquo; with Windows 8.1. The mandatory full-screen start menu was removed, and the system became more usable again. Nevertheless, Microsoft was already starting with its next great idea: automatic syncing of documents to OneDrive. Instead of asking users, Microsoft simply assumed users would love it if their data just landed in the Microsoft cloud. Additionally, the free storage was too small for most people anyway. But then you can just pay for it.&lt;/p&gt;
&lt;h2 id=&#34;the-forever-windows&#34;&gt;The &amp;ldquo;Forever&amp;rdquo; Windows&lt;/h2&gt;
&lt;p&gt;Windows 10 was then the &amp;ldquo;forever&amp;rdquo; Windows. It was supposed to be the last version of Windows and be continuously developed. The operating concept was now more classic again, but in many corners, things were strategically degraded. The start menu no longer just searched for programs but also documents and even online. Accordingly, it was slow and inaccurate. The tradition of pre-installed third-party software was continued with apps like Candy Crush and LinkedIn, which were automatically installed after a fresh installation of the system.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;improvements&amp;rdquo; came gradually: OneDrive was touted ever more aggressively, Edge made itself the default browser, more and more apps that nobody wanted appeared in the taskbar, and much more. Every major update brought some improvements and many downgrades.&lt;/p&gt;
&lt;h2 id=&#34;windows-11-and-ai&#34;&gt;Windows 11 and AI&lt;/h2&gt;
&lt;p&gt;A strong shift in mood toward Microsoft was felt with the announcement of Windows 11. The Windows that was actually supposed to be the &amp;ldquo;forever&amp;rdquo; Windows would be replaced. And this time, many PCs were not allowed to come along. With Windows 11, Microsoft made TPM 2.0 and Secure Boot mandatory. For much older hardware, this was the end. The strong encouragement to use a Microsoft account in Windows 10 now became a requirement. Of course, this could be bypassed with a few tricks, but Microsoft quickly made it clear: &amp;ldquo;This is no longer your operating system; you are just a guest here.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This mentality was only expanded further, and the pressure increased. Users were frustrated; we just wanted to use our computers. But then the unexpected happened that was to change the world: ChatGPT.&lt;/p&gt;
&lt;p&gt;The gates were opened, tech companies got scared, and seemingly overnight, AI was what was supposed to rule everything. From now on, everything had to have AI. AI chat, AI search, AI-AI. If it didn&amp;rsquo;t have AI, it wasn&amp;rsquo;t good. The more invasive, the more intrusive, the more unavoidable, the better. AI in Windows, AI in Paint, AI in Word, AI in Excel, AI in Notepad. Nothing was safe. AI was even supposed to play our games for us from now on.&lt;/p&gt;
&lt;h2 id=&#34;a-valve-for-frustration&#34;&gt;A Valve for Frustration&lt;/h2&gt;
&lt;p&gt;While Microsoft was working on designing our desktop more and more according to their ideas, a small company called Valve was quietly working on its own solution. With the Steam Deck, they brought a PC to the market, shaped like an overweight Nintendo Switch console. The hardware itself was very interesting, but the truly exciting part was the software. The special thing was that the device ran Linux.&lt;/p&gt;
&lt;p&gt;It must be said that Valve had already tried once in the past to bring a Linux console to the market. Then conceived as a living room device, the hope was that by leading by example, other developers would also release their games for Linux. However, that did not happen.&lt;/p&gt;
&lt;p&gt;But Valve had learned from it and invested a lot of money and time behind the scenes to make Windows games not just runnable on Linux, but run well. The Steam Deck was proof that it worked even without Microsoft and that the mantra that you can&amp;rsquo;t play games on Linux was from now on false. Of course, not everything was perfect from the start. But the foundation was laid, the infrastructure was there, and the dam was broken.&lt;/p&gt;
&lt;h2 id=&#34;the-perfect-wave&#34;&gt;The Perfect Wave&lt;/h2&gt;
&lt;p&gt;Since the launch of the Steam Deck, a lot has happened in game support, and most titles run without problems (sometimes even better than under Windows). Only anti-cheat software still causes issues. Valve has announced more hardware that skips Windows. This, coupled with the increasing annoyance of Windows, has now convinced many people to give Linux a chance. And that is great news for everyone. When Microsoft suddenly has to compete with a free operating system that respects the user and constantly gets better, it can&amp;rsquo;t be bad for anyone. I very much hope for the year of the Linux desktop. It won&amp;rsquo;t always be easy, because not everyone wants to just play, and Linux still has many sharp edges.&lt;/p&gt;
&lt;p&gt;For me personally, however, the year of the Linux desktop already began in 2025, and I can only benefit if more people take the step with me.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The Fediverse, Meta, and Threads</title>
    <link href="https://staging.cperrin.xyz/en/2023/07/04/the-fediverse-meta-and-threads/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2023/07/04/the-fediverse-meta-and-threads/</id>
    <published>2023-07-04T00:00:00+00:00</published>
    <updated>2026-06-19T23:07:43+02:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;The Fediverse is growing. Spurred by the problems at Twitter and Reddit, more and more users are now venturing onto alternative platforms. Especially &lt;a href=&#34;https://joinmastodon.org&#34;&gt;Mastodon&lt;/a&gt;, &lt;a href=&#34;https://join-lemmy.org&#34;&gt;Lemmy&lt;/a&gt;, and &lt;a href=&#34;https://kbin.pub&#34;&gt;KBin&lt;/a&gt; have experienced an explosive surge in users recently. This didn&amp;rsquo;t happen without problems, of course, but it at least shows that there might be a way not to throw all data into the gullets of large corporations.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/2023/07/04/das-fediverse-meta-und-threads/fediverse.png&#34; alt=&#34;The many branches of the Fediverse&#34;&gt;&lt;/p&gt;
&lt;p&gt;With the &lt;a href=&#34;https://www.w3.org/TR/activitypub/&#34;&gt;ActivityPub protocol&lt;/a&gt; as the glue between all Fediverse projects, the formation of silos should finally come to an end. Everyone can talk to everyone: Mastodon with Pixelfed, Pleroma with PeerTube, Lemmy with KBin. The boundaries between projects are blurring, even if sometimes content from one software makes no sense in the interface of another. But this is where the problem begins.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;The Fediverse is growing. Spurred by the problems at Twitter and Reddit, more and more users are now venturing onto alternative platforms. Especially &lt;a href=&#34;https://joinmastodon.org&#34;&gt;Mastodon&lt;/a&gt;, &lt;a href=&#34;https://join-lemmy.org&#34;&gt;Lemmy&lt;/a&gt;, and &lt;a href=&#34;https://kbin.pub&#34;&gt;KBin&lt;/a&gt; have experienced an explosive surge in users recently. This didn&amp;rsquo;t happen without problems, of course, but it at least shows that there might be a way not to throw all data into the gullets of large corporations.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/2023/07/04/das-fediverse-meta-und-threads/fediverse.png&#34; alt=&#34;The many branches of the Fediverse&#34;&gt;&lt;/p&gt;
&lt;p&gt;With the &lt;a href=&#34;https://www.w3.org/TR/activitypub/&#34;&gt;ActivityPub protocol&lt;/a&gt; as the glue between all Fediverse projects, the formation of silos should finally come to an end. Everyone can talk to everyone: Mastodon with Pixelfed, Pleroma with PeerTube, Lemmy with KBin. The boundaries between projects are blurring, even if sometimes content from one software makes no sense in the interface of another. But this is where the problem begins.&lt;/p&gt;
&lt;h2 id=&#34;meta-threads&#34;&gt;Meta Threads&lt;/h2&gt;
&lt;p&gt;Because even at the large corporations, the mills don&amp;rsquo;t stand still, even if it might sometimes seem that way. Meta (formerly Facebook) has decided to also be part of the Fediverse revolution. With a new project now named &lt;a href=&#34;https://www.threads.net/&#34;&gt;Threads&lt;/a&gt;, they want to connect to the Fediverse. It&amp;rsquo;s supposed to be a kind of microblogging platform like Twitter or Mastodon. The announcements and leaks were, of course, received in the Fediverse with great anticipation and recognition. NOT!&lt;/p&gt;
&lt;p&gt;Many critics were reminded of the strategy coined by Microsoft: &amp;ldquo;Embrace, Extend, Extinguish.&amp;rdquo; This involves first welcoming a project with open arms to attract users, then equipping it with proprietary extensions that are incompatible with the original, and thus slowly pushing the competitor out of the market until it is extinguished. It&amp;rsquo;s not hard to see how Meta could use such a strategy against the Fediverse.&lt;/p&gt;
&lt;p&gt;But the critics go further. As we all know, at the latest after the Cambridge Analytica scandal, Meta has significant problems with data protection. Additionally, their primary business model consists of creating and capitalizing on detailed user profiles. And here, the strength of the Fediverse becomes a potential weakness.&lt;/p&gt;
&lt;h2 id=&#34;federation-not-just-in-star-trek&#34;&gt;Federation Not Just in Star Trek&lt;/h2&gt;
&lt;p&gt;The problem can be understood most easily with a small excursion into the subject of ActivityPub. As mentioned at the beginning, it is the protocol that enables communication between all Fediverse projects. As soon as, for example, a Mastodon instance like mastodon.social allows its users to follow users from other instances and vice versa, that server is considered federated. This applies equally to groups, communities, magazines, or other &amp;ldquo;things&amp;rdquo; you can follow. As soon as a user on Instance A follows a user on Instance B, all public updates from the user on Instance B are sent to Instance A and stored on Instance A.&lt;/p&gt;
&lt;p&gt;The attentive reader may have discovered the problem here. If a Threads user now follows a user on a Fediverse instance, data from Fediverse users inevitably ends up on Meta servers. This can be restricted by an instance defederating from Threads, thus blocking the instance&amp;rsquo;s communication with Threads. Many instance operators have already announced this step, while others want to wait and see. Opinions are certainly divided.&lt;/p&gt;
&lt;h2 id=&#34;my-bits-alone&#34;&gt;My bits alone!&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m not the biggest fan of Meta and the rest myself, but I must say that I see the panic as somewhat misdirected. I&amp;rsquo;m also not thrilled that my data flows to the large corporations, but I have also decided to publish this data. An analogy for this would be standing in a marketplace to shout your opinion to the world and then getting annoyed if someone writes it down.&lt;/p&gt;
&lt;p&gt;The concept hasn&amp;rsquo;t changed from Facebook, Twitter &amp;amp; Co. The data there is indeed in its own silos, but even there, data is forwarded to advertising partners and analysis firms, scraped from public pages, and processed otherwise. In the Fediverse, it&amp;rsquo;s just more obvious that the data is being forwarded. And that&amp;rsquo;s not a criticism of the Fediverse. That&amp;rsquo;s the core principle of the Fediverse.&lt;/p&gt;
&lt;h2 id=&#34;social-private-media&#34;&gt;Social Private Media&lt;/h2&gt;
&lt;p&gt;What is the solution to the problem? My answer: There is none. At least not in the way many would like. As a society, we have forgotten that it&amp;rsquo;s not always good to stand in the marketplace and start shouting. We have started showing strangers our baby photos, sharing our location, and revealing our innermost selves. All without really making clear what the implications are. Partly they were obscured from us, partly we ignored them.&lt;/p&gt;
&lt;p&gt;The problems of the Fediverse, like the solution, are not new. We need to reveal less about ourselves. We must be aware that a sent Toot, just like an Instagram post, is no longer in our hands after sending. They can be processed, correlated, and made into a personal profile. For that, you don&amp;rsquo;t even need Threads from Meta. The public sharing of data is incompatible with a desire for control.&lt;/p&gt;
&lt;p&gt;We can try to strengthen the rights of users through laws and make the processing of data more difficult, but ultimately, even without big evil companies, one thing remains the same:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Social Media is not Private Media&lt;/strong&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>New is Always Better (?)</title>
    <link href="https://staging.cperrin.xyz/en/2021/09/16/new-is-always-better/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2021/09/16/new-is-always-better/</id>
    <published>2021-09-16T00:00:00+00:00</published>
    <updated>2026-01-28T14:29:44+01:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;I have something to confess. I have a problem. I&amp;rsquo;m not sure if my problem has a name, so I&amp;rsquo;ll give it one. I call it &amp;ldquo;Neoprogrammism.&amp;rdquo; What is it? Well, it&amp;rsquo;s best explained with an example.&lt;/p&gt;
&lt;h2 id=&#34;example-1&#34;&gt;Example 1&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m now well-versed in Python and Django from several projects, but I&amp;rsquo;m not as familiar with JavaScript. There&amp;rsquo;s a new project to generate APIs directly from the database schema that relies entirely on JavaScript? I&amp;rsquo;ll take it!&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;I have something to confess. I have a problem. I&amp;rsquo;m not sure if my problem has a name, so I&amp;rsquo;ll give it one. I call it &amp;ldquo;Neoprogrammism.&amp;rdquo; What is it? Well, it&amp;rsquo;s best explained with an example.&lt;/p&gt;
&lt;h2 id=&#34;example-1&#34;&gt;Example 1&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m now well-versed in Python and Django from several projects, but I&amp;rsquo;m not as familiar with JavaScript. There&amp;rsquo;s a new project to generate APIs directly from the database schema that relies entirely on JavaScript? I&amp;rsquo;ll take it!&lt;/p&gt;
&lt;h2 id=&#34;example-2&#34;&gt;Example 2&lt;/h2&gt;
&lt;p&gt;JavaScript isn&amp;rsquo;t that familiar to me, but I like CSS. To make my life easier and follow best practices better, I decide on a CSS framework. Now, there are a lot of established frameworks in this area, but I recently read with half my brain in an article that there&amp;rsquo;s a new slim framework. Better take that one!&lt;/p&gt;
&lt;h2 id=&#34;what-i-mean-to-say-is&#34;&gt;What I mean to say is&amp;hellip;&lt;/h2&gt;
&lt;p&gt;Neoprogrammism can affect us all because few of us are immune to the latest &amp;ldquo;bling.&amp;rdquo; It&amp;rsquo;s often tempting to use the latest and &amp;ldquo;greatest&amp;rdquo; for a new project. That doesn&amp;rsquo;t necessarily have to be a bad thing. New projects sometimes do things better or have a chance of receiving support for longer in the future.&lt;/p&gt;
&lt;p&gt;However, one must not forget that there might be a reason why &amp;ldquo;older projects&amp;rdquo; are still there and being actively developed. There might also be good reasons why these projects work the way they do. Additionally, there has been more time to build an ecosystem around them.&lt;/p&gt;
&lt;p&gt;The most important question I ask myself to defeat my Neoprogrammism is whether I only want to use something because it&amp;rsquo;s new or trendy.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>New Design for the Blog</title>
    <link href="https://staging.cperrin.xyz/en/2020/02/20/new-design-for-the-blog/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2020/02/20/new-design-for-the-blog/</id>
    <published>2020-02-20T00:00:00+00:00</published>
    <updated>2026-01-28T14:29:44+01:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;The era of downloaded and adapted designs is over. My first own design sees the light of day. I call it cperrin-hugo-theme. Poetic, isn&amp;rsquo;t it?&lt;/p&gt;
&lt;p&gt;But that&amp;rsquo;s not the only new thing. I came up with my own brand-hot and ultra-creative logo to make the crowds scream.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;The era of downloaded and adapted designs is over. My first own design sees the light of day. I call it cperrin-hugo-theme. Poetic, isn&amp;rsquo;t it?&lt;/p&gt;
&lt;p&gt;But that&amp;rsquo;s not the only new thing. I came up with my own brand-hot and ultra-creative logo to make the crowds scream.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/2020/02/20/neues-design-f%C3%BCr-den-blog/logo.png&#34; alt=&#34;New Logo&#34;&gt;&lt;/p&gt;
&lt;p&gt;Does the work make sense, considering how many posts I&amp;rsquo;ve written since the beginning of the blog? Certainly not! Was it fun? Yeah. Was it a good way not to do what I should be doing? Definitely!!&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Ansible: DevOps Made Easy</title>
    <link href="https://staging.cperrin.xyz/en/2017/09/08/ansible-devops-made-easy/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2017/09/08/ansible-devops-made-easy/</id>
    <published>2017-09-08T00:00:00+00:00</published>
    <updated>2026-01-28T14:29:44+01:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;The problem is quite old: A large number of servers need to be set up or homogenized, ideally with minimal effort. This problem has been solved several times. So-called orchestration tools execute specific commands on multiple systems based on predefined instructions.&lt;/p&gt;
&lt;p&gt;Examples of such tools are &lt;a href=&#34;https://puppet.com/&#34;&gt;Puppet&lt;/a&gt;, &lt;a href=&#34;https://www.chef.io/&#34;&gt;Chef&lt;/a&gt;, or &lt;a href=&#34;https://cfengine.com/&#34;&gt;CFEngine&lt;/a&gt;. However, these representatives have one major disadvantage for me: they require a client to be installed on the remote side for execution.&lt;/p&gt;
&lt;p&gt;This is where &lt;a href=&#34;https://www.ansible.com/&#34;&gt;Ansible&lt;/a&gt; comes in. Ansible uses only an SSH connection to execute scripts or playbooks on the clients.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;The problem is quite old: A large number of servers need to be set up or homogenized, ideally with minimal effort. This problem has been solved several times. So-called orchestration tools execute specific commands on multiple systems based on predefined instructions.&lt;/p&gt;
&lt;p&gt;Examples of such tools are &lt;a href=&#34;https://puppet.com/&#34;&gt;Puppet&lt;/a&gt;, &lt;a href=&#34;https://www.chef.io/&#34;&gt;Chef&lt;/a&gt;, or &lt;a href=&#34;https://cfengine.com/&#34;&gt;CFEngine&lt;/a&gt;. However, these representatives have one major disadvantage for me: they require a client to be installed on the remote side for execution.&lt;/p&gt;
&lt;p&gt;This is where &lt;a href=&#34;https://www.ansible.com/&#34;&gt;Ansible&lt;/a&gt; comes in. Ansible uses only an SSH connection to execute scripts or playbooks on the clients.&lt;/p&gt;
&lt;p&gt;The best way to demonstrate the simplicity of Ansible is with a small example in which a list of packages is installed via apt. First, we create the basic structure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mkdir ansible
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; ansible
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we need to create an inventory, which is a list of servers and groups on which the playbooks will be executed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ansible/inventory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[group1]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;server1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;server2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;server3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this example, we have a group called &lt;code&gt;group1&lt;/code&gt; containing servers 1-3.&lt;/p&gt;
&lt;p&gt;Next, we need to create a playbook containing the instructions for Ansible:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# ansible/site.yml&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nn&#34;&gt;---&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- &lt;span class=&#34;nt&#34;&gt;hosts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;all                &lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# select servers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;become&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;yes&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# execute as sudo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;tasks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                     &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# list of tasks&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Install packages&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# name for the task&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;apt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;                   &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# use the APT module&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ items }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# name of the package&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;present      &lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# status of the package&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;with_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# loop with a list. fills {{ items }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;program1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;program2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;program3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This playbook installs the programs &lt;code&gt;program1-3&lt;/code&gt; via apt.&lt;/p&gt;
&lt;p&gt;To run this playbook, we just need to execute:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ansible-playbook site.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you haven&amp;rsquo;t set up SSH key authentication, you need to append the &lt;code&gt;-k&lt;/code&gt; option. To authenticate with a user other than the currently logged-in user, use the &lt;code&gt;-u &amp;lt;username&amp;gt;&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it. Ansible should now connect to all servers via SSH and install the listed packages. If the packages are already installed, Ansible will simply skip them.&lt;/p&gt;
&lt;p&gt;Ansible now has a &lt;a href=&#34;https://docs.ansible.com/ansible/latest/collections/index.html&#34;&gt;huge number of modules&lt;/a&gt; to choose from, allowing you to use Ansible in a wide variety of use cases.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Seafile: OwnCloud, Only Better</title>
    <link href="https://staging.cperrin.xyz/en/2017/01/02/seafile-owncloud-only-better/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2017/01/02/seafile-owncloud-only-better/</id>
    <published>2017-01-02T00:00:00+00:00</published>
    <updated>2026-01-28T14:29:44+01:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;Anyone who has read my &lt;a href=&#34;https://staging.cperrin.xyz/en/2012/08/13/owncloud-self-hosted-dropbox/&#34;&gt;post about OwnCloud&lt;/a&gt; will know that I strive to store my data, if possible, not with Dropbox &amp;amp; Co. In the past, OwnCloud was the best and simplest solution, but for some time now, there has been an alternative that is worth seeing: &lt;a href=&#34;https://seafile.com&#34;&gt;Seafile&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Seafile offers free sync clients for every common platform (Windows, Linux, macOS, Android, iOS).&lt;/p&gt;
&lt;p&gt;In the background, the application, written in Python, works in two parts. The &lt;code&gt;seafile&lt;/code&gt; application controls the saving and syncing of data. It uses a filesystem based on git, which means that by default, all files are versioned. The other part is &lt;code&gt;seahub&lt;/code&gt;, which provides the web interface to Seafile.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;Anyone who has read my &lt;a href=&#34;https://staging.cperrin.xyz/en/2012/08/13/owncloud-self-hosted-dropbox/&#34;&gt;post about OwnCloud&lt;/a&gt; will know that I strive to store my data, if possible, not with Dropbox &amp;amp; Co. In the past, OwnCloud was the best and simplest solution, but for some time now, there has been an alternative that is worth seeing: &lt;a href=&#34;https://seafile.com&#34;&gt;Seafile&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Seafile offers free sync clients for every common platform (Windows, Linux, macOS, Android, iOS).&lt;/p&gt;
&lt;p&gt;In the background, the application, written in Python, works in two parts. The &lt;code&gt;seafile&lt;/code&gt; application controls the saving and syncing of data. It uses a filesystem based on git, which means that by default, all files are versioned. The other part is &lt;code&gt;seahub&lt;/code&gt;, which provides the web interface to Seafile.&lt;/p&gt;
&lt;p&gt;From my perspective, Seafile has the major advantage that it is not written in PHP. One has to torture PHP very much to extract functionality like OwnCloud from it. This is noticeable in performance. Likewise, the separation of the web interface and the sync server is advantageous. Sync clients speak directly to the sync server, and the website is just another sync client.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Moving to Hugo and a New Domain</title>
    <link href="https://staging.cperrin.xyz/en/2016/05/19/moving-to-hugo-and-a-new-domain/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2016/05/19/moving-to-hugo-and-a-new-domain/</id>
    <published>2016-05-19T00:00:00+00:00</published>
    <updated>2026-01-28T14:29:44+01:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;I have long maintained a WordPress blog and rarely posted anything. In the process, I repeatedly noticed how slow WordPress actually is. Additionally, I need PHP and a database to keep everything running. This, coupled with the fact that there were recurring security vulnerabilities in WordPress, led me to search for an alternative.&lt;/p&gt;
&lt;p&gt;Since I don&amp;rsquo;t need much dynamic content on my website, I looked for a static site generator and came across &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;I have long maintained a WordPress blog and rarely posted anything. In the process, I repeatedly noticed how slow WordPress actually is. Additionally, I need PHP and a database to keep everything running. This, coupled with the fact that there were recurring security vulnerabilities in WordPress, led me to search for an alternative.&lt;/p&gt;
&lt;p&gt;Since I don&amp;rsquo;t need much dynamic content on my website, I looked for a static site generator and came across &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hugo is an application written in Go that generates static HTML files from Markdown files and templates. I now deliver these only with an Nginx and have a beautiful blog without PHP and MySQL. Thanks to Disqus, I don&amp;rsquo;t even have to give up a comment function.&lt;/p&gt;
&lt;p&gt;To make my life even easier, I use &lt;a href=&#34;https://gogs.io&#34;&gt;Gogs&lt;/a&gt; and &lt;a href=&#34;https://drone.io/&#34;&gt;Drone.io&lt;/a&gt; to automatically build my blog and copy it to the server. For this, I use the following &lt;code&gt;.drone.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;build&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;production&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;publysher/hugo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;commands&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;hugo --destination=&amp;lt;production_source&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;when&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;branch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;master&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;staging&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;publysher/hugo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;commands&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;hugo --destination=&amp;lt;staging_source&amp;gt; --buildDrafts=true --buildFuture=true --baseUrl=&amp;lt;staging_url&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;publish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;rsync&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;&amp;lt;server&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;&amp;lt;user&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;&amp;lt;staging_source&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;&amp;lt;staging_target&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;recursive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;rsync&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;&amp;lt;server&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;&amp;lt;user&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;&amp;lt;production_source&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;&amp;lt;production_target&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;recursive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;when&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;branch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;master&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This ensures that every push to my Gogs repo triggers a build and loads a production and a staging version onto the server. It&amp;rsquo;s almost magic.&lt;/p&gt;
&lt;p&gt;To top it all off, I have acquired a new and more personal domain. My blog will be found at &lt;a href=&#34;https://cperrin.xyz&#34;&gt;https://cperrin.xyz&lt;/a&gt; in the future.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>PAMMySQLTools: Manage libnss-mysql and pam-mysql Users via the Shell</title>
    <link href="https://staging.cperrin.xyz/en/2016/05/13/pammysqltools-manage-libnss-mysql-and-pam-mysql-users-via-the-shell/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2016/05/13/pammysqltools-manage-libnss-mysql-and-pam-mysql-users-via-the-shell/</id>
    <published>2016-05-13T00:00:00+00:00</published>
    <updated>2026-01-28T14:29:44+01:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;Through my work, I faced the problem that we wanted to authenticate users centrally via MySQL. This is not inherently a problem thanks to &lt;em&gt;libnss-mysql&lt;/em&gt; and &lt;em&gt;pam-mysql&lt;/em&gt;, but unfortunately, there is a lack of programs to manage users effectively.&lt;/p&gt;
&lt;p&gt;Therefore, I have written tools that imitate the Linux programs &lt;code&gt;user{add,mod,del}&lt;/code&gt; and &lt;code&gt;group{add,mod,del}&lt;/code&gt; and published them as &lt;a href=&#34;https://github.com/cperrin88/PAMMySQLTools&#34;&gt;PAMMySQLTools&lt;/a&gt; on &lt;a href=&#34;https://pypi.python.org/pypi/PAMMySQLTools&#34;&gt;PyPI&lt;/a&gt;.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;Through my work, I faced the problem that we wanted to authenticate users centrally via MySQL. This is not inherently a problem thanks to &lt;em&gt;libnss-mysql&lt;/em&gt; and &lt;em&gt;pam-mysql&lt;/em&gt;, but unfortunately, there is a lack of programs to manage users effectively.&lt;/p&gt;
&lt;p&gt;Therefore, I have written tools that imitate the Linux programs &lt;code&gt;user{add,mod,del}&lt;/code&gt; and &lt;code&gt;group{add,mod,del}&lt;/code&gt; and published them as &lt;a href=&#34;https://github.com/cperrin88/PAMMySQLTools&#34;&gt;PAMMySQLTools&lt;/a&gt; on &lt;a href=&#34;https://pypi.python.org/pypi/PAMMySQLTools&#34;&gt;PyPI&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;installation&#34;&gt;Installation&lt;/h1&gt;
&lt;p&gt;Thanks to &lt;code&gt;pip&lt;/code&gt;, you only need to run the command:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pip install pammysqltools
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;or&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pip3 install pammysqltools
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;to install the tools. This will install the following programs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;myuseradd&lt;/li&gt;
&lt;li&gt;myusermod&lt;/li&gt;
&lt;li&gt;myuserdel&lt;/li&gt;
&lt;li&gt;mygroupadd&lt;/li&gt;
&lt;li&gt;mygroupmod&lt;/li&gt;
&lt;li&gt;mygroupdel&lt;/li&gt;
&lt;li&gt;myimportusers&lt;/li&gt;
&lt;li&gt;myimportgroups&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;myuser*&lt;/code&gt; and &lt;code&gt;mygroup*&lt;/code&gt; tools are mostly modeled after the Linux programs and behave largely the same.&lt;/p&gt;
&lt;p&gt;The tools &lt;code&gt;myimportusers&lt;/code&gt; and &lt;code&gt;myimportgroups&lt;/code&gt; import users from &lt;code&gt;/etc/passwd&lt;/code&gt; and &lt;code&gt;/etc/groups&lt;/code&gt;, or &lt;code&gt;/etc/shadow&lt;/code&gt; and &lt;code&gt;/etc/gshadow&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For an overview of the arguments, simply append &lt;code&gt;--help&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Example: myuseradd&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ myuseradd --help
Usage: myuseradd [OPTIONS] LOGIN

Options:
  -b, --basedir BASE_DIR          base directory for the home directory of the
                                  new account
  -c, --comment COMMENT           GECOS field of the new account
  -d, --home-dir HOME_DIR         home directory of the new account
  -e, --expiredate EXPIRE_DATE    expiration date of the new account
  -f, --inactive INACTIVE         password inactivity period of the new
                                  account
  -g, --gid GROUP                 name or ID of the primary group of the new
                                  account
  -G, --groups GROUPS             list of supplementary groups of the new
                                  account
  -k, --skel SKEL_DIR             use this alternative skeleton directory
  -K, --key KEY=VALUE             override /etc/login.defs defaults
  -M, --no-create-home / -m, --create-home
                                  do not create the user&amp;#39;s home directory
  -U, --no-user-group / -N, --user-group
                                  do not create a group with the same name as
                                  the user
  -o, --non-unique                allow to create users with duplicate (non-
                                  unique) UID
  -p, --password PASSWORD         encrypted password of the new account
  -r, --system                    create a system account
  -s, --shell SHELL               login shell of the new account
  -u, --uid UID                   user ID of the new account
  --config CONF_PATH              path to the config file for this tool
  --help                          Show this message and exit.
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;configuration&#34;&gt;Configuration&lt;/h1&gt;
&lt;p&gt;To customize the database connection and the naming of tables and columns, the file &lt;code&gt;/etc/pam_mysql_manager.conf&lt;/code&gt; must be created according to &lt;a href=&#34;https://github.com/cperrin88/PAMMySQLTools/blob/master/conf/pam_mysql_manager.conf&#34;&gt;this scheme&lt;/a&gt;. Alternatively, the path to the configuration file can be passed with the &lt;code&gt;--config&lt;/code&gt; argument. For all options not specified here, the values in the sample file are the defaults.&lt;/p&gt;
&lt;p&gt;Once everything is set up, you&amp;rsquo;re ready to go.&lt;/p&gt;
&lt;h1 id=&#34;examples&#34;&gt;Examples&lt;/h1&gt;
&lt;p&gt;Create a user:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ myuseradd testuser
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Change the shell:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ myusermod -s /bin/zsh testuser
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Import groups without passwords:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ mygroupimport -i
&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <title>CARP &amp; HAProxy: High-Availability for Beginners</title>
    <link href="https://staging.cperrin.xyz/en/2012/12/21/carp-haproxy-high-availability-for-beginners/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2012/12/21/carp-haproxy-high-availability-for-beginners/</id>
    <published>2012-12-21T00:00:00+00:00</published>
    <updated>2026-01-28T14:29:44+01:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;The field of high-availability in the web area is often complicated, large, and hard to grasp. But it doesn&amp;rsquo;t have to be, thanks to CARP and HAProxy. The combination of these two techniques makes it possible to distribute requests to multiple servers and thereby avoid the single-point-of-failure problem. For this, we only need at least 2 computers with FreeBSD (or another BSD system with CARP support) that are in the same subnet and some time to set up the following software:&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;The field of high-availability in the web area is often complicated, large, and hard to grasp. But it doesn&amp;rsquo;t have to be, thanks to CARP and HAProxy. The combination of these two techniques makes it possible to distribute requests to multiple servers and thereby avoid the single-point-of-failure problem. For this, we only need at least 2 computers with FreeBSD (or another BSD system with CARP support) that are in the same subnet and some time to set up the following software:&lt;/p&gt;
&lt;h1 id=&#34;haproxy&#34;&gt;HAProxy&lt;/h1&gt;
&lt;p&gt;HAProxy is a reverse TCP proxy with load-balancing functionality. It distributes the load to multiple (backend) servers and detects when one of them is no longer reachable. HAProxy can be used for balancing both MySQL requests and HTTP requests. I will focus exclusively on the latter here.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;The easiest way to install it is through the ports tree:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd /usr/ports/net/haproxy
make install clean
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This compiles and installs HAProxy on the system.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The configuration file for HAProxy is located at &lt;code&gt;/usr/local/etc/haproxy.conf&lt;/code&gt;. A starting point for a working configuration could be the following:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-conf&#34; data-lang=&#34;conf&#34;&gt;global
        daemon
        maxconn 256

defaults
        mode http
        timeout connect 5000ms
        timeout client 5000ms
        timeout server 5000ms
        stats enable

frontend http-in
        option httplog
        log global
        default_backend servers

backend servers
        server server1 server1.example.com:8080 check
        server server2 server2.example.com:8080 check
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;carp&#34;&gt;CARP&lt;/h1&gt;
&lt;p&gt;CARP stands for &amp;ldquo;Common Address Redundancy Protocol&amp;rdquo;. It allows an IP address to be automatically taken over by another host if it is no longer reachable. The prerequisite for this is that all computers are in the same network segment, as CARP works via broadcast.&lt;/p&gt;
&lt;h2 id=&#34;installation-1&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Starting with FreeBSD 9.0, CARP is enabled by default. For older versions, support must either be compiled into the kernel or the kernel module must be activated with the entry:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-conf&#34; data-lang=&#34;conf&#34;&gt;if_carp_load=&amp;#34;YES&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;in the file &lt;code&gt;/boot/loader.conf&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;configuration-files&#34;&gt;Configuration Files&lt;/h2&gt;
&lt;p&gt;The configuration of CARP is relatively simple. First, a master server is configured. This server holds the IP by default.&lt;/p&gt;
&lt;p&gt;To do this, we need to create and configure a CARP interface. During operation, we use:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ifconfig carp0 create
ifconfig vhid 1 pass &amp;lt;password&amp;gt; 10.10.0.1/16
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The password and the vhid number must be the same on all backup systems. To ensure this configuration works after a restart, we add the following lines to &lt;code&gt;/etc/rc.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-conf&#34; data-lang=&#34;conf&#34;&gt;cloned_interfaces=&amp;#34;carp0&amp;#34;
ifconfig_carp0=&amp;#34;vhid 1 pass &amp;lt;password&amp;gt; 10.10.0.1/16&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On the backup systems, the CARP interface is created in a similar way, but the &amp;ldquo;advskew&amp;rdquo; argument is inserted:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-conf&#34; data-lang=&#34;conf&#34;&gt;cloned_interfaces=&amp;#34;carp0&amp;#34;
ifconfig_carp0=&amp;#34;vhid 1 advskew 100 pass &amp;lt;password&amp;gt; 10.10.0.1/16&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The higher the value after &amp;ldquo;advskew&amp;rdquo;, the lower the priority if the main system fails.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>OwnCloud: Self-Hosted Dropbox</title>
    <link href="https://staging.cperrin.xyz/en/2012/08/13/owncloud-self-hosted-dropbox/" rel="alternate" type="text/html"/>
    <id>https://staging.cperrin.xyz/en/2012/08/13/owncloud-self-hosted-dropbox/</id>
    <published>2012-08-13T00:00:00+00:00</published>
    <updated>2026-01-28T14:29:44+01:00</updated>
    <author>
      <name>Christopher Perrin</name>
    </author>
    <summary type="html">&lt;p&gt;Dropbox is one of the most practical tools that help me in my daily work. Whether it&amp;rsquo;s just synchronizing data or even sharing it with others, it&amp;rsquo;s possible with just a few clicks.&lt;/p&gt;
&lt;p&gt;Unfortunately, the whole thing has a serious drawback: My data is no longer with me! Although data in Dropbox is reportedly encrypted, you can NEVER be sure what might happen to your own data.&lt;/p&gt;
&lt;p&gt;For this dilemma, there is now a solution: &lt;a href=&#34;http://owncloud.org/&#34;&gt;OwnCloud&lt;/a&gt;&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;Dropbox is one of the most practical tools that help me in my daily work. Whether it&amp;rsquo;s just synchronizing data or even sharing it with others, it&amp;rsquo;s possible with just a few clicks.&lt;/p&gt;
&lt;p&gt;Unfortunately, the whole thing has a serious drawback: My data is no longer with me! Although data in Dropbox is reportedly encrypted, you can NEVER be sure what might happen to your own data.&lt;/p&gt;
&lt;p&gt;For this dilemma, there is now a solution: &lt;a href=&#34;http://owncloud.org/&#34;&gt;OwnCloud&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;OwnCloud is an Open Source PHP application to offer your own Dropbox-like service. With OwnCloud, it is easy to maintain full control over your data without much extra effort.&lt;/p&gt;
&lt;p&gt;The installation is child&amp;rsquo;s play and doesn&amp;rsquo;t even necessarily require the installation of a MySQL server. By default, SQLite is used. The installation can be divided into two simple steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Webserver Configuration: There are templates for many servers on the OwnCloud website.&lt;/li&gt;
&lt;li&gt;OwnCloud Setup: The setup of OwnCloud consists of ONE page. You only need to create an admin account and, if desired, specify a MySQL server.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Finished!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By now, there is also a sync client for almost every platform (Linux, Mac, Windows, Android, iOS).&lt;/p&gt;
&lt;p&gt;However, OwnCloud wants to be more than just a simple Dropbox replacement. Here are some features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Calendar&lt;/li&gt;
&lt;li&gt;Music player for stored music&lt;/li&gt;
&lt;li&gt;Contacts&lt;/li&gt;
&lt;li&gt;Image gallery&lt;/li&gt;
&lt;li&gt;Encryption of files on the server&lt;/li&gt;
&lt;li&gt;Integration of Dropbox, GDrive, etc., into your own OwnCloud&lt;/li&gt;
&lt;li&gt;Ampache/WebDAV/CalDAV/CardDAV server&lt;/li&gt;
&lt;li&gt;Plugin interface&lt;/li&gt;
&lt;li&gt;LDAP authentication&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OwnCloud is definitely worth a look and has by now become a truly viable alternative to Dropbox and similar services.&lt;/p&gt;</content>
  </entry>
</feed>
