<rss xmlns:source="http://source.scripting.com/" version="2.0">
  <channel>
    <title>rMdes - a place to write and think freely</title>
    <link>https://blog.rmendes.net/</link>
    <description></description>
    
    <language>en</language>
    
    <lastBuildDate>Fri, 16 Jan 2026 17:44:00 +0100</lastBuildDate>
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2026/01/16/revamped-my-domain-name-site.html</link>
      <pubDate>Fri, 16 Jan 2026 17:44:00 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2026/01/16/revamped-my-domain-name-site.html</guid>
      <description>&lt;p&gt;Revamped my domain name site &lt;a href=&#34;https://rmendes.net&#34;&gt;rmendes.net&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;plan to use it like a live CV showcasing work related stuff&lt;/li&gt;
&lt;li&gt;couldn&amp;rsquo;t resist to play with the code and implement #indieweb using #go existing libraries&lt;/li&gt;
&lt;li&gt;also has webmentions support, feel free to test :)&lt;/li&gt;
&lt;/ul&gt;
</description>
      <source:markdown>Revamped my domain name site [rmendes.net](https://rmendes.net) 
- plan to use it like a live CV showcasing work related stuff
- couldn&#39;t resist to play with the code and implement #indieweb using #go existing libraries
- also has webmentions support, feel free to test :)
</source:markdown>
    </item>
    
    <item>
      <title>Claude Code Journey </title>
      <link>https://blog.rmendes.net/2026/01/12/claude-code-journey.html</link>
      <pubDate>Mon, 12 Jan 2026 18:23:10 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2026/01/12/claude-code-journey.html</guid>
      <description>&lt;p&gt;I have been using Claude Code for a few months now, first on small personal code bases that urgently needed refactoring and then professionally on small internal tools then bigger code bases that are actually in production but are legacy code that haven&amp;rsquo;t been updated in a few years.&lt;/p&gt;
&lt;p&gt;Now I&amp;rsquo;m finally working on my own attempt at making sense of Juridical Data (65GB) of PDF&amp;rsquo;s and media coverage of the OKC judicial case.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m basically creating a Juridically oriented LLM/RAG solution to ingest PDF content and then use pgvector and other technologies to be able to interact with the whole Archive from my browser interface.&lt;/p&gt;
&lt;p&gt;This will never be published publicly obviously but it&amp;rsquo;s a very interesting use case and learning curve.&lt;/p&gt;
</description>
      <source:markdown>I have been using Claude Code for a few months now, first on small personal code bases that urgently needed refactoring and then professionally on small internal tools then bigger code bases that are actually in production but are legacy code that haven&#39;t been updated in a few years. 

Now I&#39;m finally working on my own attempt at making sense of Juridical Data (65GB) of PDF&#39;s and media coverage of the OKC judicial case. 

I&#39;m basically creating a Juridically oriented LLM/RAG solution to ingest PDF content and then use pgvector and other technologies to be able to interact with the whole Archive from my browser interface. 

This will never be published publicly obviously but it&#39;s a very interesting use case and learning curve. 
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2026/01/12/je-serais-sur-nrj-belgique.html</link>
      <pubDate>Mon, 12 Jan 2026 17:32:07 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2026/01/12/je-serais-sur-nrj-belgique.html</guid>
      <description>&lt;p&gt;Je serais sur NRJ Belgique vers 18h30 pour parler de &lt;a href=&#34;https://chardonsbleus.org&#34;&gt;chardonsbleus.org&lt;/a&gt; et de l&amp;rsquo;affaire OKC-Spatz en France&lt;/p&gt;
