<?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:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arch Linux – Linux und Ich</title>
	<atom:link href="https://linuxundich.de/en/tag/arch-linux/feed/" rel="self" type="application/rss+xml" />
	<link>https://linuxundich.de/en</link>
	<description>A German Linux blog, in English</description>
	<lastBuildDate>Wed, 28 Oct 2026 08:37:14 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.4</generator>
	<item>
		<title>Ghostty 1.4: Leaner Linux terminal with drag-and-drop splits</title>
		<link>https://linuxundich.de/en/ghostty-1-4-linux-terminal/</link>
					<comments>https://linuxundich.de/en/ghostty-1-4-linux-terminal/#respond</comments>
		
		<dc:creator><![CDATA[Christoph Langner]]></dc:creator>
		<pubDate>Wed, 28 Oct 2026 08:37:14 +0000</pubDate>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Arch Linux]]></category>
		<category><![CDATA[Ghostty]]></category>
		<category><![CDATA[GNOME]]></category>
		<category><![CDATA[GTK]]></category>
		<category><![CDATA[Terminal]]></category>
		<guid isPermaLink="false">https://linuxundich.de/en/?p=302</guid>

					<description><![CDATA[Ghostty 1.4 compresses its scrollback and saves up to 90 percent memory. On Linux, text looks sharper, and you can now move splits with the mouse.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">For a long time, <a href="https://gnunn1.github.io/tilix-web/">Tilix</a> was my terminal on Linux. Splitting one window into several terminals without bothering with <a href="https://github.com/tmux/tmux/wiki">Tmux</a> or <a href="https://zellij.dev/">Zellij</a> is just nice. But Tilix depends on old libraries and has become a pain to build from the AUR on Arch Linux. Yes, it still works. But compiling gtkd, its binding to GTK 3, takes what feels like forever.</p>



<p class="wp-block-paragraph">So I&#8217;m glad there&#8217;s <a href="https://ghostty.org/">Ghostty</a>, a modern terminal with tiling built on GTK 4 and libadwaita. On my machine, it has replaced Tilix, which I introduced back in 2016 under its old name <a href="https://linuxundich.de/terminix-gtk3-terminal-mit-tiling-funktion-dragdrop-und-transparenz/">Terminix</a> (in German). I covered Ghostty in depth in the German magazine LinuxUser, issue 06/2026. Now version 1.4 is out, and it brings quite a few changes that matter to Linux users in particular.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e4920b6f&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e4920b6f" class="wp-block-image wp-lightbox-container"><img fetchpriority="high" decoding="async" height="720" sizes="(max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/01-ghostty-splits-640x360.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/01-ghostty-splits-768x432.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/01-ghostty-splits.webp 1280w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/01-ghostty-splits.webp" alt="Ghostty window on the GNOME desktop with four splits: Fastfetch, htop, a Git log and Midnight Commander"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Ghostty splits one window into as many terminals as you like, here with Fastfetch, htop, a Git log and Midnight Commander.</figcaption></figure>



<h2 class="wp-block-heading">What is Ghostty?</h2>



<p class="wp-block-paragraph">If you haven&#8217;t come across Ghostty yet: the terminal comes from Mitchell Hashimoto, whom many of you will know as the founder of HashiCorp (Vagrant, Terraform). Ghostty aims to be fast and feature-rich while still feeling like a regular desktop app. On Linux, it uses GTK 4 for that and fits in nicely with GNOME. Ghostty is free software under the MIT license.</p>



<p class="wp-block-paragraph">Tabs, splits and an overview of all open tabs come built in. You open new splits with <code>Ctrl</code>+<code>Shift</code>+<code>O</code> to the right and with <code>Ctrl</code>+<code>Shift</code>+<code>E</code> below. What you won&#8217;t find is a menu bar with settings dialogs. You configure Ghostty in the text file <code>~/.config/ghostty/config</code>. On top of that, programs running in Ghostty can show images right in the terminal, for example as a preview in a file manager.</p>



<h2 class="wp-block-heading">Less memory for weaker machines</h2>



<p class="wp-block-paragraph">Ghostty 1.4 compresses the scrollback whenever nothing is happening in the terminal. According to the developers, it then needs 70 to 90 percent less memory. Most people won&#8217;t notice that in everyday use. But if you want to squeeze the most out of a weaker machine, or you work with huge files and output, you also need a terminal that goes easy on resources.</p>



<p class="wp-block-paragraph">At the same time, Ghostty now remembers more. The project raises the scrollback per terminal from 10 to 50 MB, so you can scroll back a lot further. When you scroll or search, Ghostty quietly decompresses the data again. Compression is available on 64-bit Linux and macOS. If you don&#8217;t want it, turn it off with <code>scrollback-compression = false</code>. By the way, Ghostty itself tells you what an option does.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e4921236&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e4921236" class="wp-block-image wp-lightbox-container"><img decoding="async" height="720" sizes="(max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/06-ghostty-explain-config-640x360.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/06-ghostty-explain-config-768x432.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/06-ghostty-explain-config.webp 1280w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/06-ghostty-explain-config.webp" alt="Ghostty shows the explanation of the scrollback-compression option in a pager, with the tab bar showing three tabs above it"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">With ghostty +explain-config, Ghostty explains an option right in the terminal, here the new scrollback compression.</figcaption></figure>



<h2 class="wp-block-heading">Sharper text with fractional scaling</h2>



<p class="wp-block-paragraph">If your monitor runs at 125 or 150 percent scaling, you&#8217;ll probably like the next change. Until now, text in Ghostty looked slightly blurry at those values. With 1.4, text and box-drawing characters are crisp there too. To get there, the project rewrote how Ghostty draws on Linux. Tearing, the kind you might see while scrolling, should be pretty much gone as well.</p>



<p class="wp-block-paragraph">The rewrite comes at a price, though. Ghostty 1.4 needs at least GTK 4.18 and libadwaita 1.7, which is no problem on an up-to-date Arch Linux. Ubuntu 24.04 LTS, on the other hand, ships versions that are too old. If you&#8217;re still on that LTS, the developers recommend sticking with an older Ghostty release or using a Flatpak.</p>



<h2 class="wp-block-heading">Moving splits with the mouse</h2>



<p class="wp-block-paragraph">If you work with splits a lot, you&#8217;ll like this one: you can now rearrange splits with the mouse. Move the pointer to the top edge of a split, and a handle with three dots appears. Drag it onto another split, and a blue area shows where it will land. This works across tabs and windows, too. Running programs, output and the working directory move along with it.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e49217eb&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e49217eb" class="wp-block-image wp-lightbox-container"><img decoding="async" height="720" sizes="(max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/02-ghostty-split-verschieben-640x360.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/02-ghostty-split-verschieben-768x432.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/02-ghostty-split-verschieben.webp 1280w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/02-ghostty-split-verschieben.webp" alt="Ghostty while moving the htop split, the left half of the Git log split is highlighted in blue as the drop target"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">When you drag a split by its handle over another one, a blue area shows where it will land once you let go.</figcaption></figure>



<p class="wp-block-paragraph">That way, you can move a running htop from the bottom to the left without restarting it. On Linux, though, you can only drop a split onto another split, not into a new tab or window of its own. Whole tabs, on the other hand, can be moved to a new window through the command palette. If the handle bothers you, hide it with <code>drag-handle = never</code>.</p>



<h2 class="wp-block-heading">Naming windows and a fully localized command palette</h2>



<p class="wp-block-paragraph">With several Ghostty windows open for different projects, it&#8217;s easy to lose track. That&#8217;s why you can now rename windows from the menu, say to &#8220;Blog&#8221; or &#8220;Server&#8221;. Leave the field in the dialog empty, and Ghostty goes back to the automatic title. The command palette is now fully translated as well. In my German setup, it shows every action in German and, where there is one, the matching shortcut.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e4921c4f&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e4921c4f" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="720" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/04-ghostty-fenstertitel-640x360.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/04-ghostty-fenstertitel-768x432.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/04-ghostty-fenstertitel.webp 1280w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/04-ghostty-fenstertitel.webp" alt="Ghostty with the Change Window Title (Fenstertitel ändern) dialog over Yazi, the input field reads Hintergründe sichten"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">From the menu, you give a Ghostty window a title of its own, here for a look through the GNOME wallpapers (German interface).</figcaption></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e4921f4f&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e4921f4f" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="720" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/05-ghostty-befehlspalette-640x360.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/05-ghostty-befehlspalette-768x432.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/05-ghostty-befehlspalette.webp 1280w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/05-ghostty-befehlspalette.webp" alt="Ghostty's command palette with the search term tab, the highlighted entry is Move Tab to New Window (Tab in neues Fenster verschieben)"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">The command palette is now fully translated and also lists the new action for moving a tab to its own window (German interface).</figcaption></figure>



<p class="wp-block-paragraph">Handy if you like a drop-down terminal in the style of Guake: the new command <code>ghostty +toggle-quick-terminal</code> shows and hides Ghostty&#8217;s quick terminal, for example from a shortcut of your own. That works on Plasma, Sway or Hyprland, but not on GNOME, which lacks the interface it needs. Also new: you can choose the screen the quick terminal appears on.</p>



<h2 class="wp-block-heading">Images in the terminal and more speed</h2>



<p class="wp-block-paragraph">Programs can show images in Ghostty through the <a href="https://sw.kovidgoyal.net/kitty/graphics-protocol/">Kitty graphics protocol</a>. With 1.4, Ghostty supports the protocol completely, including animated images, and loads large graphics noticeably faster. Terminal file managers such as <a href="https://yazi-rs.github.io/">Yazi</a> or <a href="https://linuxundich.de/en/tfm-a-modern-file-manager-for-the-terminal/">Tfm</a> benefit from this, since they show images right in their preview. That way you find the right photo without opening an image viewer first.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e492253e&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e492253e" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="720" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/03-ghostty-yazi-bildvorschau-640x360.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/03-ghostty-yazi-bildvorschau-768x432.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/03-ghostty-yazi-bildvorschau.webp 1280w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/03-ghostty-yazi-bildvorschau.webp" alt="Ghostty with the Yazi file manager in the folder /usr/share/backgrounds/gnome, on the right the preview of the wallpaper fold-l.jxl"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">The Yazi file manager shows a preview of the GNOME wallpapers in Ghostty, made possible by the Kitty graphics protocol.</figcaption></figure>



<p class="wp-block-paragraph">Ghostty has become faster elsewhere, too. According to the project&#8217;s measurements, the terminal processes plain text 5.7 times as fast as before. You&#8217;ll notice that when a build or a log writes lots of lines to the terminal. Resizing the window with a long scrollback is supposed to be up to six times quicker. Some of the other numbers in the release notes only apply to macOS, though.</p>



<h2 class="wp-block-heading">No more error messages over SSH</h2>



<p class="wp-block-paragraph">If you log in to a server over SSH from Ghostty, you may know errors like &#8220;missing or unsuitable terminal: xterm-ghostty&#8221;. Programs like htop or nano then don&#8217;t work properly on the server, because the server doesn&#8217;t know Ghostty. New is the command <code>ghostty +ssh</code>, which hands the server the information it needs when necessary. If that fails, it falls back to a compatible setting.</p>



<pre class="wp-block-code"><code>$ ghostty +ssh user@server</code></pre>



<p class="wp-block-paragraph">There&#8217;s also a security reason to update. Ghostty 1.4 fixes ten vulnerabilities. Among other things, crafted graphics commands could crash the terminal. On top of that, you could trick the paste protection, which is supposed to warn you before multi-line commands run by accident right away. Some of the vulnerabilities only affect macOS or Zsh as your shell, though.</p>



<h2 class="wp-block-heading">Watch out for shortcuts and copying</h2>



<p class="wp-block-paragraph">A few changes break old behavior. On Linux, <code>Ctrl</code>+<code>Shift</code>+<code>Page Up</code> and <code>Ctrl</code>+<code>Shift</code>+<code>Page Down</code> now move tabs. To jump to the previous or next prompt, use <code>Ctrl</code>+<code>Shift</code>+<code>Up</code> and <code>Ctrl</code>+<code>Shift</code>+<code>Down</code> instead. Programs running in the terminal no longer see these key combinations. If you need them there, remove the binding again with <code>unbind</code> in the configuration.</p>



<p class="wp-block-paragraph">If you&#8217;ve set Ghostty to copy selected text automatically, you should also take a look at your configuration. With <code>copy-on-select = clipboard</code>, the selection now only ends up in the regular clipboard. If you want to keep pasting it with the middle mouse button as before, change the value to <code>both</code>. What the middle mouse button pastes is set by <code>middle-click-action</code>.</p>



<h2 class="wp-block-heading">libghostty: Ghostty is coming to other programs</h2>



<p class="wp-block-paragraph">In the <a href="https://news.ycombinator.com/item?id=50261998">discussion on Hacker News</a> about the release, Mitchell Hashimoto points to libghostty. The library contains Ghostty&#8217;s core, meaning everything that makes up a terminal on the inside. Other programs can use it instead of writing their own terminal. Hashimoto jokingly calls Ghostty itself &#8220;just a glorified tech demo for libghostty&#8221;.</p>



<p class="wp-block-paragraph">For you, this means Ghostty&#8217;s technology is gradually showing up in other programs. The terminals in JetBrains&#8217; IDEs already run on it, and a switch is being discussed for Neovim. And a <a href="https://news.ycombinator.com/item?id=50265788">KDE developer is building a new terminal</a> based on libghostty that could eventually succeed Konsole. Version 1.0 of the library is expected in the next few months.</p>



<h2 class="wp-block-heading">Installation</h2>



<p class="wp-block-paragraph">On Arch Linux, Ghostty is in the Extra repository, though at the time of writing still at version 1.3.1. Version 1.4 should follow there in the next few days. Besides the terminal itself, you should also install the shell integration and the terminfo. If you don&#8217;t want to wait, the AUR has the package <code>ghostty-nightly-bin</code>, which I also used for the screenshots in this article.</p>



<pre class="wp-block-code"><code>$ sudo pacman -S ghostty ghostty-shell-integration ghostty-terminfo</code></pre>



<p class="wp-block-paragraph">The project itself doesn&#8217;t provide ready-made packages for Linux; that&#8217;s left to the distributions. Ubuntu has shipped Ghostty in its official repositories since 26.04, though not always in the latest version. For Fedora, there&#8217;s a COPR repository, plus a Snap, an AppImage and a Debian package from the community. Ghostty&#8217;s <a href="https://ghostty.org/docs/install/binary">installation guide</a> gives you an overview.</p>



<p class="wp-block-paragraph">All in all, Ghostty 1.4 is a well-rounded update in my opinion. As someone who switched from Tilix, I&#8217;m glad to see a modern tiling terminal on a GTK base being developed so actively. If you&#8217;d rather stay closer to how Tilix works, take a look at <a href="https://linuxundich.de/en/rutile-0-2-2-a-modern-alternative-to-tilix/">Rutile</a> as well. You&#8217;ll find all changes in the <a href="https://ghostty.org/docs/install/release-notes/1-4-0">release notes</a>. Which terminal do you use?</p>
<hr><p>☕ <strong>Support Linux und Ich</strong><br>Thanks for reading <a href="https://linuxundich.de/en/">Linux und Ich</a>. If you enjoy the blog and would like to support my work, you will find more information on the <a href="https://linuxundich.de/en/support/">donation page</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://linuxundich.de/en/ghostty-1-4-linux-terminal/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WebKitGTK 2.54: Tiny Star, Massive Memory Leak</title>
		<link>https://linuxundich.de/en/webkitgtk-memory-leak-backdrop-filter/</link>
					<comments>https://linuxundich.de/en/webkitgtk-memory-leak-backdrop-filter/#respond</comments>
		
		<dc:creator><![CDATA[Christoph Langner]]></dc:creator>
		<pubDate>Fri, 23 Oct 2026 14:34:05 +0000</pubDate>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Arch Linux]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Epiphany]]></category>
		<category><![CDATA[GNOME]]></category>
		<category><![CDATA[GNOME Web]]></category>
		<category><![CDATA[PlanetFOSS]]></category>
		<guid isPermaLink="false">https://linuxundich.de/en/?p=280</guid>

					<description><![CDATA[While working on PlanetFOSS, I ran into a massive memory leak in WebKitGTK 2.54: a harmless frosted-glass effect via backdrop-filter pushes GNOME Web to as much as 9.8 GB. Firefox and Chrome don't even flinch at the same page.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Firefox and Chrome are mandatory when you build a website, while a quick look at <a href="https://apps.gnome.org/Epiphany/">GNOME Web aka Epiphany</a> tends to fall by the wayside. Not entirely for me, since I sit in front of a GNOME desktop. And so, while working on <a href="https://planetfoss.net/">PlanetFOSS</a>, <a href="https://linuxundich.de/en/planetfoss-launch-linux-news-bundles-supernovas/">my little Linux and FOSS news aggregator</a>, a full-blown memory leak in <a href="https://webkitgtk.org/">WebKitGTK</a> landed right at my feet.</p>



<p class="wp-block-paragraph">The start page simply froze Epiphany solid. Afterwards, the journal held a core dump of the web process, and systemd had logged a memory peak of 5.8 GB. For a news site with a handful of cards, that&#8217;s a bit much in my opinion. Restarting didn&#8217;t help either: Epiphany dutifully restores the PlanetFOSS tab and promptly chokes on it again.</p>



<h2 class="wp-block-heading">Following the trail</h2>



<p class="wp-block-paragraph">A look at the package history gave the first clue: on October 7, Arch Linux had updated WebKitGTK, the browser engine behind Epiphany, to version 2.54. The browser itself was quickly off the hook. MiniBrowser, a bare-bones test browser that ships with WebKitGTK, ballooned to several gigabytes within seconds on the PlanetFOSS start page. A plain example page, on the other hand, gets by with 170 MB.</p>



<h2 class="wp-block-heading">The trail leads to the star</h2>



<p class="wp-block-paragraph">An AI gave me a hand with the debugging, but narrowing things down was good old process of elimination. Without JavaScript, the page still hung. Without the stylesheet, it ran just fine. After that, one style rule after another got the boot until the culprit was clear: <code>backdrop-filter</code>. It <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/backdrop-filter">blurs the background behind an element</a> and creates the popular frosted-glass look.</p>



<p class="wp-block-paragraph">PlanetFOSS uses the effect in several places, but mostly on the small bookmark stars in the top left corner of every article card. The start page has 55 of them, plus eight news cards and ten play icons on the videos. Each of these elements gets its own frosted-glass layer. In those numbers, WebKitGTK 2.54 apparently buckles. Tiny star, massive impact.</p>



<p class="wp-block-paragraph">To double-check, I built a test page full of cards, each with one small frosted-glass element. With ten to 14 cards, memory stayed in the green. With 18 cards, around one gigabyte was already taken, and from 22 cards on, usage shot up to seven or eight gigabytes. So things tip over somewhere around 20 layers, although the exact limit is hard to pin down.</p>



<p class="wp-block-paragraph">The interesting part: the blur itself isn&#8217;t to blame at all. Frosted glass without any blur, or a simple grayscale filter, bloats WebKitGTK just the same. So the problem lies in how the new version manages these layers. Turning off the engine&#8217;s hardware acceleration does keep the test page lean. That&#8217;s no fix, though, since I can hardly tell my visitors how to launch their browser.</p>



<h2 class="wp-block-heading">Firefox and Chrome couldn&#8217;t care less</h2>



<p class="wp-block-paragraph">That leaves the question of whether only WebKitGTK is affected. So I loaded the same copy of the start page in different browsers, once with the old and once with the new design, and measured memory usage each time. I did this on my Arch notebook and in a virtual machine running Ubuntu 26.04. Images and text were identical in every run.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e4926bba&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e4926bba" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="745" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/02-speicherverbrauch-640x372.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/02-speicherverbrauch-768x447.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/02-speicherverbrauch-1280x745.webp 1280w, https://linuxundich.de/wp-content/uploads/2026/10/02-speicherverbrauch-1536x894.webp 1536w, https://linuxundich.de/wp-content/uploads/2026/10/02-speicherverbrauch.webp 1650w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/02-speicherverbrauch-1280x745.webp" alt="Bar chart: memory usage of WebKitGTK, Epiphany, Firefox, and Chrome before and after the CSS fix on Arch Linux and in an Ubuntu VM"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Only WebKitGTK 2.54 balloons with the old stylesheet, while Firefox, Chrome, and WebKitGTK 2.52 stay calm.</figcaption></figure>



<p class="wp-block-paragraph">The result is clear. Firefox and Chrome show practically the same usage before and after. Even Ubuntu&#8217;s older WebKitGTK 2.52 stays perfectly calm at around 680 MB. Only version 2.54 explodes: on my notebook, memory usage climbed to 9.8 GB in 40 seconds. After reworking the page, it was a mere 300 MB.</p>



<p class="wp-block-paragraph">In the VM, Epiphany ran as a Flatpak, which brings the new engine along. There, the browser ballooned to 4.3 GB within a minute, until only 300 MB of the roughly 5 GB of RAM were left. In an earlier run, the tab threw in the towel entirely: <em>Oops! Something went wrong while displaying this page</em>. With the new design, it stayed at 721 MB.</p>



<h2 class="wp-block-heading">Opaque background instead of frosted glass</h2>



<p class="wp-block-paragraph">The fix on the PlanetFOSS side is unspectacular. Stars, news cards, and play icons now do without frosted glass, and their background is simply a little less transparent instead. You&#8217;ll really only notice the difference if you put both versions side by side and look very closely. For a few gigabytes less memory hunger, that&#8217;s more than a fair trade in my opinion.</p>



<figure data-wp-context="{&quot;galleryId&quot;:&quot;6aef7e4926e1b&quot;}" data-wp-interactive="core/gallery" class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">

<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e4926eac&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e4926eac" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" height="738" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-vorher-640x369.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-vorher-768x443.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-vorher-1280x738.webp 1280w, https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-vorher-1536x886.webp 1536w, https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-vorher.webp 1560w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-vorher-1280x738.webp" alt="Detail of the PlanetFOSS start page with a magnifier on the bookmark star of an article card, old version with blur"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Before: A blur via backdrop-filter sits behind the star, which makes WebKitGTK 2.54 balloon to as much as 9.8 GB.</figcaption></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e4927095&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e4927095" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" height="738" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-nachher-640x369.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-nachher-768x443.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-nachher-1280x738.webp 1280w, https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-nachher-1536x886.webp 1536w, https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-nachher.webp 1560w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/01-lupe-nachher-1280x738.webp" alt="Detail of the PlanetFOSS start page with a magnifier on the bookmark star of an article card, new version without blur"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">After: A more opaque background replaces the blur, the star just gets a little darker, and WebKitGTK needs 300 MB.</figcaption></figure>

</figure>



<p class="wp-block-paragraph">The change has been live for a few days, and MiniBrowser once again gets by with 213 MB on the real start page. I kept the frosted-glass effect in the pop-out section bar and on the source links in the lead story. That&#8217;s only a handful of layers, and they don&#8217;t throw WebKit off balance. linuxundich.de also uses the effect in just two places and was never affected.</p>



<p class="wp-block-paragraph">All in all, the problem clearly lies in WebKitGTK 2.54 and not in my stylesheet. Presumably every page that uses enough elements with <code>backdrop-filter</code> is affected. So my advice to everyone who builds websites: go easy on the frosted glass and load your site in Epiphany every now and then. I&#8217;ve <a href="https://bugs.webkit.org/show_bug.cgi?id=328065">filed a bug report</a> with a test case in the WebKit Bugzilla. Hopefully I didn&#8217;t kill anyone&#8217;s browser session.</p>
<hr><p>☕ <strong>Support Linux und Ich</strong><br>Thanks for reading <a href="https://linuxundich.de/en/">Linux und Ich</a>. If you enjoy the blog and would like to support my work, you will find more information on the <a href="https://linuxundich.de/en/support/">donation page</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://linuxundich.de/en/webkitgtk-memory-leak-backdrop-filter/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Samba for Sonos S1: Allowing SMB1 without throwing your whole home network wide open</title>
		<link>https://linuxundich.de/en/samba-sonos-s1-smb1-ntlmv1-secure-setup/</link>
					<comments>https://linuxundich.de/en/samba-sonos-s1-smb1-ntlmv1-secure-setup/#respond</comments>
		
		<dc:creator><![CDATA[Christoph Langner]]></dc:creator>
		<pubDate>Sun, 18 Oct 2026 15:46:40 +0000</pubDate>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Arch Linux]]></category>
		<category><![CDATA[Homelab]]></category>
		<category><![CDATA[How-to]]></category>
		<category><![CDATA[Samba]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Sonos]]></category>
		<guid isPermaLink="false">https://linuxundich.de/en/?p=260</guid>

					<description><![CDATA[Older Sonos speakers only play your music collection over SMB1 and NTLMv1. A dedicated user, a read-only share, and a few lines in smb.conf keep the speakers playing without leaving the rest of your home server needlessly exposed.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">If you still run first-generation Sonos speakers and keep your music collection on your own server, Samba quickly hands you a little problem: Without SMB1 and the old NTLMv1 login, the speakers won&#8217;t play a single track. That&#8217;s why the usual guides on the web simply turn everything back on that Samba switched off for good reason. But there&#8217;s a much cleaner way to do it, and you don&#8217;t have to give up your music.</p>



<h2 class="wp-block-heading">Why Sonos S1 still needs SMB1</h2>



<p class="wp-block-paragraph">I still have two Play:3, a Play:1, and a Connect:Amp on my network. All of them run the S1 software, for which Sonos only ships bug fixes these days. The speakers don&#8217;t just play streams, they also play my music collection from the server. According to a <a href="https://en.community.sonos.com/conversations/86047">discussion in the Sonos forum</a>, however, the S1 devices only have enough resources for SMBv1 – the old hardware simply can&#8217;t do more.</p>



<p class="wp-block-paragraph">Samba, on the other hand, retired the old protocol a long time ago. Since <a href="https://devel.samba.org/samba/history/samba-4.11.0.html">version 4.11</a>, <code>server min protocol</code> defaults to SMB2_02, and according to the <a href="https://www.samba.org/samba/security/CVE-2018-1139.html">Samba project</a>, NTLMv1 authentication has been disabled since version 4.5. The usual guides turn both back on globally with two lines. Sure, the speakers play after that, but they&#8217;re not the only ones who get the door held open for them.</p>



<p class="wp-block-paragraph">If you run an S2 system, you&#8217;re off the hook. Sonos added SMBv2 and SMBv3 there with version 13.4.1 in December 2021 and no longer speaks SMBv1 at all. S2 users can leave Samba&#8217;s defaults alone. The rest of this article is for everyone who, like me, is still attached to their old speakers and doesn&#8217;t want to throw them out over a protocol.</p>



<h2 class="wp-block-heading">What&#8217;s wrong with the quick fix</h2>



<p class="wp-block-paragraph">Samba can only allow SMB1 for the whole server, not for individual shares or devices. Ever since WannaCry exploited a hole in Microsoft&#8217;s SMB1 in 2017 at the latest, the protocol has been considered legacy baggage, and NTLMv1 makes it easy for attackers to crack captured logins. If the speaker then logs in with your regular user on top of that, it&#8217;s your main password of all things that travels across the network using the weakest method available.</p>



<p class="wp-block-paragraph">On top of that come lines that people like to copy along while they&#8217;re at it. With <code>wide links</code> and <code>allow insecure wide links</code>, Samba follows symlinks even when they point outside the share. Often the entire data directory is shared writable, too. Sure, from the outside a little home server like this is usually locked down. But the same LAN is also home to TVs, smart plugs, and speakers whose software you have no control over.</p>



<h2 class="wp-block-heading">A dedicated user just for Sonos</h2>



<p class="wp-block-paragraph">The most important step is a dedicated user that exists only for the speakers and isn&#8217;t allowed to do anything else. It needs neither a home directory nor a shell; Samba only knows it for logging in. You set the password once and don&#8217;t use it anywhere else, because with NTLMv1 you should consider it semi-public. Creating it from scratch takes two commands:</p>



<pre data-lui-lang="bash" class="wp-block-code"><code>$ sudo useradd -r -M -s /usr/bin/nologin sonos
$ sudo smbpasswd -a sonos</code></pre>



<p class="wp-block-paragraph">If you already have a user the speakers log in with, trim it down with <code>usermod</code>. It loses its shell and gets <code>/</code> as its home directory and a locked Unix password. Logging in to Samba uses the separate password from <code>smbpasswd</code> and keeps working regardless. If your speakers have been using your regular user so far, however, you&#8217;re better off creating a new one:</p>



<pre data-lui-lang="bash" class="wp-block-code"><code>$ sudo usermod -s /usr/bin/nologin -d / sonos
$ sudo passwd -l sonos</code></pre>



<h2 class="wp-block-heading">The smb.conf</h2>



<p class="wp-block-paragraph">The configuration allows SMB1 and NTLMv1 but fences in everything around it. Samba only listens on the LAN interface and not on Docker bridges or VPN tunnels. Guests are kicked out, there are no printers, and every share gets a list of users who are allowed in. You&#8217;ll of course have to adapt the name of the network interface (<code>enp0s25</code> on my machine) and the paths to your system:</p>



<pre data-lui-lang="ini" data-lui-file="smb.conf" class="wp-block-code"><code>[global]
   workgroup = WORKGROUP
   server string = bender
   server role = standalone server

   # Sonos S1: nur SMB1 + NTLMv1
   server min protocol = NT1
   server max protocol = SMB3
   ntlm auth = ntlmv1-permitted

   # nur LAN und lokal, nicht auf den Docker-Bridges
   interfaces = lo enp0s25
   bind interfaces only = yes

   map to guest = never

   # keine Drucker
   load printers = no
   printing = bsd
   printcap name = /dev/null
   disable spoolss = yes

[homes]
   browseable = no
   writable = yes
   valid users = %S
   invalid users = sonos

[musik]
   path = /data/musik
   browseable = yes
   read only = yes
   valid users = sonos anna ben lena

[data]
   path = /data
   writable = yes
   valid users = anna ben</code></pre>



<p class="wp-block-paragraph">By the way, <code>ntlmv1-permitted</code> is just the more descriptive name for the old <code>yes</code>. The <code>[musik]</code> share (German for music) is read-only; <code>sonos</code> and the family, here <code>anna</code>, <code>ben</code>, and <code>lena</code>, are allowed to read it. Even if someone cracks the speaker&#8217;s login, all they get is the music. Only <code>anna</code> and <code>ben</code> can access <code>[data]</code>, <code>wide links</code> doesn&#8217;t appear anywhere, and symlinks therefore stay within their share.</p>



<p class="wp-block-paragraph">The line <code>invalid users = sonos</code> under <code>[homes]</code> matters, too. This share offers every user their home directory, and for the speaker user that&#8217;s the root directory after the <code>usermod</code> above. Without that line, there would be a writable share <code>\\bender\sonos</code> covering the entire system. What actually works there is still governed by file permissions, but directories like <code>/tmp</code> are open to everyone.</p>



<p class="wp-block-paragraph">If you can&#8217;t set up the Sonos library from scratch right now, there&#8217;s also an intermediate step without a separate music share. In that case, add <code>sonos</code> to the <code>valid users</code> of the existing share and also set <code>read list = sonos</code>. The speaker can then still read everything the file permissions allow, but can&#8217;t write anything. In the long run, though, a separate share is clearly the better choice.</p>



<p class="wp-block-paragraph">Before you activate the new file, have <code>testparm</code> check it. It complains about typos and unknown options before Samba trips over them. Then restart the service – on Arch it&#8217;s called <code>smb</code>, on Debian and Ubuntu <code>smbd</code>. Open connections drop briefly, but mounted shares on your computers usually reconnect on their own:</p>



<pre class="wp-block-code"><code>$ sudo testparm -s
$ sudo systemctl restart smb</code></pre>



<h2 class="wp-block-heading">The music library in the Sonos app</h2>



<p class="wp-block-paragraph">Finally, add the share as a music library in the S1 app. Open <em>Settings</em> and go to <em>Music Library</em> and <em>Music Library Setup</em>. Enter the share in Windows format as the path, i.e. <code>\\bender\musik</code>, followed by the user <code>sonos</code> and its password. Sonos then indexes the collection, which can take a while for large libraries.</p>



<figure data-wp-context="{&quot;galleryId&quot;:&quot;6aef7e4936110&quot;}" data-wp-interactive="core/gallery" class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex">

<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e4936216&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e4936216" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" height="1024" sizes="auto, (max-width: 456px) 100vw, 456px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/01-s1-app-musikbibliothek-456x1024.webp 456w, https://linuxundich.de/wp-content/uploads/2026/10/01-s1-app-musikbibliothek-640x1436.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/01-s1-app-musikbibliothek-684x1536.webp 684w, https://linuxundich.de/wp-content/uploads/2026/10/01-s1-app-musikbibliothek-768x1724.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/01-s1-app-musikbibliothek-912x2048.webp 912w, https://linuxundich.de/wp-content/uploads/2026/10/01-s1-app-musikbibliothek.webp 1080w" width="456" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/01-s1-app-musikbibliothek-456x1024.webp" alt="Music library settings in the Sonos S1 app"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">In the S1 app, you add the Samba share as a new folder for the music library.</figcaption></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e4936543&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e4936543" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" height="1024" sizes="auto, (max-width: 456px) 100vw, 456px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/02-s1-app-freigabe-anmeldung-456x1024.webp 456w, https://linuxundich.de/wp-content/uploads/2026/10/02-s1-app-freigabe-anmeldung-640x1436.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/02-s1-app-freigabe-anmeldung-684x1536.webp 684w, https://linuxundich.de/wp-content/uploads/2026/10/02-s1-app-freigabe-anmeldung-768x1724.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/02-s1-app-freigabe-anmeldung-912x2048.webp 912w, https://linuxundich.de/wp-content/uploads/2026/10/02-s1-app-freigabe-anmeldung.webp 1080w" width="456" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/02-s1-app-freigabe-anmeldung-456x1024.webp" alt="Entering the share path, user name, and password in the Sonos S1 app"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">The share login is the dedicated user sonos, not your regular user.</figcaption></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e493681d&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e493681d" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" height="1024" sizes="auto, (max-width: 456px) 100vw, 456px" srcset="https://linuxundich.de/wp-content/uploads/2026/10/03-s1-app-bibliothek-eingelesen-456x1024.webp 456w, https://linuxundich.de/wp-content/uploads/2026/10/03-s1-app-bibliothek-eingelesen-640x1436.webp 640w, https://linuxundich.de/wp-content/uploads/2026/10/03-s1-app-bibliothek-eingelesen-684x1536.webp 684w, https://linuxundich.de/wp-content/uploads/2026/10/03-s1-app-bibliothek-eingelesen-768x1724.webp 768w, https://linuxundich.de/wp-content/uploads/2026/10/03-s1-app-bibliothek-eingelesen-912x2048.webp 912w, https://linuxundich.de/wp-content/uploads/2026/10/03-s1-app-bibliothek-eingelesen.webp 1080w" width="456" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/10/03-s1-app-bibliothek-eingelesen-456x1024.webp" alt="Music library in the Sonos S1 app after indexing"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Once indexing is done, the music collection from the home server shows up in the Sonos app.</figcaption></figure>

</figure>



<h2 class="wp-block-heading">Checking the result</h2>



<p class="wp-block-paragraph"><code>smbstatus</code> shows you whether everything works as intended. The <em>Protocol Version</em> column tells you who is connected with which protocol. Regular computers should keep connecting via SMB3 – my notebook, for example, uses SMB3_11 – and only the speakers show up with NT1. A guest login without a password, on the other hand, should bounce off with <code>NT_STATUS_ACCESS_DENIED</code> when you try it with <code>smbclient</code> from another computer:</p>



<pre class="wp-block-code"><code>$ sudo smbstatus -b
$ smbclient -N //bender/data -c ls</code></pre>



<p class="wp-block-paragraph">Don&#8217;t let the output of the second command mislead you. The line &#8220;Anonymous login successful&#8221; sounds like an open door, but it only concerns the connection to the server itself, which a client uses to fetch the list of shares, for example. The second line is what counts, because nobody gets into the share itself without a user name and password:</p>



<pre class="wp-block-code"><code>$ smbclient -N //bender/data -c ls
Anonymous login successful
tree connect failed: NT_STATUS_ACCESS_DENIED</code></pre>



<p class="wp-block-paragraph">On my server it looks like this: The speaker in the bedroom reads as <code>sonos</code> via NT1, while the notebook is connected with SMB3_11 and a signed connection. That&#8217;s exactly how it should be, because the old protocol stays limited to the devices that can&#8217;t do anything else. The other speakers only show up while they&#8217;re actually accessing the library:</p>



<pre class="wp-block-code"><code>$ sudo smbstatus -b

Samba version 4.25.0
PID     Username     Group        Machine                                   Protocol Version  Encryption           Signing              
----------------------------------------------------------------------------------------------------------------------------------------
732192  sonos        sonos        192.168.0.60 (ipv4:192.168.0.60:38427)    NT1               -                    -                    
711090  anna         anna         192.168.0.191 (ipv4:192.168.0.191:52826)  SMB3_11           -                    partial(AES-128-CMAC)</code></pre>



<h2 class="wp-block-heading">And in the long run?</h2>



<p class="wp-block-paragraph">Of course, I&#8217;m still not entirely happy with SMB1. My server already runs <a href="https://github.com/simojenki/bonob">bonob</a>, which brings Navidrome into the Sonos app as a music service. If the music comes through that, no speaker needs a Samba share anymore, and SMB1 could go for good. But if you can&#8217;t do without Sonos&#8217;s built-in library, the restricted setup is a good compromise in my view.</p>



<p class="wp-block-paragraph">All in all, the clean approach only costs you one user and a few extra lines in <code>smb.conf</code>. The speakers play just as well as with the quick fix, except that they no longer offer a path to the rest of the server. How did you hook up your old Sonos speakers? Is SMB1 still running on your network, too, or did you switch to S2 long ago?</p>
<hr><p>☕ <strong>Support Linux und Ich</strong><br>Thanks for reading <a href="https://linuxundich.de/en/">Linux und Ich</a>. If you enjoy the blog and would like to support my work, you will find more information on the <a href="https://linuxundich.de/en/support/">donation page</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://linuxundich.de/en/samba-sonos-s1-smb1-ntlmv1-secure-setup/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Mounting Network Shares Automatically: What Can Go Wrong with the NetworkManager Dispatcher</title>
		<link>https://linuxundich.de/en/mounting-network-shares-automatically-what-can-go-wrong-with-the-networkmanager-dispatcher/</link>
					<comments>https://linuxundich.de/en/mounting-network-shares-automatically-what-can-go-wrong-with-the-networkmanager-dispatcher/#respond</comments>
		
		<dc:creator><![CDATA[Christoph Langner]]></dc:creator>
		<pubDate>Fri, 21 Aug 2026 16:11:08 +0000</pubDate>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Arch Linux]]></category>
		<category><![CDATA[GNOME]]></category>
		<category><![CDATA[Homelab]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[NetworkManager]]></category>
		<category><![CDATA[Tips]]></category>
		<guid isPermaLink="false">https://linuxundich.de/en/?p=13</guid>

					<description><![CDATA[All my mount script was supposed to do was one thing: mount the Samba share when I'm at home. In the end it broke shutdown, resume and standby for me, and taught me a few things about D-state processes and the Linux freezer.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">You may know the situation: at home you have a NAS or a cloud storage that you mount via Samba or WebDAV. But only when you are actually on your home network. Nobody wants to sit in a café waiting because the laptop is desperately trying to mount a share that is simply not reachable right now.</p>



<p class="wp-block-paragraph">The obvious solution: <code>/etc/fstab</code> plus a dispatcher script for NetworkManager that mounts automatically based on the SSID or on whether the server is reachable. Sounds like an evening project. It isn&#8217;t quite. I tripped over three pitfalls that you only notice when the machine shuts down, wakes up, or is supposed to go into standby. Those are the three I&#8217;ll walk you through here.</p>



<p class="wp-block-paragraph">I tested all of this on Arch Linux, but the setup is not Arch-specific. As long as your distro ships systemd and NetworkManager (so Fedora, Ubuntu, Debian or openSUSE, for example), everything here works one to one.</p>



<h3 class="wp-block-heading">The basic setup</h3>



<p class="wp-block-paragraph">Network shares traditionally get <code>noauto</code> in the fstab, so they are not mounted immediately at boot but only when needed:</p>



<pre class="wp-block-code"><code>//server/home /mnt/server/home cifs credentials=/etc/samba/server.credentials,rw,uid=1000,gid=100,noauto,_netdev 0 0
//server/data /mnt/server/data cifs credentials=/etc/samba/server.credentials,rw,uid=1000,gid=100,noauto,_netdev 0 0</code></pre>



<p class="wp-block-paragraph">For the mount type itself, the Arch Wiki has good guides depending on the protocol, for example on <a href="https://wiki.archlinux.org/title/Samba">Samba/CIFS</a> and on <a href="https://wiki.archlinux.org/title/Davfs2">davfs2 for WebDAV</a>. Both work on any distribution, as long as <em>cifs-utils</em> or <em>davfs2</em> are installed.</p>



<p class="wp-block-paragraph">The actual mounting is then handled by a script in <code>/etc/NetworkManager/dispatcher.d/</code>. NetworkManager calls such scripts on every connection change and passes along the interface and the status (up, down, pre-down and a few more). All the details are in the <a href="https://man.archlinux.org/man/NetworkManager-dispatcher.8.en">NetworkManager dispatcher man page</a>. A simple script checks the active Wi-Fi SSID and mounts if it matches:</p>



<pre class="wp-block-code"><code>#!/bin/bash
IFACE=&quot;$1&quot;
STATUS=&quot;$2&quot;

case &quot;$STATUS&quot; in
    up)
        SSID=$(nmcli -t -f active,ssid dev wifi | awk -F: '$1 == &quot;yes&quot; {print $2; exit}')
        if &amp;#91;&amp;#91; &quot;$SSID&quot; == &quot;MeinHeimnetz&quot; ]]; then
            mount /mnt/server/home
            mount /mnt/server/data
        fi
        ;;
    down)
        umount /mnt/server/home
        umount /mnt/server/data
        ;;
