<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: vast cow</title>
    <description>The latest articles on Forem by vast cow (@vast-cow).</description>
    <link>https://forem.com/vast-cow</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3717506%2F91ec5ce0-4f1b-458d-b9ad-d524e0befb41.png</url>
      <title>Forem: vast cow</title>
      <link>https://forem.com/vast-cow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/vast-cow"/>
    <language>en</language>
    <item>
      <title>Understanding `$@`, `$*`, `"$@"`, and `"$*"` in Shell Scripts</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Fri, 17 Apr 2026 10:20:55 +0000</pubDate>
      <link>https://forem.com/vast-cow/understanding-and-in-shell-scripts-455g</link>
      <guid>https://forem.com/vast-cow/understanding-and-in-shell-scripts-455g</guid>
      <description>&lt;p&gt;When working with shell scripts, handling command-line arguments correctly is critical. Variables like &lt;code&gt;$@&lt;/code&gt; and &lt;code&gt;$*&lt;/code&gt; are commonly used to access all positional parameters—but their behavior changes significantly depending on whether they are quoted.&lt;/p&gt;

&lt;p&gt;This subtle distinction is a frequent source of bugs. In this article, we’ll break down exactly how each form behaves, with concrete examples.&lt;/p&gt;




&lt;h2&gt;
  
  
  Positional Parameters: A Quick Refresher
&lt;/h2&gt;

&lt;p&gt;Consider the following script invocation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./script.sh foo bar &lt;span class="s2"&gt;"baz qux"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The positional parameters are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$1&lt;/code&gt; → &lt;code&gt;foo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$2&lt;/code&gt; → &lt;code&gt;bar&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$3&lt;/code&gt; → &lt;code&gt;baz qux&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To refer to &lt;em&gt;all&lt;/em&gt; arguments, we use &lt;code&gt;$@&lt;/code&gt; or &lt;code&gt;$*&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Expression&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All arguments&lt;/td&gt;
&lt;td&gt;Word-split into separate tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All arguments&lt;/td&gt;
&lt;td&gt;Word-split into separate tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"$@"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All arguments&lt;/td&gt;
&lt;td&gt;Preserves each argument as a separate item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"$*"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All arguments&lt;/td&gt;
&lt;td&gt;Joins all arguments into a single string&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;$@&lt;/code&gt; and &lt;code&gt;$*&lt;/code&gt; (Unquoted)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;arg &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;arg &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Behavior
&lt;/h3&gt;

&lt;p&gt;Without quotes, both &lt;code&gt;$@&lt;/code&gt; and &lt;code&gt;$*&lt;/code&gt; behave almost identically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They expand to all arguments&lt;/li&gt;
&lt;li&gt;Then undergo &lt;strong&gt;word splitting&lt;/strong&gt; based on whitespace&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./script.sh &lt;span class="s2"&gt;"hello world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will be treated as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hello&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;world&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The original argument structure is lost, which can lead to incorrect behavior.&lt;/p&gt;

&lt;p&gt;👉 In practice, unquoted &lt;code&gt;$@&lt;/code&gt; and &lt;code&gt;$*&lt;/code&gt; are rarely appropriate.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;"$@"&lt;/code&gt;: The Safe Default
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;arg &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Behavior
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Each argument is preserved as a &lt;strong&gt;distinct element&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Whitespace inside arguments is retained&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./script.sh foo &lt;span class="s2"&gt;"bar baz"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;foo
bar baz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Properties
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Maintains the original number of arguments&lt;/li&gt;
&lt;li&gt;Preserves boundaries between arguments&lt;/li&gt;
&lt;li&gt;Safe for filenames and arbitrary input&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;This is the form you should use in almost all cases.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;"$*"&lt;/code&gt;: Single String Expansion
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Behavior
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All arguments are concatenated into &lt;strong&gt;one string&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Separated by the first character of &lt;code&gt;IFS&lt;/code&gt; (space by default)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./script.sh foo &lt;span class="s2"&gt;"bar baz"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;foo bar baz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Caveats
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Argument boundaries are lost&lt;/li&gt;
&lt;li&gt;Not suitable for iteration or per-argument processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Useful primarily for logging or display purposes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Visual Comparison
&lt;/h2&gt;

&lt;p&gt;Given:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./script.sh A &lt;span class="s2"&gt;"B C"&lt;/span&gt; D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Expression&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A B C D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A B C D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"$@"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"A" "B C" "D"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"$*"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;"A B C D"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Common Pitfall
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Incorrect
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;arg &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; /dest/
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an argument contains spaces, it will be split incorrectly.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Correct
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;arg &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; /dest/
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This preserves each argument exactly as passed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Practical Guidelines
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;"$@"&lt;/code&gt; when passing or iterating over arguments&lt;/li&gt;
&lt;li&gt;Avoid unquoted &lt;code&gt;$@&lt;/code&gt; and &lt;code&gt;$*&lt;/code&gt; unless you explicitly want word splitting&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;"$*"&lt;/code&gt; only when you intentionally need a single combined string&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why This Difference Exists
&lt;/h2&gt;

&lt;p&gt;The distinction arises from how the shell performs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parameter expansion&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Word splitting&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quote removal&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notably, &lt;code&gt;"$@"&lt;/code&gt; is a special case: it expands to multiple quoted strings, preserving each positional parameter individually. This behavior is unique and not shared by other expansions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;"$@"&lt;/code&gt; is the safest and most predictable way to handle arguments&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$@&lt;/code&gt; and &lt;code&gt;$*&lt;/code&gt; (unquoted) can break argument boundaries&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"$*"&lt;/code&gt; collapses everything into a single string&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you follow one rule, make it this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Always use &lt;code&gt;"$@"&lt;/code&gt; unless you have a specific reason not to.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>bash</category>
      <category>cli</category>
      <category>linux</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>My Favorite rclone mount Settings</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Fri, 17 Apr 2026 06:25:09 +0000</pubDate>
      <link>https://forem.com/vast-cow/my-favorite-rclone-mount-settings-2ide</link>
      <guid>https://forem.com/vast-cow/my-favorite-rclone-mount-settings-2ide</guid>
      <description>&lt;p&gt;&lt;code&gt;rclone mount&lt;/code&gt; is a useful way to access remote storage as if it were a local folder. With the right options, it can feel more responsive and predictable during everyday use. The configuration below is a practical setup for mounting a remote path to a local directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Configuration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rclone mount remote:/path /mnt/remote &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vfs-cache-mode&lt;/span&gt; full &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vfs-write-back&lt;/span&gt; 0s &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dir-cache-time&lt;/span&gt; 1s &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--attr-timeout&lt;/span&gt; 1s &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--poll-interval&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vfs-read-ahead&lt;/span&gt; 1M
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Purpose of This Setup
&lt;/h2&gt;

&lt;p&gt;This configuration is designed to make a mounted remote storage path behave more like a normal local filesystem. It is especially useful when you want quick file visibility, immediate write handling, and fewer delays caused by cached directory or file metadata.&lt;/p&gt;

&lt;p&gt;The general goal is simplicity: keep the mount usable for regular file operations while reducing the chance of stale information.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Each Option Does
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--vfs-cache-mode full&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This enables full VFS caching. It helps many applications work correctly with the mounted remote, especially those that expect normal filesystem behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--vfs-write-back 0s&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This makes writes get handled without an added write-back delay. It is useful when you want changes to be processed immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--dir-cache-time 1s&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This keeps directory listings fresh by caching them for only a very short time. It helps when files are added, removed, or changed frequently.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--attr-timeout 1s&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This short timeout reduces how long file attributes are cached. It helps the mount reflect recent changes more quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--poll-interval 0&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This disables polling for remote changes. In this setup, the mount relies more on short cache times instead of background polling.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--vfs-read-ahead 1M&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This reads a small amount of extra data in advance. It can improve reading performance without using too much additional memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Setup Is Useful
&lt;/h2&gt;

