<?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>How-to – Linux und Ich</title>
	<atom:link href="https://linuxundich.de/en/tag/how-to/feed/" rel="self" type="application/rss+xml" />
	<link>https://linuxundich.de/en</link>
	<description>A German Linux blog, in English</description>
	<lastBuildDate>Thu, 22 Oct 2026 08:01:43 +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>PHP2Shell: How to check your Docker containers for the PHP vulnerability</title>
		<link>https://linuxundich.de/en/php2shell-check-docker-containers/</link>
					<comments>https://linuxundich.de/en/php2shell-check-docker-containers/#comments</comments>
		
		<dc:creator><![CDATA[Christoph Langner]]></dc:creator>
		<pubDate>Thu, 22 Oct 2026 07:53:20 +0000</pubDate>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Homelab]]></category>
		<category><![CDATA[How-to]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Server]]></category>
		<guid isPermaLink="false">https://linuxundich.de/en/php2shell-check-docker-containers/</guid>

					<description><![CDATA[The critical PHP vulnerabilities CVE-2026-109618 and CVE-2026-109619 also affect self-hosted services. A small loop shows which Docker containers still ship a vulnerable PHP version.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Since October 21, PHP2Shell has been all over the news. Behind the catchy name are two vulnerabilities in PHP, CVE-2026-109618 and CVE-2026-109619, which let attackers run code on a web server with a crafted HTTP request, no login required. The PHP developers rate both at 9.2 under CVSS 4.0, and according to <a href="https://watchtowr.com/intelligence/php-cve-2026-109618-faq/">watchTowr</a> the flaw is already being exploited. If you self-host, now is the time to take a look.</p>



<p class="wp-block-paragraph">The holes are plugged in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. For PHP 8.1 and older there are no regular releases with the fix so far, so the only way out is moving to a supported branch. On a regular server, the package manager takes care of that. Docker is a different story: every container brings its own PHP, and that PHP stays exactly as old as the image.</p>



<h2 class="wp-block-heading">Which container runs which PHP?</h2>



<p class="wp-block-paragraph">So the first question is: which containers on my little home server actually contain PHP? For Nextcloud or WordPress that&#8217;s obvious, for self-built images or small web apps less so. Instead of going through every container by hand, the following loop asks all running containers for their PHP version and compares it with the patched releases right away.</p>



<pre data-lui-file="php2shell-check.sh" class="wp-block-code"><code>for c in $(docker ps --format '{{.Names}}'); do
  v=$(docker exec &quot;$c&quot; php -r 'echo PHP_VERSION;' 2&gt;/dev/null) || continue
  case &quot;${v%.*}&quot; in
    8.5) fix=8.5.12 ;;
    8.4) fix=8.4.27 ;;
    8.3) fix=8.3.36 ;;
    8.2) fix=8.2.35 ;;
    *)   fix=99 ;;
  esac
  if [ &quot;$(printf '%s\n' &quot;$fix&quot; &quot;$v&quot; | sort -V | head -n1)&quot; = &quot;$fix&quot; ]; then
    printf '\e[32m%-30s %-8s ok\e[0m\n' &quot;$c&quot; &quot;$v&quot;
  else
    printf '\e[31m%-30s %-8s anfällig?\e[0m\n' &quot;$c&quot; &quot;$v&quot;
  fi
done</code></pre>



<p class="wp-block-paragraph">The loop silently skips containers without PHP. For all others, the version shows up in green if it is at least at the patch level and in red if it is below. PHP 8.1, 7.x and older also end up in red, because there simply is no fix for them. The red lines say “anfällig?”, German for “vulnerable?”. On my server, the result looks like this:</p>



<pre class="wp-block-code"><code>$ ./php2shell-simple.sh
nextcloud-app-1                8.5.12   ok
nextcloud-cron-1               8.5.12   ok
linuxundich-test-wordpress-1   8.3.36   ok
planetfoss-web                 8.3.33   anfällig?
sisu-web                       8.4.26   anfällig?</code></pre>



<p class="wp-block-paragraph">So Nextcloud and the test WordPress had already pulled their updates, while PlanetFOSS and the site for Sisu were still lagging behind. By the way, the question mark after “vulnerable” is on purpose. The loop only compares version numbers. If an image uses the PHP package from Debian, Ubuntu or Alpine, the fix may have been backported without the number changing. In that case, only the distribution&#8217;s security advisories can tell you more.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212baa43&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212baa43" class="wp-block-image wp-lightbox-container"><img fetchpriority="high" decoding="async" height="877" width="1397" 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/php2shell-simple.webp" alt="Split terminal window on bender: on the left the script php2shell-simple.sh with line numbers, on the right its output with green and red container names and their PHP versions"/><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 loop as a small script on the left, its output on the right: planetfoss-web and sisu-web show up in red, the rest in green.</figcaption></figure>



<p class="wp-block-paragraph">For a closer look, there is <a href="https://github.com/EXT-IT/php2shell-check">php2shell-check</a> by EXT IT. The MIT-licensed script is read-only and judges PHP by package versions rather than just the version number, so it also takes backported fixes into account. It looks into Docker containers, FPM pools and old processes that are still running, and on request sends a harmless request to your website. For the containers it needs root or membership in the docker group.</p>



<p class="wp-block-paragraph">The project page suggests the usual one-liner with <code>curl</code> and <code>sudo bash</code>. For a script that runs with root privileges on my server, I&#8217;m not too fond of that. Better download the script together with <code>SHA256SUMS</code> from the releases, check it with <code>sha256sum -c SHA256SUMS</code>, skim through it once and then start it by hand. According to the developers, a “not vulnerable” is no guarantee, by the way:</p>



<pre class="wp-block-code"><code>$ sudo bash php2shell-check.sh https://eure-seite.example</code></pre>



<p class="wp-block-paragraph">On my home server I ran the script with sudo. As a member of the docker group it would see the containers without root as well, but running processes of other users and some logs would stay hidden. This is how I fetched and started it:</p>



<pre class="wp-block-code"><code>$ curl -fsSLO https://github.com/EXT-IT/php2shell-check/releases/latest/download/php2shell-check.sh
$ chmod +x php2shell-check.sh 
$ sudo ./php2shell-check.sh </code></pre>