esac</code></pre>



<p class="wp-block-paragraph">Done, right? Not quite. As soon as you shut down the system, wake it from standby or put it into standby, it turns out that this approach has its catches.</p>



<h3 class="wp-block-heading">Why not just use GVfs?</h3>



<p class="wp-block-paragraph">You may now be wondering why I put myself through fstab and dispatcher scripts at all. GNOME offers “Connect to Server” in the file manager, which is a much easier way to mount network shares via SMB or WebDAV. That is exactly where my problem lies.</p>



<p class="wp-block-paragraph">Such mounts don&#8217;t go through the kernel but through GVfs, GNOME&#8217;s virtual file system. Programs that use the GIO library (almost all GTK apps, first and foremost the file manager itself) talk to shares directly through their own URIs like <code>smb://</code> or <code>dav://</code>, and accordingly display thumbnails and metadata correctly. For programs that can&#8217;t do that, GVfs additionally exposes the share as a perfectly normal path under <code>/run/user/&lt;uid&gt;/gvfs</code>. This bridge does run through FUSE. GVfs itself is not a classic FUSE file system but its own architecture with a daemon process per protocol, yet for exactly this case it provides a POSIX-compatible path via gvfsd-fuse.</p>



<p class="wp-block-paragraph">This very bridge is the sticking point for me: not every program copes with it reliably. In my case it shows up in a Markdown editor where I also embed images for articles. The file manager displays the images on the network drive just fine, because it speaks GVfs natively. The Markdown editor, on the other hand, shows only a placeholder for the same image. Access via the FUSE path simply doesn&#8217;t work reliably, even though the file is demonstrably there.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e493b1d8&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e493b1d8" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="720" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/08/apostrophe-webdav-bild-640x360.webp 640w, https://linuxundich.de/wp-content/uploads/2026/08/apostrophe-webdav-bild-768x432.webp 768w, https://linuxundich.de/wp-content/uploads/2026/08/apostrophe-webdav-bild-1280x720.webp 1280w, https://linuxundich.de/wp-content/uploads/2026/08/apostrophe-webdav-bild-1536x864.webp 1536w, https://linuxundich.de/wp-content/uploads/2026/08/apostrophe-webdav-bild-2048x1152.webp 2048w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/08/apostrophe-webdav-bild-1280x720.webp" alt="Two windows are open on a computer screen. On the left is a text editor with a file showing structured text with headings and paragraphs. On the right is a document viewer with a longer body of text that also contains paragraphs and a heading. In the background a desktop with a gradient of dark and purple tones is visible. At the top, the interface shows a menu bar with icons and the time." style="width:100%"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button></figure>