</description>
      <source:markdown>Je serais sur NRJ Belgique vers 18h30 pour parler de [chardonsbleus.org](https://chardonsbleus.org) et de l&#39;affaire OKC-Spatz en France 
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2026/01/05/venezuela-the-precedents-by-snyder.html</link>
      <pubDate>Mon, 05 Jan 2026 07:11:17 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2026/01/05/venezuela-the-precedents-by-snyder.html</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://open.substack.com/pub/snyder/p/venezuela-the-precedents&#34;&gt;Venezuela&lt;/a&gt;: the precedents by Snyder&lt;/p&gt;
</description>
      <source:markdown>[Venezuela](https://open.substack.com/pub/snyder/p/venezuela-the-precedents): the precedents by Snyder
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2026/01/01/not-sure-about-solving-how.html</link>
      <pubDate>Thu, 01 Jan 2026 13:25:33 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2026/01/01/not-sure-about-solving-how.html</guid>
      <description>&lt;p&gt;Not sure about solving&amp;hellip;&lt;/p&gt;
&lt;p&gt;How AI Labs Are &amp;ldquo;Solving&amp;rdquo; the Power Crisis: The Onsite Gas Deep Dive &lt;a href=&#34;https://newsletter.semianalysis.com/p/how-ai-labs-are-solving-the-power&#34;&gt;Read More&lt;/a&gt;&lt;/p&gt;
</description>
      <source:markdown>Not sure about solving...

How AI Labs Are &#34;Solving&#34; the Power Crisis: The Onsite Gas Deep Dive [Read More](https://newsletter.semianalysis.com/p/how-ai-labs-are-solving-the-power)



</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/12/29/so-i-have-been-busy.html</link>
      <pubDate>Mon, 29 Dec 2025 20:21:08 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/12/29/so-i-have-been-busy.html</guid>
      <description>&lt;p&gt;So &amp;hellip; I have been busy contributing to &lt;a href=&#34;http://v2.osintukraine.com&#34;&gt;this&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;tldr: real-time #telegram archive of the Russian War against Ukraine.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s 100% built with Claude Code in a bit more than 2 months&lt;/p&gt;
&lt;p&gt;it&amp;rsquo;s near 200.000 lines of #python code, without counting with &lt;a href=&#34;https://v2.osintukraine.com/platform-docs&#34;&gt;documentation&lt;/a&gt; of course.&lt;/p&gt;
&lt;p&gt;check it out !&lt;/p&gt;
</description>
      <source:markdown>So ... I have been busy contributing to [this](http://v2.osintukraine.com)

tldr: real-time #telegram archive of the Russian War against Ukraine.

It&#39;s 100% built with Claude Code in a bit more than 2 months 

it&#39;s near 200.000 lines of #python code, without counting with [documentation](https://v2.osintukraine.com/platform-docs) of course. 

check it out ! 
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/12/29/let-me-rephrase-that-title.html</link>
      <pubDate>Mon, 29 Dec 2025 20:11:37 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/12/29/let-me-rephrase-that-title.html</guid>
      <description>&lt;p&gt;let me rephrase that title : Big Tech basically flipped their script and bowed to the King (other images come to mind but would be very vulgar)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://arstechnica.com/tech-policy/2025/12/big-tech-basically-took-trumps-unpredictable-trade-war-lying-down/&#34;&gt;arstechnica.com/tech-poli&amp;hellip;&lt;/a&gt;&lt;/p&gt;
</description>
      <source:markdown>let me rephrase that title : Big Tech basically flipped their script and bowed to the King (other images come to mind but would be very vulgar)

[arstechnica.com/tech-poli...](https://arstechnica.com/tech-policy/2025/12/big-tech-basically-took-trumps-unpredictable-trade-war-lying-down/)
</source:markdown>
    </item>
    
    <item>
      <title>Upgrading Funkwhale from 1.4.0 to 2.0.0-rc5 on Debian</title>
      <link>https://blog.rmendes.net/2025/12/29/upgrading-funkwhale-from-to-rc.html</link>
      <pubDate>Mon, 29 Dec 2025 17:48:24 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/12/29/upgrading-funkwhale-from-to-rc.html</guid>
      <description>&lt;p&gt;After running Funkwhale 1.4.0 for a while, I decided to upgrade to the 2.0.0-rc5 release candidate. This post documents the full upgrade process on a Debian 12 (bookworm) server, including the issues I encountered and how to resolve them.&lt;/p&gt;
&lt;h2 id=&#34;whats-new-in-funkwhale-20&#34;&gt;What&amp;rsquo;s New in Funkwhale 2.0&lt;/h2&gt;
&lt;p&gt;Funkwhale 2.0 brings significant changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Libraries replaced by Playlists&lt;/strong&gt; - The old &amp;ldquo;Libraries&amp;rdquo; concept has been migrated to a more intuitive playlist-based system&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python 3.11+ required&lt;/strong&gt; - The minimum Python version has been bumped&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Django 5.1.6&lt;/strong&gt; - Major framework upgrade&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;venv instead of virtualenv&lt;/strong&gt; - The recommended virtual environment tool has changed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved artist credits system&lt;/strong&gt; - Better handling of artist metadata&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Federation improvements&lt;/strong&gt; - Enhanced ActivityPub support (though this may break compatibility with older instances)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Before starting the upgrade, ensure you have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Root access to your server&lt;/li&gt;
&lt;li&gt;Sufficient disk space for backups (~2x your database size + config files)&lt;/li&gt;
&lt;li&gt;Python 3.11 installed (&lt;code&gt;python3 --version&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;python3.11-venv&lt;/code&gt; package installed&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;apt install python3.11-venv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;step-1-create-a-full-backup&#34;&gt;Step 1: Create a Full Backup&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Never skip this step.&lt;/strong&gt; The database backup is your lifeline if something goes wrong.&lt;/p&gt;
&lt;h3 id=&#34;database-backup&#34;&gt;Database Backup&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;sudo -u postgres pg_dumpall &amp;gt; /srv/funkwhale/backups/dump_&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;date +%d-%m-%Y_%H_%M_%S&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;.sql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;media-backup&#34;&gt;Media Backup&lt;/h3&gt;
&lt;p&gt;If you have a lot of music, consider syncing your media directory to another location:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# From your local machine (if you have rsync access)&lt;/span&gt;
rsync -avz --progress user@yourserver:/srv/funkwhale/data/music ~/funkwhale-backup/music/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or create a compressed archive on the server:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;tar -czvf /srv/funkwhale/backups/media-backup.tar.gz /srv/funkwhale/data/music
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;configuration-backup&#34;&gt;Configuration Backup&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;cp -a /srv/funkwhale/config /srv/funkwhale/backups/config-backup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;step-2-stop-funkwhale-services&#34;&gt;Step 2: Stop Funkwhale Services&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;systemctl stop funkwhale.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Verify everything is stopped:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;systemctl status funkwhale-server funkwhale-worker funkwhale-beat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;step-3-backup-current-installation&#34;&gt;Step 3: Backup Current Installation&lt;/h2&gt;
&lt;p&gt;Before removing anything, backup the current installation for potential rollback:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;BACKUP_DIR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/srv/funkwhale/backups/upgrade-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;date +%Y%m%d_%H%M%S&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
mkdir -p &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;

cp -a /srv/funkwhale/api &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/api&amp;#34;&lt;/span&gt;
cp -a /srv/funkwhale/front &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/front&amp;#34;&lt;/span&gt;
cp -a /srv/funkwhale/virtualenv &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/virtualenv&amp;#34;&lt;/span&gt;
cp -a /srv/funkwhale/config &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/config&amp;#34;&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# Backup systemd units&lt;/span&gt;
mkdir -p &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/systemd&amp;#34;&lt;/span&gt;
cp /etc/systemd/system/funkwhale*.service &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/systemd/&amp;#34;&lt;/span&gt;
cp /etc/systemd/system/funkwhale.target &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/systemd/&amp;#34;&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# Backup nginx config&lt;/span&gt;
mkdir -p &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/nginx&amp;#34;&lt;/span&gt;
cp /etc/nginx/sites-enabled/your-site.conf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/nginx/&amp;#34;&lt;/span&gt;
cp /etc/nginx/funkwhale_proxy.conf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/nginx/&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;step-4-download-funkwhale-200-rc5&#34;&gt;Step 4: Download Funkwhale 2.0.0-rc5&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;export FUNKWHALE_VERSION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.0.0-rc5&amp;#34;&lt;/span&gt;
cd /srv/funkwhale

&lt;span style=&#34;color:#75715e&#34;&gt;# Download API&lt;/span&gt;
curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;api-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/download?job=build_api&amp;#34;&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# Download Frontend&lt;/span&gt;
curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;front-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/download?job=build_front&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;step-5-install-the-new-version&#34;&gt;Step 5: Install the New Version&lt;/h2&gt;
&lt;h3 id=&#34;remove-old-files&#34;&gt;Remove Old Files&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;rm -rf /srv/funkwhale/api/*
rm -rf /srv/funkwhale/front/*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;extract-new-files&#34;&gt;Extract New Files&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;cd /srv/funkwhale

&lt;span style=&#34;color:#75715e&#34;&gt;# Extract API&lt;/span&gt;
unzip -q &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;api-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt; -d extracted
mv extracted/api/* api/
rm -rf extracted &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;api-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# Extract Frontend&lt;/span&gt;
unzip -q &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;front-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt; -d extracted
mv extracted/front/* front/
rm -rf extracted &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;front-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;create-new-python-virtual-environment&#34;&gt;Create New Python Virtual Environment&lt;/h3&gt;
&lt;p&gt;Funkwhale 2.0 uses &lt;code&gt;venv&lt;/code&gt; instead of &lt;code&gt;virtualenv&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;cd /srv/funkwhale

&lt;span style=&#34;color:#75715e&#34;&gt;# Remove old virtualenv (if upgrading from 1.x)&lt;/span&gt;
rm -rf virtualenv

&lt;span style=&#34;color:#75715e&#34;&gt;# Create new venv&lt;/span&gt;
python3 -m venv venv
venv/bin/pip install --upgrade pip wheel

&lt;span style=&#34;color:#75715e&#34;&gt;# Install Funkwhale API&lt;/span&gt;
venv/bin/pip install --editable ./api

&lt;span style=&#34;color:#75715e&#34;&gt;# Set correct permissions&lt;/span&gt;
chown -R funkwhale:funkwhale api front venv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;step-6-update-systemd-unit-files&#34;&gt;Step 6: Update Systemd Unit Files&lt;/h2&gt;
&lt;p&gt;The systemd unit files need to be updated to point to the new &lt;code&gt;venv&lt;/code&gt; directory instead of &lt;code&gt;virtualenv&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can download them from the repository:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;export FUNKWHALE_VERSION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.0.0-rc5&amp;#34;&lt;/span&gt;

curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/etc/systemd/system/funkwhale.target&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/deploy/funkwhale.target&amp;#34;&lt;/span&gt;
curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/etc/systemd/system/funkwhale-server.service&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/deploy/funkwhale-server.service&amp;#34;&lt;/span&gt;
curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/etc/systemd/system/funkwhale-worker.service&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/deploy/funkwhale-worker.service&amp;#34;&lt;/span&gt;
curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/etc/systemd/system/funkwhale-beat.service&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/deploy/funkwhale-beat.service&amp;#34;&lt;/span&gt;

systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If the curl commands return HTML instead of the service files (404 errors), you may need to clone the repository and copy the files manually:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;git clone --branch 2.0.0-rc5 --depth &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; https://dev.funkwhale.audio/funkwhale/funkwhale.git /tmp/funkwhale-2.0
cp /tmp/funkwhale-2.0/deploy/funkwhale*.service /etc/systemd/system/
cp /tmp/funkwhale-2.0/deploy/funkwhale.target /etc/systemd/system/
systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;step-7-update-nginx-configuration-optional&#34;&gt;Step 7: Update Nginx Configuration (Optional)&lt;/h2&gt;
&lt;p&gt;If you want to use the latest nginx configuration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;curl -L -o /etc/nginx/funkwhale_proxy.conf &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/deploy/funkwhale_proxy.conf&amp;#34;&lt;/span&gt;

nginx -t &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;step-8-run-database-migrations&#34;&gt;Step 8: Run Database Migrations&lt;/h2&gt;
&lt;p&gt;This is the critical step that updates your database schema:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;cd /srv/funkwhale

&lt;span style=&#34;color:#75715e&#34;&gt;# Collect static files&lt;/span&gt;
sudo -u funkwhale venv/bin/funkwhale-manage collectstatic --no-input

&lt;span style=&#34;color:#75715e&#34;&gt;# Run migrations&lt;/span&gt;
sudo -u funkwhale venv/bin/funkwhale-manage migrate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You should see output showing the migrations being applied, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;music.0001_initial&lt;/code&gt; through various migrations&lt;/li&gt;
&lt;li&gt;&lt;code&gt;playlists&lt;/code&gt; migrations (new in 2.0)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;common&lt;/code&gt; and &lt;code&gt;federation&lt;/code&gt; updates&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;step-9-start-services&#34;&gt;Step 9: Start Services&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;systemctl start funkwhale.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wait a few seconds and verify everything is running:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;systemctl status funkwhale-server funkwhale-worker funkwhale-beat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All three services should show &lt;code&gt;active (running)&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;step-10-verify-the-upgrade&#34;&gt;Step 10: Verify the Upgrade&lt;/h2&gt;
&lt;p&gt;Check that the API is responding:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;curl -s https://your-domain.com/api/v2/ | head -20
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You should see the API root response with version information.&lt;/p&gt;
&lt;h2 id=&#34;troubleshooting&#34;&gt;Troubleshooting&lt;/h2&gt;
&lt;h3 id=&#34;issue-ensurepip-is-not-available&#34;&gt;Issue: &amp;ldquo;ensurepip is not available&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;If you see this error when creating the venv:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Error: Command &#39;[&#39;/srv/funkwhale/venv/bin/python3&#39;, &#39;-m&#39;, &#39;ensurepip&#39;, &#39;--upgrade&#39;, &#39;--default-pip&#39;]&#39; returned non-zero exit status 1.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Install the python3.11-venv package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;apt install python3.11-venv
rm -rf /srv/funkwhale/venv
python3 -m venv /srv/funkwhale/venv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;issue-celery-beat-fails-to-start&#34;&gt;Issue: Celery Beat Fails to Start&lt;/h3&gt;
&lt;p&gt;If funkwhale-beat keeps restarting with database errors:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;_dbm.error: cannot add item to database
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Remove the corrupted schedule database:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;rm /srv/funkwhale/api/celerybeat-schedule.db
systemctl restart funkwhale-beat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;issue-systemd-unit-download-returns-html&#34;&gt;Issue: Systemd Unit Download Returns HTML&lt;/h3&gt;
&lt;p&gt;The GitLab raw file URLs sometimes don&amp;rsquo;t work for tags. Clone the repo and copy manually (see Step 6).&lt;/p&gt;
&lt;h3 id=&#34;issue-permission-errors&#34;&gt;Issue: Permission Errors&lt;/h3&gt;
&lt;p&gt;Always ensure the funkwhale user owns all files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;chown -R funkwhale:funkwhale /srv/funkwhale/api /srv/funkwhale/front /srv/funkwhale/venv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;rollback-procedure&#34;&gt;Rollback Procedure&lt;/h2&gt;
&lt;p&gt;If something goes seriously wrong, you can rollback:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Stop services:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;systemctl stop funkwhale.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Restore files from backup:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;BACKUP_DIR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/srv/funkwhale/backups/upgrade-YYYYMMDD_HHMMSS&amp;#34;&lt;/span&gt;
rm -rf /srv/funkwhale/api /srv/funkwhale/front /srv/funkwhale/venv
cp -a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/api&amp;#34;&lt;/span&gt; /srv/funkwhale/
cp -a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/front&amp;#34;&lt;/span&gt; /srv/funkwhale/
cp -a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/virtualenv&amp;#34;&lt;/span&gt; /srv/funkwhale/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Restore systemd units:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;cp &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/systemd/&amp;#34;&lt;/span&gt;* /etc/systemd/system/
systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Restore database (if needed):
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;sudo -u postgres psql &amp;lt; /srv/funkwhale/backups/dump_DD-MM-YYYY_HH_MM_SS.sql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Start services:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;systemctl start funkwhale.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;automated-upgrade-script&#34;&gt;Automated Upgrade Script&lt;/h2&gt;
&lt;p&gt;For convenience, I&amp;rsquo;ve created a script that automates the entire process with rollback capability. You can find it below:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;span style=&#34;color:#75715e&#34;&gt;# Funkwhale Upgrade Script: 1.4.0 -&amp;gt; 2.0.0-rc5&lt;/span&gt;
&lt;span style=&#34;color:#75715e&#34;&gt;# With rollback capability&lt;/span&gt;
&lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;span style=&#34;color:#75715e&#34;&gt;# Usage: ./upgrade-funkwhale-2.0.sh [upgrade|rollback|status]&lt;/span&gt;
&lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;

set -e

&lt;span style=&#34;color:#75715e&#34;&gt;# Configuration&lt;/span&gt;
FUNKWHALE_VERSION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2.0.0-rc5&amp;#34;&lt;/span&gt;
FUNKWHALE_DIR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/srv/funkwhale&amp;#34;&lt;/span&gt;
BACKUP_DIR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/srv/funkwhale/backups/upgrade-&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;date +%Y%m%d_%H%M%S&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
ROLLBACK_MARKER&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/srv/funkwhale/backups/.rollback_info&amp;#34;&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# Colors for output&lt;/span&gt;
RED&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\033[0;31m&amp;#39;&lt;/span&gt;
GREEN&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\033[0;32m&amp;#39;&lt;/span&gt;
YELLOW&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\033[1;33m&amp;#39;&lt;/span&gt;
NC&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\033[0m&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# No Color&lt;/span&gt;

log_info&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; echo -e &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;GREEN&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;[INFO]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;NC&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; &lt;/span&gt;$1&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
log_warn&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; echo -e &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;YELLOW&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;[WARN]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;NC&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; &lt;/span&gt;$1&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
log_error&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; echo -e &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;RED&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;[ERROR]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;NC&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; &lt;/span&gt;$1&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

check_root&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[[&lt;/span&gt; $EUID -ne &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
        log_error &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;This script must be run as root&amp;#34;&lt;/span&gt;
        exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

check_services_stopped&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; systemctl is-active --quiet funkwhale-server.service; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
        log_error &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Funkwhale services are still running. Stop them first with: systemctl stop funkwhale.target&amp;#34;&lt;/span&gt;
        exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

backup_current&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Creating backup in &lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;...&amp;#34;&lt;/span&gt;
    mkdir -p &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backing up API...&amp;#34;&lt;/span&gt;
    cp -a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/api&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/api&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backing up frontend...&amp;#34;&lt;/span&gt;
    cp -a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/front&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/front&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backing up virtualenv...&amp;#34;&lt;/span&gt;
    cp -a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/virtualenv&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/virtualenv&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backing up config...&amp;#34;&lt;/span&gt;
    cp -a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/config&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/config&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backing up systemd units...&amp;#34;&lt;/span&gt;
    mkdir -p &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/systemd&amp;#34;&lt;/span&gt;
    cp /etc/systemd/system/funkwhale*.service &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/systemd/&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; true
    cp /etc/systemd/system/funkwhale.target &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/systemd/&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; true

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backing up nginx config...&amp;#34;&lt;/span&gt;
    mkdir -p &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/nginx&amp;#34;&lt;/span&gt;
    cp /etc/nginx/sites-enabled/*.conf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/nginx/&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; true
    cp /etc/nginx/funkwhale_proxy.conf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/nginx/&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; true

    &lt;span style=&#34;color:#75715e&#34;&gt;# Save rollback info&lt;/span&gt;
    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ROLLBACK_MARKER&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;BACKUP_DATE=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;date&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ROLLBACK_MARKER&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OLD_VERSION=1.4.0&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ROLLBACK_MARKER&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NEW_VERSION=&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ROLLBACK_MARKER&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backup complete: &lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

download_new_version&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Downloading Funkwhale &lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;...&amp;#34;&lt;/span&gt;

    cd &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Downloading API...&amp;#34;&lt;/span&gt;
    curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;api-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/download?job=build_api&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Downloading Frontend...&amp;#34;&lt;/span&gt;
    curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;front-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/download?job=build_front&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Downloads complete&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

install_new_version&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Installing Funkwhale &lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;...&amp;#34;&lt;/span&gt;

    cd &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Removing old API and frontend...&amp;#34;&lt;/span&gt;
    rm -rf api/* front/*

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Extracting API...&amp;#34;&lt;/span&gt;
    unzip -q &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;api-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt; -d extracted
    mv extracted/api/* api/
    rm -rf extracted &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;api-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Extracting frontend...&amp;#34;&lt;/span&gt;
    unzip -q &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;front-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt; -d extracted
    rm -rf front/*
    mv extracted/front/* front/
    rm -rf extracted &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;front-&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;.zip&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Creating new Python virtual environment...&amp;#34;&lt;/span&gt;
    rm -rf venv
    python3 -m venv venv
    venv/bin/pip install --upgrade pip wheel

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Installing Funkwhale API package...&amp;#34;&lt;/span&gt;
    venv/bin/pip install --editable ./api

    chown -R funkwhale:funkwhale api front venv

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Installation complete&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

update_systemd_units&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Updating systemd unit files...&amp;#34;&lt;/span&gt;

    curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/etc/systemd/system/funkwhale.target&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/deploy/funkwhale.target&amp;#34;&lt;/span&gt;
    curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/etc/systemd/system/funkwhale-server.service&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/deploy/funkwhale-server.service&amp;#34;&lt;/span&gt;
    curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/etc/systemd/system/funkwhale-worker.service&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/deploy/funkwhale-worker.service&amp;#34;&lt;/span&gt;
    curl -L -o &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/etc/systemd/system/funkwhale-beat.service&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/&lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;/deploy/funkwhale-beat.service&amp;#34;&lt;/span&gt;

    systemctl daemon-reload
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Systemd units updated&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

run_migrations&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Running database migrations...&amp;#34;&lt;/span&gt;

    cd &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Collecting static files...&amp;#34;&lt;/span&gt;
    sudo -u funkwhale venv/bin/funkwhale-manage collectstatic --no-input

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Applying database migrations...&amp;#34;&lt;/span&gt;
    sudo -u funkwhale venv/bin/funkwhale-manage migrate

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Migrations complete&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

start_services&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Starting Funkwhale services...&amp;#34;&lt;/span&gt;
    systemctl start funkwhale.target
    systemctl reload nginx

    sleep &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;

    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; systemctl is-active --quiet funkwhale-server.service; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
        log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Funkwhale services started successfully!&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;
        log_error &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Services failed to start. Check logs with: journalctl -u funkwhale-server.service&amp;#34;&lt;/span&gt;
        exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

do_upgrade&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Starting Funkwhale upgrade to &lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
    log_warn &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Make sure you have a database backup before proceeding!&amp;#34;&lt;/span&gt;

    check_root
    check_services_stopped

    backup_current
    download_new_version
    install_new_version
    update_systemd_units
    run_migrations
    start_services

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;==========================================&amp;#34;&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Upgrade complete!&amp;#34;&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Funkwhale &lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt; is now running&amp;#34;&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;==========================================&amp;#34;&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;If something goes wrong, run: &lt;/span&gt;$0&lt;span style=&#34;color:#e6db74&#34;&gt; rollback&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

do_rollback&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Starting rollback...&amp;#34;&lt;/span&gt;

    check_root

    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[[&lt;/span&gt; ! -f &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ROLLBACK_MARKER&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
        log_error &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;No rollback information found. Cannot rollback.&amp;#34;&lt;/span&gt;
        exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;

    BACKUP_DIR&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;head -1 &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ROLLBACK_MARKER&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;

    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[[&lt;/span&gt; ! -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
        log_error &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Backup directory not found: &lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
        exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Rolling back from backup: &lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;

    systemctl stop funkwhale.target 2&amp;gt;/dev/null &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; true

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Restoring API...&amp;#34;&lt;/span&gt;
    rm -rf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/api&amp;#34;&lt;/span&gt;
    cp -a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/api&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/api&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Restoring frontend...&amp;#34;&lt;/span&gt;
    rm -rf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/front&amp;#34;&lt;/span&gt;
    cp -a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/front&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/front&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Restoring virtualenv...&amp;#34;&lt;/span&gt;
    rm -rf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/venv&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/virtualenv&amp;#34;&lt;/span&gt;
    cp -a &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/virtualenv&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/virtualenv&amp;#34;&lt;/span&gt;

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Restoring systemd units...&amp;#34;&lt;/span&gt;
    cp &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/systemd/&amp;#34;&lt;/span&gt;* /etc/systemd/system/
    systemctl daemon-reload

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Restoring nginx config...&amp;#34;&lt;/span&gt;
    cp &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/nginx/&amp;#34;&lt;/span&gt;* /etc/nginx/sites-enabled/ 2&amp;gt;/dev/null &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; true
    cp &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$BACKUP_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/nginx/funkwhale_proxy.conf&amp;#34;&lt;/span&gt; /etc/nginx/ 2&amp;gt;/dev/null &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; true

    log_warn &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NOTE: Database was NOT rolled back automatically.&amp;#34;&lt;/span&gt;
    log_warn &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;To restore database, run:&amp;#34;&lt;/span&gt;
    log_warn &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  sudo -u postgres psql &amp;lt; /srv/funkwhale/backups/dump_*.sql&amp;#34;&lt;/span&gt;

    systemctl start funkwhale.target
    systemctl reload nginx

    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;==========================================&amp;#34;&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Rollback complete!&amp;#34;&lt;/span&gt;
    log_info &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;==========================================&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

show_status&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Current Funkwhale installation:&amp;#34;&lt;/span&gt;
    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;================================&amp;#34;&lt;/span&gt;

    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[[&lt;/span&gt; -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/venv&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Virtual env: venv (2.0 style)&amp;#34;&lt;/span&gt;
        VERSION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/venv/bin/pip&amp;#34;&lt;/span&gt; show funkwhale-api 2&amp;gt;/dev/null | grep Version | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;elif&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[[&lt;/span&gt; -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/virtualenv&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Virtual env: virtualenv (1.x style)&amp;#34;&lt;/span&gt;
        VERSION&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$FUNKWHALE_DIR&lt;span style=&#34;color:#e6db74&#34;&gt;/virtualenv/bin/pip&amp;#34;&lt;/span&gt; show funkwhale-api 2&amp;gt;/dev/null | grep Version | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;

    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Installed version: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;VERSION&lt;span style=&#34;color:#66d9ef&#34;&gt;:-&lt;/span&gt;unknown&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Service status:&amp;#34;&lt;/span&gt;
    systemctl status funkwhale.target --no-pager 2&amp;gt;/dev/null &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  Not running&amp;#34;&lt;/span&gt;

    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[[&lt;/span&gt; -f &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ROLLBACK_MARKER&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Rollback available:&amp;#34;&lt;/span&gt;
        cat &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$ROLLBACK_MARKER&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# Main&lt;/span&gt;
&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;1&lt;span style=&#34;color:#66d9ef&#34;&gt;:-&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; in
    upgrade&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
        do_upgrade
        ;;
    rollback&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
        do_rollback
        ;;
    status&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
        show_status
        ;;
    *&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Funkwhale Upgrade Script&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;========================&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Usage: &lt;/span&gt;$0&lt;span style=&#34;color:#e6db74&#34;&gt; [command]&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Commands:&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  upgrade   - Upgrade Funkwhale to &lt;/span&gt;$FUNKWHALE_VERSION&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  rollback  - Rollback to previous version&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  status    - Show current installation status&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Before upgrading:&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  1. Ensure database is backed up&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  2. Ensure media files are backed up&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  3. Stop services: systemctl stop funkwhale.target&amp;#34;&lt;/span&gt;
        echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
        ;;
&lt;span style=&#34;color:#66d9ef&#34;&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Save this as &lt;code&gt;upgrade-funkwhale-2.0.sh&lt;/code&gt;, make it executable with &lt;code&gt;chmod +x upgrade-funkwhale-2.0.sh&lt;/code&gt;, and run with &lt;code&gt;sudo ./upgrade-funkwhale-2.0.sh upgrade&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The upgrade from Funkwhale 1.4.0 to 2.0.0-rc5 went smoothly once I resolved the Python venv package issue and worked around the systemd unit file download problem. The database migrations ran without issues, and all my music library was preserved (now organized under the new playlist system instead of libraries).&lt;/p&gt;
&lt;p&gt;If you encounter any issues not covered here, check the &lt;a href=&#34;https://docs.funkwhale.audio/&#34;&gt;Funkwhale documentation&lt;/a&gt; or join the community on Matrix/IRC for help.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Last updated: December 2025&lt;/em&gt;&lt;/p&gt;
</description>
      <source:markdown>After running Funkwhale 1.4.0 for a while, I decided to upgrade to the 2.0.0-rc5 release candidate. This post documents the full upgrade process on a Debian 12 (bookworm) server, including the issues I encountered and how to resolve them.
## What&#39;s New in Funkwhale 2.0

Funkwhale 2.0 brings significant changes:

- **Libraries replaced by Playlists** - The old &#34;Libraries&#34; concept has been migrated to a more intuitive playlist-based system
- **Python 3.11+ required** - The minimum Python version has been bumped
- **Django 5.1.6** - Major framework upgrade
- **venv instead of virtualenv** - The recommended virtual environment tool has changed
- **Improved artist credits system** - Better handling of artist metadata
- **Federation improvements** - Enhanced ActivityPub support (though this may break compatibility with older instances)

## Prerequisites

Before starting the upgrade, ensure you have:

- Root access to your server
- Sufficient disk space for backups (~2x your database size + config files)
- Python 3.11 installed (`python3 --version`)
- The `python3.11-venv` package installed

```bash
apt install python3.11-venv
```
## Step 1: Create a Full Backup

**Never skip this step.** The database backup is your lifeline if something goes wrong.

### Database Backup

```bash
sudo -u postgres pg_dumpall &gt; /srv/funkwhale/backups/dump_$(date +%d-%m-%Y_%H_%M_%S).sql
```
### Media Backup

If you have a lot of music, consider syncing your media directory to another location:

```bash
# From your local machine (if you have rsync access)
rsync -avz --progress user@yourserver:/srv/funkwhale/data/music ~/funkwhale-backup/music/
```
Or create a compressed archive on the server:

```bash
tar -czvf /srv/funkwhale/backups/media-backup.tar.gz /srv/funkwhale/data/music
```
### Configuration Backup

```bash
cp -a /srv/funkwhale/config /srv/funkwhale/backups/config-backup
```
## Step 2: Stop Funkwhale Services

```bash
systemctl stop funkwhale.target
```
Verify everything is stopped:

```bash
systemctl status funkwhale-server funkwhale-worker funkwhale-beat
```
## Step 3: Backup Current Installation

Before removing anything, backup the current installation for potential rollback:

```bash
BACKUP_DIR=&#34;/srv/funkwhale/backups/upgrade-$(date +%Y%m%d_%H%M%S)&#34;
mkdir -p &#34;$BACKUP_DIR&#34;

cp -a /srv/funkwhale/api &#34;$BACKUP_DIR/api&#34;
cp -a /srv/funkwhale/front &#34;$BACKUP_DIR/front&#34;
cp -a /srv/funkwhale/virtualenv &#34;$BACKUP_DIR/virtualenv&#34;
cp -a /srv/funkwhale/config &#34;$BACKUP_DIR/config&#34;

# Backup systemd units
mkdir -p &#34;$BACKUP_DIR/systemd&#34;
cp /etc/systemd/system/funkwhale*.service &#34;$BACKUP_DIR/systemd/&#34;
cp /etc/systemd/system/funkwhale.target &#34;$BACKUP_DIR/systemd/&#34;

# Backup nginx config
mkdir -p &#34;$BACKUP_DIR/nginx&#34;
cp /etc/nginx/sites-enabled/your-site.conf &#34;$BACKUP_DIR/nginx/&#34;
cp /etc/nginx/funkwhale_proxy.conf &#34;$BACKUP_DIR/nginx/&#34;
```
## Step 4: Download Funkwhale 2.0.0-rc5

```bash
export FUNKWHALE_VERSION=&#34;2.0.0-rc5&#34;
cd /srv/funkwhale

# Download API
curl -L -o &#34;api-$FUNKWHALE_VERSION.zip&#34; \
    &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/$FUNKWHALE_VERSION/download?job=build_api&#34;

# Download Frontend
curl -L -o &#34;front-$FUNKWHALE_VERSION.zip&#34; \
    &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/$FUNKWHALE_VERSION/download?job=build_front&#34;
```
## Step 5: Install the New Version

### Remove Old Files

```bash
rm -rf /srv/funkwhale/api/*
rm -rf /srv/funkwhale/front/*
```
### Extract New Files

```bash
cd /srv/funkwhale

# Extract API
unzip -q &#34;api-$FUNKWHALE_VERSION.zip&#34; -d extracted
mv extracted/api/* api/
rm -rf extracted &#34;api-$FUNKWHALE_VERSION.zip&#34;

# Extract Frontend
unzip -q &#34;front-$FUNKWHALE_VERSION.zip&#34; -d extracted
mv extracted/front/* front/
rm -rf extracted &#34;front-$FUNKWHALE_VERSION.zip&#34;
```
### Create New Python Virtual Environment

Funkwhale 2.0 uses `venv` instead of `virtualenv`:

```bash
cd /srv/funkwhale

# Remove old virtualenv (if upgrading from 1.x)
rm -rf virtualenv

# Create new venv
python3 -m venv venv
venv/bin/pip install --upgrade pip wheel

# Install Funkwhale API
venv/bin/pip install --editable ./api

# Set correct permissions
chown -R funkwhale:funkwhale api front venv
```
## Step 6: Update Systemd Unit Files

The systemd unit files need to be updated to point to the new `venv` directory instead of `virtualenv`.

You can download them from the repository:

```bash
export FUNKWHALE_VERSION=&#34;2.0.0-rc5&#34;

curl -L -o &#34;/etc/systemd/system/funkwhale.target&#34; \
    &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale.target&#34;
curl -L -o &#34;/etc/systemd/system/funkwhale-server.service&#34; \
    &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale-server.service&#34;
curl -L -o &#34;/etc/systemd/system/funkwhale-worker.service&#34; \
    &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale-worker.service&#34;
curl -L -o &#34;/etc/systemd/system/funkwhale-beat.service&#34; \
    &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale-beat.service&#34;

systemctl daemon-reload
```
**Note:** If the curl commands return HTML instead of the service files (404 errors), you may need to clone the repository and copy the files manually:

```bash
git clone --branch 2.0.0-rc5 --depth 1 https://dev.funkwhale.audio/funkwhale/funkwhale.git /tmp/funkwhale-2.0
cp /tmp/funkwhale-2.0/deploy/funkwhale*.service /etc/systemd/system/
cp /tmp/funkwhale-2.0/deploy/funkwhale.target /etc/systemd/system/
systemctl daemon-reload
```
## Step 7: Update Nginx Configuration (Optional)

If you want to use the latest nginx configuration:

```bash
curl -L -o /etc/nginx/funkwhale_proxy.conf \
    &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale_proxy.conf&#34;

nginx -t &amp;&amp; systemctl reload nginx
```
## Step 8: Run Database Migrations

This is the critical step that updates your database schema:

```bash
cd /srv/funkwhale

# Collect static files
sudo -u funkwhale venv/bin/funkwhale-manage collectstatic --no-input

# Run migrations
sudo -u funkwhale venv/bin/funkwhale-manage migrate
```
You should see output showing the migrations being applied, including:
- `music.0001_initial` through various migrations
- `playlists` migrations (new in 2.0)
- `common` and `federation` updates

## Step 9: Start Services

```bash
systemctl start funkwhale.target
```
Wait a few seconds and verify everything is running:

```bash
systemctl status funkwhale-server funkwhale-worker funkwhale-beat
```
All three services should show `active (running)`.

## Step 10: Verify the Upgrade

Check that the API is responding:

```bash
curl -s https://your-domain.com/api/v2/ | head -20
```
You should see the API root response with version information.

## Troubleshooting

### Issue: &#34;ensurepip is not available&#34;

If you see this error when creating the venv:

```
Error: Command &#39;[&#39;/srv/funkwhale/venv/bin/python3&#39;, &#39;-m&#39;, &#39;ensurepip&#39;, &#39;--upgrade&#39;, &#39;--default-pip&#39;]&#39; returned non-zero exit status 1.
```
**Solution:** Install the python3.11-venv package:

```bash
apt install python3.11-venv
rm -rf /srv/funkwhale/venv
python3 -m venv /srv/funkwhale/venv
```
### Issue: Celery Beat Fails to Start

If funkwhale-beat keeps restarting with database errors:

```
_dbm.error: cannot add item to database
```
**Solution:** Remove the corrupted schedule database:

```bash
rm /srv/funkwhale/api/celerybeat-schedule.db
systemctl restart funkwhale-beat
```
### Issue: Systemd Unit Download Returns HTML

The GitLab raw file URLs sometimes don&#39;t work for tags. Clone the repo and copy manually (see Step 6).

### Issue: Permission Errors

Always ensure the funkwhale user owns all files:

```bash
chown -R funkwhale:funkwhale /srv/funkwhale/api /srv/funkwhale/front /srv/funkwhale/venv
```
## Rollback Procedure

If something goes seriously wrong, you can rollback:

1. Stop services:
   ```bash
   systemctl stop funkwhale.target
   ```
2. Restore files from backup:
   ```bash
   BACKUP_DIR=&#34;/srv/funkwhale/backups/upgrade-YYYYMMDD_HHMMSS&#34;
   rm -rf /srv/funkwhale/api /srv/funkwhale/front /srv/funkwhale/venv
   cp -a &#34;$BACKUP_DIR/api&#34; /srv/funkwhale/
   cp -a &#34;$BACKUP_DIR/front&#34; /srv/funkwhale/
   cp -a &#34;$BACKUP_DIR/virtualenv&#34; /srv/funkwhale/
   ```
3. Restore systemd units:
   ```bash
   cp &#34;$BACKUP_DIR/systemd/&#34;* /etc/systemd/system/
   systemctl daemon-reload
   ```
4. Restore database (if needed):
   ```bash
   sudo -u postgres psql &lt; /srv/funkwhale/backups/dump_DD-MM-YYYY_HH_MM_SS.sql
   ```
5. Start services:
   ```bash
   systemctl start funkwhale.target
   ```
## Automated Upgrade Script

For convenience, I&#39;ve created a script that automates the entire process with rollback capability. You can find it below:

```bash
#!/bin/bash
#
# Funkwhale Upgrade Script: 1.4.0 -&gt; 2.0.0-rc5
# With rollback capability
#
# Usage: ./upgrade-funkwhale-2.0.sh [upgrade|rollback|status]
#

set -e

# Configuration
FUNKWHALE_VERSION=&#34;2.0.0-rc5&#34;
FUNKWHALE_DIR=&#34;/srv/funkwhale&#34;
BACKUP_DIR=&#34;/srv/funkwhale/backups/upgrade-$(date +%Y%m%d_%H%M%S)&#34;
ROLLBACK_MARKER=&#34;/srv/funkwhale/backups/.rollback_info&#34;

# Colors for output
RED=&#39;\033[0;31m&#39;
GREEN=&#39;\033[0;32m&#39;
YELLOW=&#39;\033[1;33m&#39;
NC=&#39;\033[0m&#39; # No Color

log_info() { echo -e &#34;${GREEN}[INFO]${NC} $1&#34;; }
log_warn() { echo -e &#34;${YELLOW}[WARN]${NC} $1&#34;; }
log_error() { echo -e &#34;${RED}[ERROR]${NC} $1&#34;; }

check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error &#34;This script must be run as root&#34;
        exit 1
    fi
}

check_services_stopped() {
    if systemctl is-active --quiet funkwhale-server.service; then
        log_error &#34;Funkwhale services are still running. Stop them first with: systemctl stop funkwhale.target&#34;
        exit 1
    fi
}

backup_current() {
    log_info &#34;Creating backup in $BACKUP_DIR...&#34;
    mkdir -p &#34;$BACKUP_DIR&#34;

    log_info &#34;Backing up API...&#34;
    cp -a &#34;$FUNKWHALE_DIR/api&#34; &#34;$BACKUP_DIR/api&#34;

    log_info &#34;Backing up frontend...&#34;
    cp -a &#34;$FUNKWHALE_DIR/front&#34; &#34;$BACKUP_DIR/front&#34;

    log_info &#34;Backing up virtualenv...&#34;
    cp -a &#34;$FUNKWHALE_DIR/virtualenv&#34; &#34;$BACKUP_DIR/virtualenv&#34;

    log_info &#34;Backing up config...&#34;
    cp -a &#34;$FUNKWHALE_DIR/config&#34; &#34;$BACKUP_DIR/config&#34;

    log_info &#34;Backing up systemd units...&#34;
    mkdir -p &#34;$BACKUP_DIR/systemd&#34;
    cp /etc/systemd/system/funkwhale*.service &#34;$BACKUP_DIR/systemd/&#34; 2&gt;/dev/null || true
    cp /etc/systemd/system/funkwhale.target &#34;$BACKUP_DIR/systemd/&#34; 2&gt;/dev/null || true

    log_info &#34;Backing up nginx config...&#34;
    mkdir -p &#34;$BACKUP_DIR/nginx&#34;
    cp /etc/nginx/sites-enabled/*.conf &#34;$BACKUP_DIR/nginx/&#34; 2&gt;/dev/null || true
    cp /etc/nginx/funkwhale_proxy.conf &#34;$BACKUP_DIR/nginx/&#34; 2&gt;/dev/null || true

    # Save rollback info
    echo &#34;$BACKUP_DIR&#34; &gt; &#34;$ROLLBACK_MARKER&#34;
    echo &#34;BACKUP_DATE=$(date)&#34; &gt;&gt; &#34;$ROLLBACK_MARKER&#34;
    echo &#34;OLD_VERSION=1.4.0&#34; &gt;&gt; &#34;$ROLLBACK_MARKER&#34;
    echo &#34;NEW_VERSION=$FUNKWHALE_VERSION&#34; &gt;&gt; &#34;$ROLLBACK_MARKER&#34;

    log_info &#34;Backup complete: $BACKUP_DIR&#34;
}

download_new_version() {
    log_info &#34;Downloading Funkwhale $FUNKWHALE_VERSION...&#34;

    cd &#34;$FUNKWHALE_DIR&#34;

    log_info &#34;Downloading API...&#34;
    curl -L -o &#34;api-$FUNKWHALE_VERSION.zip&#34; \
        &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/$FUNKWHALE_VERSION/download?job=build_api&#34;

    log_info &#34;Downloading Frontend...&#34;
    curl -L -o &#34;front-$FUNKWHALE_VERSION.zip&#34; \
        &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/artifacts/$FUNKWHALE_VERSION/download?job=build_front&#34;

    log_info &#34;Downloads complete&#34;
}

install_new_version() {
    log_info &#34;Installing Funkwhale $FUNKWHALE_VERSION...&#34;

    cd &#34;$FUNKWHALE_DIR&#34;

    log_info &#34;Removing old API and frontend...&#34;
    rm -rf api/* front/*

    log_info &#34;Extracting API...&#34;
    unzip -q &#34;api-$FUNKWHALE_VERSION.zip&#34; -d extracted
    mv extracted/api/* api/
    rm -rf extracted &#34;api-$FUNKWHALE_VERSION.zip&#34;

    log_info &#34;Extracting frontend...&#34;
    unzip -q &#34;front-$FUNKWHALE_VERSION.zip&#34; -d extracted
    rm -rf front/*
    mv extracted/front/* front/
    rm -rf extracted &#34;front-$FUNKWHALE_VERSION.zip&#34;

    log_info &#34;Creating new Python virtual environment...&#34;
    rm -rf venv
    python3 -m venv venv
    venv/bin/pip install --upgrade pip wheel

    log_info &#34;Installing Funkwhale API package...&#34;
    venv/bin/pip install --editable ./api

    chown -R funkwhale:funkwhale api front venv

    log_info &#34;Installation complete&#34;
}

update_systemd_units() {
    log_info &#34;Updating systemd unit files...&#34;

    curl -L -o &#34;/etc/systemd/system/funkwhale.target&#34; \
        &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale.target&#34;
    curl -L -o &#34;/etc/systemd/system/funkwhale-server.service&#34; \
        &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale-server.service&#34;
    curl -L -o &#34;/etc/systemd/system/funkwhale-worker.service&#34; \
        &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale-worker.service&#34;
    curl -L -o &#34;/etc/systemd/system/funkwhale-beat.service&#34; \
        &#34;https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale-beat.service&#34;

    systemctl daemon-reload
    log_info &#34;Systemd units updated&#34;
}

run_migrations() {
    log_info &#34;Running database migrations...&#34;

    cd &#34;$FUNKWHALE_DIR&#34;

    log_info &#34;Collecting static files...&#34;
    sudo -u funkwhale venv/bin/funkwhale-manage collectstatic --no-input

    log_info &#34;Applying database migrations...&#34;
    sudo -u funkwhale venv/bin/funkwhale-manage migrate

    log_info &#34;Migrations complete&#34;
}

start_services() {
    log_info &#34;Starting Funkwhale services...&#34;
    systemctl start funkwhale.target
    systemctl reload nginx

    sleep 5

    if systemctl is-active --quiet funkwhale-server.service; then
        log_info &#34;Funkwhale services started successfully!&#34;
    else
        log_error &#34;Services failed to start. Check logs with: journalctl -u funkwhale-server.service&#34;
        exit 1
    fi
}

do_upgrade() {
    log_info &#34;Starting Funkwhale upgrade to $FUNKWHALE_VERSION&#34;
    log_warn &#34;Make sure you have a database backup before proceeding!&#34;

    check_root
    check_services_stopped

    backup_current
    download_new_version
    install_new_version
    update_systemd_units
    run_migrations
    start_services

    log_info &#34;==========================================&#34;
    log_info &#34;Upgrade complete!&#34;
    log_info &#34;Funkwhale $FUNKWHALE_VERSION is now running&#34;
    log_info &#34;==========================================&#34;
    log_info &#34;If something goes wrong, run: $0 rollback&#34;
}

do_rollback() {
    log_info &#34;Starting rollback...&#34;

    check_root

    if [[ ! -f &#34;$ROLLBACK_MARKER&#34; ]]; then
        log_error &#34;No rollback information found. Cannot rollback.&#34;
        exit 1
    fi

    BACKUP_DIR=$(head -1 &#34;$ROLLBACK_MARKER&#34;)

    if [[ ! -d &#34;$BACKUP_DIR&#34; ]]; then
        log_error &#34;Backup directory not found: $BACKUP_DIR&#34;
        exit 1
    fi

    log_info &#34;Rolling back from backup: $BACKUP_DIR&#34;

    systemctl stop funkwhale.target 2&gt;/dev/null || true

    log_info &#34;Restoring API...&#34;
    rm -rf &#34;$FUNKWHALE_DIR/api&#34;
    cp -a &#34;$BACKUP_DIR/api&#34; &#34;$FUNKWHALE_DIR/api&#34;

    log_info &#34;Restoring frontend...&#34;
    rm -rf &#34;$FUNKWHALE_DIR/front&#34;
    cp -a &#34;$BACKUP_DIR/front&#34; &#34;$FUNKWHALE_DIR/front&#34;

    log_info &#34;Restoring virtualenv...&#34;
    rm -rf &#34;$FUNKWHALE_DIR/venv&#34; &#34;$FUNKWHALE_DIR/virtualenv&#34;
    cp -a &#34;$BACKUP_DIR/virtualenv&#34; &#34;$FUNKWHALE_DIR/virtualenv&#34;

    log_info &#34;Restoring systemd units...&#34;
    cp &#34;$BACKUP_DIR/systemd/&#34;* /etc/systemd/system/
    systemctl daemon-reload

    log_info &#34;Restoring nginx config...&#34;
    cp &#34;$BACKUP_DIR/nginx/&#34;* /etc/nginx/sites-enabled/ 2&gt;/dev/null || true
    cp &#34;$BACKUP_DIR/nginx/funkwhale_proxy.conf&#34; /etc/nginx/ 2&gt;/dev/null || true

    log_warn &#34;NOTE: Database was NOT rolled back automatically.&#34;
    log_warn &#34;To restore database, run:&#34;
    log_warn &#34;  sudo -u postgres psql &lt; /srv/funkwhale/backups/dump_*.sql&#34;

    systemctl start funkwhale.target
    systemctl reload nginx

    log_info &#34;==========================================&#34;
    log_info &#34;Rollback complete!&#34;
    log_info &#34;==========================================&#34;
}

show_status() {
    echo &#34;Current Funkwhale installation:&#34;
    echo &#34;================================&#34;

    if [[ -d &#34;$FUNKWHALE_DIR/venv&#34; ]]; then
        echo &#34;Virtual env: venv (2.0 style)&#34;
        VERSION=$(&#34;$FUNKWHALE_DIR/venv/bin/pip&#34; show funkwhale-api 2&gt;/dev/null | grep Version | awk &#39;{print $2}&#39;)
    elif [[ -d &#34;$FUNKWHALE_DIR/virtualenv&#34; ]]; then
        echo &#34;Virtual env: virtualenv (1.x style)&#34;
        VERSION=$(&#34;$FUNKWHALE_DIR/virtualenv/bin/pip&#34; show funkwhale-api 2&gt;/dev/null | grep Version | awk &#39;{print $2}&#39;)
    fi

    echo &#34;Installed version: ${VERSION:-unknown}&#34;
    echo &#34;&#34;
    echo &#34;Service status:&#34;
    systemctl status funkwhale.target --no-pager 2&gt;/dev/null || echo &#34;  Not running&#34;

    if [[ -f &#34;$ROLLBACK_MARKER&#34; ]]; then
        echo &#34;&#34;
        echo &#34;Rollback available:&#34;
        cat &#34;$ROLLBACK_MARKER&#34;
    fi
}

# Main
case &#34;${1:-}&#34; in
    upgrade)
        do_upgrade
        ;;
    rollback)
        do_rollback
        ;;
    status)
        show_status
        ;;
    *)
        echo &#34;Funkwhale Upgrade Script&#34;
        echo &#34;========================&#34;
        echo &#34;&#34;
        echo &#34;Usage: $0 [command]&#34;
        echo &#34;&#34;
        echo &#34;Commands:&#34;
        echo &#34;  upgrade   - Upgrade Funkwhale to $FUNKWHALE_VERSION&#34;
        echo &#34;  rollback  - Rollback to previous version&#34;
        echo &#34;  status    - Show current installation status&#34;
        echo &#34;&#34;
        echo &#34;Before upgrading:&#34;
        echo &#34;  1. Ensure database is backed up&#34;
        echo &#34;  2. Ensure media files are backed up&#34;
        echo &#34;  3. Stop services: systemctl stop funkwhale.target&#34;
        echo &#34;&#34;
        ;;
esac
```
Save this as `upgrade-funkwhale-2.0.sh`, make it executable with `chmod +x upgrade-funkwhale-2.0.sh`, and run with `sudo ./upgrade-funkwhale-2.0.sh upgrade`.

## Conclusion

The upgrade from Funkwhale 1.4.0 to 2.0.0-rc5 went smoothly once I resolved the Python venv package issue and worked around the systemd unit file download problem. The database migrations ran without issues, and all my music library was preserved (now organized under the new playlist system instead of libraries).

If you encounter any issues not covered here, check the [Funkwhale documentation](https://docs.funkwhale.audio/) or join the community on Matrix/IRC for help.

---

*Last updated: December 2025*
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/12/14/information-manipulation-is-a-market.html</link>
      <pubDate>Sun, 14 Dec 2025 10:55:00 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/12/14/information-manipulation-is-a-market.html</guid>
      <description>&lt;p&gt;Information Manipulation is a market.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.cam.ac.uk/stories/price-bot-army-global-index&#34;&gt;www.cam.ac.uk/stories/p&amp;hellip;&lt;/a&gt;&lt;/p&gt;
</description>
      <source:markdown>Information Manipulation is a market.

[www.cam.ac.uk/stories/p...](https://www.cam.ac.uk/stories/price-bot-army-global-index)
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/12/10/do-you-like-to-develop.html</link>
      <pubDate>Wed, 10 Dec 2025 18:43:15 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/12/10/do-you-like-to-develop.html</guid>
      <description>&lt;p&gt;do you like to develop on #android and &lt;a href=&#34;https://github.com/sam1am/anyapk&#34;&gt;sideload&lt;/a&gt; your APK freely on devices you own?&lt;/p&gt;
</description>
      <source:markdown>do you like to develop on #android and [sideload](https://github.com/sam1am/anyapk) your APK freely on devices you own?



</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/12/10/this-is-really-funny-futuristic.html</link>
      <pubDate>Wed, 10 Dec 2025 18:40:36 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/12/10/this-is-really-funny-futuristic.html</guid>
      <description>&lt;p&gt;This is really &lt;a href=&#34;https://news.ycombinator.com/item?id=46205632&#34;&gt;funny&lt;/a&gt; futuristic HN frontpage post reach HN frontpage and delivers gold satire 😅&lt;/p&gt;
</description>
      <source:markdown>This is really [funny](https://news.ycombinator.com/item?id=46205632) futuristic HN frontpage post reach HN frontpage and delivers gold satire 😅
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/12/02/photo-prs-de-mon-nouveau.html</link>
      <pubDate>Tue, 02 Dec 2025 21:05:47 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/12/02/photo-prs-de-mon-nouveau.html</guid>
      <description>&lt;p&gt;Photo près de mon nouveau chez moi l&amp;rsquo;autre jour en allant au boulot.. c&amp;rsquo;est fou que pendant des décennies l&amp;rsquo;horrible building de la gare du Nord cachait cette beauté dans le paysage nord de Bruxelles.&lt;/p&gt;
&lt;img src=&#34;https://blog.rmendes.net/uploads/2025/64f19c3e00.jpg&#34; width=&#34;451&#34; height=&#34;600&#34; alt=&#34;A domed building is framed by two tall structures and silhouetted trees under a warm, glowing sky.&#34;&gt;
</description>
      <source:markdown>Photo près de mon nouveau chez moi l&#39;autre jour en allant au boulot.. c&#39;est fou que pendant des décennies l&#39;horrible building de la gare du Nord cachait cette beauté dans le paysage nord de Bruxelles. 

&lt;img src=&#34;https://blog.rmendes.net/uploads/2025/64f19c3e00.jpg&#34; width=&#34;451&#34; height=&#34;600&#34; alt=&#34;A domed building is framed by two tall structures and silhouetted trees under a warm, glowing sky.&#34;&gt;
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/11/24/damn-the-new-cloudron-ui.html</link>
      <pubDate>Mon, 24 Nov 2025 21:49:35 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/11/24/damn-the-new-cloudron-ui.html</guid>
      <description>&lt;p&gt;Damn.. the new #Cloudron UI revamp is sick 😲 loving it! &lt;a href=&#34;https://cloudron.io&#34;&gt;cloudron.io&lt;/a&gt;&lt;/p&gt;
</description>
      <source:markdown>Damn.. the new #Cloudron UI revamp is sick 😲 loving it! [cloudron.io](https://cloudron.io)
</source:markdown>
    </item>
    
    <item>
      <title>Can you even imagine, if #Carlin was still alive, under #Trump ? </title>
      <link>https://blog.rmendes.net/2025/10/14/can-you-even-imagine-if.html</link>
      <pubDate>Tue, 14 Oct 2025 20:14:17 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/10/14/can-you-even-imagine-if.html</guid>
      <description>&lt;p&gt;it wouldn&amp;rsquo;t be roasting, perhaps Trump wouldn&amp;rsquo;t even be elected in the first place.&lt;/p&gt;
&lt;p&gt;I feel like even the &lt;a href=&#34;https://youtu.be/gRNeroeULyo?si=D6o9ou7AKAHQbHT9&#34;&gt;best&lt;/a&gt; comedians, commentators and opinionated individuals out there, all those not losing their north star, would greatly appreciate it if anything remotely as close to Carlin was alive today and dismantling whatever is the ongoing political/economic cast in power (not just in the USA)&lt;/p&gt;
</description>
      <source:markdown>it wouldn&#39;t be roasting, perhaps Trump wouldn&#39;t even be elected in the first place. 

I feel like even the [best](https://youtu.be/gRNeroeULyo?si=D6o9ou7AKAHQbHT9) comedians, commentators and opinionated individuals out there, all those not losing their north star, would greatly appreciate it if anything remotely as close to Carlin was alive today and dismantling whatever is the ongoing political/economic cast in power (not just in the USA)
</source:markdown>
    </item>
    
    <item>
      <title>[Link] The Chinese Firewall Technology That Every Western Company Now Uses“</title>
      <link>https://blog.rmendes.net/2025/10/12/link-the-chinese-firewall-technology.html</link>
      <pubDate>Sun, 12 Oct 2025 18:14:04 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/10/12/link-the-chinese-firewall-technology.html</guid>
      <description>&lt;p&gt;“A senior security engineer at a major European bank recently told me (off the record, obviously) that their “next-generation threat detection system” was producing better results than anything they’d used before. Only later did they discover that the core algorithms were developed by a Chinese company with close ties to government surveillance programs.“&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://medium.com/@sohail_saifii/the-chinese-firewall-technology-that-every-western-company-now-uses-4d8b249a59a7&#34;&gt;Read more&lt;/a&gt;&lt;/p&gt;
</description>
      <source:markdown>“A senior security engineer at a major European bank recently told me (off the record, obviously) that their “next-generation threat detection system” was producing better results than anything they’d used before. Only later did they discover that the core algorithms were developed by a Chinese company with close ties to government surveillance programs.“

[Read more](https://medium.com/@sohail_saifii/the-chinese-firewall-technology-that-every-western-company-now-uses-4d8b249a59a7)
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/09/25/assine-a-petio-para-libertar.html</link>
      <pubDate>Thu, 25 Sep 2025 20:58:29 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/09/25/assine-a-petio-para-libertar.html</guid>
      <description>&lt;p&gt;Assine a &lt;a href=&#34;https://petitions.protecthumanitarians.org/en/petitions/1-free-joseph-figueira-martin-humanitarian-arbitrarily-detained-and-tortured-in-the-central-african-republic&#34;&gt;Petição&lt;/a&gt; para libertar Joseph Figueira Martin&lt;/p&gt;
&lt;p&gt;Em 26 de maio de 2024, Joseph Figueira Martin, um humanitário belga-português, foi preso em Zémio, uma cidade no leste da República Centro-Africana.&lt;/p&gt;
&lt;p&gt;Bélgica e Portugal têm que tomar ação!&lt;/p&gt;
&lt;p&gt;#Wagner&lt;/p&gt;
</description>
      <source:markdown>Assine a [Petição](https://petitions.protecthumanitarians.org/en/petitions/1-free-joseph-figueira-martin-humanitarian-arbitrarily-detained-and-tortured-in-the-central-african-republic) para libertar Joseph Figueira Martin

Em 26 de maio de 2024, Joseph Figueira Martin, um humanitário belga-português, foi preso em Zémio, uma cidade no leste da República Centro-Africana. 

Bélgica e Portugal têm que tomar ação! 

#Wagner 
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/09/25/sign-the-petition-to-free.html</link>
      <pubDate>Thu, 25 Sep 2025 20:56:18 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/09/25/sign-the-petition-to-free.html</guid>
      <description>&lt;p&gt;Sign The &lt;a href=&#34;https://petitions.protecthumanitarians.org/en/petitions/1-free-joseph-figueira-martin-humanitarian-arbitrarily-detained-and-tortured-in-the-central-african-republic&#34;&gt;Petition&lt;/a&gt; to free Joseph Figueira Martin&lt;/p&gt;
&lt;p&gt;On 26 May 2024, Joseph Figueira Martin, a Belgian-Portuguese humanitarian, was arrested in Zémio, a town in the east of the Central African Republic.&lt;/p&gt;
&lt;p&gt;Portugal and Belgium must act!&lt;/p&gt;
</description>
      <source:markdown>Sign The [Petition](https://petitions.protecthumanitarians.org/en/petitions/1-free-joseph-figueira-martin-humanitarian-arbitrarily-detained-and-tortured-in-the-central-african-republic) to free Joseph Figueira Martin

On 26 May 2024, Joseph Figueira Martin, a Belgian-Portuguese humanitarian, was arrested in Zémio, a town in the east of the Central African Republic.

Portugal and Belgium must act! 
</source:markdown>
    </item>
    
    <item>
      <title>Le comble de notre époque c&#39;est le mirage de l&#39;immigration </title>
      <link>https://blog.rmendes.net/2025/09/23/le-comble-de-notre-poque.html</link>
      <pubDate>Tue, 23 Sep 2025 22:54:32 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/09/23/le-comble-de-notre-poque.html</guid>
      <description>&lt;p&gt;Le comble de notre époque : après des décennies de perte de souveraineté économique, financière et technologique, l’Europe, les États-Unis et d’autres puissances prétendent la « récupérer » en fermant leurs frontières. Mais pas aux marchandises, pas au capital, pas aux dérives financières, ni à l’exode fiscal des 1 %.&lt;/p&gt;
&lt;p&gt;Non, c’est sur les corps que se concentre la répression. On en vient à parquer des êtres humains dans des conditions inhumaines, pour satisfaire des rhétoriques d’extrême droite devenues banales, présentées comme des vérités canoniques.&lt;/p&gt;
&lt;p&gt;Monstrueuses vérités qui masquent l’éléphant rose au milieu du magasin de porcelaine : un capitalisme débridé, responsable premier de la misère de masse et de la dégradation des systèmes sociaux.&lt;/p&gt;
&lt;p&gt;Voilà la véritable cause de l’anxiété généralisée, qui comme toujours finit par se retourner contre les plus vulnérables.&lt;/p&gt;
</description>
      <source:markdown>Le comble de notre époque : après des décennies de perte de souveraineté économique, financière et technologique, l’Europe, les États-Unis et d’autres puissances prétendent la « récupérer » en fermant leurs frontières. Mais pas aux marchandises, pas au capital, pas aux dérives financières, ni à l’exode fiscal des 1 %. 

Non, c’est sur les corps que se concentre la répression. On en vient à parquer des êtres humains dans des conditions inhumaines, pour satisfaire des rhétoriques d’extrême droite devenues banales, présentées comme des vérités canoniques. 

Monstrueuses vérités qui masquent l’éléphant rose au milieu du magasin de porcelaine : un capitalisme débridé, responsable premier de la misère de masse et de la dégradation des systèmes sociaux. 

Voilà la véritable cause de l’anxiété généralisée, qui comme toujours finit par se retourner contre les plus vulnérables.
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/09/23/the-groyper-wars-the-seriousness.html</link>
      <pubDate>Tue, 23 Sep 2025 22:52:33 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/09/23/the-groyper-wars-the-seriousness.html</guid>
      <description>&lt;p&gt;The Groyper Wars
The seriousness of this story is rivaled only by its dizzying stupidity.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.webworm.co/groyperwars/&#34;&gt;www.webworm.co/groyperwa&amp;hellip;&lt;/a&gt;&lt;/p&gt;
</description>
      <source:markdown>The Groyper Wars
The seriousness of this story is rivaled only by its dizzying stupidity.

[www.webworm.co/groyperwa...](https://www.webworm.co/groyperwars/)
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/09/18/ever-needed-to-duplicate-a.html</link>
      <pubDate>Thu, 18 Sep 2025 10:46:09 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/09/18/ever-needed-to-duplicate-a.html</guid>
      <description>&lt;p&gt;Ever needed to duplicate a #keycloak realm.json, change a few values and re-import into the same keycloak ?
this is a &lt;a href=&#34;https://github.com/rmdes/realm-duplicator-keycloak&#34;&gt;Keycloak&lt;/a&gt; realm rekeying utility, safe UUID regeneration and alias normalization to avoid duplicate constraints during import&lt;/p&gt;
</description>
      <source:markdown>Ever needed to duplicate a #keycloak realm.json, change a few values and re-import into the same keycloak ? 
this is a [Keycloak](https://github.com/rmdes/realm-duplicator-keycloak) realm rekeying utility, safe UUID regeneration and alias normalization to avoid duplicate constraints during import
</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/09/15/on-maga-factions-and-the.html</link>
      <pubDate>Mon, 15 Sep 2025 20:20:28 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/09/15/on-maga-factions-and-the.html</guid>
      <description>&lt;p&gt;On MAGA factions and the meme wars of 2025 and beyond :&lt;/p&gt;
&lt;p&gt;This is a PHD/level &lt;a href=&#34;https://vm.tiktok.com/ZGdaytfdH/&#34;&gt;breakdown&lt;/a&gt; of the two alt-right movements set out to destroy each other and the rest of the USA in the process. The creator is Cy Canterel.&lt;/p&gt;
&lt;p&gt;On my &lt;a href=&#34;https://open.substack.com/pub/cybelecanterel/p/lost-in-the-kingdom-of-kitsch&#34;&gt;reading list&lt;/a&gt; : Lost in the Kingdom of Kitsch&lt;/p&gt;
</description>
      <source:markdown>On MAGA factions and the meme wars of 2025 and beyond :

This is a PHD/level [breakdown](https://vm.tiktok.com/ZGdaytfdH/) of the two alt-right movements set out to destroy each other and the rest of the USA in the process. The creator is Cy Canterel.

On my [reading list](https://open.substack.com/pub/cybelecanterel/p/lost-in-the-kingdom-of-kitsch) : Lost in the Kingdom of Kitsch

</source:markdown>
    </item>
    
    <item>
      <title></title>
      <link>https://blog.rmendes.net/2025/09/13/chris-hedge-on-kirk-death.html</link>
      <pubDate>Sat, 13 Sep 2025 10:01:51 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/09/13/chris-hedge-on-kirk-death.html</guid>
      <description>&lt;p&gt;Chris Hedge on Kirk death &amp;ldquo;Martyrs are the lifeblood of violent movements. Any flinching over the use of violence, any talk of compassion or understanding, any effort to mediate or discuss, is a betrayal of the martyr and the cause the martyr died defending.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://scheerpost.com/2025/09/12/chris-hedges-the-martyrdom-of-charlie-kirk/&#34;&gt;Read Full Article&lt;/a&gt;&lt;/p&gt;
</description>
      <source:markdown>Chris Hedge on Kirk death &#34;Martyrs are the lifeblood of violent movements. Any flinching over the use of violence, any talk of compassion or understanding, any effort to mediate or discuss, is a betrayal of the martyr and the cause the martyr died defending.&#34;

[Read Full Article](https://scheerpost.com/2025/09/12/chris-hedges-the-martyrdom-of-charlie-kirk/)
</source:markdown>
    </item>
    
    <item>
      <title>La Belgique doit agir pour ne pas laisser brûler les droits des femmes</title>
      <link>https://blog.rmendes.net/2025/09/13/la-belgique-doit-agir-pour.html</link>
      <pubDate>Sat, 13 Sep 2025 09:56:56 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/09/13/la-belgique-doit-agir-pour.html</guid>
      <description>&lt;p&gt;Aux États-Unis, l’administration Trump a marqué un tournant idéologique majeur. Sous couvert de réformes et de moralité, elle a mené une véritable offensive contre l’autonomie des femmes: remise en cause du droit à l’avortement, pressions sur les financements de la santé reproductive, et obstacles à l’accès aux contraceptifs.&lt;/p&gt;
&lt;p&gt;La destruction programmée de stocks entiers de contraceptifs (sur le sol belge) encore parfaitement utilisables ne peut se lire autrement que comme un geste idéologique politique.&lt;/p&gt;
&lt;p&gt;C’est l’incarnation d’une logique &amp;ldquo;talibanesque&amp;rdquo; patriarcale qui préfère incinérer des moyens de liberté plutôt que de permettre aux femmes de décider pour elles-mêmes.&lt;/p&gt;
&lt;p&gt;En Belgique, notre cadre légal et éthique est aux antipodes de cette vision.&lt;/p&gt;
&lt;p&gt;La destruction de médicaments et de produits de santé encore conformes y est interdite, car ils représentent une ressource précieuse qu’il faut redistribuer plutôt que gaspiller.&lt;/p&gt;
&lt;p&gt;Cette approche traduit un choix de société: protéger la santé publique, lutter contre le gaspillage, et surtout garantir que les droits des femmes ne soient pas sacrifiés sur l’autel d’idéologies rétrogrades.&lt;/p&gt;
&lt;p&gt;C’est pourquoi il faut appeler la Belgique à agir: à se lever contre cette politique américaine destructrice et, si nécessaire, à racheter ce stock pour le mettre au service de programmes humanitaires.&lt;/p&gt;
&lt;p&gt;Chaque dose redistribuée est une victoire contre l’obscurantisme, et un pas de plus vers l’égalité et la dignité des femmes dans le monde.&lt;/p&gt;
</description>
      <source:markdown>Aux États-Unis, l’administration Trump a marqué un tournant idéologique majeur. Sous couvert de réformes et de moralité, elle a mené une véritable offensive contre l’autonomie des femmes: remise en cause du droit à l’avortement, pressions sur les financements de la santé reproductive, et obstacles à l’accès aux contraceptifs. 

La destruction programmée de stocks entiers de contraceptifs (sur le sol belge) encore parfaitement utilisables ne peut se lire autrement que comme un geste idéologique politique. 

C’est l’incarnation d’une logique &#34;talibanesque&#34; patriarcale qui préfère incinérer des moyens de liberté plutôt que de permettre aux femmes de décider pour elles-mêmes.

En Belgique, notre cadre légal et éthique est aux antipodes de cette vision. 

La destruction de médicaments et de produits de santé encore conformes y est interdite, car ils représentent une ressource précieuse qu’il faut redistribuer plutôt que gaspiller. 

Cette approche traduit un choix de société: protéger la santé publique, lutter contre le gaspillage, et surtout garantir que les droits des femmes ne soient pas sacrifiés sur l’autel d’idéologies rétrogrades.

C’est pourquoi il faut appeler la Belgique à agir: à se lever contre cette politique américaine destructrice et, si nécessaire, à racheter ce stock pour le mettre au service de programmes humanitaires. 

Chaque dose redistribuée est une victoire contre l’obscurantisme, et un pas de plus vers l’égalité et la dignité des femmes dans le monde.
</source:markdown>
    </item>
    
    <item>
      <title>From Distrust to Retribution: America’s Escalating Spiral </title>
      <link>https://blog.rmendes.net/2025/09/11/from-distrust-to-retribution-americas.html</link>
      <pubDate>Thu, 11 Sep 2025 19:18:07 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/09/11/from-distrust-to-retribution-americas.html</guid>
      <description>&lt;p&gt;The core problem in the 🇺🇸 right now is trust in information, democracy, institutions.&lt;/p&gt;
&lt;p&gt;Whatever is put forward, whether a “manifesto,” “killer’s note,” or shooting suspect’s story, no matter what the authorities claim, the public has come to believe that it’s all manipulated.&lt;/p&gt;
&lt;p&gt;That distrust is being weaponized by the alt-right / MAGA crowd, and it won’t be long before they demand retribution, for real or imagined.&lt;/p&gt;
&lt;p&gt;Because the current administration is seen as deeply biased, compromised, even complicit by many, every statement, every slip, every omission becomes fuel. Whether intentional or not, its behavior and rhetoric will stoke the flames and lead to real retribution.&lt;/p&gt;
&lt;p&gt;There’s only one way to halt this descent: the people, those not yet indoctrinated, those still able to think beyond rage, must step forward.&lt;/p&gt;
&lt;p&gt;Those sections of society that are not caught up in fear, indoctrination and fury need to raise clear, honest voices. Without that, with a death like Charlie Kirk’s hanging over everything, we’re not just witnessing a case: we’re seeing a tipping point.&lt;/p&gt;
</description>
      <source:markdown>The core problem in the 🇺🇸 right now is trust in information, democracy, institutions.

 Whatever is put forward, whether a “manifesto,” “killer’s note,” or shooting suspect’s story, no matter what the authorities claim, the public has come to believe that it’s all manipulated. 

That distrust is being weaponized by the alt-right / MAGA crowd, and it won’t be long before they demand retribution, for real or imagined.

Because the current administration is seen as deeply biased, compromised, even complicit by many, every statement, every slip, every omission becomes fuel. Whether intentional or not, its behavior and rhetoric will stoke the flames and lead to real retribution.

There’s only one way to halt this descent: the people, those not yet indoctrinated, those still able to think beyond rage, must step forward.
 
Those sections of society that are not caught up in fear, indoctrination and fury need to raise clear, honest voices. Without that, with a death like Charlie Kirk’s hanging over everything, we’re not just witnessing a case: we’re seeing a tipping point.
</source:markdown>
    </item>
    
    <item>
      <title>Face aux horreurs du monde, tenir debout</title>
      <link>https://blog.rmendes.net/2025/09/11/face-aux-horreurs-du-monde.html</link>
      <pubDate>Thu, 11 Sep 2025 18:27:25 +0100</pubDate>
      
      <guid>http://rmdes.micro.blog/2025/09/11/face-aux-horreurs-du-monde.html</guid>
      <description>&lt;p&gt;Avec toute l’horreur qui se déroule sous nos yeux éblouis par la lumière bleue de nos écrans, j’ai parfois l’impression que le 11 septembre n’a plus aucune importance. Comme si, face au génocide à Gaza, à la guerre perpétuelle en Ukraine et aux conflits oubliés qui ensanglantent d’autres continents, la tragédie d’il y a vingt-quatre ans n’était plus qu’un fait divers. Pourtant, c’est elle qui a propulsé le monde dans une dérive dont nous ressentons encore les secousses.&lt;/p&gt;
&lt;p&gt;Mais les horreurs ne s’effacent pas les unes les autres. Elles s’empilent, elles se superposent. Pour celles et ceux qui les subissent, il n’y a pas de hiérarchie. Une guerre, un exil, un génocide, une agression, ou une bataille juridique contre une secte qui a brisé des vies : à chaque fois, c’est un monde qui s’écroule, c’est une violence qui impose son poids total. De l’extérieur, on compare. De l’intérieur, on survit.&lt;/p&gt;
&lt;p&gt;C’est ce que nous vivons avec Chardons Bleus. Alors que les horreurs du monde se déroulent en direct, nous affrontons depuis des années une autre forme d’horreur, moins visible, mais pas moins dévastatrice. Des procédures judiciaires interminables, des souvenirs qui resurgissent au détour d’une audience, des victimes qui portent encore les stigmates d’une enfance volée. À l’échelle du monde, cela paraît dérisoire. À l’échelle de nos vies, cela est absolu.&lt;/p&gt;
&lt;p&gt;Chaque drame collectif ou intime vient recouvrir le précédent sans jamais l’effacer. L’histoire mondiale et l’histoire personnelle se croisent, se répondent, parfois se confondent. Et ce qui reste, c’est cette impression de vivre dans un palimpseste de douleurs et de luttes, où chaque nouvelle couche ne détruit pas l’ancienne mais la rend plus difficile à porter.&lt;/p&gt;
&lt;p&gt;Et pourtant, dans ce chaos, quelque chose résiste. À travers chaque combat, chaque témoignage, chaque geste de solidarité, une lumière persiste, fragile mais tenace. Elle n’efface pas l’horreur, mais elle empêche qu’elle soit totale. C’est cette lumière qui nous relie, qui nous maintient debout, et qui nous rappelle que même au cœur de la nuit, il reste toujours une part de jour à reconquérir.&lt;/p&gt;
&lt;p&gt;c&amp;rsquo;est la résilience qui nous maintient debout, et qui affirme que malgré l’horreur, nous pouvons encore choisir la justice, la solidarité et la vie.&lt;/p&gt;
</description>
      <source:markdown>Avec toute l’horreur qui se déroule sous nos yeux éblouis par la lumière bleue de nos écrans, j’ai parfois l’impression que le 11 septembre n’a plus aucune importance. Comme si, face au génocide à Gaza, à la guerre perpétuelle en Ukraine et aux conflits oubliés qui ensanglantent d’autres continents, la tragédie d’il y a vingt-quatre ans n’était plus qu’un fait divers. Pourtant, c’est elle qui a propulsé le monde dans une dérive dont nous ressentons encore les secousses.

Mais les horreurs ne s’effacent pas les unes les autres. Elles s’empilent, elles se superposent. Pour celles et ceux qui les subissent, il n’y a pas de hiérarchie. Une guerre, un exil, un génocide, une agression, ou une bataille juridique contre une secte qui a brisé des vies : à chaque fois, c’est un monde qui s’écroule, c’est une violence qui impose son poids total. De l’extérieur, on compare. De l’intérieur, on survit.

C’est ce que nous vivons avec Chardons Bleus. Alors que les horreurs du monde se déroulent en direct, nous affrontons depuis des années une autre forme d’horreur, moins visible, mais pas moins dévastatrice. Des procédures judiciaires interminables, des souvenirs qui resurgissent au détour d’une audience, des victimes qui portent encore les stigmates d’une enfance volée. À l’échelle du monde, cela paraît dérisoire. À l’échelle de nos vies, cela est absolu.

Chaque drame collectif ou intime vient recouvrir le précédent sans jamais l’effacer. L’histoire mondiale et l’histoire personnelle se croisent, se répondent, parfois se confondent. Et ce qui reste, c’est cette impression de vivre dans un palimpseste de douleurs et de luttes, où chaque nouvelle couche ne détruit pas l’ancienne mais la rend plus difficile à porter.

Et pourtant, dans ce chaos, quelque chose résiste. À travers chaque combat, chaque témoignage, chaque geste de solidarité, une lumière persiste, fragile mais tenace. Elle n’efface pas l’horreur, mais elle empêche qu’elle soit totale. C’est cette lumière qui nous relie, qui nous maintient debout, et qui nous rappelle que même au cœur de la nuit, il reste toujours une part de jour à reconquérir.

c&#39;est la résilience qui nous maintient debout, et qui affirme que malgré l’horreur, nous pouvons encore choisir la justice, la solidarité et la vie.
</source:markdown>
    </item>
    
  </channel>
</rss>