<p class="wp-block-paragraph">The verdict matches the loop: planetfoss-web with PHP 8.3.33 and sisu-web with PHP 8.4.26 are vulnerable, Nextcloud and the test WordPress are not. On top of that, it found a stopped container from Tuxsucht that my loop had completely missed:</p>



<pre class="wp-block-code"><code>PHP in docker containers
  [ OK ] container      nextcloud-app-1 (nextcloud:35-apache)
         PHP 8.5.12 (fixed from 8.5.12)
[...]
  [VULN] container      planetfoss-web (planetfoss-web:local)
         PHP 8.3.33, fixed in 8.3.36
         -&gt; Update PHP to 8.3.36 or later (container: pull the new image and recreate)
[...]
  [VULN] container      sisu-web (sisu-web:local)
         PHP 8.4.26, fixed in 8.4.27
[...]
  [WARN] container      php83 (stopped, tuxsucht-php)
         stopped, but its image ships PHP 8.3.33: it comes back vulnerable on the next start
[...]
Summary  2 vulnerable, 3 undecided, 12 warnings, 11 ok</code></pre>



<p class="wp-block-paragraph">Sure, <code>docker ps</code> only lists running containers, and a stopped container doesn&#8217;t accept any requests. But if someone starts it again at some point, the hole is back right away. The script is also very clear about mod_php: all five running containers serve PHP through the Apache module, and the advisory demonstrates a complete attack without login against exactly this setup.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212bb046&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212bb046" class="wp-block-image wp-lightbox-container"><img decoding="async" height="877" width="1397" 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/php2shell-check.webp" alt="Terminal window with the output of php2shell-check on bender: color-coded VULN, WARN and OK entries for the containers planetfoss-web, sisu-web and php83"/><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">php2shell-check flags sisu-web as vulnerable, warns about mod_php and also finds the stopped container php83 with an old PHP.</figcaption></figure>



<p class="wp-block-paragraph">Until you can update, the script suggests a stopgap: set <code>session.upload_progress.enabled=0</code> and <code>expose_php=0</code>, and keep <code>post_max_size</code> below a quarter of <code>memory_limit</code>. The check from the outside, on the other hand, wasn&#8217;t much help. For the two websites, the script only reports that the headers don&#8217;t reveal a PHP version and that there is no WAF in front. That says nothing about the patch level, which the script honestly admits.</p>



<h2 class="wp-block-heading">And how do you update PHP?</h2>



<p class="wp-block-paragraph">Don&#8217;t update anything inside the container itself, it would be gone again with the next recreate. Instead, pull the new image in the respective Compose directory and recreate the container with it. For self-built images with their own Dockerfile you need <code>docker compose build --pull</code>, so that Docker also fetches a fresh base image:</p>



<pre class="wp-block-code"><code>docker compose pull &amp;&amp; docker compose up -d</code></pre>



<p class="wp-block-paragraph">Important: of course this only helps if the base image already contains the patched version. According to <a href="https://www.it-connect.tech/php2shell-and-docker-how-to-check-and-update-your-php-containers/">IT-Connect</a>, the new tags initially even showed up without an image behind them, but by now generic tags such as <code>php:8.3-apache</code> ship the patched PHP. If your Dockerfile pins a fixed version like <code>php:8.4.24-fpm</code>, you have to bump it yourself. Simply run the loop again after the update. Take care of the containers that are reachable from the internet first.</p>



<p class="wp-block-paragraph">The PlanetFOSS test environment shows what this looks like in practice. Its image is based on <code>php:8.3-apache</code>, and the Dockerfile only adds extensions such as GD and Intl. My deploy script does call <code>docker compose up -d --build</code>, but that doesn&#8217;t fetch a new base image, it takes the one from August out of the cache. That&#8217;s where the old PHP 8.3.33 came from. Only <code>--pull</code> fetches the fresh version:</p>



<pre class="wp-block-code"><code>$ cd /data/docker/planetfoss
$ docker compose build --pull web
$ docker compose up -d web</code></pre>



<p class="wp-block-paragraph">After a good minute the new image was ready, and the container ran PHP 8.3.36. The database in the same Compose project stays untouched, because both commands only address the web service. Afterwards the loop shows PlanetFOSS in green, and php2shell-check also reports only sisu-web as vulnerable. The old image is still lying around on disk as a leftover, by the way; <code>docker image prune</code> cleans it up.</p>



<pre class="wp-block-code"><code>$ ./php2shell-simple.sh
[...]
nextcloud-cron-1               8.5.12   ok
linuxundich-test-wordpress-1   8.3.36   ok
sisu-web                       8.4.26   anfällig?</code></pre>