<p class="wp-block-paragraph">A classic kernel mount via CIFS or davfs2, as described in the rest of this article, shows up as a perfectly normal, stable POSIX path in the file system, with no special treatment and the same for every program. So the extra effort with fstab and dispatcher scripts pays off precisely when you want to use shares reliably not just in the file manager but in all kinds of apps.</p>



<h3 class="wp-block-heading">Problem 1: The computer doesn&#8217;t shut down cleanly anymore</h3>



<p class="wp-block-paragraph">If the fstab lacks the option _netdev, systemd doesn&#8217;t know that this is a network share. On shutdown, systemd may then try to unmount <em>after</em> the network is already gone. The umount blocks until the job timeout kicks in, and your system hangs on shutdown.</p>



<p class="wp-block-paragraph"><a href="https://wiki.archlinux.org/title/Fstab#Remote_filesystem">_netdev</a> fixes that, because systemd then knows the right order: unmount first, then cut the network. It is also important that a dispatcher script reacts not just to down but to pre-down. That status fires before the connection actually drops, while down comes afterward and is too late for a clean unmount. For this to work, you additionally need a symlink in the subfolder <code>pre-down.d/</code>.</p>



<h3 class="wp-block-heading">Problem 2: The file manager freezes after waking up</h3>



<p class="wp-block-paragraph">A mount call for CIFS or WebDAV runs in the kernel and can block for quite a while if the server is unreachable, especially right after waking up, when DNS or routing aren&#8217;t fully back yet. By default, NetworkManager waits synchronously until such a dispatcher script has finished before it carries on. If the mount call hangs, suddenly your file manager or the network indicator hangs too, because they depend on the connection state.</p>



