<?xml version="1.0" encoding="utf-8"?><rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:media="http://search.yahoo.com/mrss/"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
<channel>
  <title>Srijan Choudhary, all posts tagged: linux</title>
  <link>https://srijan.ch/feed/all/tag:linux</link>
  <lastBuildDate>Mon, 29 Dec 2025 22:20:00 +0000</lastBuildDate>
  <image>
    <url>https://srijan.ch/assets/favicon/favicon-32x32.png</url>
    <title>Srijan Choudhary, all posts tagged: linux</title>
    <link>https://srijan.ch/feed/all/tag:linux</link>
  </image>
  <sy:updatePeriod>daily</sy:updatePeriod>
  <sy:updateFrequency>1</sy:updateFrequency>
  <generator>Kirby</generator>
  <atom:link href="https://srijan.ch/feed/all.xml/tag:linux" rel="self" type="application/rss+xml" />
  <description>Srijan Choudhary&#039;s Articles and Notes Feed for tag: linux</description>
  <item>
    <title>2025-12-29-001</title>
    <description><![CDATA[Faced a failing disk in my raidz2 ZFS pool today. Recovery was pretty simple: Asked the service provider to replace the disk Find new disk ID etc using: lsblk -o NAME,SIZE,MODEL,SERIAL,LABEL,FSTYPE ls -ltrh /dev/disk/by-id/ata-* Resilver using: sudo zpool replace lake &lt;old_disk_id&gt; &lt;new_disk_id&gt; Watch status using: watch zpool status -v Re-silvering is still ongoing, but hopefully …]]></description>
    <link>https://srijan.ch/notes/2025-12-29-001</link>
    <guid isPermaLink="false">tag:srijan.ch:/notes/2025-12-29-001</guid>
    <category><![CDATA[linux]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Mon, 29 Dec 2025 22:20:00 +0000</pubDate>
    <content:encoded><![CDATA[<p>Faced a failing disk in my raidz2 ZFS pool today.</p>
<p>Recovery was pretty simple:</p>
<ol>
<li>Asked the service provider to replace the disk</li>
<li>Find new disk ID etc using:<pre><code>lsblk -o NAME,SIZE,MODEL,SERIAL,LABEL,FSTYPE
ls -ltrh /dev/disk/by-id/ata-*</code></pre>
</li>
<li>Resilver using:<pre><code>sudo zpool replace lake &lt;old_disk_id&gt; &lt;new_disk_id&gt;</code></pre>
</li>
<li>Watch status using:<pre><code>watch zpool status -v</code></pre>
</li>
</ol>
<p>Re-silvering is still ongoing, but hopefully completes without issues. Will run a manual <code>zpool scrub</code> at the end to make sure everything is okay.</p>]]></content:encoded>
    <comments>https://srijan.ch/notes/2025-12-29-001#comments</comments>
    <slash:comments>0</slash:comments>
  </item><item>
    <title>2025-03-24-002</title>
    <description><![CDATA[Read Jeremy&#039;s post on quickly switching the default browser. I had a shell script to do this as well. Doing it from Emacs makes more sense because I can have a completion UI. So, here's my modified version for Linux: (defun sj/default-browser (&amp;optional name) "Set the default browser based on the given NAME." (interactive (list (completing-read "Browser: " (split-string …]]></description>
    <link>https://srijan.ch/notes/2025-03-24-002</link>
    <guid isPermaLink="false">tag:srijan.ch:/notes/2025-03-24-002</guid>
    <category><![CDATA[emacs]]></category>
    <category><![CDATA[linux]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Mon, 24 Mar 2025 20:55:00 +0000</pubDate>
    <content:encoded><![CDATA[<p>Read <a href="https://takeonrules.com/2025/02/05/quick-switch-default-browser/">Jeremy&#039;s post on quickly switching the default browser</a>.</p>
<p>I had a shell script to do this as well. Doing it from Emacs makes more sense because I can have a completion UI.</p>
<p>So, here's my modified version for Linux:</p>
<pre><code class="language-elisp">(defun sj/default-browser (&amp;optional name)
  "Set the default browser based on the given NAME."
  (interactive
   (list
    (completing-read
     "Browser: "
     (split-string
      (shell-command-to-string
       "find /usr/share/applications ~/.local/share/applications -name \"*.desktop\" -exec grep -l \"Categories=.*WebBrowser\" {} \\;")
      "\n" t))))
  (let ((browser-desktop (file-name-nondirectory name)))
    (shell-command (format "xdg-mime default %s text/html" browser-desktop))
    (shell-command (format "xdg-mime default %s application/xhtml+xml" browser-desktop))
    (shell-command (format "xdg-mime default %s application/x-extension-html" browser-desktop))
    (shell-command (format "xdg-settings set default-web-browser %s" browser-desktop))))</code></pre>
<p>As a plus, it automatically lists the installed browsers based on <code>.desktop</code> files on your system.</p>]]></content:encoded>
    <comments>https://srijan.ch/notes/2025-03-24-002#comments</comments>
    <slash:comments>2</slash:comments>
  </item><item>
    <title>2024-10-08-001</title>
    <description><![CDATA[Tried using X11 on #Linux the last few days due to some issues with Zoom screensharing in Wayland with the latest pipewire, and I already miss #Wayland. Issues I faced with X11: Smooth scrolling broken Apps work noticeably slower Screen tearing This bug in Emacs GTK build: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=67654 (To be fair, this is a GTK-specific issue, not X11 specific) I will go …]]></description>
    <link>https://srijan.ch/notes/2024-10-08-001</link>
    <guid isPermaLink="false">tag:srijan.ch:/notes/2024-10-08-001</guid>
    <category><![CDATA[wayland]]></category>
    <category><![CDATA[linux]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Tue, 08 Oct 2024 03:45:00 +0000</pubDate>
    <content:encoded><![CDATA[<p>Tried using X11 on <a href="/tags/linux" class="p-category">#Linux</a> the last few days due to some issues with Zoom screensharing in Wayland with the latest pipewire, and I already miss <a href="/tags/wayland" class="p-category">#Wayland</a>.</p>
<p>Issues I faced with X11:</p>
<ol>
<li>Smooth scrolling broken</li>
<li>Apps work noticeably slower</li>
<li>Screen tearing</li>
<li>This bug in Emacs GTK build: <a href="https://debbugs.gnu.org/cgi/bugreport.cgi?bug=67654">https://debbugs.gnu.org/cgi/bugreport.cgi?bug=67654</a> (To be fair, this is a GTK-specific issue, not X11 specific)</li>
</ol>
<p>I will go back to Wayland as soon as Zoom fixes this: <a href="https://community.zoom.com/t5/Zoom-Meetings/share-screen-linux-wayland-broken/m-p/203624/highlight/true#M112235">https://community.zoom.com/t5/Zoom-Meetings/share-screen-linux-wayland-broken/m-p/203624/highlight/true#M112235</a></p><p>Syndicated to:</p><ul><li><a href="https://bsky.app/profile/srijan4.bsky.social/post/3l5ycxn4gak27">https://bsky.app/profile/srijan4.bsky.social/post/3l5ycxn4gak27</a></li></ul>]]></content:encoded>
    <comments>https://srijan.ch/notes/2024-10-08-001#comments</comments>
    <slash:comments>7</slash:comments>
  </item><item>
    <title>2024-10-01-002</title>
    <description><![CDATA[I have been using #karousel on #KDE for several weeks, and yesterday shifted to #PaperWM on #GNOME. Took some time to configure things like I wanted, but it's much smoother than karousel (and fancier). Overall, I like the scrolling tiling pane paradigm. I realized I've been manually doing something like this using workspaces with 1-2 windows per workspace with two keybindings - one to change …]]></description>
    <link>https://srijan.ch/notes/2024-10-01-002</link>
    <guid isPermaLink="false">tag:srijan.ch:/notes/2024-10-01-002</guid>
    <category><![CDATA[linux]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Tue, 01 Oct 2024 22:50:00 +0000</pubDate>
    <content:encoded><![CDATA[<p>I have been using #karousel on #KDE for several weeks, and yesterday shifted to #PaperWM on #GNOME. Took some time to configure things like I wanted, but it's much smoother than karousel (and fancier).</p>
<p>Overall, I like the scrolling tiling pane paradigm. I realized I've been manually doing something like this using workspaces with 1-2 windows per workspace with two keybindings - one to change workspace and one to switch windows inside a workspace. So, this window management model really clicks for me.</p>
<p>I switched from GNOME to KDE several years ago due to getting burnt by extensions breaking too frequently, but hopefully things are better now.</p><p>Syndicated to:</p><ul><li><a href="https://bsky.app/profile/srijan4.bsky.social/post/3l5icw34klr2e">https://bsky.app/profile/srijan4.bsky.social/post/3l5icw34klr2e</a></li></ul>]]></content:encoded>
    <comments>https://srijan.ch/notes/2024-10-01-002#comments</comments>
    <slash:comments>0</slash:comments>
  </item><item>
    <title>2024-04-29-001</title>
    <description><![CDATA[Using sysrq on my laptop - documenting mostly for myself. My laptop has started freezing sometimes, not sure why. Usually, I can just force power off using the power button and start it again, but it has happened twice that I had to recover the system by booting via a USB drive, chrooting, and recovering the damaged files using fsck or pacman magic. The linux kernel has: a ‘magical’ key combo you …]]></description>
    <link>https://srijan.ch/notes/2024-04-29-001</link>
    <guid isPermaLink="false">tag:srijan.ch:/notes/2024-04-29-001</guid>
    <category><![CDATA[linux]]></category>
    <category><![CDATA[devops]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Mon, 29 Apr 2024 03:10:00 +0000</pubDate>
    <content:encoded><![CDATA[<p>Using sysrq on my laptop - documenting mostly for myself.</p>
<p>My laptop has started freezing sometimes, not sure why. Usually, I can just force power off using the power button and start it again, but it has happened twice that I had to recover the system by booting via a USB drive, chrooting, and recovering the damaged files using fsck or pacman magic.</p>
<p>The linux kernel has:</p>
<blockquote>
<p>a ‘magical’ key combo you can hit which the kernel will respond to regardless of whatever else it is doing, unless it is completely locked up.</p>
</blockquote>
<p>(More details on <a href="https://wiki.archlinux.org/title/keyboard_shortcuts#Kernel_(SysRq)">archwiki</a> and <a href="https://docs.kernel.org/admin-guide/sysrq.html">kernel doc</a>)</p>
<p>To enable, I did:</p>
<pre><code>echo "kernel.sysrq = 244" | sudo tee /etc/sysctl.d/sysreq.conf
sudo sysctl --system</code></pre>
<p>However, to trigger this on my laptop, I was not able to find the right key combination for SysRq. I was able to make it work using an external keyboard that has a PrintScreen binding on a layer, by using the following:</p>
<p>Press Alt and keep it pressed for the whole sequence: PrintScreen - R - E - I - S - U - B</p>
<p>Currently, PrintScreen on my external keyboard is bound to Caps lock long press + Up arrow.</p>]]></content:encoded>
    <comments>https://srijan.ch/notes/2024-04-29-001#comments</comments>
    <slash:comments>3</slash:comments>
  </item><item>
    <title>Exploring conflicting oneshot services in systemd</title>
    <description><![CDATA[Exploring ways to make two systemd services using a shared resource work with each other]]></description>
    <link>https://srijan.ch/exploring-conflicting-oneshot-services-in-systemd</link>
    <guid isPermaLink="false">64807b30f6b0810001fa0d01</guid>
    <category><![CDATA[linux]]></category>
    <category><![CDATA[devops]]></category>
    <category><![CDATA[emacs]]></category>
    <category><![CDATA[systemd]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Thu, 08 Jun 2023 19:20:00 +0000</pubDate>
    <media:content url="https://srijan.ch/media/pages/blog/exploring-conflicting-oneshot-services-in-systemd/0c15993753-1699621096/systemd-conflicts-01.png" medium="image" />
    <content:encoded><![CDATA[<figure data-ratio="auto">
    <img src="https://srijan.ch/media/pages/blog/exploring-conflicting-oneshot-services-in-systemd/0c15993753-1699621096/systemd-conflicts-01.png" alt="Exploring conflicting oneshot services in systemd">
  
    <figcaption class="text-center">
    Midjourney: two systemd services fighting over who will start first  </figcaption>
  </figure>
<h2>Background</h2>
<p>I use <a href="https://isync.sourceforge.io/mbsync.html" rel="noreferrer">mbsync</a> to sync my mailbox from my online provider (<a href="https://ref.fm/u12054901" rel="noreferrer">FastMail</a> - referer link) to my local system to eventually use with <a href="https://djcbsoftware.nl/code/mu/mu4e.html" rel="noreferrer">mu4e</a> (on Emacs).</p> <p>For periodic sync, I have a systemd service file called <code>mbsync.service</code> defining a oneshot service and a timer file called <code>mbsync.timer</code> that runs this service periodically. I can also activate the same service using a keybinding from inside mu4e.</p><figure>
  <pre><code class="language-ini">[Unit]
Description=Mailbox synchronization service
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/mbsync fastmail-all
ExecStartPost=bash -c &quot;emacsclient -s srijan -n -e &#039;(mu4e-update-index)&#039; || mu index&quot;

[Install]
WantedBy=default.target</code></pre>
    <figcaption class="text-center">mbsync.service</figcaption>
  </figure>
<figure>
  <pre><code class="language-ini">[Unit]
Description=Mailbox synchronization timer
BindsTo=graphical-session.target
After=graphical-session.target

[Timer]
OnBootSec=2m
OnUnitActiveSec=5m
Unit=mbsync.service

[Install]
WantedBy=graphical-session.target</code></pre>
    <figcaption class="text-center">mbsync.timer</figcaption>
  </figure>
<p>Also, for instant download of new mail, I have another service called <a href="https://gitlab.com/shackra/goimapnotify" rel="noreferrer">goimapnotify</a> configured that listens for new/updated/deleted messages on the remote mailbox using IMAP IDLE, and calls the above <code>mbsync.service</code> when there are changes.</p><p>This has worked well for me for several years.</p><h2>The Problem</h2>
<p>I
 recently split my (huge) archive folder into yearly archives so that I 
can keep/sync only the recent years on my phone. [ Aside: <a href="https://fedi.srijan.dev/notice/AVGV5TuD1cOEWQ8iQa" rel="noreferrer">yearly refile in mu4e snippet</a>
 ]. This lead to an increase in the number of folders that mbsync has to
 sync, and this increased the time taken to sync because it syncs the 
folders one by one.</p> <p>It does have the feature to sync a subset of folders, so I created a second systemd service called <code>mbsync-quick.service</code>
 and only synced my Inbox from this service. Then I updated the 
goimapnotify config to trigger this quick service instead of the full 
service when it detects changes.</p> <p>But, this caused a problem: these
 two services can run at the same time, and hence can cause corruption 
or sync conflicts in the mail files. So, I wanted a way to make sure 
that these two services don't run at the same time.</p> <p>Ideally,
 whenever any of these services are triggered and the other service is 
already running, then it should wait for the other service to stop 
before starting, essentially forming a queue.</p><h2>Solution 1: Using systemd features</h2>
<p>Systemd has a <a href="https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Conflicts=" rel="noreferrer">way to specify conflicts</a> in the unit section. From the docs:</p><blockquote>
  If a unit has a<code>Conflicts=</code>setting on another unit, starting the former will stop the latter and vice versa.<br>[...] to ensure that the conflicting unit is stopped before the other unit is started, an<code>After=</code>or<code>Before=</code>dependency must be declared.  </blockquote>
<p>This
 is different from our requirement that the conflicting service should 
be allowed to finish before the triggered service starts, but maybe a 
good enough way to at least prevent both running at the same time.</p> <p>To test this, I added <code>Conflicts=</code>
 in both the services with the other service as the conflicting service,
 and it works. The only problem is that when a service is triggered, the
 other service is <code>SIGTERM</code>ed. This itself might not cause a 
corruption issue, but if this happens with the mbsync-quick service, 
then there might be a delay getting the mail.</p> <p>This is the best way
 I found that uses built-in systemd features without any workarounds or 
hacks. Other solutions below involve some workarounds.</p><h2>Solution 2: Conflict + stop after sync complete</h2>
<p>This
 is a variation on solution 1 - add a wrapper script to trap the SIGTERM
 and only exit when the sync is complete. This also worked.</p> <p>But, 
the drawback with this method is that anyone calling stop on these 
services (like the system shutting down) will have to wait for this to 
finish (or till timeout of 90s). This can cause slowdowns in system 
shutdown that are hard to debug. So, I don't prefer this solution.</p><h2>Solution 3: Delay start until the other service is finished</h2>
<p>This is also a hacky solution - use <code>ExecStartPre</code> to check if the other service is running, and busywait for it to stop before starting ourselves.</p><figure>
  <pre><code class="language-ini">[Unit]
Description=Mailbox synchronization service (quick)
After=network-online.target

[Service]
Type=oneshot
ExecStartPre=/bin/sh -c &#039;while systemctl --user is-active mbsync.service | grep -q activating; do sleep 0.5; done&#039;
ExecStart=/usr/bin/mbsync fastmail-inbox
ExecStartPost=bash -c &quot;emacsclient -s srijan -n -e &#039;(mu4e-update-index)&#039; || mu index&quot;</code></pre>
    <figcaption class="text-center">mbsync-quick.service</figcaption>
  </figure>
<p>Here, we use <code>systemctl is-active</code> to query the status of the other service, and wait until the other service is not in <code>activating</code> state anymore. The state is called <code>activating</code> instead of <code>active</code> because these are oneshot services that go from <code>inactive</code> to <code>activating</code> to <code>inactive</code> without ever reaching <code>active</code>.</p><p>To not make this an actual busywait on the CPU, I added a sleep of 0.5s.</p><p>This worked the best for my use case. When one of the services is triggered, it checks if the other service is running and waits for it to stop before running itself. It also does not have the drawback of solution 2 of trapping exits and delaying a stop command.</p><p>But, after using it for a day, I found there is a race condition (!) that can cause a deadlock between these two services and none of them are able to start.</p><p>The reason for the race condition was:</p><ul><li>A service is marked as <code>activating</code> when it's <code>ExecStartPre</code> command starts</li><li>I added a sleep of 0.5 seconds</li></ul><p>So, if the other service is triggered again in between those 0.5 seconds, both services will be marked as <code>activating</code> and they will indefinitely wait for each other to complete. This is what I get for using workarounds.</p><h2>Solution 4: One-way conflict, other way delay</h2>
<p>So,
 the final good-enough solution I came up with was to break this cyclic 
dependency by doing a hybrid of Solution 1 and Solution 3. I was okay 
with the <code>mbsync.service</code> being stopped for the (higher priority) <code>mbsync-quick.service</code>.</p> <p>So, I added <code>mbsync.service</code> in Conflicts section of <code>mbsync-quick.service</code>, and used the <code>ExecStartPre</code> method in <code>mbsync.service</code>.</p> <p>💡Let me know if you know a better way to achieve this.</p><h2>References</h2>
<ul><li><a href="https://unix.stackexchange.com/questions/503719/how-to-set-a-conflict-in-systemd-in-one-direction-only" rel="noreferrer">https://unix.stackexchange.com/questions/503719/how-to-set-a-conflict-in-systemd-in-one-direction-only</a></li><li><a href="https://unix.stackexchange.com/questions/465794/is-it-possible-to-make-a-systemd-unit-wait-until-all-its-conflicts-are-stopped/562959" rel="noreferrer">https://unix.stackexchange.com/questions/465794/is-it-possible-to-make-a-systemd-unit-wait-until-all-its-conflicts-are-stopped/562959</a></li></ul>]]></content:encoded>
    <comments>https://srijan.ch/exploring-conflicting-oneshot-services-in-systemd#comments</comments>
    <slash:comments>0</slash:comments>
  </item><item>
    <title>Graphical password prompt for disk decryption on ArchLinux</title>
    <description><![CDATA[Enabling a graphical password prompt for disk decryption on ArchLinux]]></description>
    <link>https://srijan.ch/graphical-password-prompt-for-disk-decryption</link>
    <guid isPermaLink="false">63f7984c4c3c0f000109a2e0</guid>
    <category><![CDATA[linux]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Thu, 23 Feb 2023 17:30:00 +0000</pubDate>
    <content:encoded><![CDATA[<p>In my last post, I described how I <a href="https://srijan.ch/encrypting-an-existing-linux-systems-root-partition" rel="noreferrer">enabled encryption on my Linux root partition</a>. However, during boot up, it asked the password using a plain text prompt. I was not satisfied with the design and found that there's a better way: <a href="https://wiki.archlinux.org/title/plymouth" rel="noreferrer">Plymouth</a>.</p><p>Plymouth is a package that provides a themeable graphical boot process / splash screen all the way up to the login manager. This includes a graphical password prompt as well. Here are the steps I took to set this up:</p><p>1. First, I installed <a href="https://aur.archlinux.org/packages/plymouth-git/" rel="noreferrer">plymouth-git</a> from the AUR. ArchWiki suggests plymouth-git instead of plymouth because it is actually less likely to cause problems for most users than the stable package.</p><p>2. Next, I updated the <code>HOOKS</code> section in my <code>/etc/mkinitcpio.conf</code> to include <code>sd-plymouth</code>:</p><figure>
  <pre><code class="language-ini">HOOKS=(base systemd plymouth autodetect modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)</code></pre>
  </figure>
<p>3. And regenerated the initramfs:</p><figure>
  <pre><code class="language-shellsession"># mkinitcpio -P</code></pre>
  </figure>
<p>4. Next, I added the following kernel parameters:</p><figure>
  <pre><code class="language-text">quiet splash</code></pre>
  </figure>
<p>ArchWiki also suggests adding <code>vt.global_cursor_default=0</code>,
 but my experience was better without it. With this option, the cursor 
in TTY terminals becomes hidden, not just for the boot sequence but even
 later.</p> <p>With the above changes, after reboot, a nice password 
prompt is shown with a spinner image. But, this hid the beautiful OEM 
ROG logo that comes first at boot up. So, here are further tweaks I did 
to make it look as I wanted.</p> <p>5. First, I tried using the built-in 
BGRT theme. This is a variation of the spinner theme that keeps the OEM 
logo if available (BGRT stands for Boot Graphics Resource Table).</p><figure>
  <pre><code class="language-shellsession"># plymouth-set-default-theme -R bgrt</code></pre>
  </figure>
<p>This
 did not show the spinner, but it still hid the OEM logo when asking for
 decryption password. Although it did show the logo again after password
 was entered. So, I guessed it just needed a little customization.</p> <p>6. So, I made a copy of the bgrt theme to make my customizations.</p><figure>
  <pre><code class="language-shellsession"># cd /usr/share/plymouth/themes
# cp -r bgrt bgrt-custom
# cd bgrt-custom
# mv bgrt.plymouth bgrt-custom.plymouth</code></pre>
  </figure>
<p>7. These are the changes I had to make in <code>bgrt-custom.plymouth</code> to make it show the prompt like I wanted:</p><figure>
  <pre><code class="language-diff">diff --git a/../bgrt/bgrt.plymouth b/bgrt-custom.plymouth
index e8e9713..ca7a293 100644
--- a/../bgrt/bgrt.plymouth
+++ b/bgrt-custom.plymouth
@@ -30,8 +30,8 @@ Name[he]=BGRT
 Name[fa]=BGRT
 Name[fi]=BGRT
 Name[ie]=BGRT
-Name=BGRT
-Description=Jimmac&#039;s spinner theme using the ACPI BGRT graphics as background
+Name=BGRT-Custom
+Description=Customized Jimmac&#039;s spinner theme using the ACPI BGRT graphics as background
 ModuleName=two-step

 [two-step]
@@ -39,9 +39,9 @@ Font=Cantarell 12
 TitleFont=Cantarell Light 30
 ImageDir=/usr/share/plymouth/themes//spinner
 DialogHorizontalAlignment=.5
-DialogVerticalAlignment=.382
+DialogVerticalAlignment=.75
 TitleHorizontalAlignment=.5
-TitleVerticalAlignment=.382
+TitleVerticalAlignment=.75
 HorizontalAlignment=.5
 VerticalAlignment=.7
 WatermarkHorizontalAlignment=.5
@@ -52,7 +52,7 @@ BackgroundStartColor=0x000000
 BackgroundEndColor=0x000000
 ProgressBarBackgroundColor=0x606060
 ProgressBarForegroundColor=0xffffff
-DialogClearsFirmwareBackground=true
+DialogClearsFirmwareBackground=false
 MessageBelowAnimation=true

 [boot-up]</code></pre>
  </figure>
<p>Basically, I tweaked <code>DialogClearsFirmwareBackground</code>, <code>DialogVerticalAlignment</code>, and <code>TitleVerticalAlignment</code> to my liking. To set this custom theme, I ran:</p><figure>
  <pre><code class="language-shellsession"># plymouth-set-default-theme -R bgrt-custom</code></pre>
  </figure>
<p>8.
 This looked perfect. But, I noticed that this increased by boot up time
 considerably. Plymouth was taking a long time before displaying the 
password prompt. On further digging, I found a parameter called <code>DeviceTimeout</code> in <code>/etc/plymouth/plymouthd.conf</code> with default value of 8 seconds.</p> <p>According to <a href="https://gitlab.freedesktop.org/plymouth/plymouth/-/merge_requests/58" rel="noreferrer">this merge request</a>,
 this was needed to keep support for certain AMD GPUs. I don't have and 
AMD GPU, and anyway I think Plymouth is using the EFI framebuffer for 
this splash screen, not the GPU. So, I reduced it to 2 seconds to make 
things faster.</p>]]></content:encoded>
    <comments>https://srijan.ch/graphical-password-prompt-for-disk-decryption#comments</comments>
    <slash:comments>2</slash:comments>
  </item><item>
    <title>Encrypting an existing Linux system&#039;s root partition</title>
    <description><![CDATA[Encrypt an unencrypted root partition on an Arch Linux system]]></description>
    <link>https://srijan.ch/encrypting-an-existing-linux-systems-root-partition</link>
    <guid isPermaLink="false">63f61c905e8d350001eda64a</guid>
    <category><![CDATA[linux]]></category>
    <category><![CDATA[security]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Wed, 22 Feb 2023 19:45:00 +0000</pubDate>
    <media:content url="https://srijan.ch/media/pages/blog/encrypting-an-existing-linux-systems-root-partition/27f278c9de-1699621096/partitions-summary.excalidraw.png" medium="image" />
    <content:encoded><![CDATA[<h2>Introduction</h2>
<p>I have an Arch Linux 
system with an unencrypted root partition that I wanted to encrypt. I've
 documented the steps I followed to achieve this here.</p> <p>I selected the "LUKS on a partition" option <a href="https://wiki.archlinux.org/title/dm-crypt/Encrypting_an_entire_system" rel="noreferrer">from here</a>. I don't have an LVM setup on this system and didn't need to encrypt the boot partition.</p><figure data-ratio="auto">
    <img src="https://srijan.ch/media/pages/blog/encrypting-an-existing-linux-systems-root-partition/27f278c9de-1699621096/partitions-summary.excalidraw.png" alt="">
  
  </figure>
<p>The
 first step was to have a backup so that if something failed, I could at
 least recover my critical files. I don't have filesystem-level backups 
configured, so I used <a href="https://github.com/kopia/kopia" rel="noreferrer">kopia</a> to back up my home folder. Details on this might be in a future blog post.</p><h2>Process</h2>
<p>1. To begin, I set up a <a href="https://wiki.archlinux.org/title/USB_flash_installation_medium" rel="noreferrer">USB flash installation medium</a>
 so that I could boot into a live environment to perform the actual 
actions. Since I needed to encrypt the root partition, this could not be
 performed from inside the system running off that partition.</p> <p>2. 
After booting into the live environment using the above USB medium, I 
first shrank the existing filesystem by 32MiB to make space for the LUKS
 encryption header, which is always stored at the beginning of the 
device. My filesystem size is exactly 500GiB, so I set the new size to <code>511968M</code>.</p><figure>
  <pre><code class="language-shellsession"># echo &quot;Check the filesystem&quot;
# e2fsck -f /dev/nvme0n1p7

# echo &quot;Resize&quot;
# resize2fs -p /dev/nvme0n1p7 511968M</code></pre>
  </figure>
<p>3. Now, I encrypted it using the default cipher. This took 37 minutes on my 500GiB partition, which was about 55% full.</p><figure>
  <pre><code class="language-shellsession"># cryptsetup reencrypt --encrypt --reduce-device-size 16M /dev/nvme0n1p7

WARNING!

========

This will overwrite data on LUKS2-temp-12345678-9012-3456-7890-123456789012.new irrevocably.

Are you sure? (Type &#039;yes&#039; in capital letters): YES
Enter passphrase for LUKS2-temp-12345678-9012-3456-7890-123456789012.new: 
Verify passphrase:</code></pre>
  </figure>
<p>4. Next, I extended the original ext4 file system to occupy all available space again on the now encrypted partition:</p><figure>
  <pre><code class="language-shellsession"># cryptsetup open /dev/nvme0n1p7 root
Enter passphrase for /dev/nvme0n1p7: 

# resize2fs /dev/mapper/root</code></pre>
  </figure>
<p>5. Now, I mounted the filesystem and chrooted into it:</p><figure>
  <pre><code class="language-shellsession"># mount /dev/mapper/root /mnt
# mount /dev/nvme0n1p1 /mnt/boot
# arch-chroot /mnt</code></pre>
  </figure>
<p>6. Since I have a systemd-based initramfs, I added <code>keyboard</code>, <code>sd-vconsole</code>, and <code>sd-encrypt</code> hooks in the <code>HOOKS</code> section of <code>/etc/mkinitcpio.conf</code>:</p><figure>
  <pre><code class="language-ini">HOOKS=(base systemd autodetect modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)</code></pre>
    <figcaption class="text-center">/etc/mkinitcpio.conf</figcaption>
  </figure>
<p>7. Next, I regenerated the initramfs ( <code>-P</code> regenerates it for all presets ):</p><figure>
  <pre><code class="language-shellsession"># mkinitcpio -P</code></pre>
  </figure>
<p>8. Next, I configured the boot loader by adding to kernel parameters:</p><figure>
  <pre><code class="language-ini">rd.luks.name=&lt;device-UUID&gt;=root root=/dev/mapper/root</code></pre>
  </figure>
<p>I found the device UUID using: <code>sudo blkid -s UUID -o value /dev/nvme0n1p7</code>. Surprisingly (for me), the UUID had changed after encrypting the partition.</p> <p>My final bootloader conf file looked like this:</p><figure>
  <pre><code class="language-text">title    Arch Linux
linux    /vmlinuz-linux
initrd   /amd-ucode.img
initrd   /initramfs-linux.img
options  rd.luks.name=1df8ea89-4274-4ef9-a670-76c13e612901=root root=/dev/mapper/root rw</code></pre>
    <figcaption class="text-center">/boot/loader/entries/arch.conf</figcaption>
  </figure>
<p>9. Lastly, I updated <code>/etc/fstab</code>:</p><figure>
  <pre><code class="language-text">/dev/mapper/root  /  ext4  rw,relatime  0 1</code></pre>
    <figcaption class="text-center">/etc/fstab</figcaption>
  </figure>
<p>10. All done. To test it out, I logged out of the chroot environment and rebooted the system.</p><p>It asked me for the disk encryption password. After entering the password selected in step 3, the system booted up as usual, and everything looked to be working.</p><h2>Final Thoughts</h2>
<p>This was surprisingly easy to do and did not take much time. The <a href="https://wiki.archlinux.org/" rel="noreferrer">ArchWiki</a> was helpful, even if the information was spread over multiple pages/sections. Taking a backup before starting also made me feel safe about the process.</p><p>I did not like the design of the decryption password prompt at bootup. Maybe there's a way to customize it to look better. Update: I found a way. <a href="https://srijan.ch/graphical-password-prompt-for-disk-decryption" rel="noreferrer">Details here</a>.</p>]]></content:encoded>
    <comments>https://srijan.ch/encrypting-an-existing-linux-systems-root-partition#comments</comments>
    <slash:comments>1</slash:comments>
  </item><item>
    <title>My backup strategy to USB disk using duply</title>
    <description><![CDATA[Local system backup using duply]]></description>
    <link>https://srijan.ch/my-backup-strategy-part-1</link>
    <guid isPermaLink="false">6030d3dab5e0920001f557ce</guid>
    <category><![CDATA[devops]]></category>
    <category><![CDATA[linux]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Thu, 04 Aug 2016 17:55:00 +0000</pubDate>
    <content:encoded><![CDATA[<p>I don't have a lot of data to backup - just my home folder (on my 
Archlinux laptop) which just has configuration for all the tools I'm 
using and my programming work.</p> <p>For photos or videos taken from my phone, I use google photos for 
backup - which works pretty well. Even if I delete the original files 
from my phone, the photos app still keeps them online.</p> <p>Coming back to my laptop, I'm currently using <a href="http://duplicity.nongnu.org/">duplicity</a> (with the <a href="http://duply.net/">duply</a>
 wrapper) to backup to multiple destinations. Why multiple locations? I 
wanted one local copy so that I can restore fast, and at least one at a 
remote location so that I can still restore if the local disk fails.</p> <p>For off-site, I'm using the fantastic <a href="http://www.rsync.net/">rsync.net</a> service. For local backups, I'm using two destinations: a USB HDD at my home, and a NFS server at my work. <strong>Depending on where I am, the backup will be done to the correct destination</strong>.</p> <p>This post will deal with the backups to my local USB disk.</p> <p>Here's what I've been able to achieve: the backups will run every 
hour as long as the USB disk is connected. If it is not connected, the 
backup script will not even be triggered. I did not want to see backup 
failures in my logs if the HDD is not connected.</p> <p>I've done this using a systemd timer and service. I've defined these units in <a href="https://wiki.archlinux.org/index.php/Systemd/User">the user-level part for systemd</a> so that root privileges are not required.</p><h3>Mounting the USB Disk</h3>
<p>To automatically mount the USB disk, I've added the following line to my <code>/etc/fstab</code>:</p><figure>
  <pre><code class="language-ini">UUID=27DFA4B43C8C0635 /mnt/Ext01 ntfs-3g nosuid,nodev,nofail,auto,x-gvfs-show,permissions 0 0</code></pre>
  </figure>
<h3>Duply config for running the backup</h3>
<p>Here's my <strong>duply</strong> config file (kept at <code>~/.duply/ext01/conf</code>) (mostly self-explanatory):</p><figure>
  <pre><code class="language-ini">TARGET=&#039;file:///mnt/Ext01/Backups/&#039;
SOURCE=&#039;/home/srijan&#039;
MAX_AGE=1Y
MAX_FULL_BACKUPS=15
MAX_FULLS_WITH_INCRS=2
MAX_FULLBKP_AGE=1M
DUPL_PARAMS=&quot;$DUPL_PARAMS --full-if-older-than $MAX_FULLBKP_AGE &quot;
VOLSIZE=4
DUPL_PARAMS=&quot;$DUPL_PARAMS --volsize $VOLSIZE &quot;
DUPL_PARAMS=&quot;$DUPL_PARAMS --exclude-other-filesystems &quot;</code></pre>
  </figure>
<p>This can be run manually using:</p><figure>
  <pre><code class="language-shellsession">$ duply ext01 backup</code></pre>
  </figure>
<p>Exclusions can be specified in the file <code>~/.config/ext01/exclude</code> in a glob-like format.</p><h3>Systemd Service for running the backup</h3>
<p>Next, here's the <strong>service file</strong> (kept at <code>~/.config/systemd/user/duply_ext01.service</code>):</p><figure>
  <pre><code class="language-ini">[Unit]
Description=Run backup using duply: ext01 profile
Requires=mnt-Ext01.mount
After=mnt-Ext01.mount

[Service]
Type=oneshot
ExecStart=/usr/bin/duply ext01 backup</code></pre>
  </figure>
<p>The <code>Requires</code> option says that this unit has a dependency on the mounting of Ext01. The <code>After</code> option specifies the order in which these two should be started (run this service <em>after</em> mounting).</p> <p>After this step, the service can be run manually (via systemd) using:</p><figure>
  <pre><code class="language-shellsession">$ systemctl --user start duply_ext01.service</code></pre>
  </figure>
<h3>Systemd timer for triggering the backup service</h3>
<p>Next step is triggering it automatically every hour. Here's the <strong>timer file</strong> (kept at <code>~/.config/systemd/user/duply_ext01.timer</code>):</p><figure>
  <pre><code class="language-ini">[Unit]
Description=Run backup using duply ext01 profile every hour
BindsTo=mnt-Ext01.mount
After=mnt-Ext01.mount

[Timer]
OnCalendar=hourly
AccuracySec=10m
Persistent=true

[Install]
WantedBy=mnt-Ext01.mount</code></pre>
  </figure>
<p>Here, the <code>BindsTo</code> option defines a dependency similar to the <code>Requires</code>
 option above, but also declares that this unit is stopped when the 
mount point goes away due to any reason. This is because I don't want 
the trigger to fire if the HDD is not connected.</p> <p>The <code>Persistent=true</code> option ensures that when the timer 
is activated, the service unit is triggered immediately if it would have
 been triggered at least once during the time when the timer was 
inactive. This is because I want to catch up on missed runs of the 
service when the disk was disconnected.</p> <p>After creating this file, I ran the following to actually link this timer to mount / unmount events for the Ext01 disk:</p><figure>
  <pre><code class="language-shellsession">$ systemctl --user enable duply_ext01.timer</code></pre>
  </figure>
<p>That's it. Now, whenever I connect the USB disk to my laptop, the 
timer is started. This timer triggers the backup service to run every 
hour. Also, it takes care that if some run was missed when the disk was 
disconnected, then it would be triggered as soon as the disk is 
connected without waiting for the next hour mark. Pretty cool!</p><h4>NOTES:</h4>
<ul><li>Changing any systemd unit file requires a <code>systemd --user daemon-reload</code> before systemd can recognize the changes.</li><li>The <a href="https://www.freedesktop.org/software/systemd/man/index.html">systemd documentation</a> was very helpful.</li></ul><h3>Coming Soon</h3>
<p>Although it would be similar, but I'll also document how to do the 
above with NFS or SSHFS filesystems (instead of local disks). The major 
difference would be handling loss of internet connectivity, timeouts, 
etc.</p>]]></content:encoded>
    <comments>https://srijan.ch/my-backup-strategy-part-1#comments</comments>
    <slash:comments>0</slash:comments>
  </item><item>
    <title>Read only root on Linux</title>
    <description><![CDATA[Setting up a read-only root filesystem on Linux]]></description>
    <link>https://srijan.ch/read-only-root-on-linux</link>
    <guid isPermaLink="false">6030d3dab5e0920001f557d2</guid>
    <category><![CDATA[devops]]></category>
    <category><![CDATA[linux]]></category>
    <dc:creator>Srijan Choudhary</dc:creator>
    <pubDate>Sat, 28 Feb 2015 00:00:00 +0000</pubDate>
    <content:encoded><![CDATA[<p>In many cases, it is required to run a system in such a way that it 
is tolerant of uncontrolled power losses, resets, etc. After such an 
event occurs, it should atleast be able to boot up and connect to the 
network so that some action can be taken remotely.</p> <p>There are a few different ways in which this could be accomplished.</p><h3>Mounting the root filesystem with read-only flags</h3>
<p>Most parts of the linux root filesystem can be mounted read-only 
without much problems, but there are some parts which don't play well. <a href="https://wiki.debian.org/ReadonlyRoot">This debian wiki page</a> has some information about this approach. I thought this approach would not be very stable, so did not try it out completely.</p><h3>Using aufs/overlayfs</h3>
<p>aufs is a union file system for linux systems, which enables us to 
mount separate filesystems as layers to form a single merged filesystem.
 Using aufs, we can mount the root file system as read-only, create a 
writable tmpfs ramdisk, and combine these so that the system thinks that
 the root filesystem is writable, but changes are not actually saved, 
and don't survive a reboot.</p> <p>I found this method to be most suitable and stable for my task, and 
have been using this for the last 6 months. This system mounts the real 
filesytem at mountpoint <code>/ro</code> with read-only flag, creates a writable ramdisk at mountpoint <code>/rw</code>, and makes a union filesystem using these two at mountpoint <code>/</code>.</p> <p>The steps I followed for my implementation are detailed below. These are just a modified version of the steps in <a href="https://help.ubuntu.com/community/aufsRootFileSystemOnUsbFlash">this ubuntu wiki page</a>. I am using Debian in my implementation.</p><ol><li><p>Install debian using live cd or your preferred method.</p></li><li><p>After first boot, upgrade and configure the system as needed.</p></li><li><p>Install <code>aufs-tools</code>.</p></li><li><p>Add aufs to initramfs and setup <a href="https://gist.github.com/srijan/383a8d7af6860de6f9de">this script</a> to start at init.</p></li></ol><figure>
  <pre><code class="language-shellsession"># echo aufs &gt;&gt; /etc/initramfs-tools/modules
# wget https://cdn.rawgit.com/srijan/383a8d7af6860de6f9de/raw/ -O /etc/initramfs-tools/scripts/init-bottom/__rootaufs
# chmod 0755 /etc/initramfs-tools/scripts/init-bottom/__rootaufs</code></pre>
  </figure>
<ol><li>Remake the initramfs.</li></ol><figure>
  <pre><code class="language-shellsession"># update-initramfs -u</code></pre>
  </figure>
<ol><li>Edit grub settings in <code>/etc/default/grub</code> and add <code>aufs=tmpfs</code> to <code>GRUB_CMDLINE_LINUX_DEFAULT</code>, and regenerate grub.</li></ol><figure>
  <pre><code class="language-shellsession"># update-grub</code></pre>
  </figure>
<ol><li>Reboot</li></ol><h4>Making changes</h4>
<p>To change something trivial (like a file edit), just remount the <code>/ro</code> mountpoint as read-write, edit the file, and reboot.</p><figure>
  <pre><code class="language-shellsession"># mount -o remount,rw /ro</code></pre>
  </figure>
<p>To do something more complicated (like install os packages), press <code>e</code> in grub menu during bootup, remove <code>aufs=tmpfs</code> from the kernel line, and boot using <code>F10</code>. The system will boot up normally once.</p> <p>Another method could be to use a configuration management tool 
(puppet, chef, ansible, etc.) to make the required changes whenever the 
system comes online. The changes would be lost on reboot, but it would 
become much easier to manage multiple such systems.</p> <p>Also, if some part of the system is required to be writable (like <code>/var/log</code>), that directory could be mounted separately as a read-write mountpoint.</p>]]></content:encoded>
    <comments>https://srijan.ch/read-only-root-on-linux#comments</comments>
    <slash:comments>1</slash:comments>
  </item></channel>
</rss>