&lt;p&gt;This mount setup is a good choice for users who care about seeing updates quickly and keeping filesystem behavior straightforward. It trades longer cache times for freshness, which can be helpful when the remote content changes often or when you want local access to reflect the remote state more closely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This &lt;code&gt;rclone mount&lt;/code&gt; configuration is a simple and practical setup for everyday use. It focuses on usability, fast visibility of changes, and stable file access. For users who want a remote mount to behave more like a local folder, it is an effective starting point.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Running a non-root Samba server on Singularity (Apptainer) using a non-privileged port and sharing `$HOME`</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Thu, 16 Apr 2026 12:56:45 +0000</pubDate>
      <link>https://forem.com/vast-cow/running-a-non-root-samba-server-on-singularity-apptainer-using-a-non-privileged-port-and-sharing-10jn</link>
      <guid>https://forem.com/vast-cow/running-a-non-root-samba-server-on-singularity-apptainer-using-a-non-privileged-port-and-sharing-10jn</guid>
      <description>&lt;p&gt;This guide documents how to run a &lt;strong&gt;Samba server inside a Singularity / Apptainer container&lt;/strong&gt; under the following constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No root privileges on the host&lt;/li&gt;
&lt;li&gt;Use of a &lt;strong&gt;non-privileged port&lt;/strong&gt; (e.g., 1445 instead of 445)&lt;/li&gt;
&lt;li&gt;Sharing the user’s &lt;strong&gt;home directory (&lt;code&gt;$HOME&lt;/code&gt;)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;All writable paths confined to user space&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup is particularly useful in &lt;strong&gt;HPC or restricted environments&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design Principles
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;smbd&lt;/code&gt; as a &lt;strong&gt;non-root user&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;port ≥1024&lt;/strong&gt; (e.g., &lt;code&gt;1445&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Disable NetBIOS (&lt;code&gt;nmbd&lt;/code&gt; not used)&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;[homes]&lt;/code&gt; for per-user home directory sharing&lt;/li&gt;
&lt;li&gt;Redirect all writable paths to &lt;code&gt;$HOME&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;bind mounts&lt;/strong&gt; for filesystem access&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Build the Container Image
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Definition file (&lt;code&gt;samba.def&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bootstrap: docker
From: ubuntu:24.04

%post
    export DEBIAN_FRONTEND=noninteractive
    apt-get update
    apt-get install -y samba smbclient
    apt-get clean
    rm -rf /var/lib/apt/lists/*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;singularity build &lt;span class="nt"&gt;--fakeroot&lt;/span&gt; samba.sif samba.def
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Prepare Host Directories
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/samba/&lt;span class="o"&gt;{&lt;/span&gt;etc,log,lock,run,cache,private&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;700 ~/samba/private
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/samba/run/ncalrpc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Create &lt;code&gt;smb.conf&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;~/samba/etc/smb.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[global]&lt;/span&gt;
   &lt;span class="err"&gt;server&lt;/span&gt; &lt;span class="py"&gt;role&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;standalone server&lt;/span&gt;
   &lt;span class="py"&gt;workgroup&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;WORKGROUP&lt;/span&gt;
   &lt;span class="err"&gt;netbios&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;MYSMB&lt;/span&gt;

   &lt;span class="py"&gt;security&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;
   &lt;span class="err"&gt;map&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="py"&gt;guest&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;never&lt;/span&gt;

   &lt;span class="err"&gt;smb&lt;/span&gt; &lt;span class="py"&gt;ports&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1445&lt;/span&gt;
   &lt;span class="err"&gt;disable&lt;/span&gt; &lt;span class="py"&gt;netbios&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;

   &lt;span class="err"&gt;lock&lt;/span&gt; &lt;span class="py"&gt;directory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/hosthome/USER/samba/lock&lt;/span&gt;
   &lt;span class="err"&gt;pid&lt;/span&gt; &lt;span class="py"&gt;directory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/hosthome/USER/samba/run&lt;/span&gt;
   &lt;span class="err"&gt;state&lt;/span&gt; &lt;span class="py"&gt;directory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/hosthome/USER/samba/cache&lt;/span&gt;
   &lt;span class="err"&gt;cache&lt;/span&gt; &lt;span class="py"&gt;directory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/hosthome/USER/samba/cache&lt;/span&gt;
   &lt;span class="err"&gt;private&lt;/span&gt; &lt;span class="py"&gt;dir&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/hosthome/USER/samba/private&lt;/span&gt;

   &lt;span class="err"&gt;log&lt;/span&gt; &lt;span class="py"&gt;file&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/hosthome/USER/samba/log/log.%m&lt;/span&gt;
   &lt;span class="err"&gt;max&lt;/span&gt; &lt;span class="err"&gt;log&lt;/span&gt; &lt;span class="py"&gt;size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1000&lt;/span&gt;

   &lt;span class="err"&gt;ncalrpc&lt;/span&gt; &lt;span class="py"&gt;dir&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/hosthome/USER/samba/run/ncalrpc&lt;/span&gt;

   &lt;span class="err"&gt;load&lt;/span&gt; &lt;span class="py"&gt;printers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;no&lt;/span&gt;
   &lt;span class="py"&gt;printing&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;bsd&lt;/span&gt;
   &lt;span class="err"&gt;printcap&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/dev/null&lt;/span&gt;
   &lt;span class="err"&gt;disable&lt;/span&gt; &lt;span class="py"&gt;spoolss&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;

&lt;span class="nn"&gt;[homes]&lt;/span&gt;
   &lt;span class="py"&gt;browseable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;no&lt;/span&gt;
   &lt;span class="err"&gt;read&lt;/span&gt; &lt;span class="py"&gt;only&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;no&lt;/span&gt;
   &lt;span class="err"&gt;valid&lt;/span&gt; &lt;span class="py"&gt;users&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;%S&lt;/span&gt;
   &lt;span class="err"&gt;create&lt;/span&gt; &lt;span class="py"&gt;mask&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;0600&lt;/span&gt;
   &lt;span class="err"&gt;directory&lt;/span&gt; &lt;span class="py"&gt;mask&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;0700&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;USER&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"s|USER|&lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="s2"&gt;|g"&lt;/span&gt; ~/samba/etc/smb.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Bind Mount Setup
&lt;/h2&gt;

&lt;p&gt;Bind your home directory into the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SMB_BIND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;:/hosthome/&lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Set Samba Password (with fakeroot)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;singularity &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--fakeroot&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bind&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SMB_BIND&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  samba.sif &lt;span class="se"&gt;\&lt;/span&gt;
  smbpasswd &lt;span class="nt"&gt;-c&lt;/span&gt; /hosthome/&lt;span class="nv"&gt;$USER&lt;/span&gt;/samba/etc/smb.conf &lt;span class="nt"&gt;-a&lt;/span&gt; root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this setup, the password is assigned to the &lt;code&gt;root&lt;/code&gt; user inside Samba.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Run the Server (Important Fixes Applied)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prepare log directory bind
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/samba/varlog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;singularity &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--fakeroot&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bind&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SMB_BIND&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bind&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/samba/varlog:/var/log/samba"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  samba.sif &lt;span class="se"&gt;\&lt;/span&gt;
  smbd &lt;span class="nt"&gt;--foreground&lt;/span&gt; &lt;span class="nt"&gt;--no-process-group&lt;/span&gt; &lt;span class="nt"&gt;--debug-stdout&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-s&lt;/span&gt; /hosthome/&lt;span class="nv"&gt;$USER&lt;/span&gt;/samba/etc/smb.conf &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-p&lt;/span&gt; 1445
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Verify
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ss &lt;span class="nt"&gt;-ltnp&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;1445
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;smbclient &lt;span class="nt"&gt;-L&lt;/span&gt; //127.0.0.1 &lt;span class="nt"&gt;-p&lt;/span&gt; 1445 &lt;span class="nt"&gt;-U&lt;/span&gt; root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Common Pitfalls and Fixes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Read-only &lt;code&gt;/var/log/samba&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unable to open new log file '/var/log/samba/log.smbd'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--bind&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/samba/varlog:/var/log/samba"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Missing &lt;code&gt;/run/samba/ncalrpc&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failed to create pipe directory /run/samba/ncalrpc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add to &lt;code&gt;smb.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;ncalrpc&lt;/span&gt; &lt;span class="py"&gt;dir&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/hosthome/$USER/samba/run/ncalrpc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/samba/run/ncalrpc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Invalid &lt;code&gt;-S&lt;/code&gt; option
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Invalid option -S
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;smbd &lt;span class="nt"&gt;--foreground&lt;/span&gt; &lt;span class="nt"&gt;--no-process-group&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Privileged ports not allowed
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ports &lt;code&gt;445&lt;/code&gt; / &lt;code&gt;139&lt;/code&gt; require root&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;1445&lt;/code&gt; or another port ≥1024&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This setup enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running Samba &lt;strong&gt;without root privileges&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Fully contained execution in Singularity&lt;/li&gt;
&lt;li&gt;Direct sharing of &lt;code&gt;$HOME&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Compatibility with restricted environments (e.g., HPC)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Redirect all writable paths to user space&lt;/li&gt;
&lt;li&gt;Override container defaults (&lt;code&gt;/var/log&lt;/code&gt;, &lt;code&gt;/run&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Always use a non-privileged port&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conceptual Note
&lt;/h2&gt;

&lt;p&gt;This approach is less about “containerizing Samba” and more about:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Running Samba entirely in user space, with Singularity acting as the runtime environment.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>Running `sshd` in Rootless Mode</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Thu, 16 Apr 2026 05:36:51 +0000</pubDate>
      <link>https://forem.com/vast-cow/running-sshd-in-rootless-mode-mc8</link>
      <guid>https://forem.com/vast-cow/running-sshd-in-rootless-mode-mc8</guid>
      <description>&lt;p&gt;This article explains how to run &lt;code&gt;sshd&lt;/code&gt; as a normal user without root privileges. The setup uses a custom configuration directory under the user’s home directory and listens on a non-privileged port.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Normally, &lt;code&gt;sshd&lt;/code&gt; is started by the system as root and listens on port &lt;code&gt;22&lt;/code&gt;. In some environments, however, it is useful to run an SSH server without root access. A rootless setup can be used for testing, development, or temporary remote access in user space.&lt;/p&gt;

&lt;p&gt;The example here creates a private SSH server environment in &lt;code&gt;~/.sshd&lt;/code&gt;, generates a host key if needed, writes a minimal &lt;code&gt;sshd_config&lt;/code&gt;, validates the configuration, and then starts the daemon in the foreground.&lt;/p&gt;

&lt;h2&gt;
  
  
  Directory and Variable Setup
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;setup.sh&lt;/code&gt; script begins by defining a few variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.sshd"&lt;/span&gt;
&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2222
&lt;span class="nv"&gt;SSHD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; sshd&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;BASE&lt;/code&gt; is the working directory for the SSH server files. &lt;code&gt;PORT&lt;/code&gt; is set to &lt;code&gt;2222&lt;/code&gt;, which is a non-privileged port and can be used without root. &lt;code&gt;SSHD&lt;/code&gt; stores the path to the &lt;code&gt;sshd&lt;/code&gt; executable.&lt;/p&gt;

&lt;p&gt;The script then creates the required directories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 700 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.ssh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that both &lt;code&gt;~/.sshd&lt;/code&gt; and &lt;code&gt;~/.ssh&lt;/code&gt; exist with secure permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating the Host Key
&lt;/h2&gt;

&lt;p&gt;An SSH server needs its own host key. The script checks whether an Ed25519 host key already exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/ssh_host_ed25519_key"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;ssh-keygen &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/ssh_host_ed25519_key"&lt;/span&gt;
&lt;span class="k"&gt;fi
&lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;600 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/ssh_host_ed25519_key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the key is missing, it generates one. The permission is then restricted to the owner only. This is important because SSH rejects private keys that are too broadly accessible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the &lt;code&gt;sshd&lt;/code&gt; Configuration
&lt;/h2&gt;

&lt;p&gt;The script writes a custom &lt;code&gt;sshd_config&lt;/code&gt; file into the user-owned directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/sshd_config"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
Port &lt;/span&gt;&lt;span class="nv"&gt;$PORT&lt;/span&gt;&lt;span class="sh"&gt;
ListenAddress 0.0.0.0

UsePAM no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes

HostKey &lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="sh"&gt;/ssh_host_ed25519_key
PidFile none

PermitRootLogin no
PrintMotd no
PrintLastLog no
X11Forwarding no
AllowUsers &lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="sh"&gt;

Subsystem sftp internal-sftp
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Settings
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Port and Listen Address
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Port $PORT&lt;/code&gt; tells the server to listen on port &lt;code&gt;2222&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ListenAddress 0.0.0.0&lt;/code&gt; allows connections on all network interfaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Authentication
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;UsePAM no&lt;/code&gt; disables PAM because PAM generally requires a system-level setup.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PasswordAuthentication no&lt;/code&gt; disables password login.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;KbdInteractiveAuthentication no&lt;/code&gt; disables keyboard-interactive authentication.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PubkeyAuthentication yes&lt;/code&gt; enables public key login.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes the server simpler and safer for rootless use by relying only on SSH keys.&lt;/p&gt;

&lt;h4&gt;
  
  
  Host Key and PID File
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HostKey $BASE/ssh_host_ed25519_key&lt;/code&gt; points to the host key generated earlier.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PidFile none&lt;/code&gt; avoids writing a PID file, which is useful in lightweight user-space execution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Restrictions
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PermitRootLogin no&lt;/code&gt; disallows root login.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PrintMotd no&lt;/code&gt; and &lt;code&gt;PrintLastLog no&lt;/code&gt; suppress extra login messages.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;X11Forwarding no&lt;/code&gt; disables X11 forwarding.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AllowUsers $USER&lt;/code&gt; limits access to the current user only.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  SFTP Support
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Subsystem sftp internal-sftp&lt;/code&gt; enables SFTP using the built-in internal subsystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Validating the Configuration
&lt;/h2&gt;

&lt;p&gt;At the end of &lt;code&gt;setup.sh&lt;/code&gt;, the script verifies the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SSHD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/sshd_config"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a useful step because it checks the syntax before starting the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting the SSH Server
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;start.sh&lt;/code&gt; script is very small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.sshd"&lt;/span&gt;
&lt;span class="nv"&gt;SSHD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; sshd&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SSHD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/sshd_config"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What This Does
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-D&lt;/code&gt; keeps &lt;code&gt;sshd&lt;/code&gt; in the foreground.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-e&lt;/code&gt; sends log output to standard error.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-f "$BASE/sshd_config"&lt;/code&gt; tells &lt;code&gt;sshd&lt;/code&gt; to use the custom configuration file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using &lt;code&gt;exec&lt;/code&gt; replaces the shell process with &lt;code&gt;sshd&lt;/code&gt;, which is a clean way to launch the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Use It
&lt;/h2&gt;

&lt;p&gt;A typical flow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;setup.sh&lt;/code&gt; once to create the configuration and host key.&lt;/li&gt;
&lt;li&gt;Make sure your public key is present in &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;start.sh&lt;/code&gt; to launch the SSH server.&lt;/li&gt;
&lt;li&gt;Connect to it on port &lt;code&gt;2222&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-p&lt;/span&gt; 2222 user@host
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits of This Approach
&lt;/h2&gt;

&lt;p&gt;This rootless SSH setup has several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It does not require system-wide configuration.&lt;/li&gt;
&lt;li&gt;It avoids privileged ports.&lt;/li&gt;
&lt;li&gt;It works well for personal environments and temporary setups.&lt;/li&gt;
&lt;li&gt;It keeps all SSH server files under the user’s home directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This example provides a compact way to run &lt;code&gt;sshd&lt;/code&gt; without root privileges. By using a private configuration directory, a non-privileged port, and public key authentication only, it creates a simple and practical SSH server for user-space operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scripts
&lt;/h2&gt;

&lt;p&gt;setup.sh&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash &lt;/span&gt;
&lt;span class="nv"&gt;BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.sshd"&lt;/span&gt; 
&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2222 
&lt;span class="nv"&gt;SSHD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; sshd&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 

&lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 700 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.ssh"&lt;/span&gt; 

&lt;span class="c"&gt;# server host key &lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/ssh_host_ed25519_key"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then 
  &lt;/span&gt;ssh-keygen &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/ssh_host_ed25519_key"&lt;/span&gt; 
&lt;span class="k"&gt;fi 
&lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;600 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/ssh_host_ed25519_key"&lt;/span&gt; 

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/sshd_config"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; 
Port &lt;/span&gt;&lt;span class="nv"&gt;$PORT&lt;/span&gt;&lt;span class="sh"&gt; 
ListenAddress 0.0.0.0 

UsePAM no 
PasswordAuthentication no 
KbdInteractiveAuthentication no 
PubkeyAuthentication yes 

HostKey &lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="sh"&gt;/ssh_host_ed25519_key 
PidFile none 

PermitRootLogin no 
PrintMotd no 
PrintLastLog no 
X11Forwarding no 
AllowUsers &lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="sh"&gt; 

Subsystem sftp internal-sftp 
&lt;/span&gt;&lt;span class="no"&gt;EOF 

&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SSHD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/sshd_config"&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;start.sh&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash &lt;/span&gt;
&lt;span class="nv"&gt;BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.sshd"&lt;/span&gt; 
&lt;span class="nv"&gt;SSHD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; sshd&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 
&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SSHD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/sshd_config"&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>How to Build NCCL Tests in an NVIDIA HPC SDK Environment</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Tue, 14 Apr 2026 08:23:44 +0000</pubDate>
      <link>https://forem.com/vast-cow/how-to-build-nccl-tests-in-an-nvidia-hpc-sdk-environment-99e</link>
      <guid>https://forem.com/vast-cow/how-to-build-nccl-tests-in-an-nvidia-hpc-sdk-environment-99e</guid>
      <description>&lt;p&gt;To build &lt;code&gt;nccl-tests&lt;/code&gt; in an NVIDIA HPC SDK environment, you need to set the correct paths for CUDA, NCCL, and MPI, and then run &lt;code&gt;make&lt;/code&gt;. This article briefly explains the required environment variables and the build command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;First, define the locations of CUDA and NCCL based on your NVIDIA HPC SDK installation. Then set &lt;code&gt;MPI_HOME&lt;/code&gt; to the Open MPI bundled with HPC-X alongside NCCL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CUDA_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVHPC_ROOT&lt;/span&gt;&lt;span class="s2"&gt;/cuda"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NCCL_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVHPC_ROOT&lt;/span&gt;&lt;span class="s2"&gt;/comm_libs/nccl"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MPI_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;readlink&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NCCL_HOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/../hpcx/latest/ompi"&lt;/span&gt;
make &lt;span class="nt"&gt;-kj&lt;/span&gt; &lt;span class="nv"&gt;MPI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;CUDA_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CUDA_HOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;NCCL_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NCCL_HOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;MPI_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MPI_HOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Meaning of Each Environment Variable
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;CUDA_HOME&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;CUDA_HOME&lt;/code&gt; points to the CUDA directory inside the NVIDIA HPC SDK installation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CUDA_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVHPC_ROOT&lt;/span&gt;&lt;span class="s2"&gt;/cuda"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the build process to find the correct CUDA headers and libraries.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;NCCL_HOME&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;NCCL_HOME&lt;/code&gt; specifies the location of the NCCL library included in the HPC SDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NCCL_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVHPC_ROOT&lt;/span&gt;&lt;span class="s2"&gt;/comm_libs/nccl"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;nccl-tests&lt;/code&gt; uses this path to locate the NCCL installation.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;MPI_HOME&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;MPI_HOME&lt;/code&gt; points to the Open MPI installation provided through HPC-X near the NCCL package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MPI_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;readlink&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NCCL_HOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/../hpcx/latest/ompi"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;readlink -f&lt;/code&gt; resolves the symbolic link and ensures that the path is based on the actual NCCL installation directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Command
&lt;/h2&gt;

&lt;p&gt;After setting the environment variables, run the following command to build &lt;code&gt;nccl-tests&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make &lt;span class="nt"&gt;-kj&lt;/span&gt; &lt;span class="nv"&gt;MPI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;CUDA_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CUDA_HOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;NCCL_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NCCL_HOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;MPI_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MPI_HOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Points
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MPI=1&lt;/code&gt;
Enables MPI support during the build.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CUDA_HOME=...&lt;/code&gt;
Explicitly sets the CUDA location.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NCCL_HOME=...&lt;/code&gt;
Explicitly sets the NCCL location.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MPI_HOME=...&lt;/code&gt;
Specifies which MPI implementation to use.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-kj&lt;/code&gt;
Enables parallel build execution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;To build &lt;code&gt;nccl-tests&lt;/code&gt; in an NVIDIA HPC SDK environment, the main requirement is to correctly define &lt;code&gt;CUDA_HOME&lt;/code&gt;, &lt;code&gt;NCCL_HOME&lt;/code&gt;, and &lt;code&gt;MPI_HOME&lt;/code&gt;, and pass them to &lt;code&gt;make&lt;/code&gt;. A notable point is that &lt;code&gt;MPI_HOME&lt;/code&gt; should be set to the HPC-X Open MPI installation associated with NCCL. With this setup, &lt;code&gt;nccl-tests&lt;/code&gt; can be built cleanly within the HPC SDK environment.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Showing the Model Name in ChatGPT with User-Agent Switcher and Manager</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Mon, 13 Apr 2026 10:03:22 +0000</pubDate>
      <link>https://forem.com/vast-cow/showing-the-model-name-in-chatgpt-with-user-agent-switcher-and-manager-3d4a</link>
      <guid>https://forem.com/vast-cow/showing-the-model-name-in-chatgpt-with-user-agent-switcher-and-manager-3d4a</guid>
      <description>&lt;p&gt;This article explains a simple way to make the model name appear more explicitly in the ChatGPT interface by using the &lt;strong&gt;User-Agent Switcher and Manager&lt;/strong&gt; Chrome extension with a custom setting for &lt;code&gt;chatgpt.com&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;By configuring &lt;strong&gt;User-Agent Switcher and Manager&lt;/strong&gt; to send a mobile Chrome-on-iPhone user agent only for &lt;code&gt;chatgpt.com&lt;/code&gt;, the ChatGPT site can display the model more clearly in the model selection area.&lt;/p&gt;

&lt;p&gt;The key idea is to apply a custom user agent to a specific domain rather than changing the browser identity globally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Used
&lt;/h2&gt;

&lt;p&gt;The following JSON configuration was used in the extension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"blacklist"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"custom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"chatgpt.com"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mozilla/5.0 (iPhone; CPU iPhone OS 13_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/146.0.0.0 Mobile/15E148 Safari/604.1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"last-update"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1776073925509&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"custom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"popular-browsers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Internet Explorer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Safari"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Chrome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Firefox"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Opera"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Edge"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Vivaldi"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"popular-oss"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Windows"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Mac OS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Linux"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Chromium OS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Android"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"protected"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"google.com/recaptcha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"gstatic.com/recaptcha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"accounts.google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"accounts.youtube.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"gitlab.com/users/sign_in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"challenges.cloudflare.com"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"remote-address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user-styling"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"userAgentData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"whitelist"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"json-guid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8455108d-186e-47c2-89ec-41d7384aec1e"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"json-forced"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What This Setting Does
&lt;/h2&gt;

&lt;p&gt;The important part of the configuration is this entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"custom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"chatgpt.com"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mozilla/5.0 (iPhone; CPU iPhone OS 13_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/146.0.0.0 Mobile/15E148 Safari/604.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells the extension to use a specific &lt;strong&gt;iPhone Chrome user agent&lt;/strong&gt; when visiting &lt;code&gt;chatgpt.com&lt;/code&gt;. Because the setting is domain-specific, it does not affect unrelated websites.&lt;/p&gt;

&lt;p&gt;The extension is also set to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"custom"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means the browser applies the custom rules defined in the &lt;code&gt;custom&lt;/code&gt; section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Model Name Becomes Visible
&lt;/h2&gt;

&lt;p&gt;With this setup, ChatGPT may serve a different interface variant based on the browser identity it detects. In this case, the model selection area can show the model name more explicitly.&lt;/p&gt;

&lt;p&gt;In practical terms, changing the user agent causes the site to treat the browser more like a mobile client, and that can alter how the interface presents model information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Details
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Site-Specific Behavior
&lt;/h3&gt;

&lt;p&gt;This configuration only targets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;chatgpt.com&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It does not apply the iPhone user agent to every site.&lt;/p&gt;

&lt;h3&gt;
  
  
  Protected Domains
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;protected&lt;/code&gt; list includes domains such as reCAPTCHA, Google sign-in pages, and Cloudflare challenge pages. These are excluded from spoofing to avoid login or verification problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  User-Agent Client Hints
&lt;/h3&gt;

&lt;p&gt;The setting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"userAgentData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;indicates that user-agent-related client hint behavior is also enabled. This can matter because modern websites may use more than the classic user agent string when deciding which interface to show.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Result
&lt;/h2&gt;

&lt;p&gt;After applying this configuration in &lt;strong&gt;User-Agent Switcher and Manager&lt;/strong&gt;, ChatGPT can be displayed in a way that makes the model shown in the model selector easier to identify.&lt;/p&gt;

&lt;p&gt;This is a lightweight workaround for users who want clearer visibility of the active model without changing their full browsing environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Using &lt;strong&gt;User-Agent Switcher and Manager&lt;/strong&gt; with a custom entry for &lt;code&gt;chatgpt.com&lt;/code&gt; is a simple method for changing how ChatGPT presents its interface. With the iPhone Chrome user agent shown above, the model name can appear explicitly in the model selection area, making it easier to confirm which model is currently being used.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Interactive SLURM Job Attachment with Bash</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Mon, 13 Apr 2026 09:49:03 +0000</pubDate>
      <link>https://forem.com/vast-cow/interactive-slurm-job-attachment-with-bash-20cc</link>
      <guid>https://forem.com/vast-cow/interactive-slurm-job-attachment-with-bash-20cc</guid>
      <description>&lt;p&gt;This script provides a streamlined method for attaching an interactive shell to a running SLURM job. It integrates several command-line tools to identify active jobs, optionally prompt the user for selection, and then attach a terminal session to the chosen job using &lt;code&gt;srun&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;In high-performance computing (HPC) environments managed by SLURM, users often need to inspect or interact with running jobs. This script automates that workflow by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifying required dependencies&lt;/li&gt;
&lt;li&gt;Retrieving active job IDs for the current user&lt;/li&gt;
&lt;li&gt;Allowing interactive selection when multiple jobs exist&lt;/li&gt;
&lt;li&gt;Launching an interactive shell inside the selected job&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dependency Checks
&lt;/h2&gt;

&lt;p&gt;At the beginning, the script ensures that all required commands are available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;squeue&lt;/code&gt;: Queries SLURM job information&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jq&lt;/code&gt;: Parses JSON output&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fzf&lt;/code&gt;: Provides an interactive selection interface&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;srun&lt;/code&gt;: Attaches to or launches SLURM jobs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of these tools are missing, the script exits immediately with an error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieving Running Jobs
&lt;/h2&gt;

&lt;p&gt;The script uses &lt;code&gt;squeue&lt;/code&gt; with JSON output to fetch running jobs for the current user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;squeue &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--states&lt;/span&gt; Running &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This output is then processed with &lt;code&gt;jq&lt;/code&gt; to extract job IDs. It accounts for different JSON structures (&lt;code&gt;.jobs&lt;/code&gt; or &lt;code&gt;.job_array&lt;/code&gt;) and filters out empty entries. The final list is sorted and deduplicated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Job Selection
&lt;/h2&gt;

&lt;p&gt;The script adapts based on how many jobs are found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No jobs&lt;/strong&gt;: Exits with a message indicating no running jobs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One job&lt;/strong&gt;: Automatically selects that job.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple jobs&lt;/strong&gt;: Uses &lt;code&gt;fzf&lt;/code&gt; to present an interactive selection menu.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the user cancels the selection, the script exits gracefully.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attaching to the Job
&lt;/h2&gt;

&lt;p&gt;Once a job ID is determined, the script attaches an interactive shell using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;srun &lt;span class="nt"&gt;--jobid&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$jobid&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--overlap&lt;/span&gt; &lt;span class="nt"&gt;--pty&lt;/span&gt; /bin/bash &lt;span class="nt"&gt;--login&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Options Explained
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--jobid&lt;/code&gt;: Specifies the target job&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--overlap&lt;/code&gt;: Allows the new step to share resources with the existing job&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--pty&lt;/code&gt;: Allocates a pseudo-terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/bin/bash --login -i&lt;/code&gt;: Starts an interactive login shell&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The use of &lt;code&gt;exec&lt;/code&gt; ensures that the script is replaced by the new shell process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error Handling and Robustness
&lt;/h2&gt;

&lt;p&gt;The script uses strict Bash settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enforces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immediate exit on errors (&lt;code&gt;-e&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Undefined variable detection (&lt;code&gt;-u&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Proper error propagation in pipelines (&lt;code&gt;-o pipefail&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These safeguards improve reliability, especially in production HPC environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This script encapsulates a common operational need in SLURM-based systems: attaching to running jobs efficiently. By combining structured data parsing, interactive selection, and robust error handling, it reduces manual steps and minimizes user error in multi-job scenarios.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="k"&gt;for &lt;/span&gt;cmd &lt;span class="k"&gt;in &lt;/span&gt;squeue jq fzf srun column&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$cmd&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: '&lt;/span&gt;&lt;span class="nv"&gt;$cmd&lt;/span&gt;&lt;span class="s2"&gt;' not found."&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
  &lt;span class="k"&gt;fi
done

&lt;/span&gt;&lt;span class="nv"&gt;job_lines&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;
  squeue &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--states&lt;/span&gt; Running &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'
        if .jobs then .jobs
        elif .job_array then .job_array
        else []
        end
        | map([
            (.job_id | tostring),
            (.name // "-"),
            (.partition // "-"),
            (.time_used // .run_time // "-"),
            (.nodes // .node_count // "-" | tostring),
            (.node_list // .nodelist // "-")
          ] | @tsv)
        | .[]
      '&lt;/span&gt;
&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$job_lines&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No running jobs found."&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;job_count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$job_lines&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; job_count &lt;span class="o"&gt;==&lt;/span&gt; 1 &lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nv"&gt;jobid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$job_lines&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-f1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nv"&gt;selected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'JOBID\tNAME\tPARTITION\tELAPSED\tNODES\tNODELIST\n'&lt;/span&gt;
      &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$job_lines&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      | column &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;$'&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      | fzf &lt;span class="se"&gt;\&lt;/span&gt;
          &lt;span class="nt"&gt;--prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Select job&amp;gt; '&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
          &lt;span class="nt"&gt;--height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50% &lt;span class="se"&gt;\&lt;/span&gt;
          &lt;span class="nt"&gt;--reverse&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
          &lt;span class="nt"&gt;--header-lines&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
  &lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;selected&lt;/span&gt;&lt;span class="k"&gt;:-}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No job selected."&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
  &lt;span class="k"&gt;fi

  &lt;/span&gt;&lt;span class="nv"&gt;jobid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $1}'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$selected&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Using jobid: &lt;/span&gt;&lt;span class="nv"&gt;$jobid&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
&lt;span class="nb"&gt;exec &lt;/span&gt;srun &lt;span class="nt"&gt;--jobid&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$jobid&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--overlap&lt;/span&gt; &lt;span class="nt"&gt;--pty&lt;/span&gt; /bin/bash &lt;span class="nt"&gt;--login&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Enabling Persistent Systemd Journal Logging on Linux</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Mon, 13 Apr 2026 04:58:31 +0000</pubDate>
      <link>https://forem.com/vast-cow/enabling-persistent-systemd-journal-logging-on-linux-39jj</link>
      <guid>https://forem.com/vast-cow/enabling-persistent-systemd-journal-logging-on-linux-39jj</guid>
      <description>&lt;p&gt;Systemd’s journal (&lt;code&gt;journald&lt;/code&gt;) stores system logs, but by default, these logs may not persist across reboots. This means that troubleshooting issues from previous sessions can be difficult. Enabling persistent logging ensures that logs are retained even after a system restart.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Enable Persistent Logging
&lt;/h2&gt;

&lt;p&gt;By default, many systems store journal logs in a temporary directory (&lt;code&gt;/run/log/journal&lt;/code&gt;), which is cleared on reboot. Enabling persistent storage allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access logs from previous boots&lt;/li&gt;
&lt;li&gt;Investigate system crashes or unexpected reboots&lt;/li&gt;
&lt;li&gt;Maintain a continuous log history for auditing and debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Steps to Enable Persistent Journal Storage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Create the Persistent Log Directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/log/journal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This directory is where systemd will store persistent journal files.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Apply Correct Permissions and Settings
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemd-tmpfiles &lt;span class="nt"&gt;--create&lt;/span&gt; &lt;span class="nt"&gt;--prefix&lt;/span&gt; /var/log/journal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command ensures that the directory has the proper ownership and permissions required by &lt;code&gt;journald&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Restart the Journaling Service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart systemd-journald
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restarting the service makes the change effective immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying the Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Check Directory Existence
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-ld&lt;/span&gt; /var/log/journal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirms that the directory exists and has the expected permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  List Available Boot Logs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;journalctl &lt;span class="nt"&gt;--list-boots&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After enabling persistence and rebooting at least once, this command will show a list of previous system boots, allowing you to inspect logs from earlier sessions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Enabling persistent journaling is a straightforward but important configuration step for maintaining system observability. Once configured, you gain access to historical logs that are essential for diagnosing issues and understanding system behavior over time.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Using Tinyproxy as a Simple Proxy</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Fri, 10 Apr 2026 07:23:26 +0000</pubDate>
      <link>https://forem.com/vast-cow/using-tinyproxy-as-a-simple-proxy-alpine-linux-example-1g</link>
      <guid>https://forem.com/vast-cow/using-tinyproxy-as-a-simple-proxy-alpine-linux-example-1g</guid>
      <description>&lt;p&gt;This article focuses strictly on setting up and using &lt;strong&gt;Tinyproxy&lt;/strong&gt;—a lightweight HTTP/HTTPS proxy—on Alpine Linux. The goal is to get a minimal proxy running and understand how to use it from another machine or client.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Installing Tinyproxy
&lt;/h2&gt;

&lt;p&gt;On Alpine Linux, installation is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apk add tinyproxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This installs the Tinyproxy service and default configuration files.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Basic Configuration
&lt;/h2&gt;

&lt;p&gt;The main configuration file is typically located at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;/&lt;span class="n"&gt;etc&lt;/span&gt;/&lt;span class="n"&gt;tinyproxy&lt;/span&gt;/&lt;span class="n"&gt;tinyproxy&lt;/span&gt;.&lt;span class="n"&gt;conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At minimum, configure the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apache"&gt;&lt;code&gt;Port 8080
&lt;span class="nc"&gt;Listen&lt;/span&gt; 0.0.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What these settings mean
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Port 8080&lt;/strong&gt;&lt;br&gt;
Tinyproxy will listen for incoming proxy connections on port 8080.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Listen 0.0.0.0&lt;/strong&gt;&lt;br&gt;
Allows connections from any network interface (not just localhost).&lt;br&gt;
This is required if you want to access the proxy from another machine.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Starting Tinyproxy
&lt;/h2&gt;

&lt;p&gt;You have two operational modes depending on your use case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A — Run in foreground (debug mode)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tinyproxy &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; /etc/tinyproxy/tinyproxy.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt;: Runs in foreground (useful for debugging/logging)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-c&lt;/code&gt;: Specifies config file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use this when testing or troubleshooting.&lt;/p&gt;




&lt;h3&gt;
  
  
  Option B — Run as a background service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rc-service tinyproxy start
rc-update add tinyproxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Starts Tinyproxy as a daemon&lt;/li&gt;
&lt;li&gt;Enables it to launch automatically at boot&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Using Tinyproxy
&lt;/h2&gt;

&lt;p&gt;Once running, Tinyproxy acts as a standard HTTP proxy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Using it from a client
&lt;/h3&gt;

&lt;p&gt;If your Tinyproxy server is at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;172.27.59.40:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can configure tools to use it as a proxy.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using &lt;code&gt;curl&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-x&lt;/span&gt; http://172.27.59.40:8080 http://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using environment variables
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://172.27.59.40:8080"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://172.27.59.40:8080"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now most CLI tools will route traffic through Tinyproxy.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Example: Using Tinyproxy with SSH (via netcat)
&lt;/h2&gt;

&lt;p&gt;Tinyproxy can also proxy TCP connections using the HTTP CONNECT method.&lt;/p&gt;

&lt;p&gt;Add this to your SSH config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;Host&lt;/span&gt; foomachine
    &lt;span class="k"&gt;HostName&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;.2.3.4
    &lt;span class="k"&gt;ProxyCommand&lt;/span&gt; nc -X connect -x &lt;span class="m"&gt;172&lt;/span&gt;.27.59.40:8080 %h %p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nc -X connect&lt;/code&gt; → uses HTTP CONNECT proxy mode&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-x 172.27.59.40:8080&lt;/code&gt; → specifies the Tinyproxy server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;%h %p&lt;/code&gt; → target host and port&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then connect normally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh foomachine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The connection will be routed through Tinyproxy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Tinyproxy provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A minimal, lightweight HTTP/HTTPS proxy&lt;/li&gt;
&lt;li&gt;Simple configuration (port + listen address)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Flexible usage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLI tools (&lt;code&gt;curl&lt;/code&gt;, env vars)&lt;/li&gt;
&lt;li&gt;SSH tunneling via &lt;code&gt;nc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;General proxy routing&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;For most use cases, the minimal configuration shown above is sufficient to get a working proxy quickly.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>networking</category>
      <category>tooling</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Automatically Re-Enable Low Power Mode on iPhone</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Sun, 29 Mar 2026 07:54:15 +0000</pubDate>
      <link>https://forem.com/vast-cow/how-to-automatically-re-enable-low-power-mode-on-iphone-3cdd</link>
      <guid>https://forem.com/vast-cow/how-to-automatically-re-enable-low-power-mode-on-iphone-3cdd</guid>
      <description>&lt;h2&gt;
  
  
  And Add a Shortcut to Toggle the Automation On and Off
&lt;/h2&gt;

&lt;p&gt;Low Power Mode on iPhone is useful, but in some cases it can turn itself off automatically.&lt;br&gt;
When that happens, turning it back on manually every time gets old fast.&lt;/p&gt;

&lt;p&gt;A practical solution is to combine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an automation that turns &lt;strong&gt;Low Power Mode back on whenever it gets turned off&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;a separate Shortcut that lets you &lt;strong&gt;enable or disable that behavior whenever you want&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this setup, a hidden file stored in &lt;strong&gt;On My iPhone&lt;/strong&gt; is used as a flag to determine whether automatic re-enabling should run. The toggle Shortcut switches between &lt;code&gt;.lowpowermode-enabled&lt;/code&gt; and &lt;code&gt;.lowpowermode-disabled&lt;/code&gt;, and also turns Low Power Mode itself on or off at the same time. &lt;br&gt;
The re-enable Shortcut checks for &lt;code&gt;.lowpowermode-enabled&lt;/code&gt;, and only turns Low Power Mode back on when that flag is active. It can also display a notification afterward. &lt;/p&gt;




&lt;h2&gt;
  
  
  What this article will build
&lt;/h2&gt;

&lt;p&gt;By the end of this guide, you will have three parts working together.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. A toggle Shortcut
&lt;/h3&gt;

&lt;p&gt;This Shortcut lets you switch the behavior between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;enabled&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;disabled&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Internally, it does that by renaming a flag file stored in &lt;strong&gt;On My iPhone&lt;/strong&gt;.&lt;br&gt;
When enabled, the file is &lt;code&gt;.lowpowermode-enabled&lt;/code&gt;.&lt;br&gt;
When disabled, the file is &lt;code&gt;.lowpowermode-disabled&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. A re-enable Shortcut
&lt;/h3&gt;

&lt;p&gt;This Shortcut is triggered by automation when Low Power Mode turns off.&lt;br&gt;
It checks whether the enabled flag is present, and if so, it turns Low Power Mode back on. &lt;/p&gt;

&lt;h3&gt;
  
  
  3. A personal automation
&lt;/h3&gt;

&lt;p&gt;This automation runs when Low Power Mode is turned off and launches the re-enable Shortcut.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the system works
&lt;/h2&gt;

&lt;p&gt;The logic is straightforward.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A toggle Shortcut changes whether the feature is enabled or disabled.&lt;/li&gt;
&lt;li&gt;That state is stored using a flag file name.&lt;/li&gt;
&lt;li&gt;Low Power Mode turns off.&lt;/li&gt;
&lt;li&gt;A personal automation runs.&lt;/li&gt;
&lt;li&gt;The re-enable Shortcut checks the flag.&lt;/li&gt;
&lt;li&gt;If enabled, it turns Low Power Mode back on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key idea is that the automation itself remains in place all the time.&lt;br&gt;
Whether it actually re-enables Low Power Mode is controlled by the flag file.&lt;/p&gt;

&lt;p&gt;That is much easier to manage than editing the automation every time you want to pause or resume the behavior.&lt;/p&gt;




&lt;h2&gt;
  
  
  Preparation
&lt;/h2&gt;

&lt;p&gt;Before building the Shortcuts, create the flag file structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storage location
&lt;/h3&gt;

&lt;p&gt;This setup uses &lt;strong&gt;On My iPhone&lt;/strong&gt; as the storage location.&lt;br&gt;
The uploaded Shortcut definitions also point to local storage under that location.&lt;/p&gt;

&lt;h3&gt;
  
  
  Files used as flags
&lt;/h3&gt;

&lt;p&gt;Create one of these files to start with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.lowpowermode-enabled&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.lowpowermode-disabled&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want the auto-re-enable behavior to start in the active state, create &lt;code&gt;.lowpowermode-enabled&lt;/code&gt; first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important note
&lt;/h3&gt;

&lt;p&gt;The file names need to match exactly.&lt;br&gt;
If the names are off by even one character, the logic will fail.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1: Build the toggle Shortcut
&lt;/h2&gt;

&lt;p&gt;Start by creating the Shortcut that enables or disables the entire behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this Shortcut does
&lt;/h3&gt;

&lt;p&gt;Based on the uploaded Shortcut definition, the flow works like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try to get &lt;code&gt;.lowpowermode-enabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If that file is returned, rename it to &lt;code&gt;.lowpowermode-disabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Turn Low Power Mode off&lt;/li&gt;
&lt;li&gt;Otherwise, get &lt;code&gt;.lowpowermode-disabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Rename it to &lt;code&gt;.lowpowermode-enabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Turn Low Power Mode on &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So this Shortcut handles two things at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;switching the flag state&lt;/li&gt;
&lt;li&gt;switching Low Power Mode itself&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to create it
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Create a new Shortcut
&lt;/h4&gt;

&lt;p&gt;Open the Shortcuts app and create a new Shortcut.&lt;/p&gt;

&lt;p&gt;A few good names:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Low Power Mode Auto Toggle&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Toggle Low Power Mode Auto Restore&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Add “Get File from Folder”
&lt;/h4&gt;

&lt;p&gt;Add &lt;strong&gt;Get File from Folder&lt;/strong&gt; as the first action.&lt;/p&gt;

&lt;p&gt;Configure it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Location: &lt;code&gt;On My iPhone&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;File path: &lt;code&gt;.lowpowermode-enabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Error if not found: Off&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Add an “If” action
&lt;/h4&gt;

&lt;p&gt;Set the condition to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;If File has any value&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This checks whether &lt;code&gt;.lowpowermode-enabled&lt;/code&gt; was successfully returned.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. In the “If” branch
&lt;/h4&gt;

&lt;p&gt;Add these actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rename File&lt;/strong&gt;
&lt;code&gt;.lowpowermode-enabled&lt;/code&gt; → &lt;code&gt;.lowpowermode-disabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set Low Power Mode&lt;/strong&gt;
Off&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means the feature is currently enabled, so the Shortcut disables it. &lt;/p&gt;

&lt;h4&gt;
  
  
  5. In the “Otherwise” branch
&lt;/h4&gt;

&lt;p&gt;Add these actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Get File from Folder&lt;/strong&gt;
&lt;code&gt;.lowpowermode-disabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rename File&lt;/strong&gt;
&lt;code&gt;.lowpowermode-disabled&lt;/code&gt; → &lt;code&gt;.lowpowermode-enabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set Low Power Mode&lt;/strong&gt;
On&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means the feature is currently disabled, so the Shortcut enables it. &lt;/p&gt;

&lt;h3&gt;
  
  
  Result
&lt;/h3&gt;

&lt;p&gt;Once finished, this Shortcut becomes a single tap toggle for the whole system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;enabled → disabled&lt;/li&gt;
&lt;li&gt;disabled → enabled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also keeps the actual Low Power Mode state synchronized with the flag state. &lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: Build the re-enable Shortcut
&lt;/h2&gt;

&lt;p&gt;Now create the Shortcut that turns Low Power Mode back on when needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  What this Shortcut does
&lt;/h3&gt;

&lt;p&gt;According to the uploaded definition, its logic is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;get &lt;code&gt;.lowpowermode-enabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;check it with an If condition&lt;/li&gt;
&lt;li&gt;if the file has a value, turn Low Power Mode on&lt;/li&gt;
&lt;li&gt;show a notification saying: &lt;strong&gt;“Turned Low Power Mode back on”&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to create it
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Create a new Shortcut
&lt;/h4&gt;

&lt;p&gt;Create another Shortcut in the Shortcuts app.&lt;/p&gt;

&lt;p&gt;Suggested names:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Re-enable Low Power Mode&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Restore Low Power Mode&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Add “Get File from Folder”
&lt;/h4&gt;

&lt;p&gt;Add &lt;strong&gt;Get File from Folder&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Configure it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Location: &lt;code&gt;On My iPhone&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;File path: &lt;code&gt;.lowpowermode-enabled&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Add an “If” action
&lt;/h4&gt;

&lt;p&gt;Use this condition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;If File has any value&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means the rest of the Shortcut only runs if the enabled flag is present.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. In the “If” branch
&lt;/h4&gt;

&lt;p&gt;Add these actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set Low Power Mode&lt;/strong&gt;
On&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Show Notification&lt;/strong&gt;
Title: &lt;code&gt;Turned Low Power Mode back on&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That matches the uploaded Shortcut behavior. &lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3: Create the personal automation
&lt;/h2&gt;

&lt;p&gt;With both Shortcuts ready, the last step is connecting the re-enable Shortcut to a personal automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Open the Automation tab
&lt;/h4&gt;

&lt;p&gt;In the Shortcuts app, go to &lt;strong&gt;Automation&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Create a new personal automation
&lt;/h4&gt;

&lt;p&gt;Tap &lt;strong&gt;Create Personal Automation&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Choose “Low Power Mode” as the trigger
&lt;/h4&gt;

&lt;p&gt;From the available triggers, select &lt;strong&gt;Low Power Mode&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Set the trigger to “Is Turned Off”
&lt;/h4&gt;

&lt;p&gt;This is the critical setting.&lt;br&gt;
You want the automation to run &lt;strong&gt;when Low Power Mode is turned off&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Add “Run Shortcut”
&lt;/h4&gt;

&lt;p&gt;For the action, choose &lt;strong&gt;Run Shortcut&lt;/strong&gt; and select your re-enable Shortcut, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Re-enable Low Power Mode&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  6. Turn off confirmation prompts
&lt;/h4&gt;

&lt;p&gt;Adjust these settings as needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;turn off &lt;strong&gt;Ask Before Running&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;optionally adjust &lt;strong&gt;Notify When Run&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, whenever Low Power Mode turns off, the automation runs the re-enable Shortcut automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;p&gt;Daily use is simple.&lt;/p&gt;

&lt;h3&gt;
  
  
  When you want auto re-enable active
&lt;/h3&gt;

&lt;p&gt;Run the toggle Shortcut once.&lt;/p&gt;

&lt;p&gt;That changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.lowpowermode-disabled&lt;/code&gt; → &lt;code&gt;.lowpowermode-enabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Low Power Mode → On &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When you want to pause the behavior
&lt;/h3&gt;

&lt;p&gt;Run the same toggle Shortcut again.&lt;/p&gt;

&lt;p&gt;That changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.lowpowermode-enabled&lt;/code&gt; → &lt;code&gt;.lowpowermode-disabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Low Power Mode → Off &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So in practice, one Shortcut controls the entire system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this setup is useful
&lt;/h2&gt;

&lt;h3&gt;
  
  
  You do not need to edit the automation every time
&lt;/h3&gt;

&lt;p&gt;The automation can stay in place permanently.&lt;br&gt;
You only change the flag state through the toggle Shortcut.&lt;/p&gt;

&lt;h3&gt;
  
  
  The state is easy to understand
&lt;/h3&gt;

&lt;p&gt;The file name tells you exactly what mode the system is in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.lowpowermode-enabled&lt;/code&gt; = active&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.lowpowermode-disabled&lt;/code&gt; = inactive&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  It is easy to extend
&lt;/h3&gt;

&lt;p&gt;Because the system is flag-based, it is also easy to expand later.&lt;br&gt;
For example, you could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;change the notification text&lt;/li&gt;
&lt;li&gt;add logging&lt;/li&gt;
&lt;li&gt;allow auto re-enable only during certain hours&lt;/li&gt;
&lt;li&gt;disable it while a Focus mode is active&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Things to watch out for
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Keep the file location consistent
&lt;/h3&gt;

&lt;p&gt;Both the toggle Shortcut and the re-enable Shortcut need to read from the same place.&lt;br&gt;
If one points to a different folder, the system will break.&lt;/p&gt;

&lt;h3&gt;
  
  
  File names must be exact
&lt;/h3&gt;

&lt;p&gt;Use these names exactly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.lowpowermode-enabled&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.lowpowermode-disabled&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Notifications may appear often
&lt;/h3&gt;

&lt;p&gt;The re-enable Shortcut includes a notification action.&lt;br&gt;
If Low Power Mode is turned off frequently, you may see that alert more often than you want. &lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This approach gives you a clean way to make iPhone automatically turn Low Power Mode back on, while still keeping the behavior easy to control.&lt;/p&gt;

&lt;p&gt;The core idea is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;strong&gt;Get File from Folder&lt;/strong&gt; to read a flag file&lt;/li&gt;
&lt;li&gt;use &lt;strong&gt;If File has any value&lt;/strong&gt; to determine whether the feature is enabled&lt;/li&gt;
&lt;li&gt;use one Shortcut to toggle the flag state&lt;/li&gt;
&lt;li&gt;use another Shortcut to restore Low Power Mode when the automation fires&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The toggle Shortcut handles both renaming the flag file and switching Low Power Mode itself, while the re-enable Shortcut checks the enabled flag and only restores the setting when appropriate.&lt;/p&gt;

&lt;p&gt;That makes this more practical than a basic always-on automation.&lt;br&gt;
It gives you automatic recovery &lt;strong&gt;and&lt;/strong&gt; manual control.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>If You Have Multiple Tailscale Machines Behind the Same NAT, Change the `tailscaled` Port</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Wed, 11 Mar 2026 09:57:10 +0000</pubDate>
      <link>https://forem.com/vast-cow/if-you-have-multiple-tailscale-machines-behind-the-same-nat-change-the-tailscaled-port-58de</link>
      <guid>https://forem.com/vast-cow/if-you-have-multiple-tailscale-machines-behind-the-same-nat-change-the-tailscaled-port-58de</guid>
      <description>&lt;p&gt;When you run multiple Tailscale nodes at the same site, you may notice that only one machine establishes a direct connection while the others fall back to using a relay.&lt;/p&gt;

&lt;p&gt;In environments where several hosts sit behind the same NAT, using the same &lt;code&gt;tailscaled&lt;/code&gt; UDP port on every machine can make direct connectivity less reliable. In that case, assigning a different port to each machine is a practical fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;By default, &lt;code&gt;tailscaled&lt;/code&gt; uses the same UDP port on every host.&lt;/p&gt;

&lt;p&gt;That is usually fine for a single machine. But when you have multiple machines in the same location, all sharing the same public IP address, NAT port mappings can become awkward. As a result, one machine may keep a clean direct path while the others end up using a relay path instead.&lt;/p&gt;

&lt;p&gt;This is not always catastrophic, but it is suboptimal. Relay traffic generally adds latency and makes the connection path less direct than it needs to be.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix
&lt;/h2&gt;

&lt;p&gt;A simple approach is to give each machine its own &lt;code&gt;tailscaled&lt;/code&gt; port.&lt;/p&gt;

&lt;p&gt;On Linux systems managed by systemd, edit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/etc/default/tailscaled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set a different port on each host.&lt;/p&gt;

&lt;p&gt;For example, on one machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;41641
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On another:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;41642
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And on a third:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;41643
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then restart the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart tailscaled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Helps
&lt;/h2&gt;

&lt;p&gt;When each machine uses a distinct UDP port, NAT mappings are less likely to collide or behave in a way that prevents stable direct paths. That improves the chances that each node can establish direct peer-to-peer connectivity instead of falling back to relay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things to Keep in Mind
&lt;/h2&gt;

&lt;p&gt;Make sure the chosen ports do not overlap across machines at the same site.&lt;/p&gt;

&lt;p&gt;Also confirm that local firewall rules or upstream network policies allow the UDP ports you assign.&lt;/p&gt;

&lt;p&gt;After restarting &lt;code&gt;tailscaled&lt;/code&gt;, verify the result with your usual Tailscale checks, such as connection status or ping tests, to confirm that nodes are using direct paths where expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;If you have multiple Tailscale machines behind the same NAT, leaving them all on the same &lt;code&gt;tailscaled&lt;/code&gt; port can lead to a situation where only one host gets a direct path and the rest use relay.&lt;/p&gt;

&lt;p&gt;A straightforward remedy is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edit &lt;code&gt;/etc/default/tailscaled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Assign a unique port per machine&lt;/li&gt;
&lt;li&gt;Restart the service
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart tailscaled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is a small change, but in multi-node same-site deployments, it can make direct connectivity much more consistent.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>tooling</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Which NVIDIA HPC SDK Versions Bundle (or Don’t Bundle) CUDA 12 and CUDA 13</title>
      <dc:creator>vast cow</dc:creator>
      <pubDate>Tue, 24 Feb 2026 07:36:07 +0000</pubDate>
      <link>https://forem.com/vast-cow/which-nvidia-hpc-sdk-versions-bundle-or-dont-bundle-cuda-12-and-cuda-13-f0d</link>
      <guid>https://forem.com/vast-cow/which-nvidia-hpc-sdk-versions-bundle-or-dont-bundle-cuda-12-and-cuda-13-f0d</guid>
      <description>&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Goal / Interpretation of “latest”&lt;/th&gt;
&lt;th&gt;Latest HPC SDK version that matches&lt;/th&gt;
&lt;th&gt;Bundled CUDA toolchains (as stated in the sources)&lt;/th&gt;
&lt;th&gt;Notes / Boundary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latest NVHPC that does &lt;em&gt;not&lt;/em&gt; bundle CUDA 13.0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;25.7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CUDA 11.8 + CUDA 12.9U1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CUDA 13.0 bundling starts at &lt;strong&gt;25.9&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;First NVHPC that bundles CUDA 13.0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;25.9&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CUDA 13.0 + CUDA 12.9U1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Marks the transition to CUDA 13.0 in the bundle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Latest NVHPC that does &lt;em&gt;not&lt;/em&gt; bundle CUDA 12&lt;/strong&gt; (i.e., last pre-CUDA-12 era)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;22.11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CUDA 10.2 / 11.0 / 11.8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CUDA 12 bundling begins at &lt;strong&gt;23.1&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;First NVHPC that bundles CUDA 12&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;23.1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;CUDA 12.0&lt;/strong&gt; (bundled/support introduced)&lt;/td&gt;
&lt;td&gt;From here onward, the “no CUDA 12 bundled” condition is not met&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
    </item>
  </channel>
</rss>