<p class="wp-block-paragraph">The fix: just run the mount attempts in the background, so the dispatcher script itself returns immediately, no matter how long the actual mount takes.</p>



<pre class="wp-block-code"><code>run_async() {
    ( &quot;$@&quot; ) &amp;&gt;/dev/null &amp;
    disown
}</code></pre>



<h3 class="wp-block-heading">Problem 3: Suspend suddenly stops working</h3>



<p class="wp-block-paragraph">And this is where it gets interesting. With the fix from problem 2 you stumble into a new and much nastier problem, which in my case looked like this: the screen turns off, but the keyboard backlight and LEDs stay on, and you have to force a hard power-off. What happened?</p>



<p class="wp-block-paragraph">The mount syscall for CIFS or davfs blocks with an unreachable server in the so-called <a href="https://eklitzke.org/uninterruptible-sleep">D state (uninterruptible sleep)</a>, a state that no signal can interrupt, not even SIGKILL. Before the kernel actually goes to sleep, it tries to freeze all processes. A process in D state can&#8217;t be frozen, so the whole suspend hangs until the network operation in the kernel gives up on its own, which can easily take a few minutes.</p>



<p class="wp-block-paragraph">Because the mount attempts from problem 2 now keep running in the background for longer, the chance also goes up that such a blocking connection attempt is active at exactly the moment you want to suspend.</p>