<p class="wp-block-paragraph">All in all, PHP2Shell is a good example of how self-hosting with Docker is convenient, but the updates don&#8217;t come by themselves. heise has collected <a href="https://www.heise.de/en/news/php2shell-Critical-flaws-allow-code-injection-in-PHP-11494897.html">more details on the vulnerabilities</a>. How to keep containers up to date without a lot of fiddling, I covered in <a href="https://linuxundich.de/en/keeping-docker-containers-up-to-date-with-dockcheck/">Keeping Docker containers up to date with Dockcheck</a>. How do you keep your containers up to date?</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/php2shell-check-docker-containers/feed/</wfw:commentRss>
			<slash:comments>1</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;6aef8212bf29e&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;6aef8212bf358&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212bf358" class="wp-block-image size-large wp-lightbox-container"><img decoding="async" height="1024" sizes="(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;6aef8212bf60a&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212bf60a" 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;6aef8212bf8a9&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212bf8a9" 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>Adding Custom Locations to GNOME Weather</title>
		<link>https://linuxundich.de/en/adding-custom-locations-to-gnome-weather/</link>
					<comments>https://linuxundich.de/en/adding-custom-locations-to-gnome-weather/#respond</comments>
		
		<dc:creator><![CDATA[Christoph Langner]]></dc:creator>
		<pubDate>Mon, 31 Mar 2025 07:13:54 +0000</pubDate>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[GNOME]]></category>
		<category><![CDATA[How-to]]></category>
		<guid isPermaLink="false">https://linuxundich.de/en/?p=72</guid>

					<description><![CDATA[GNOME Weather doesn't list many smaller places. A script lets you add the missing towns and cities yourself, without waiting for an official update.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">If you live in a bigger city like Berlin, Munich, London, or New York, you&#8217;ll have no trouble finding your location in GNOME Weather. Just open the app, type the city into the location picker, and you&#8217;re done. It gets harder with smaller places. GNOME Weather offers no convenient way to add them manually. A small script gets around the problem, though.</p>



<h3 class="wp-block-heading">Why are so many places missing from GNOME Weather?</h3>



<p class="wp-block-paragraph">GNOME uses the <a href="https://gitlab.gnome.org/GNOME/libgweather">libgweather</a> library for location selection. It contains a large database of cities and weather stations. The location data lives in the file <a href="https://gitlab.gnome.org/GNOME/libgweather/-/blob/main/data/Locations.xml">Locations.xml</a>. On top of that, libgweather can use OpenStreetMap&#8217;s Nominatim geocoding service to search over the internet.</p>



<p class="wp-block-paragraph">Not every place makes it into the static database, though. As a rule of thumb, GNOME names cities with at least 100,000 inhabitants. The limit isn&#8217;t rigid: smaller places can be included too, for example if they have regional importance or if there is no larger city nearby that could serve as an alternative. GNOME describes the current criteria and how to contribute <a href="https://gnome.pages.gitlab.gnome.org/libgweather/adding-locations.html">in its documentation</a>.</p>



<p class="has-pale-cyan-blue-background-color has-background wp-block-paragraph"><strong>UPDATE August 12, 2026:</strong> The original script is offline by now. I therefore point to a current fork that is available as a gist on GitHub.</p>



<p class="wp-block-paragraph">If you still want to use your small hometown directly in GNOME Weather, you can fall back on a script. The original script by <a href="https://gitlab.com/julianfairfax">Julian Fairfax</a> is no longer available. A maintained fork exists, though, <a href="https://gist.github.com/dotbanana/1dc4d95d644ce72ab8741d6886b86acc">as a gist on GitHub</a>. The script looks up the place you want via OpenStreetMap and then adds it to the GNOME Weather settings.</p>



<h3 class="wp-block-heading">Adding your own locations to GNOME Weather</h3>



<p class="wp-block-paragraph">You don&#8217;t need to install the script, since you&#8217;ll usually only need it once. First download it from the gist, then make it executable:</p>



<pre class="wp-block-code"><code>$ &lt;strong&gt;wget https://gist.githubusercontent.com/dotbanana/1dc4d95d644ce72ab8741d6886b86acc/raw/add-location-to-gnome-weather.sh&lt;/strong&gt;
$ &lt;strong&gt;chmod +x add-location-to-gnome-weather.sh&lt;/strong&gt;</code></pre>



<p class="wp-block-paragraph">Then run the script:</p>



<pre class="wp-block-code"><code>$ &lt;strong&gt;./add-location-to-gnome-weather.sh&lt;/strong&gt;</code></pre>



<p class="wp-block-paragraph">The script asks for the place you want and runs a search via Nominatim. It then shows you the entry it found, so you can check whether it picked the right place:</p>



<pre class="wp-block-code"><code>$ &lt;strong&gt;./add-location-to-gnome-weather.sh&lt;/strong&gt;
Type the name of the location you want to add to GNOME Weather: Ravensburg
If this is not the location you wanted, consider adding search terms
Are you sure you want to add Ravensburg, Verwaltungsverband Mittleres Schussental, Landkreis Ravensburg, Baden-Württemberg, Deutschland? &amp;#91;y/n] : y
Adding location</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212c2c93&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212c2c93" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="735" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2025/03/gnome-wetter-ravensburg-640x368.webp 640w, https://linuxundich.de/wp-content/uploads/2025/03/gnome-wetter-ravensburg-768x441.webp 768w, https://linuxundich.de/wp-content/uploads/2025/03/gnome-wetter-ravensburg-1280x735.webp 1280w, https://linuxundich.de/wp-content/uploads/2025/03/gnome-wetter-ravensburg-1536x882.webp 1536w, https://linuxundich.de/wp-content/uploads/2025/03/gnome-wetter-ravensburg.webp 1706w" 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/03/gnome-wetter-ravensburg-1280x735.webp" alt="Location successfully added to GNOME Weather." 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">Location successfully added to GNOME Weather.</figcaption></figure>



<p class="wp-block-paragraph">After you confirm, the script creates the location directly in the GNOME Weather settings. The current fork supports both a regular installation and the Flatpak version of GNOME Weather. Afterwards, the new location should show up in the app&#8217;s location list.</p>



<h3 class="wp-block-heading">How does GNOME Weather store locations?</h3>



<p class="wp-block-paragraph">The locations selected in GNOME Weather are stored via GSettings. The script sets the key <code>org.gnome.Weather locations</code>. For a regular installation it uses <code>gsettings</code>; for the Flatpak version it runs the command inside the Flatpak environment.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212c2f6c&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212c2f6c" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="944" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2025/03/gnome-weather-dconf-640x496.webp 640w, https://linuxundich.de/wp-content/uploads/2025/03/gnome-weather-dconf-768x595.webp 768w, https://linuxundich.de/wp-content/uploads/2025/03/gnome-weather-dconf.webp 1218w" width="1218" 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/03/gnome-weather-dconf.webp" alt="Editing GNOME Weather's location data in dconf." 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">Editing GNOME Weather&#8217;s location data in dconf.</figcaption></figure>



<p class="wp-block-paragraph">If you want to remove a location added this way, you can edit the stored settings with the <em>dconf Editor</em>, for example. The relevant entry is located at <code>org.gnome.Weather</code>. The format of the stored location data isn&#8217;t exactly user-friendly, so be careful when you do this.</p>



<p class="wp-block-paragraph">The current solution isn&#8217;t particularly elegant, but it works reliably. GNOME has since extended the location database with an online search via Nominatim, so the library can also find places that aren&#8217;t in the static database. The script uses exactly that and then transfers the place it found into the settings GNOME Weather uses.</p>



<p class="wp-block-paragraph">The fork by <a href="https://gist.github.com/dotbanana/1dc4d95d644ce72ab8741d6886b86acc">dotbanana</a> is therefore a practical solution for everyone whose hometown can&#8217;t be selected through GNOME Weather&#8217;s regular search. Since both GNOME Weather and libgweather keep evolving, this behavior may change in the future. As of now, the script also works with the Flatpak version of GNOME Weather.</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/adding-custom-locations-to-gnome-weather/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Custom Nautilus scripts: Convert images to WebP</title>
		<link>https://linuxundich.de/en/custom-nautilus-scripts-convert-images-to-webp/</link>
					<comments>https://linuxundich.de/en/custom-nautilus-scripts-convert-images-to-webp/#respond</comments>
		
		<dc:creator><![CDATA[Christoph Langner]]></dc:creator>
		<pubDate>Sun, 16 Mar 2025 09:02:56 +0000</pubDate>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[GNOME]]></category>
		<category><![CDATA[How-to]]></category>
		<category><![CDATA[Nautilus]]></category>
		<category><![CDATA[Shell Scripts]]></category>
		<guid isPermaLink="false">https://linuxundich.de/en/?p=88</guid>

					<description><![CDATA[Nautilus scripts can make your GNOME desktop a lot more efficient. This example lets you convert images to WebP right in the file manager, without opening a separate image editor.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I use the GNOME desktop every day and appreciate its minimalist design. Still, some features are missing that could make my workflow more efficient, like running certain tasks straight from the file manager with a single click. Nautilus scripts make that easy to fix.</p>



<p class="wp-block-paragraph">In this post, I&#8217;ll show you how to create such a script. As an example, I want to demonstrate how to convert images to WebP without having to open an image editor. For that, I use <code>cwebp</code>, a powerful tool for converting images to the WebP format, and Zenity to provide a graphical dialog for entering image sizes.</p>



<figure class="wp-block-video"><video controls src="https://linuxundich.de/wp-content/uploads/2025/03/ConvertToWebP.webm"></video></figure>



<h3 class="wp-block-heading" id="warum-webp">Why WebP?</h3>



<p class="wp-block-paragraph">WebP is a modern image format that compresses better than JPG or PNG without noticeably hurting image quality. It is especially useful for web developers and bloggers, since it reduces page load times and improves performance.</p>



<h3 class="wp-block-heading" id="vorbereitung-benötigte-pakete-installieren">Preparation: Installing the required packages</h3>



<p class="wp-block-paragraph">Before you start with the script, make sure the required programs are installed. If they aren&#8217;t, you can install them on Debian-based distributions like Ubuntu or TUXEDO OS with the following command:</p>



<pre class="wp-block-code"><code>### Unter Arch Linux, Manjaro und Co.
$ &lt;strong&gt;sudo pacman -S libwebp zenity&lt;/strong&gt;
### Unter Ubuntu, Debian und Co.
$ &lt;strong&gt;sudo apt install webp zenity&lt;/strong&gt;</code></pre>



<h3 class="wp-block-heading" id="erstellung-des-skripts-zur-webp-konvertierung">Creating the WebP conversion script</h3>



<p class="wp-block-paragraph">Create a new script in the Nautilus scripts folder:</p>



<pre class="wp-block-code"><code>$ &lt;strong&gt;mkdir -p ~/.local/share/nautilus/scripts&lt;/strong&gt;
$ &lt;strong&gt;gedit ~/.local/share/nautilus/scripts/ConvertToWebP&lt;/strong&gt;</code></pre>



<p class="wp-block-paragraph">Now paste the following code into the file and save it:</p>



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

# Überprüfen, ob cwebp und zenity installiert sind
if ! command -v cwebp &amp;&gt; /dev/null; then
    zenity --error --text=&quot;cwebp ist nicht installiert.&quot;
    exit 1
fi

# Benutzer nach Breite und Höhe fragen
input=$(zenity --forms --title=&quot;Bildkonvertierung nach WebP&quot; 
    --text=&quot;Gebt die gewünschte Breite und Höhe ein (0 für Originalgröße):&quot; 
    --add-entry=&quot;Breite&quot; 
    --add-entry=&quot;Höhe&quot;)

# Falls der Benutzer abbricht, das Skript beenden
if &amp;#91; -z &quot;$input&quot; ]; then
    exit 1
fi

width=$(echo &quot;$input&quot; | cut -d '|' -f1)
height=$(echo &quot;$input&quot; | cut -d '|' -f2)

# Falls keine Werte eingegeben wurden, Standardwerte setzen
width=${width:-0}
height=${height:-0}

# Alle ausgewählten Dateien verarbeiten
for file in &quot;$@&quot;; do
    if &amp;#91; -f &quot;$file&quot; ]; then
        output=&quot;${file%.*}.webp&quot;
        
        if &amp;#91;&amp;#91; &quot;$width&quot; -eq 0 &amp;&amp; &quot;$height&quot; -eq 0 ]]; then
            # Keine Skalierung, direkt konvertieren
            cwebp &quot;$file&quot; -o &quot;${file%.*}.webp&quot; &gt;/dev/null 2&gt;&amp;1
        else
            cwebp -resize &quot;$width&quot; &quot;$height&quot; &quot;$file&quot; -o &quot;${file%.*}.webp&quot; &gt;/dev/null 2&gt;&amp;1
        fi
    fi
done</code></pre>



<h3 class="wp-block-heading" id="rechte-setzen">Setting permissions</h3>



<p class="wp-block-paragraph">For the script to run, it has to be marked as executable. You do that with:</p>



<pre class="wp-block-code"><code>$ &lt;strong&gt;chmod +x ~/.local/share/nautilus/scripts/ConvertToWebP&lt;/strong&gt;</code></pre>



<h3 class="wp-block-heading" id="skript-in-nautilus-einbinden">Using the script in Nautilus</h3>



<p class="wp-block-paragraph">Once the script is created, it is available right away in the Nautilus file manager. Select one or more images, right-click them, go to <em>Scripts</em>, and choose <em>ConvertToWebP</em>.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212d2474&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212d2474" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="759" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2025/03/nautilus-skripte-ConvertToWebP1-640x423.webp 640w, https://linuxundich.de/wp-content/uploads/2025/03/nautilus-skripte-ConvertToWebP1-768x507.webp 768w, https://linuxundich.de/wp-content/uploads/2025/03/nautilus-skripte-ConvertToWebP1.webp 1149w" width="1149" 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/03/nautilus-skripte-ConvertToWebP1.webp" alt="The script shows up in the Scripts menu of the Nautilus file manager right after you save it." 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 script shows up in the Scripts menu of the Nautilus file manager right after you save it.</figcaption></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212d2bb6&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212d2bb6" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="759" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2025/03/nautilus-skripte-ConvertToWebP2-640x423.webp 640w, https://linuxundich.de/wp-content/uploads/2025/03/nautilus-skripte-ConvertToWebP2-768x507.webp 768w, https://linuxundich.de/wp-content/uploads/2025/03/nautilus-skripte-ConvertToWebP2.webp 1149w" width="1149" 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/03/nautilus-skripte-ConvertToWebP2.webp" alt="Zenity asks for the target image size. If the size should stay the same, leave the fields empty or enter 0." 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">Zenity asks for the target image size. If the size should stay the same, leave the fields empty or enter 0.</figcaption></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212d30be&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212d30be" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="762" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2025/03/nautilus-skripte-ConvertToWebP3-640x420.webp 640w, https://linuxundich.de/wp-content/uploads/2025/03/nautilus-skripte-ConvertToWebP3-768x504.webp 768w, https://linuxundich.de/wp-content/uploads/2025/03/nautilus-skripte-ConvertToWebP3.webp 1160w" width="1160" 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/03/nautilus-skripte-ConvertToWebP3.webp" alt="Converted to WebP, the images are only 1/10 to 1/20 of their original file size at the same dimensions." 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">Converted to WebP, the images are only 1/10 to 1/20 of their original file size at the same dimensions.</figcaption></figure>



<p class="wp-block-paragraph">The script now converts all selected image files in common formats to WebP and reduces their size while keeping the aspect ratio. If <code>cwebp</code> is not installed, it shows an error message. Alternatively, you can enter the target width and height in pixels.</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/custom-nautilus-scripts-convert-images-to-webp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://linuxundich.de/wp-content/uploads/2025/03/ConvertToWebP.webm" length="0" type="video/webm" />

			</item>
		<item>
		<title>PiShrink Shrinks Raspberry Pi Images</title>
		<link>https://linuxundich.de/en/pishrink-shrinks-raspberry-pi-images/</link>
					<comments>https://linuxundich.de/en/pishrink-shrinks-raspberry-pi-images/#respond</comments>
		
		<dc:creator><![CDATA[Christoph Langner]]></dc:creator>
		<pubDate>Mon, 27 Feb 2017 19:31:28 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[dd]]></category>
		<category><![CDATA[Hard Drive]]></category>
		<category><![CDATA[How-to]]></category>
		<guid isPermaLink="false">https://linuxundich.de/en/pishrink-shrinks-raspberry-pi-images/</guid>

					<description><![CDATA[PiShrink shrinks the image of a Raspberry Pi SD card to the space actually used and automatically expands the system again on first boot.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In an earlier article, I described how to back up and restore a Raspberry Pi installation from its memory card – no shit, Sherlock. One question came up again and again, though: the image file ends up exactly as large as the memory card, even if there&#8217;s still plenty of free space on it. The &#8220;empty&#8221; area is more or less packed into the image as well. As a result, the new memory card has to be at least as large as the old one. In addition, an image intended for archiving takes up a lot of storage space. So how do you let the air out of a Raspberry Pi image?</p>



<span id="more-156"></span>



<p class="wp-block-paragraph">On GitHub, I recently stumbled across <a href="https://github.com/Drewsif/PiShrink/">the PiShrink script</a>, which does exactly that. The little program takes a Pi image, reduces the partition size to the necessary minimum and also adds a script to the archived system that automatically expands the partition to the maximum available space on the next boot on real hardware. This way, you can quickly shrink the image of a Raspbian system from several gigabytes to a few hundred megabytes – without much effort. You also save time when restoring, since the file system automatically expands to its full size again the first time the Raspberry Pi boots.</p>



<pre class="wp-block-code"><code>$ <strong>mkdir ~/bin</strong>
$ <strong>wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh -P ~/bin</strong>
$ <strong>chmod +x ~/bin/pishrink.sh</strong></code></pre>



<p class="wp-block-paragraph">Since PiShrink is a simple Bash script, installing it isn&#8217;t particularly complicated: you just download the script and set the execute permission. Personally, I put scripts like this in the <code>~/bin</code> directory in my home folder. The system should automatically add this folder to your user&#8217;s <code>$PATH</code>, so you can run the command from anywhere without specifying a path. If that&#8217;s not the case for you, there are plenty of guides online on <a href="https://askubuntu.com/questions/60218/how-to-add-a-directory-to-the-path">extending the environment variable</a> (the linked article refers to Ubuntu, but the procedure is very similar on other distributions).</p>



<h2 class="wp-block-heading">PiShrink compresses Raspberry Pi images</h2>



<p class="wp-block-paragraph">You should now be able to call the PiShrink script directly in the terminal with a bold <code>pishrink.sh</code>. Without an image, the script merely shows its syntax. In the end, calling it comes down to specifying an image file and, optionally, a second file name if PiShrink should leave the original Raspberry Pi image untouched. If you only specify one file name, PiShrink edits that image directly.</p>



<p class="wp-block-paragraph">The only switch, <code>-s</code>, matters if you want to shrink the image of a Pi system that isn&#8217;t based on Raspbian – for example the Kodi distributions LibreELEC or OpenELEC. More precisely, the switch tells PiShrink not to expand the system automatically on the next boot. To do this, PiShrink normally adds a command to the <code>/etc/rc.local</code> file, which Raspbian runs automatically at boot. However, this file doesn&#8217;t exist on LibreELEC (and some other distributions).</p>



<pre class="wp-block-code"><code>### Show PiShrink's help:
$ <strong>pishrink.sh</strong>
Usage: /home/toff/bin/pishrink.sh &#91;-s] imagefile.img &#91;newimagefile.img]
### Shrink an existing Pi image:
$ <strong>sudo pishrink.sh raspberry-pi.img</strong>
### Shrink the image and keep the original:
$ <strong>sudo pishrink.sh raspberry-pi.img raspberry-pi_pishrink.img</strong>
### Disable automatic expansion of the partition:
$ <strong>sudo pishrink.sh -s raspberry-pi.img raspberry-pi_small.img</strong></code></pre>



<p class="wp-block-paragraph">So how does it all come together? As an example, I&#8217;m using a current installation of Raspbian Lite on a 16 GB SD card. You insert it into the card reader, determine the device ID with <code>lsblk</code> and then back up the image to the hard disk with <code>dd</code>. The image file then sits on the hard disk as <code>raspberry-pi.img</code>, around 16 GB in size – even though the image is actually mostly empty. Apart from the Raspbian system and a few configuration files, there&#8217;s no other data on the system.</p>



<pre class="wp-block-code"><code>$ <strong>lsblk</strong>
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
&#91;...]
sdd      8:48   1  14.9G  0 disk
├─sdd1   8:49   1    63M  0 part /run/media/&#91;...]/boot
└─sdd2   8:50   1  14.8G  0 part /run/media/&#91;...]/0aed834e-8c8f-412d-a276-a26
$ <strong>sudo dd if=/dev/sdd of=~/raspberry-pi.img</strong>
15894831104 bytes (16 GB, 15 GiB) copied, 210 s, 75.7 MB/s
31116288+0 records in
31116288+0 records out
15931539456 bytes (16 GB, 15 GiB) copied, 210.459 s, 75.7 MB/s
$ <strong>ls -alh ~/raspberry-pi.img</strong>
-rw-r--r-- 1 root root 15G Feb 24 21:48 raspberry-pi.img</code></pre>



<p class="wp-block-paragraph">Then you call PiShrink accordingly – since this is a Raspbian system, I leave out the <code>-s</code> option. PiShrink first copies the image (so make sure there&#8217;s enough free space), mounts the copy in a temporary directory under <code>/tmp</code> and then reduces the size of the image: from just under 16 GB originally to only about 1.6 GB. The effect you achieve naturally depends on how much real data was stored on the Raspberry Pi&#8217;s SD card.</p>



<pre class="wp-block-code"><code>$ <strong>sudo pishrink.sh raspberry-pi.img raspberry-pi_pishrink.img</strong>
Copying raspberry-pi.img to raspberry-pi_pishrink.img...
Creating new /etc/rc.local
e2fsck 1.43.4 (31-Jan-2017)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/loop2: 35832/959616 files (0.2% non-contiguous), 321790/3872384 blocks
resize2fs 1.43.4 (31-Jan-2017)
resize2fs 1.43.4 (31-Jan-2017)
Resizing the filesystem on /dev/loop2 to 382429 (4k) blocks.
Begin pass 2 (max = 40814)
Relocating blocks             XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 3 (max = 119)
Scanning inode table          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 4 (max = 3178)
Updating inode references     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/loop2 is now 382429 (4k) blocks long.

Shrunk raspberry-pi_pishrink.img from 15G to 1.6G
$ <strong>ls -alh raspberry-pi*</strong>
-rw-r--r-- 1 root root  15G Feb 27 11:08 raspberry-pi.img
-rw-r--r-- 1 root root 1.6G Feb 27 11:30 raspberry-pi_pishrink.img
</code></pre>



<h2 class="wp-block-heading">Restoring a shrunk Pi image</h2>



<p class="wp-block-paragraph">As a test, the Raspbian system originally installed on a 16 GB SD card is to move to a microSD card with only 8 GB. To do this, I write the image shrunk with PiShrink back to the new card with <code>dd</code>, insert it into the Raspberry Pi and boot the shrunk system. To make full use of the available storage space, the system automatically reboots once during the first boot. After that, you land in the familiar Raspbian system – a <code>df -h</code> shows that the system now uses the entire SD card.</p>



<pre class="wp-block-code"><code>$ <strong>lsblk</strong>
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
&#91;...]
sdd      8:48   1   7.4G  0 disk
├─sdd1   8:49   1    63M  0 part /run/media/&#91;...]/boot
└─sdd2   8:50   1   7.3G  0 part /run/media/&#91;...]/0aed834e-8c8f-412d-a276-a26
$ <strong>sudo dd if=raspberry-pi_pishrink.img of=/dev/sdd bs=1M; sync</strong>
1560+1 records in
1560+1 records out
1636684288 bytes (1.6 GB, 1.5 GiB) copied, 116.203 s, 14.1 MB/s</code></pre>



<pre class="wp-block-code"><code>pi@raspberrypi:~ $ <strong>df -h</strong>
Filesystem      Size  Used Avail Use% Mounted on
/dev/root       7.2G  990M  6.0G  14% /
devtmpfs        459M     0  459M   0% /dev
tmpfs           463M     0  463M   0% /dev/shm
tmpfs           463M  6.2M  457M   2% /run
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
tmpfs           463M     0  463M   0% /sys/fs/cgroup
/dev/mmcblk0p1   63M   21M   42M  33% /boot</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212d64cc&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212d64cc" class="wp-block-image size-full wp-lightbox-container"><img loading="lazy" decoding="async" height="845" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2017/02/pishrink-beispiel-640x465.png 640w, https://linuxundich.de/wp-content/uploads/2017/02/pishrink-beispiel-768x558.png 768w, https://linuxundich.de/wp-content/uploads/2017/02/pishrink-beispiel.png 1164w" width="1164" 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/2017/02/pishrink-beispiel.png" alt="PiShrink running in the terminal; the file manager next to it shows the original at 15.9 GB and the shrunk copy at 811 MB." 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">PiShrink reduces the image of a Raspberry Pi system to its minimum size.</figcaption></figure>



<p class="wp-block-paragraph">If you back up a Raspberry Pi system that isn&#8217;t based on Raspbian and has no <code>/etc/rc.local</code> – such as the Kodi distributions LibreELEC or OpenELEC mentioned above – error messages appear when shrinking it with PiShrink. The reason: by default, PiShrink tries to add a command to this file that later expands the partition automatically. To avoid this, you have to use the <code>-s</code> option. That way, you can shrink the image successfully even without an <code>rc.local</code>.</p>



<pre class="wp-block-code"><code>### Error messages when shrinking a LibreELEC image:
$ <strong>sudo pishrink.sh libreelec.img</strong>
&#91;...]
md5sum: /tmp/tmp.4ornQ3Va4y/etc/rc.local: No such file or directory
/home/&#91;...]/bin/pishrink.sh: line 63: &#91;: !=: unary operator expected
&#91;...]
### LibreELEC, OpenELEC and co. are better shrunk like this:
$ <strong>sudo pishrink.sh -s libreelec.img</strong>
Skipping autoexpanding process...
e2fsck 1.43.4 (31-Jan-2017)
/dev/loop2: recovering journal
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/loop2: 861/1810432 files (1.0% non-contiguous), 252448/7235584 blocks
resize2fs 1.43.4 (31-Jan-2017)
resize2fs 1.43.4 (31-Jan-2017)
Resizing the filesystem on /dev/loop2 to 49976 (1k) blocks.
Begin pass 2 (max = 15759)
Relocating blocks             XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 3 (max = 884)
Scanning inode table          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 4 (max = 143)
Updating inode references     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/loop2 is now 49976 (1k) blocks long.

Shrunk libreelec.img from 7.5G to 563M</code></pre>



<p class="wp-block-paragraph">However, the restored system then doesn&#8217;t expand automatically, because LibreELEC (and, as far as I know, OpenELEC too) offers no option in its menus to manually expand the data partition to the full card size. The internal resizing routine only kicks in on a freshly copied first installation, as you can see in the <a href="https://github.com/LibreELEC/LibreELEC.tv/blob/master/packages/sysutils/busybox/scripts/fs-resize">script</a>. To make full use of the partition anyway, the only option is to fix it up manually with a partitioning tool such as GParted. On Linux, GParted is readily available; Windows users can use the tool via a <a href="https://gparted.org/liveusb.php">live CD or live USB stick</a>.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212d6905&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212d6905" class="wp-block-image size-full wp-lightbox-container"><img loading="lazy" decoding="async" height="725" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2017/02/gparted-partition-vergroessern-640x511.png 640w, https://linuxundich.de/wp-content/uploads/2017/02/gparted-partition-vergroessern-768x613.png 768w, https://linuxundich.de/wp-content/uploads/2017/02/gparted-partition-vergroessern.png 908w" width="908" 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/2017/02/gparted-partition-vergroessern.png" alt="GParted shows a LibreELEC card with 6.85 GB of unallocated space and the dialog for resizing the partition." 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">With tools such as GParted, you can quickly adjust the partition size again.</figcaption></figure>

<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/pishrink-shrinks-raspberry-pi-images/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SSH Tips: Changed Host Keys, Killing and Parking Connections</title>
		<link>https://linuxundich.de/en/ssh-tips-changed-host-keys-killing-and-parking-connections/</link>
					<comments>https://linuxundich.de/en/ssh-tips-changed-host-keys-killing-and-parking-connections/#respond</comments>
		
		<dc:creator><![CDATA[Christoph Langner]]></dc:creator>
		<pubDate>Sat, 07 May 2016 06:32:42 +0000</pubDate>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[How-to]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[Tips]]></category>
		<guid isPermaLink="false">https://linuxundich.de/en/ssh-tips-changed-host-keys-killing-and-parking-connections/</guid>

					<description><![CDATA[SSH tips: remove changed host keys with ssh-keygen -R, kill hung connections and park sessions.]]></description>
										<content:encoded><![CDATA[
<p class="dropcapp wp-block-paragraph">If you like tinkering with the Raspberry Pi or other single-board computers such as the Banana Pi, Odroid and the like, you keep running into SSH. The images made for these mini computers are usually based on Linux and therefore mostly come with SSH access built in. In everyday tinkering, however, you set these machines up from scratch again and again, or you quickly pull the power plug to &#8220;just&#8221; restart the device. That throws SSH off balance: after installing a new system, the stored SSH key no longer matches, or the SSH client hangs when you suddenly pull the plug. You can solve these problems the quick and dirty way, but there is always a clean way, too.</p>

<span id="more-153"></span>

<p class="wp-block-paragraph">When establishing a connection via SSH, the SSH client usually stores the public SSH key of the remote system together with its hostname and IP address in the file <code>~/.ssh/known_hosts</code> in the current user&#8217;s home directory on the client machine. Among other things, this is done to prevent <a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">man-in-the-middle attacks</a>, in which an attacker pretends to be the target machine in order to phish your login credentials. However, this security measure also kicks in when there is no threat at all: for example, when you set up a Pi from scratch and try to log in via SSH again. In such a case, SSH reports <code>WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED</code> in big letters.</p>

<h2 class="wp-block-heading">SSH after reinstalling the system</h2>

<pre class="wp-block-preformatted">$ <strong>grep 192.168.111.100 ~/.ssh/known_hosts</strong>
raspberrypi,192.168.111.100 ecdsa-sha2-nistp256 AAAAE2...ABBBBqf</pre>

<pre class="wp-block-preformatted">$ <strong>ssh pi@192.168.111.100</strong>
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:6rR+0/i3KnPLds3EuGkfWiudIgu8VMpe1xq+X3I3yNM.
Please contact your system administrator.
Add correct host key in /home/toff/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/toff/.ssh/known_hosts:10
ECDSA host key for 192.168.111.100 has changed and you have requested strict checking.
Host key verification failed.</pre>

<p class="wp-block-paragraph">You could now open the file <code>~/.ssh/known_hosts</code> in a text editor and delete the offending line 10 from the list by hand, but there is a better way: with <code>ssh-keygen -R IP-address</code>, you remove the key from the file with a single command, so the next time you connect, you start from scratch – and have to confirm the key just like the very first time you connected to this machine. This also works if you use the hostname instead of the IP address to connect. To be on the safe side, the command copies the old state to <code>~/.ssh/known_hosts.old</code> in the same directory.</p>

<pre class="wp-block-preformatted">$ <strong>ssh-keygen -R 192.168.111.100</strong>
# Host 192.168.111.100 found: line 10
/home/toff/.ssh/known_hosts updated.
Original contents retained as /home/toff/.ssh/known_hosts.old</pre>

<pre class="wp-block-preformatted">$ <strong>ssh pi@192.168.111.100</strong>
The authenticity of host 'raspberrypi (192.168.111.100)' can't be established.
ECDSA key fingerprint is SHA256:6rR+0/i3KnPLds3EuGkfWiudIgu8VMpe1xq+X3I3yNM.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.111.100' (ECDSA) to the list of known hosts.
pi@192.168.111.100's password:

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Apr 22 08:40:10 2016 from 192.168.178.57</pre>

<h2 class="wp-block-heading">Forcibly terminating an SSH connection</h2>

<p class="dropcapp wp-block-paragraph">If you are logged in to a remote machine via SSH and shut it down with <code>shutdown</code>, <code>halt</code> or <code>reboot</code>, the system doesn&#8217;t kill the SSH connection abruptly. It stops the SSH server cleanly during shutdown, so you end up back in the terminal of the client machine and can keep working in the same terminal window. Now, I – and surely other Pi tinkerers too – like to unplug the Raspberry Pi and plug it back in to restart it quickly and painlessly. This is certainly not ideal for the integrity of the data on the memory card, but if I&#8217;m going to set up the system on it from scratch anyway, I don&#8217;t much care.</p>

<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212d8d02&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212d8d02" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="577" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2016/05/raspberry-pi-ssh-steuercodes-640x475.png 640w, https://linuxundich.de/wp-content/uploads/2016/05/raspberry-pi-ssh-steuercodes-768x570.png 768w, https://linuxundich.de/wp-content/uploads/2016/05/raspberry-pi-ssh-steuercodes.png 777w" width="777" 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/2016/05/raspberry-pi-ssh-steuercodes.png" alt="SSH connections can be managed with a set of escape sequences." 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">SSH connections can be managed with a set of escape sequences.</figcaption></figure>

<p class="wp-block-paragraph">The downside is that SSH usually hangs in the terminal when you do this – after all, you just pulled the chair out from under it. You could now kill the SSH process or close the terminal window and open it again, but there is a clean solution for this situation, too: SSH knows a number of escape sequences that let you manage the current SSH session. You get an overview of the available commands if you type <code>~?</code> on a new line in the terminal. To be on the safe side, simply press Enter once beforehand.</p>

<pre class="wp-block-preformatted">pi@raspberrypi:~ # <strong>~?</strong>
Supported escape sequences:
 ~.   - terminate connection (and any multiplexed sessions)
 ~B   - send a BREAK to the remote system
 ~C   - open a command line
 ~R   - request rekey
 ~V/v - decrease/increase verbosity (LogLevel)
 ~^Z  - suspend ssh
 ~#   - list forwarded connections
 ~&amp;   - background ssh (when waiting for connections to terminate)
 ~?   - this message
 ~~   - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)</pre>

<p class="wp-block-paragraph">The first sequence shown in the help is exactly the function we&#8217;re looking for: if you type <code>~.</code> as text during an SSH session, you terminate the current SSH connection, no matter what. This doesn&#8217;t only work with a session that is still active and working (which you could close with <code>exit</code> at any time anyway), but also when, for example, you cut the power to the Pi and nothing happens in the terminal anymore. Here, too, it can help to press Enter once more before the actual command. Otherwise the escape sequence may come to nothing.</p>

<h2 class="wp-block-heading">Pausing and resuming an SSH connection</h2>

<p class="dropcapp wp-block-paragraph">The escape sequences can do other handy things, too. For example, you can suspend an SSH connection and resume it later without having to use a terminal multiplexer such as <code>screen</code> or <code>tmux</code>. If a process takes longer than expected, you can park the connection this way while the process on the remote machine keeps running. Unlike with the two terminal multiplexers mentioned, you don&#8217;t have to think ahead that the task might take longer and start them as a precaution. The corresponding sequence is the somewhat cryptic <code>~^Z</code>, where the caret doesn&#8217;t stand for a character but for the Ctrl key. So you type <kbd>~</kbd> and then press <kbd>Ctrl</kbd>+<kbd>Z</kbd>. You then land back in the terminal of the machine on which you originally ran <code>ssh</code>. From there, you can pick up the connection again by typing <code>fg</code> and pressing Enter.</p>

<figure data-wp-context="{&quot;imageId&quot;:&quot;6aef8212d9029&quot;}" data-wp-interactive="core/image" data-wp-key="6aef8212d9029" class="wp-block-image wp-lightbox-container"><img loading="lazy" decoding="async" height="664" sizes="auto, (max-width: 781px) 100vw, 680px" srcset="https://linuxundich.de/wp-content/uploads/2016/05/ssh-raspberry-pi-suspend-640x550.png 640w, https://linuxundich.de/wp-content/uploads/2016/05/ssh-raspberry-pi-suspend-768x661.png 768w, https://linuxundich.de/wp-content/uploads/2016/05/ssh-raspberry-pi-suspend.png 772w" width="772" 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/2016/05/ssh-raspberry-pi-suspend.png" alt="Pausing and resuming an SSH connection." 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">Pausing and resuming an SSH connection.</figcaption></figure>

<p class="wp-block-paragraph">If you work on a &#8220;truly&#8221; remote system over the internet, the connection may well drop. On the one hand, this is because the server terminates the connection after a period of inactivity; on the other hand, your own network infrastructure (read: the router) may interfere. However, you can prevent the timeout with a keep-alive function. Depending on the situation, you can either configure the SSH server accordingly (which of course requires root privileges) or call SSH with the appropriate parameters right away. In that case, you don&#8217;t need any special privileges on either system.</p>

<h3 class="wp-block-heading">Keep-alive on the server side</h3>

<pre class="wp-block-preformatted">### Default keep-alive settings:
$ <strong>grep Alive /etc/ssh/sshd_config</strong>
#TCPKeepAlive yes
#ClientAliveInterval 0
#ClientAliveCountMax 3
### Edit the SSH server configuration:
$ <strong>sudo nano /etc/ssh/sshd_config</strong>

### In the end, the relevant lines should look like this:
$ <strong>grep Alive /etc/ssh/sshd_config</strong>
TCPKeepAlive yes
ClientAliveInterval 60
ClientAliveCountMax 3

### Restart the SSH server once:
$ <strong>sudo systemctl restart sshd</strong></pre>

<h3 class="wp-block-heading">Keep-alive on the client side</h3>

<pre class="wp-block-preformatted">### Keep the SSH connection alive from the client side
$ <strong>ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=1 pi@raspberrypi</strong></pre>

<p class="wp-block-paragraph">In the first case, the setting applies to all users who want to log in to the system via SSH. As a rule, you should therefore only make this change if all users actually need it. Most of the time, though, you only need keep-alive in exceptional cases, so it makes sense to set the option only when needed when calling <code>ssh</code>. For me, this is the case with a web service I can log in to via SSH, for example. If I start long-running backups there, my router terminates the connection before the backup process can report success. With the keep-alive settings mentioned above, however, that&#8217;s no longer a problem.</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/ssh-tips-changed-host-keys-killing-and-parking-connections/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