<p class="wp-block-paragraph">The reliable way out: before every mount, first check with a real userspace connection test whether the server is reachable at all. That kind of test can actually be aborted with a timeout, for example via Bash&#8217;s built-in /dev/tcp:</p>



<pre class="wp-block-code"><code>tcp_reachable() {
    local HOST=&quot;$1&quot;
    local PORT=&quot;$2&quot;
    local TIMEOUT_SECONDS=&quot;${3:-2}&quot;
    timeout &quot;${TIMEOUT_SECONDS}s&quot; bash -c &quot;echo &gt;/dev/tcp/${HOST}/${PORT}&quot; &amp;&gt;/dev/null
}</code></pre>



<p class="wp-block-paragraph">Only if the test succeeds does the actual mount follow. That way you almost never end up in the risky, blocking kernel connect, because by then you already know the server is there.</p>



<h3 class="wp-block-heading">The combination that works for me</h3>



<p class="wp-block-paragraph">In the end, a robust setup needs four ingredients:</p>



<ul class="wp-block-list">

<li><strong>_netdev</strong> in the fstab, so systemd classifies network shares correctly on shutdown.</li>


<li><strong>pre-down handling</strong> plus a symlink in pre-down.d/, so the unmount is guaranteed to happen before the connection is torn down, with a timeout and lazy unmount as a backup in case the normal umount acts up.</li>


<li><strong>Asynchronous mounts</strong> on up, so NetworkManager and everything that depends on it doesn&#8217;t block.</li>


<li><strong>A reachability test</strong> before every mount, so the actual, potentially blocking kernel connect never happens in the first place.</li>

</ul>



<p class="wp-block-paragraph">On top of that, a small health check via a systemd timer that looks a few minutes after boot and regularly afterward to see whether the shares are really there, and nudges things along if needed. Handy in case the triggering network event comes too early or too late.</p>



<h3 class="wp-block-heading">All files at a glance</h3>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e493c040&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e493c040" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="884" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2026/08/nm-dispatcher-helper-640x454.webp 640w, https://linuxundich.de/wp-content/uploads/2026/08/nm-dispatcher-helper-768x545.webp 768w, https://linuxundich.de/wp-content/uploads/2026/08/nm-dispatcher-helper.webp 1246w" width="1246" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2026/08/nm-dispatcher-helper.webp" alt="A computer screen shows a terminal window with a black background and white text. At the top is a tree structure of the directories and files under '/etc/NetworkManager/dispatcher.d'. The structure contains several subdirectories and shell scripts. On the left, timestamps and commands are visible, on the right the respective outputs. The window is framed by a gray menu bar." style="width:100%"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">This is what it looks like on my machine: the NetworkManager dispatcher mounts shares automatically as soon as it finds the right server on the network or connects via Wi-Fi to a specific SSID.</figcaption></figure>



<p class="wp-block-paragraph">So you can rebuild all of this right away, here is the complete set of files. I replaced the example names from my own setup (a Samba server called bender, WebDAV via tuxedo) with generic placeholders. You&#8217;ll of course have to adapt them to your own environment.</p>



<p class="wp-block-paragraph"><strong>/etc/fstab</strong>: the two shares, one Samba, one WebDAV:</p>



<pre class="wp-block-code"><code>//server/home /mnt/server/home cifs credentials=/etc/samba/server.credentials,rw,uid=1000,gid=100,noauto,_netdev,x-systemd.mount-timeout=15s,soft 0 0
//server/data /mnt/server/data cifs credentials=/etc/samba/server.credentials,rw,uid=1000,gid=100,noauto,_netdev,x-systemd.mount-timeout=15s,soft 0 0
https://cloud.example.com/remote.php/dav/files/user /mnt/webdav davfs noauto,_netdev,uid=1000,gid=100,x-systemd.automount,x-systemd.idle-timeout=300,x-systemd.mount-timeout=15s 0 0</code></pre>



<p class="wp-block-paragraph">The fstab only references the credentials; they are stored in separate files, if only so the password doesn&#8217;t sit in plain text in a file that everyone can read.</p>



<p class="wp-block-paragraph"><strong>/etc/samba/server.credentials</strong>: credentials for the Samba share:</p>



<pre class="wp-block-code"><code>username=maxmuster
password=GeheimesPasswort123</code></pre>



<p class="wp-block-paragraph"><strong>/etc/davfs2/secrets</strong>: credentials for the WebDAV share. Here the mount point is referenced instead of an option in the fstab:</p>



<pre class="wp-block-code"><code>/mnt/webdav maxmuster GeheimesPasswort123</code></pre>



<p class="wp-block-paragraph">Both files belong to root and must not be readable by anyone else:</p>



<pre class="wp-block-code"><code>$ sudo chmod 600 /etc/samba/server.credentials /etc/davfs2/secrets
$ sudo chown root:root /etc/samba/server.credentials /etc/davfs2/secrets</code></pre>



<p class="wp-block-paragraph"><strong>/etc/NetworkManager/dispatcher.d/lib/mount-helpers.sh</strong>: the shared library that all the other scripts source:</p>



<pre class="wp-block-code"><code>#!/bin/bash
log() {
    &amp;#91;&amp;#91; &quot;$DEBUG&quot; == &quot;1&quot; ]] &amp;&amp; logger -t &quot;$LOG_TAG&quot; -- &quot;$1&quot;
}

run_async() {
    ( &quot;$@&quot; ) &amp;&gt;/dev/null &amp;
    disown
}

tcp_reachable() {
    local HOST=&quot;$1&quot;
    local PORT=&quot;$2&quot;
    local TIMEOUT_SECONDS=&quot;${3:-2}&quot;
    timeout &quot;${TIMEOUT_SECONDS}s&quot; bash -c &quot;echo &gt;/dev/tcp/${HOST}/${PORT}&quot; &amp;&gt;/dev/null
}

mount_with_retry() {
    local MOUNT=&quot;$1&quot;
    local MAX_ATTEMPTS=&quot;${2:-3}&quot;
    local SLEEP_SECONDS=&quot;${3:-2}&quot;
    local MOUNT_TIMEOUT=&quot;${4:-10}&quot;

    if mountpoint -q &quot;$MOUNT&quot;; then
        log &quot;$MOUNT ist bereits eingehängt&quot;
        return 0
    fi

    log &quot;Hänge $MOUNT ein&quot;

    local OUT ATTEMPT
    for ((ATTEMPT = 1; ATTEMPT &lt;= MAX_ATTEMPTS; ATTEMPT++)); do
        if OUT=$(timeout &quot;${MOUNT_TIMEOUT}s&quot; mount &quot;$MOUNT&quot; 2&gt;&amp;1); then
            log &quot;$MOUNT erfolgreich eingehängt&quot;
            return 0
        fi
        log &quot;Versuch $ATTEMPT/$MAX_ATTEMPTS für $MOUNT fehlgeschlagen (evtl. Timeout nach ${MOUNT_TIMEOUT}s): $OUT&quot;
        &amp;#91;&amp;#91; &quot;$ATTEMPT&quot; -lt &quot;$MAX_ATTEMPTS&quot; ]] &amp;&amp; sleep &quot;$SLEEP_SECONDS&quot;
    done

    log &quot;Alle Versuche für $MOUNT fehlgeschlagen&quot;
    return 1
}

umount_with_fallback() {
    local MOUNT=&quot;$1&quot;
    local TIMEOUT_SECONDS=&quot;${2:-5}&quot;

    if ! mountpoint -q &quot;$MOUNT&quot;; then
        log &quot;$MOUNT ist nicht eingehängt&quot;
        return 0
    fi

    log &quot;Hänge $MOUNT aus&quot;

    if timeout &quot;${TIMEOUT_SECONDS}s&quot; umount &quot;$MOUNT&quot;; then
        log &quot;$MOUNT erfolgreich ausgehängt&quot;
        return 0
    fi

    log &quot;Normaler Unmount von $MOUNT fehlgeschlagen, versuche Lazy Unmount&quot;
    if umount -l &quot;$MOUNT&quot;; then
        log &quot;$MOUNT per Lazy Unmount ausgehängt&quot;
        return 0
    fi

    log &quot;$MOUNT konnte nicht ausgehängt werden&quot;
    return 1
}</code></pre>



<p class="wp-block-paragraph"><strong>/etc/NetworkManager/dispatcher.d/90-server-mount</strong>: Samba share, bound to a specific Wi-Fi SSID or to the wired network:</p>



<pre class="wp-block-code"><code>#!/bin/bash

DEBUG=1
LOG_TAG=&quot;server-mount&quot;

LIB=&quot;/etc/NetworkManager/dispatcher.d/lib/mount-helpers.sh&quot;
if &amp;#91;&amp;#91; -r &quot;$LIB&quot; ]]; then
    source &quot;$LIB&quot;
else
    logger -t &quot;$LOG_TAG&quot; -- &quot;Bibliothek $LIB nicht gefunden, breche ab&quot;
    exit 1
fi

IFACE=&quot;$1&quot;
STATUS=&quot;$2&quot;

MOUNTS=(
    &quot;/mnt/server/home&quot;
    &quot;/mnt/server/data&quot;
)

mount_server() {
    if ! tcp_reachable server 445 2; then
        log &quot;server auf Port 445 nicht erreichbar, überspringe Mount-Versuch&quot;
        return 1
    fi

    for MOUNT in &quot;${MOUNTS&amp;#91;@]}&quot;; do
        mount_with_retry &quot;$MOUNT&quot; 3 2 10
    done
}

umount_server() {
    for MOUNT in &quot;${MOUNTS&amp;#91;@]}&quot;; do
        umount_with_fallback &quot;$MOUNT&quot; 5
    done
}

log &quot;Dispatcher gestartet: Interface=$IFACE, Status=$STATUS&quot;

case &quot;$STATUS&quot; in
    up)
        if &amp;#91;&amp;#91; &quot;$IFACE&quot; == wl* ]]; then
            SSID=$(nmcli -t -f active,ssid dev wifi |
                awk -F: '$1 == &quot;yes&quot; {print $2; exit}')

            log &quot;Aktive WLAN-SSID: $SSID&quot;

            if &amp;#91;&amp;#91; &quot;$SSID&quot; == &quot;MeinHeimnetz&quot; ]]; then
                run_async mount_server
            fi

        elif &amp;#91;&amp;#91; &quot;$IFACE&quot; == enp* || &quot;$IFACE&quot; == eth* ]]; then
            run_async mount_server
        fi
        ;;

    pre-down|vpn-pre-down)
        log &quot;Netzwerkverbindung wird beendet – Mounts aushängen&quot;
        umount_server
        ;;
esac

log &quot;Dispatcher beendet&quot;
exit 0</code></pre>



<p class="wp-block-paragraph"><strong>/etc/NetworkManager/dispatcher.d/90-webdav-mount</strong>: WebDAV share, which simply requires a reachable cloud server:</p>



<pre class="wp-block-code"><code>#!/bin/bash

DEBUG=1
LOG_TAG=&quot;webdav-mount&quot;

LIB=&quot;/etc/NetworkManager/dispatcher.d/lib/mount-helpers.sh&quot;
if &amp;#91;&amp;#91; -r &quot;$LIB&quot; ]]; then
    source &quot;$LIB&quot;
else
    logger -t &quot;$LOG_TAG&quot; -- &quot;Bibliothek $LIB nicht gefunden, breche ab&quot;
    exit 1
fi

IFACE=&quot;$1&quot;
STATUS=&quot;$2&quot;

MOUNTPOINT=&quot;/mnt/webdav&quot;
HOST=&quot;cloud.example.com&quot;

mount_webdav() {
    if ! tcp_reachable &quot;$HOST&quot; 443 3; then
        log &quot;$HOST auf Port 443 nicht erreichbar, überspringe Mount-Versuch&quot;
        return 1
    fi

    mount_with_retry &quot;$MOUNTPOINT&quot; 3 2 10
}

log &quot;Dispatcher gestartet: Interface=$IFACE, Status=$STATUS&quot;

case &quot;$STATUS&quot; in
    up)
        run_async mount_webdav
        ;;

    pre-down|vpn-pre-down)
        log &quot;Netzwerkverbindung wird beendet – Mount aushängen&quot;
        umount_with_fallback &quot;$MOUNTPOINT&quot; 5
        ;;
esac

log &quot;Dispatcher beendet&quot;
exit 0</code></pre>



<p class="wp-block-paragraph">For both scripts you also need the matching symlinks, so that pre-down is guaranteed to fire before the connection is torn down:</p>



<pre class="wp-block-code"><code>$ sudo ln -s /etc/NetworkManager/dispatcher.d/90-server-mount 
             /etc/NetworkManager/dispatcher.d/pre-down.d/90-server-mount
$ sudo ln -s /etc/NetworkManager/dispatcher.d/90-webdav-mount 
             /etc/NetworkManager/dispatcher.d/pre-down.d/90-webdav-mount</code></pre>



<p class="wp-block-paragraph"><strong>/usr/local/bin/mount-healthcheck.sh</strong>: the safety net that checks regularly:</p>



<pre class="wp-block-code"><code>#!/bin/bash
DEBUG=1
LOG_TAG=&quot;mount-healthcheck&quot;

LIB=&quot;/etc/NetworkManager/dispatcher.d/lib/mount-helpers.sh&quot;
if &amp;#91;&amp;#91; -r &quot;$LIB&quot; ]]; then
    source &quot;$LIB&quot;
else
    logger -t &quot;$LOG_TAG&quot; -- &quot;Bibliothek $LIB nicht gefunden, breche ab&quot;
    exit 1
fi

log &quot;Healthcheck gestartet&quot;

SSID=$(nmcli -t -f active,ssid dev wifi 2&gt;/dev/null |
    awk -F: '$1 == &quot;yes&quot; {print $2; exit}')

if &amp;#91;&amp;#91; &quot;$SSID&quot; == &quot;MeinHeimnetz&quot; ]] || ping -c 1 -W 1 server &gt;/dev/null 2&gt;&amp;1; then
    mount_with_retry &quot;/mnt/server/home&quot; 2 3
    mount_with_retry &quot;/mnt/server/data&quot; 2 3
else
    log &quot;server im aktuellen Netz nicht erreichbar, überspringe&quot;
fi

mount_with_retry &quot;/mnt/webdav&quot; 2 3

log &quot;Healthcheck beendet&quot;
exit 0</code></pre>



<p class="wp-block-paragraph"><strong>/etc/systemd/system/mount-healthcheck.service</strong> and <strong>mount-healthcheck.timer</strong>: systemd units that trigger the health check script 60 seconds after boot and every 10 minutes after that:</p>



<pre class="wp-block-code"><code>&amp;#91;Unit]
Description=Prueft und stellt Netzwerk-Mounts sicher
After=network-online.target
Wants=network-online.target

&amp;#91;Service]
Type=oneshot
TimeoutStartSec=120
ExecStart=/usr/local/bin/mount-healthcheck.sh</code></pre>



<pre class="wp-block-code"><code>&amp;#91;Unit]
Description=Fuehrt den Mount-Healthcheck 60s nach Boot und danach alle 10 Minuten aus

&amp;#91;Timer]
OnBootSec=60s
OnUnitActiveSec=10min
AccuracySec=30s

&amp;#91;Install]
WantedBy=timers.target</code></pre>



<p class="wp-block-paragraph">Don&#8217;t forget to enable it:</p>



<pre class="wp-block-code"><code>$ sudo systemctl daemon-reload
$ sudo systemctl enable --now mount-healthcheck.timer</code></pre>



<p class="wp-block-paragraph"><strong>/usr/lib/systemd/system-sleep/90-cancel-network-mounts</strong>: an optional safety net before suspend:</p>



<pre class="wp-block-code"><code>#!/bin/bash
case &quot;$1/$2&quot; in
    pre/*)
        logger -t sleep-mount-guard &quot;Breche evtl. laufende Netzwerk-Mount-Versuche vor Suspend ab&quot;
        pkill -9 -f 'mount.cifs' 2&gt;/dev/null
        pkill -9 -f 'mount.davfs' 2&gt;/dev/null
        ;;
esac

exit 0</code></pre>



<p class="wp-block-paragraph">All scripts have to be executable:</p>



<pre class="wp-block-code"><code>$ sudo chmod +x /etc/NetworkManager/dispatcher.d/lib/mount-helpers.sh 
              /etc/NetworkManager/dispatcher.d/90-server-mount 
              /etc/NetworkManager/dispatcher.d/90-webdav-mount 
              /usr/local/bin/mount-healthcheck.sh 
              /usr/lib/systemd/system-sleep/90-cancel-network-mounts</code></pre>



<h3 class="wp-block-heading">Long story short</h3>



<p class="wp-block-paragraph">Automatically mounting network shares via NetworkManager works well, but it is not a five-minute job, as the docs might make you think. If you just put the mount command into an up script, sooner or later one of the three problems will catch up with you, usually exactly when you&#8217;re on the road and have no log at hand.</p>



<p class="wp-block-paragraph">With _netdev, correct pre-down timing, asynchronous execution and a real reachability test before every mount, you&#8217;re on the safe side. And the pattern carries over one to one to other network-dependent automations, such as VPN connections or backup jobs that should only run on the right network.</p>
<hr><p>☕ <strong>Support Linux und Ich</strong><br>Thanks for reading <a href="https://linuxundich.de/en/">Linux und Ich</a>. If you enjoy the blog and would like to support my work, you will find more information on the <a href="https://linuxundich.de/en/support/">donation page</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://linuxundich.de/en/mounting-network-shares-automatically-what-can-go-wrong-with-the-networkmanager-dispatcher/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Spotify on GNOME: How to Fix the Blue Window Border</title>
		<link>https://linuxundich.de/en/spotify-on-gnome-how-to-fix-the-blue-window-border/</link>
					<comments>https://linuxundich.de/en/spotify-on-gnome-how-to-fix-the-blue-window-border/#respond</comments>
		
		<dc:creator><![CDATA[Christoph Langner]]></dc:creator>
		<pubDate>Fri, 28 Nov 2025 14:01:59 +0000</pubDate>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Arch Linux]]></category>
		<category><![CDATA[GNOME]]></category>
		<category><![CDATA[Spotify]]></category>
		<category><![CDATA[Tips]]></category>
		<guid isPermaLink="false">https://linuxundich.de/en/?p=58</guid>

					<description><![CDATA[A blue frame around Spotify on GNOME ruins the look, even though everything still works as it should. On Arch Linux, the fix is easy: either go through Flatpak or use a launch flag for the client from the AUR.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">If you use Spotify on Linux with <a href="https://linuxundich.de/tag/gnome/" data-type="post_tag" data-id="1734">GNOME</a>, you may have noticed an ugly blue border around the app window over the last few days. I&#8217;m seeing the problem here on my machine under <a href="https://linuxundich.de/tag/arch/" data-type="post_tag" data-id="1762">Arch Linux</a>, but it should affect all distributions.</p>



<p class="wp-block-paragraph">The culprit is an update to the official Electron-based Linux client that messed up the GTK-style window decoration. <a href="https://linuxundich.de/tag/spotify/" data-type="post_tag" data-id="1480">Spotify</a> itself works just as before, but visually it looks anything but nice.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e493fa2b&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e493fa2b" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="780" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2025/11/spotify-aur-blue-640x390.webp 640w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-aur-blue-768x468.webp 768w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-aur-blue-1280x780.webp 1280w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-aur-blue.webp 1491w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2025/11/spotify-aur-blue-1280x780.webp" alt="Spotify with a blue border. An update to the Linux client broke the GTK-style window decoration, so the window is framed in an ugly blue and isn't displayed correctly." style="width:100%"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Spotify with a blue border. An update to the Linux client broke the GTK-style window decoration, so the window is framed in an ugly blue and isn&#8217;t displayed correctly.</figcaption></figure>



<h2 class="wp-block-heading">Solutions for Spotify</h2>



<p class="wp-block-paragraph">There are two easy ways to fix the problem. The most convenient one is to install Spotify as a <a href="https://flathub.org/en/apps/com.spotify.Client">Flatpak</a>. The Flatpak version doesn&#8217;t show the blue frame, and you don&#8217;t have to worry about anything. No configuration changes are needed.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e493fc9f&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e493fc9f" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="780" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2025/11/spotify-flatpak-640x390.webp 640w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-flatpak-768x468.webp 768w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-flatpak-1280x780.webp 1280w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-flatpak.webp 1491w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2025/11/spotify-flatpak-1280x780.webp" alt="The Flatpak version of Spotify doesn't show the blue frame. The GTK-style window decoration is rendered correctly, and after installation the window looks normal and error-free." style="width:100%"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">The Flatpak version of Spotify doesn&#8217;t show the blue frame. The GTK-style window decoration is rendered correctly, and after installation the window looks normal and error-free.</figcaption></figure>



<p class="wp-block-paragraph">If you installed Spotify via the <a href="https://github.com/kpcyrd/spotify-launcher">Spotify Launcher</a> (the <em>spotify-launcher</em> package from Arch&#8217;s extra repository) or directly from the <a href="https://aur.archlinux.org/packages/spotify">AUR</a> (the <em>spotify</em> entry), you need to set the launch flag <code>--ozone-platform=x11</code> instead. That makes the GTK decoration show up correctly. Depending on how you installed it, add the flag like this:</p>



<p class="wp-block-paragraph"><strong>For AUR Spotify</strong> in the file <code>~/.config/spotify-flags.conf</code>:</p>



<pre class="wp-block-code"><code>--ozone-platform=x11</code></pre>



<p class="wp-block-paragraph"><strong>For Spotify Launcher</strong> in <code>~/.config/spotify-launcher.conf</code>:</p>



<pre class="wp-block-code"><code>&amp;#91;spotify]
extra_arguments = &amp;#91;&quot;--ozone-platform=x11&quot;]</code></pre>



<p class="wp-block-paragraph">You may have to create these files first. After restarting Spotify, the blue frame should be gone and everything should look normal again.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e494000d&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e494000d" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="853" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2025/11/spotify-ozone-platform-640x473.webp 640w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-ozone-platform-768x568.webp 768w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-ozone-platform.webp 1153w" width="1153" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2025/11/spotify-ozone-platform.webp" alt="The configuration files under ~/.config. You may have to create them first. You only need the file that matches your installation method, not both at the same time." style="width:100%"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">The configuration files under ~/.config. You may have to create them first. You only need the file that matches your installation method, not both at the same time.</figcaption></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef7e4940237&quot;}" data-wp-interactive="core/image" data-wp-key="6aef7e4940237" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="780" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2025/11/spotify-flatpak-flags-640x390.webp 640w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-flatpak-flags-768x468.webp 768w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-flatpak-flags-1280x780.webp 1280w, https://linuxundich.de/wp-content/uploads/2025/11/spotify-flatpak-flags.webp 1491w" width="1280" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on--pointerdown="actions.preloadImage" data-wp-on--pointerenter="actions.preloadImageWithDelay" data-wp-on--pointerleave="actions.cancelPreload" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://linuxundich.de/wp-content/uploads/2025/11/spotify-flatpak-flags-1280x780.webp" alt="Alternatively, you can set the flag --ozone-platform=x11 if you installed Spotify from the AUR. The window frame is then displayed correctly and normally again." style="width:100%"/><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			data-wp-bind--aria-label="state.thisImage.triggerButtonAriaLabel"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.thisImage.buttonRight"
			data-wp-style--top="state.thisImage.buttonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Alternatively, you can set the flag &#8211;ozone-platform=x11 if you installed Spotify from the AUR. The window frame is then displayed correctly and normally again.</figcaption></figure>



<p class="has-pale-cyan-blue-background-color has-background wp-block-paragraph"><strong>Correction from <a href="https://social.anoxinon.de/@fabiscafe@mstdn.social/115627842495268735">Fabian on Mastodon</a>:</strong> That&#8217;s not quite right. This is solely down to Spotify running natively on Wayland, where under GNOME it needs a client-side decoration (CSD), which it provides through that blue one. Forcing it back to X11 might cause real problems, like blurry fonts, bad (or no) scaling and so on. Also, Spotify isn&#8217;t Electron, it&#8217;s the Chromium Embedded Framework (CEF).</p>



<p class="wp-block-paragraph">Sure, it&#8217;s a crutch, but one that helps right now. And you can undo the change quickly, too. The other options would be to run GNOME under X11 or to make friends with the blue frames. To me, neither is exactly ideal. So for now this is a workaround, and of course you shouldn&#8217;t forget about it in case Spotify starts acting up again at some point.</p>
<hr><p>☕ <strong>Support Linux und Ich</strong><br>Thanks for reading <a href="https://linuxundich.de/en/">Linux und Ich</a>. If you enjoy the blog and would like to support my work, you will find more information on the <a href="https://linuxundich.de/en/support/">donation page</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://linuxundich.de/en/spotify-on-gnome-how-to-fix-the-blue-window-border/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
