<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on Random Stuff - Too Many Machines</title><link>https://random.too-many-machines.com/posts/</link><description>Recent content in Posts on Random Stuff - Too Many Machines</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>© Igor Wawrzyniak</copyright><lastBuildDate>Sat, 14 Dec 2024 21:00:00 +0100</lastBuildDate><atom:link href="https://random.too-many-machines.com/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>The state of post-quantum cryptography at the end of 2024</title><link>https://random.too-many-machines.com/posts/post-quantum-2024/</link><pubDate>Sat, 14 Dec 2024 21:00:00 +0100</pubDate><guid>https://random.too-many-machines.com/posts/post-quantum-2024/</guid><description>&lt;img src="https://random.too-many-machines.com/posts/post-quantum-2024/pqc-cloudflare.png" alt="Featured image of post The state of post-quantum cryptography at the end of 2024" /&gt;&lt;p&gt;The recent hype about Google Willow inspired me to recheck what&amp;rsquo;s happening in the world of post-quantum cryptography.&lt;/p&gt;
&lt;p&gt;You probably already heard the alarming news - all of our encryption is becoming useless. The reality is not as tragic. What is true is that most &lt;strong&gt;asymmetric&lt;/strong&gt; algorithms (those with public and private key) are very weak against quantum computers. They are widely used for two purposes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most encrypted protocols (that utilize a much faster symmetric encryption for the vast majority of the traffic) randomly generate a key at the beginning of the session and use asymmetric encryption to send this key to the other party. This is called KEX (Key EXchange) or KEM (Key Encapsulation Mechanism), depending on the exact way.&lt;/li&gt;
&lt;li&gt;Digital signatures, for example those that confirm who&amp;rsquo;s the owner of a TLS certificate or a publisher of a software package.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But the alarming articles routinely fail to mention the good news:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We don&amp;rsquo;t have a quantum computer that can break a modern encryption (although it doesn&amp;rsquo;t exist, it already has a name: &lt;strong&gt;CRQC&lt;/strong&gt;, Cryptographically-Relevant Quantum Computer), current ones are either too small or too unstable. We are getting closer, experts predict CRQC will be available in the next few years.&lt;/li&gt;
&lt;li&gt;Symmetric algorithms, which do almost 100% of the work, are safe. There are some quantum-based attacks that slightly reduce the effectiveness of the cyphers, but simply increasing the key length (which we had to do anyway due to the widespread use of GPU computing for cracking encryption) mitigates the risk.&lt;/li&gt;
&lt;li&gt;Hash algorithms (used, among other things, for storing encrypted passwords) are also safe. Again, the real danger came from GPUs, but this has already been taken care of.&lt;/li&gt;
&lt;li&gt;Current software can be easily modified for post-quantum secrecy. It&amp;rsquo;s modular, algorithms are changed every few years anyway, due to increase in CPU/GPU power and sometimes when the weaknesses are found.&lt;/li&gt;
&lt;li&gt;We already have some quantum-resistant asymmetric algorithms in use and adoption is rising very fast - according to Cloudflare, from 2% in January to 13% in December 2024 in the traffic they see.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="official-standards"&gt;Official standards
&lt;/h2&gt;&lt;p&gt;In August 2024 NIST, (National Institute of Standards and Technology, a US government agency) published the first 3 official standards and more are coming:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FIPS203 for key exchange.&lt;/li&gt;
&lt;li&gt;FIPS204 and FIPS205 for digital signatures.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of those, at least FIPS203 was already (relatively) widely used, although not always called that. NIST doesn&amp;rsquo;t develop new algorithms, it chooses from the submitted proposals. The one that became FIPS203 is mostly known as Kyber or ML-KEM. Adversaries can (and do) harvest encrypted data now to decrypt it in future (just as you can easily crack 1990s encryption with a PC of today), therefore it&amp;rsquo;s a good idea to move to post-quantum standards as soon as possible.&lt;/p&gt;
&lt;p&gt;Securing digital signatures against the quantum computing is not as urgent. Once CRQC are available, they will be a huge threat. Quick refresher: signatures can be checked with a public key, but to make them you need a private key, which should be well guarded. Obtaining the private key from the public key is, for all practical purposes, impossible with a classical computer (as in: even if you use all the world computing power to break just one key, you&amp;rsquo;d still need more time than the life expectancy of the Sun). But it&amp;rsquo;s fast with a quantum computer. However, it&amp;rsquo;s not much use retroactively. You could use a CRQC to decrypt TLS traffic harvested now, that&amp;rsquo;s a real threat for some use cases. But forging 2024 certificate in 2034 will be useless. We just need to switch to quantum-safe algorithms before CRQC.&lt;/p&gt;
&lt;h2 id="client-support---mostly-done"&gt;Client support - mostly done
&lt;/h2&gt;&lt;p&gt;Chrome has implemented Kyber/FIPS203 since version 115 released in August 2023. That also includes all derivative browsers such as Edge, Opera and Vivaldi. Firefox added support in January 2024. The only major browser that doesn&amp;rsquo;t support it is Safari.&lt;/p&gt;
&lt;p&gt;Messaging apps such as Signal, WhatsApp and iMessage also support at least one form of post-quantum cryptography.&lt;/p&gt;
&lt;h2 id="server-support---not-as-good"&gt;Server support - not as good
&lt;/h2&gt;&lt;p&gt;I found it peculiar that server-side lags behind client-side in security standards. But Google decided to introduce Kyber early, other browsers followed and since they aggressively auto-update (for good reasons), pretty much all browsers support a quantum-resistant key encapsulation, and most client-side software uses browser components to do the connection. But, until servers get the support, new protocols won&amp;rsquo;t see much use. And servers tend to run older software, also for good reasons: new algorithms mean new security risks. It would be ironic to increase security to the future theoretical threats only to decrease to the current threats - and yet it happened. Few years ago SIDH was a top contender for a quantum-resistant KEM, but it was broken in 2022. And not by a quantum computer, not even by a powerful GPU, a puny single-core CPU was enough - yikes.&lt;/p&gt;
&lt;p&gt;So where do we stand now, in December 2024?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OpenSSL, the library responsible for something like 50% of the TLS support [citation needed], has a policy of only supporting official standards. They are now working on adding FIPS203, but current versions are missing it. However, OpenSSL can be extended with &amp;ldquo;providers&amp;rdquo; - external libraries that add additional crypto algorithms.&lt;/li&gt;
&lt;li&gt;Go language, probably the second most common technology in the server world, has its own crypto libraries and you guessed it: official versions don&amp;rsquo;t support Kyber.&lt;/li&gt;
&lt;li&gt;OpenSSH supports FIPS203, but only in the latest version 9.9, released in September 2024. It is, of course, too new to be included in mainstream Linux distros (Kali is a notable exception, though I&amp;rsquo;m stretching the definition of mainstream).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cloudflare-to-the-rescue"&gt;Cloudflare to the rescue
&lt;/h2&gt;&lt;p&gt;Cloudflare is one of the early adopters. The company provides many services, including TLS termination. Incidentally, I use it for my photo gallery. Nice to know that my completely insignificant website that only contains 100% public information is well protected against state-level adversaries of the future! They also publish &lt;a class="link" href="https://blog.cloudflare.com/tag/post-quantum/" target="_blank" rel="noopener"
 &gt;stats and articles about the topic&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="open-quantum-safe"&gt;Open Quantum Safe
&lt;/h2&gt;&lt;p&gt;Open Quantum Safe or OQS is a research project of the Linux Foundation. One of their works is liboqs, a C library providing a large number of quantum-resistant algorithms, plus integrations into current software, such as OpenSSL or OpenSSH. If you want to get started with it, the fastest way is compiling a provider for OpenSSL. It is available on &lt;a class="link" href="https://github.com/open-quantum-safe/oqs-provider" target="_blank" rel="noopener"
 &gt;the GitHub repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I checked a few recent Linux distro and none had a liboqs package. Why, if it&amp;rsquo;s free, opensource, and comes from a reputable source? One of the reasons might be, ironically, security. The goal of the project is to help with research and software testing, it&amp;rsquo;s not intended for production use. The library contains numerous algorithms, not only the official ones or top contenders, but also those that aren&amp;rsquo;t well tested, or even those that were rejected. Which means a large attack surface. In fact, there are known security vulnerabilities in liboqs. If you want to help with testing, then go ahead. If you want to have a full-featured client, be careful. But if you want to protect your server - don&amp;rsquo;t do it, you will be introducing more vulnerabilities than you&amp;rsquo;re fixing.&lt;/p&gt;
&lt;h2 id="how-to-check-common-software-for-post-quantum-support"&gt;How to check common software for post-quantum support
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Browser: go to &lt;a class="link" href="https://pq.cloudflareresearch.com/" target="_blank" rel="noopener"
 &gt;Cloudflare Research Post-Quantum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SSH client: type &lt;code&gt;ssh -Q kex&lt;/code&gt; and look for a line starting with mlkem&lt;/li&gt;
&lt;li&gt;SSH server: connect with &lt;code&gt;-vv&lt;/code&gt; option and check &amp;ldquo;peer server KEXINIT proposal&amp;rdquo; (as a bonus &amp;ldquo;local client KEXINIT proposal&amp;rdquo; will show what your client supports). Alternatively, &lt;code&gt;nmap --script ssh2-enum-algos -sV -p 22 your.ssh.host&lt;/code&gt;. In any case, look for mlkem.&lt;/li&gt;
&lt;li&gt;OpenSSL: &lt;code&gt;openssl list -kem-algorithms&lt;/code&gt; and look for mlkem or kyber.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="SSH client supporting FIPS203 (mlkem)" class="gallery-image" data-flex-basis="323px" data-flex-grow="134" height="373" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://random.too-many-machines.com/posts/post-quantum-2024/pqc-ssh.png" width="503"&gt;&lt;/p&gt;</description></item><item><title>Secret files in Git - transparent encryption and history rewriting</title><link>https://random.too-many-machines.com/posts/git-encrypt/</link><pubDate>Thu, 10 Oct 2024 16:00:00 +0200</pubDate><guid>https://random.too-many-machines.com/posts/git-encrypt/</guid><description>&lt;p&gt;I accidentally posted on GitHub some files I shouldn&amp;rsquo;t: my input files from Advent of Code. I thought it doesn&amp;rsquo;t matter since the files are generated for each player, but AoC author specifically prohibits this.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t think it&amp;rsquo;s a big deal: few people visit my GitHub anyway. But let&amp;rsquo;s solve it. I might need that skill one day for a more serious problem.&lt;/p&gt;
&lt;p&gt;This is a two part problem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I still like to keep my input files on GitHub. I use several computers and sharing files through the repo is convenient. I just have to encrypt them.&lt;/li&gt;
&lt;li&gt;But first, I need to remove the files I posted. It&amp;rsquo;s not enough to delete them, they would still be available in the git history.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="how-to-really-delete-files-from-git"&gt;How to really delete files from git
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;You need an extension called &lt;strong&gt;Filter Repo&lt;/strong&gt;. On Debian or Ubuntu, you can simply run &lt;code&gt;sudo apt install git-filter-repo&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Make sure the state is as clean as possible: no changes, untracked files, open PRs, nobody pushing other changes.&lt;/li&gt;
&lt;li&gt;Next, get a fresh clone of the repo in a new place - for two reasons. Filter Repo insists on working on a fresh clone. And, you want a copy anyway in case something goes wrong.&lt;/li&gt;
&lt;li&gt;Now, the main part: &lt;code&gt;git filter-repo --path &amp;lt;path to the file or directory&amp;gt; --invert-paths&lt;/code&gt;. Don&amp;rsquo;t forget the last argument - the default is to keep only files matched by the filter, but you want to delete those and keep everything else. Instead of &lt;code&gt;--path&lt;/code&gt; you can use &lt;code&gt;--path-glob&lt;/code&gt; or &lt;code&gt;--path-regex&lt;/code&gt; to match multiple files. You can also add &lt;code&gt;--dry-run&lt;/code&gt; to see what files would be deleted. Verify that you deleted everything you wanted to and nothing else.&lt;/li&gt;
&lt;li&gt;Filter Repo also intentionally removes links to remote repositories. There are two ways to deal with it:
&lt;ul&gt;
&lt;li&gt;If the repo is used by many people (or worse, CI systems), the recommended option is to create a new remote repo and inform everyone to switch to it (preferably by cloning a fresh copy).&lt;/li&gt;
&lt;li&gt;Another possibility is to set the remote repo to the same value as it was before and push the changes (with &amp;ndash;force) back to the original upstream repo. Be aware that the files you wanted gone will be deleted from your local copy and from the upstream, but any other copy of the repo will still have them, plus the original, incompatible history. So, all other copies will need to be made clean, either with some heavy git magic, involving rebasing and a lot of &amp;ndash;force, or better deleted and cloned again. Since I&amp;rsquo;m the only user (that I know of), I went with the second option.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The whole set of commands looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git clone git@github.com:igorwaw/advent22.git
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cp -a advent22 advent22.bak &lt;span style="color:#75715e"&gt;# backup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cd advent22
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ls day*/*-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git filter-repo --invert-paths --path-glob &lt;span style="color:#e6db74"&gt;&amp;#39;day*/*-input.txt&amp;#39;&lt;/span&gt; --force
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ls day*/*-input.txt &lt;span style="color:#75715e"&gt;# verification - files are gone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git remote add origin git@github.com:igorwaw/advent22.git
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git pull &lt;span style="color:#75715e"&gt;# to get the remote branches - most of my repos use main, older ones still use master&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git branch --set-upstream-to&lt;span style="color:#f92672"&gt;=&lt;/span&gt;origin/main main
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git pull &lt;span style="color:#75715e"&gt;# verification - this is expected to fail as I have incompatible changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git push --force &lt;span style="color:#75715e"&gt;# rewrite the remote&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git pull &lt;span style="color:#75715e"&gt;# verification - no incoming changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A quick check on GitHub - the files are gone and there are no new commits, no traces of what just happened. This is scary stuff, a proper removal from history. Luckily, the real world history can&amp;rsquo;t be so easily rewritten (OR CAN IT?).&lt;/p&gt;
&lt;h2 id="how-to-transparently-encrypt-files-in-the-repo"&gt;How to transparently encrypt files in the repo
&lt;/h2&gt;&lt;p&gt;There are millions of ways to encrypt files, but the best solution for this use case is something completely transparent: files are encrypted on &lt;em&gt;git push&lt;/em&gt; and decrypted on &lt;em&gt;git pull&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The tool called &lt;strong&gt;git-crypt&lt;/strong&gt; fits perfectly. Easy to get (simple &lt;code&gt;sudo apt install git-crypt&lt;/code&gt;), fast and secure (uses symmetric encryption with AES-256 by default, multi-user setup with GPG keys is also possible). It has some limitations too:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;By far the biggest limitation: no good mechanism for revoking the key. If you simply change it, only new commits will use it, old versions of files will still be encrypted with the old key. Reencrypting old versions is doable, but complex (see above).&lt;/li&gt;
&lt;li&gt;It doesn&amp;rsquo;t hide any metadata. Filenames, modification dates etc. are plainly visible.&lt;/li&gt;
&lt;li&gt;Some git GUIs fail with git-crypt.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of these is relevant for me and advantages clearly outweigh the potential issues. I don&amp;rsquo;t need to hide metadata and if the key leaks, I can just delete and recreate the whole repo.&lt;/p&gt;
&lt;p&gt;First, go to your repo, generate and export the key:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git-crypt init
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git-crypt export-key ../git-crypt-key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, create a file &lt;code&gt;.gitattributes&lt;/code&gt;. It&amp;rsquo;s similar to well-known .gitignore, but informs git to use other transformations than simply ignoring the file. For this case, I needed the following content:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; day*/*-input.txt filter&lt;span style="color:#f92672"&gt;=&lt;/span&gt;git-crypt diff&lt;span style="color:#f92672"&gt;=&lt;/span&gt;git-crypt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course I had to put the input files back. Then, &lt;code&gt;git-crypt status -e&lt;/code&gt; shows what files will be encrypted:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ advent22 git:&lt;span style="color:#f92672"&gt;(&lt;/span&gt;main&lt;span style="color:#f92672"&gt;)&lt;/span&gt; ✗ git-crypt status -e
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day1-9/1-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day1-9/2-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day1-9/3-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day1-9/4-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day1-9/5-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day1-9/6-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day1-9/7-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day1-9/8-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day1-9/9-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day10-14/10-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day10-14/11-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day10-14/12-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day10-14/13-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; encrypted: day10-14/14-input.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can encrypt them with &lt;code&gt;git-crypt lock&lt;/code&gt;, but there&amp;rsquo;s no need. Simply add the new files, commit them and push to the remote repo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git add .gitattributes day*/*input.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git commit -m &lt;span style="color:#e6db74"&gt;&amp;#34;encrypted inputs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, go to GitHub and see what was committed - the files will look like this: &lt;code&gt; GITCRYPT r5”4Â)ùKåæÜ¿„ÚÊ¶&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="using-the-encrypted-repo-on-another-machine"&gt;Using the encrypted repo on another machine
&lt;/h3&gt;&lt;p&gt;Copy the exported keyfile to another machine in a secure way (eg. using &lt;code&gt;sftp&lt;/code&gt; or &lt;code&gt;rsync -e ssh&lt;/code&gt;). Place the keyfile in any convenient place outside the repo (one directory level up is convenient), then run the command: &lt;code&gt;git-crypt unlock ../git-crypt-key&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="reusing-the-encryption-key"&gt;Reusing the encryption key
&lt;/h3&gt;&lt;p&gt;I&amp;rsquo;m going to use the same key for all of my Advent of Code repos. No, it&amp;rsquo;s not the same as using the same password for many websites. These are all under my control, just split into several repos for convenience. How do you do that? Simple: the same way as unlocking the repo on another machine in the previous step.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd ../advent15
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git-crypt unlock ../git-crypt-key
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There&amp;rsquo;s nothing to unlock yet, but the command also initializes the hidden git-crypt files if they don&amp;rsquo;t exist, only it doesn&amp;rsquo;t create the new keyfile. Confusing, yes. Then, create the &lt;code&gt;.gitattributes&lt;/code&gt;, add, commit and push files exactly the same way as in the previous repo.&lt;/p&gt;</description></item><item><title>Switching from Docker to Podman</title><link>https://random.too-many-machines.com/posts/from-docker-to-podman/</link><pubDate>Sat, 21 Sep 2024 16:00:00 +0200</pubDate><guid>https://random.too-many-machines.com/posts/from-docker-to-podman/</guid><description>&lt;p&gt;Many distributions have switched from Docker to other container engines. There were different reasons for it - licensing or design choices - but for years I ignored the trend. I thought: container engines are supposedly 99% compatible with Docker, after all they all claim to support OCI standard, but somehow I always run into this 1% of incompatibility. So I just always installed Docker to avoid the issues.&lt;/p&gt;
&lt;p&gt;Few months ago the principal engineer at my workplace, who&amp;rsquo;s a big fan of Podman, encouraged me to give it another try - to spend a few hours learning about the differences before I decide that something doesn&amp;rsquo;t work with Podman. I quickly discovered things that are obvious to any Podman user: while the command line tool is compatible and you can do &amp;ldquo;alias docker=podman&amp;rdquo;, there are some deeper differences. Once you learn them, you can do all the same things as with Docker, plus some more.&lt;/p&gt;
&lt;p&gt;Short version: whenever there&amp;rsquo;s a choice between convenience and security, Docker defaults to convenience and Podman to security.&lt;/p&gt;
&lt;h2 id="container-registries"&gt;Container registries
&lt;/h2&gt;&lt;p&gt;Let&amp;rsquo;s start with the simplest one. Check any tutorial on Docker and it will start with &amp;ldquo;docker run -it ubuntu&amp;rdquo; or something similar. Such command will probably fail with Podman. Docker tries to run a locally available image, if it doesn&amp;rsquo;t find one, it downloads it from docker.io registry. You can point it to another registry by giving full path, but that&amp;rsquo;s the default one.&lt;/p&gt;
&lt;p&gt;Anyone can upload their software to docker.io registry. Obviously it has some good sides - a huge range of images to choose from and a place to store your own stuff. But that also means you can accidentally download some low quality code. Or worse, malicious code that steals your data. Many companies forbid the use of public container registries.&lt;/p&gt;
&lt;p&gt;Podman has no default container registry (unless your distro already changed the default configuration). You can configure one (or multiple) in /etc/containers/registries.conf, it might be your company&amp;rsquo;s internal server, might be docker.io or another public one eg. quay.io. Or you can provide full path: &amp;ldquo;podman run -it docker.io/ubuntu&amp;rdquo;. Or you can configure shortnames only for specific images - for example Ubuntu does that with their Podman package, meaning that &amp;ldquo;podman run&amp;rdquo; will work with ubuntu, rhel, alpine, python and many other well-known images, but not with some random stuff found on the net. All of these don&amp;rsquo;t prevent the problem of downloading the bad stuff, but it makes it a bit harder to do by accident. If you don&amp;rsquo;t agree, it&amp;rsquo;s easy to change the default to the same as Docker&amp;rsquo;s.&lt;/p&gt;
&lt;h2 id="networks-and-pods"&gt;Networks and pods
&lt;/h2&gt;&lt;p&gt;Let&amp;rsquo;s now move from Docker to Docker Compose tutorial. It usually involves running several containers, let&amp;rsquo;s say: frontend, backend and database. Each one can connect to others using their names. That won&amp;rsquo;t work with Podman - unless you inform Podman that this is your intention. For example, by placing them in the same pod.&lt;/p&gt;
&lt;p&gt;The concept of pods comes from Kubernetes. Pods contain several containers grouped together - and they obviously are supposed to communicate. They can also be started/stopped together. But they really show their strength when you move to Kubernetes - see a few points below.&lt;/p&gt;
&lt;p&gt;There are also other ways to connect the containers, you&amp;rsquo;re not forced to use pods. You can use the host&amp;rsquo;s hostname if the ports are exposed. Or configure a private network, they have name resolution. Or configure a service mesh or a discovery service. Or, if you insist, you can enable dnsname plugin on the default network (the one simply called podman). Podman is just missing one shortcut option that&amp;rsquo;s present in Docker because, again, it makes it harder to do insecure things by accident.&lt;/p&gt;
&lt;h2 id="rootless"&gt;Rootless
&lt;/h2&gt;&lt;p&gt;The biggest difference between Docker and Podman. By default, Docker runs as root. Even if you run docker command as a user, it talks with the daemon that runs as root - and so the containers are started as root. Podman, on the other hand, really runs with the privileges of the user who invoked it. This has some serious implications:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The good: Podman is much more secure by design. If Docker fails to properly isolate the container (and there were such vulnerabilities in the past), the container can get full root rights to the host system and other containers. With Podman, the worst case scenario is getting access to one user account.&lt;/li&gt;
&lt;li&gt;The bad: some containers need more than 1 user id. Podman can provide a full set of 2^16 ids using subids. No big deal, but: you have to have a proper configuration in /etc/subuid and /etc/subgid - with any modern distro and the standard way of creating accounts, you usually do, if you do something uncommon you might have to manually edit the file. And if your containers bind mount directories from the host filesystem, you may run into permission problems. Again, quite easily fixable with &amp;ldquo;podman unshare chown&amp;rdquo; or &amp;ldquo;:U&amp;rdquo; option for the volume, but more than one person ran into this and decided that Podman doesn&amp;rsquo;t work.&lt;/li&gt;
&lt;li&gt;The ugly: some, but very few containers, really need extra privileges. If that is the case, you know what you&amp;rsquo;re doing and you&amp;rsquo;re accepting security implications, you can simply run podman as root. You&amp;rsquo;re opting out of extra isolation, but at least it&amp;rsquo;s for the selected few containers, not all of them. Even better, you can fine-tune the security options by adding and removing capabilities and seccomp filters, it&amp;rsquo;s not only the choice between full root access and nothing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="daemonless"&gt;Daemonless
&lt;/h2&gt;&lt;p&gt;Podman doesn&amp;rsquo;t run a daemon by default. When you run a podman command, it will do what you requested (eg. run a container, delete an image, query for information) and simply exit. Again, security - no huge binaries running all the time, no exposed ports. You can choose to run a daemon if it&amp;rsquo;s needed for better Docker compatibility eg. with a 3rd party tool.&lt;/p&gt;
&lt;h2 id="systemd-for-starting-containers"&gt;Systemd for starting containers
&lt;/h2&gt;&lt;p&gt;Docker doesn&amp;rsquo;t play well with Systemd. It&amp;rsquo;s the design choice - both tools try to configure cgroups and namespaces, restart services etc. Docker developers plainly refuse to cooperate, they want complete control. On the other hand, Podman authors decided it&amp;rsquo;s not the job of the container engine to autostart services. It&amp;rsquo;s either done with an orchestrator such as Kubernetes, or, for running on a single machine, you can just use the same software that starts other services, which is systemd.&lt;/p&gt;
&lt;p&gt;Just one command, &amp;ldquo;podman generate systemd&amp;rdquo; will create the config file for autostarting your service. And you can even run it as user (yes, systemd supports that). Instead of autostarting at boot, you can also attach it to a socket and only activate it to handle incoming connection (if you&amp;rsquo;re as old as me, you remember inetd doing the same thing).&lt;/p&gt;
&lt;p&gt;Fine print: &amp;ldquo;generate systemd&amp;rdquo; is now deprecated and Podman wants you to use quadlets. Quadlets are more powerful, but also more complex, which spoils my narrative. But the old command still works.&lt;/p&gt;
&lt;h2 id="systemd-inside-the-containers"&gt;Systemd inside the containers
&lt;/h2&gt;&lt;p&gt;The most common way to use containers today is to isolate a single application. One container, one process, if it exits, the whole container exits (and possibly gets restarted). But there is another approach - treat container as something like a VM, running multiple daemons. Anything in between is also possible.&lt;/p&gt;
&lt;p&gt;Personally, I&amp;rsquo;m in a single process camp. It&amp;rsquo;s been several years since I ran multiple processes (and that was because I didn&amp;rsquo;t know how to handle multi-container setup). But I think it&amp;rsquo;s better to have a choice. If you need to run systemd inside the container, Podman will detect it and automatically set the environment properly.&lt;/p&gt;
&lt;h2 id="kubernetes"&gt;Kubernetes
&lt;/h2&gt;&lt;p&gt;Kubernetes used to use Docker, but switched to other container engines (CRI-O by default). Yet it&amp;rsquo;s Podman that works better with it.&lt;/p&gt;
&lt;p&gt;The idea is: you use Podman to develop and test software and then you can easily run it in production on Kubernetes. Podman, unlike Docker, has a concept of pods. If you&amp;rsquo;re ready to move your software from a single machine to Kubernetes cluster, you can use &amp;ldquo;podman generate kube&amp;rdquo; to create the YAML file in the Kubernetes format. Since the format is not easy to create by hand, it saves a lot of time.&lt;/p&gt;
&lt;p&gt;But there&amp;rsquo;s more. What if you have some software already running on Kubernetes, but want to test it on a single machine? There&amp;rsquo;s &amp;ldquo;podman play kube&amp;rdquo; which reads Kubernetes YAML. Of course it only accepts a subset of options as Podman can&amp;rsquo;t do scaling and multi-node deployment.&lt;/p&gt;</description></item><item><title>Running IBM Storage Scale on VMs</title><link>https://random.too-many-machines.com/posts/ibm-storage-scale/</link><pubDate>Thu, 23 Nov 2023 19:00:00 +0100</pubDate><guid>https://random.too-many-machines.com/posts/ibm-storage-scale/</guid><description>&lt;img src="https://random.too-many-machines.com/posts/ibm-storage-scale/gpfs-fs.png" alt="Featured image of post Running IBM Storage Scale on VMs" /&gt;&lt;p&gt;IBM Storage Scale (formerly &lt;strong&gt;Spectrum Scale&lt;/strong&gt;, formerly &lt;strong&gt;GPFS&lt;/strong&gt;) is a distributed file system often found in HPC clusters, Machine Learning platforms etc. It can scale up to an unimaginable size, it can provide higher throughput than any physical drive, it allows concurrent access from many nodes in the cluster. It supports distributed locking. It has all the standard features of Unix filesystems such as quotas or ACLs. Nodes and disks can be added and removed on the fly. There&amp;rsquo;s no single point of failure. It can also be accessed with S3, NFS or Hadoop compatible interface. And that&amp;rsquo;s not even a full list of features.&lt;/p&gt;
&lt;p&gt;Which also means it&amp;rsquo;s not something you would run at home, not even a usual datacenter. Unless, of course, you need a playground for learning or testing. I felt quite uncomfortable running commands on a production system, that stored some petabytes of data and was used by thousands of people, without testing them first.&lt;/p&gt;
&lt;h2 id="creating-vms"&gt;Creating VMs
&lt;/h2&gt;&lt;p&gt;I used Vagrant with a default provider (Virtualbox). Vagrant makes it easy to launch VMs for test environments. No need for configuration and installation, just &lt;code&gt;vagrant init name-of-your-image ; vagrant up&lt;/code&gt; and you&amp;rsquo;re done. That is, if the default configuration works for you. If not, then a simple modification to the Vagrantfile takes only a few minutes, and that&amp;rsquo;s including time spent on searching the web for examples.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s getting a bit tricky if you need to test a distributed system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the syntax is a little different for multiple VMs in one file,&lt;/li&gt;
&lt;li&gt;you should probably configure a private network,&lt;/li&gt;
&lt;li&gt;if you need port forwarding (eg. for SSH access), you need to use a different port for each VM.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I configured one client and three servers, sr1, sr2 and sr3. Servers both have extra hard drives in addition to the standard system drive. All machines have 2GB of RAM and 2 vCPUs (except the first server which needs more power), all connect to the same private network. All use the same operating system. Spectrum Scale supports several versions of RHEL, Ubuntu and SLES, it should work with other distributions, but no guarantees, and you&amp;rsquo;d be forced to use manual installation.&lt;/p&gt;
&lt;p&gt;Here is my Vagrantfile. It&amp;rsquo;s not the initial version, that&amp;rsquo;s where I arrived after some experiments.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Vagrant&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;configure(&lt;span style="color:#e6db74"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;config&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;define &lt;span style="color:#e6db74"&gt;&amp;#34;sr1&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;sr1&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;box &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ubuntu/jammy64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hostname &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;sr1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;provision &lt;span style="color:#e6db74"&gt;&amp;#34;shell&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;path&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;boot-tasks.sh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;disk &lt;span style="color:#e6db74"&gt;:disk&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;size&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1GB&amp;#34;&lt;/span&gt;, name: &lt;span style="color:#e6db74"&gt;&amp;#34;extra_storage1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;disk &lt;span style="color:#e6db74"&gt;:disk&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;size&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1GB&amp;#34;&lt;/span&gt;, name: &lt;span style="color:#e6db74"&gt;&amp;#34;extra_storage2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;network &lt;span style="color:#e6db74"&gt;:private_network&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;ip&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;192.168.56.101&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#sr1.vm.network :forwarded_port, guest: 22, host: 2021, id: &amp;#34;ssh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;provider &lt;span style="color:#e6db74"&gt;:virtualbox&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;v&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;customize &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;modifyvm&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;--natdnshostresolver1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;on&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;memory &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cpus &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;define &lt;span style="color:#e6db74"&gt;&amp;#34;sr2&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;sr2&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;box &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ubuntu/jammy64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hostname &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;sr2&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;provision &lt;span style="color:#e6db74"&gt;&amp;#34;shell&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;path&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;boot-tasks.sh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;network &lt;span style="color:#e6db74"&gt;:private_network&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;ip&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;192.168.56.102&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#sr2.vm.network :forwarded_port, guest: 22, host: 2022, id: &amp;#34;ssh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;disk &lt;span style="color:#e6db74"&gt;:disk&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;size&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1GB&amp;#34;&lt;/span&gt;, name: &lt;span style="color:#e6db74"&gt;&amp;#34;extra_storage1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;disk &lt;span style="color:#e6db74"&gt;:disk&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;size&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1GB&amp;#34;&lt;/span&gt;, name: &lt;span style="color:#e6db74"&gt;&amp;#34;extra_storage2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;provider &lt;span style="color:#e6db74"&gt;:virtualbox&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;v&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;customize &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;modifyvm&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;--natdnshostresolver1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;on&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;memory &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2048&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cpus &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;define &lt;span style="color:#e6db74"&gt;&amp;#34;sr3&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;sr3&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;box &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ubuntu/jammy64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hostname &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;sr3&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;provision &lt;span style="color:#e6db74"&gt;&amp;#34;shell&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;path&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;boot-tasks.sh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;network &lt;span style="color:#e6db74"&gt;:private_network&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;ip&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;192.168.56.103&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#sr3.vm.network :forwarded_port, guest: 22, host: 2023, id: &amp;#34;ssh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;disk &lt;span style="color:#e6db74"&gt;:disk&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;size&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1GB&amp;#34;&lt;/span&gt;, name: &lt;span style="color:#e6db74"&gt;&amp;#34;extra_storage1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;disk &lt;span style="color:#e6db74"&gt;:disk&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;size&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1GB&amp;#34;&lt;/span&gt;, name: &lt;span style="color:#e6db74"&gt;&amp;#34;extra_storage2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sr3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;provider &lt;span style="color:#e6db74"&gt;:virtualbox&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;v&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;customize &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;modifyvm&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;--natdnshostresolver1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;on&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;memory &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2048&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cpus &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;define &lt;span style="color:#e6db74"&gt;&amp;#34;client&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;client&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;box &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ubuntu/jammy64&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;hostname &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;client&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;provision &lt;span style="color:#e6db74"&gt;&amp;#34;shell&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;path&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;boot-tasks.sh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;network &lt;span style="color:#e6db74"&gt;:private_network&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;ip&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;192.168.56.104&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#client.vm.network :forwarded_port, guest: 22, host: 2024, id: &amp;#34;ssh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;provider &lt;span style="color:#e6db74"&gt;:virtualbox&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;v&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;customize &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;modifyvm&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;:id&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;--natdnshostresolver1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;on&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;memory &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2048&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; v&lt;span style="color:#f92672"&gt;.&lt;/span&gt;cpus &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vagrantfile references another file, boot-tasks.sh, which needs to be in the same directory. You can remove this line from Vagrantfile for now, we&amp;rsquo;ll use it in a few minutes. Run the first VM with &lt;code&gt;vagrant up sr1&lt;/code&gt;. We&amp;rsquo;ll use it as the installer machine. Other VMs can be started later.&lt;/p&gt;
&lt;h2 id="preventing-installation-errors"&gt;Preventing installation errors
&lt;/h2&gt;&lt;p&gt;If you&amp;rsquo;re running the VMs on your own computer, you might be tempted to give them less resources. Unfortunately, GPFS is a memory hog. Just the main daemon gpfsd consumes 1.2GB of RAM at startup. You need at least 2GB of RAM on all nodes, I also recommend to assign 4GB to one of the nodes and use it for running GUI and installer. That means that for 3 servers and client you need at least 10GB - a bit tough if your computer only has 16GB. But if your nodes don&amp;rsquo;t have enough memory, daemons will fail to start or crash, what&amp;rsquo;s worse, they might not even show any meaningful error message.&lt;/p&gt;
&lt;p&gt;I also had problems, quite ironically, with storage performance. I&amp;rsquo;m running several VMs out of one hard drive (not even SSD). Linux block layer by default timeouts if it can&amp;rsquo;t finish a disk operation in 30 seconds. A reasonable value for a physical system, but if several VMs are doing write-heavy operations, it might not be enough. I&amp;rsquo;d rather wait a bit more than risk data corruption. I prepared a script &lt;code&gt;time.sh&lt;/code&gt; and put it in the same directory as Vagrantfile. I configured Vagrant to run it automatically while rebuilding the VMs, I can also run it manually if I need to change the value.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TIMEOUT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;Increasing disk timeout&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; f in /sys/block/sd?/device/timeout; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo $TIMEOUT &amp;gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$f&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="getting-storage-scale"&gt;Getting Storage Scale
&lt;/h2&gt;&lt;p&gt;Storage Scale Developer Edition is available for free, but you need to register for an IBM account and accept countless license agreements. You&amp;rsquo;ll get a 1.7G zip file. Put it in the directory where you have your Vagrantfile, it will be available for VMs under /vagrant. Connect to the first server with &lt;code&gt;vagrant ssh sr1&lt;/code&gt;. Unzip and add executable bit to the installer: &lt;code&gt;chmod a+x Storage_Scale_Developer-5.1.9.0-x86_64-Linux-install&lt;/code&gt; and run it with root privileges: &lt;code&gt;sudo ./Storage_Scale_Developer-5.1.9.0-x86_64-Linux-install&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It will list a few installation options. First one is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; To install a cluster or deploy protocols with the IBM Storage Scale Installation Toolkit:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /usr/lpp/mmfs/5.1.9.0/ansible-toolkit/spectrumscale -h
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ansible? Now you&amp;rsquo;ve got my attention! Last time I created GPFS testbed I installed the packages manually, but I like this option more. Let&amp;rsquo;s read the documentation for the IBM Storage Scale Installation Toolkit.&lt;/p&gt;
&lt;p&gt;The guide lists some requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;obviously, we need Ansible on the machine that will start the installation: &lt;code&gt;sudo apt install ansible&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;we need to resolve hostnames of all nodes to IPs, either a local DNS or /etc/hosts,&lt;/li&gt;
&lt;li&gt;installer needs to be run as root,&lt;/li&gt;
&lt;li&gt;we need password-less SSH (as root! abomination!),&lt;/li&gt;
&lt;li&gt;we need to install make, C, and C++ compiler - on all nodes, including the client&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="configuring-vms"&gt;Configuring VMs
&lt;/h2&gt;&lt;p&gt;Connect to the first server with &lt;code&gt;vagrant ssh sr1&lt;/code&gt;. Edit /etc/hosts by adding these lines:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;192.168.56.101 sr1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;192.168.56.102 sr2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;192.168.56.103 sr3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;192.168.56.104 client
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Copy the file to /vagrant. Then, generate a password-less keypair. Now, we&amp;rsquo;re going to do something against the normal security rules: share the same keypair. It&amp;rsquo;s fine for a temporary test environment only available on the home LAN. Copy both key files to /vagrant.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh-keygen
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp /etc/hosts /vagrant
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp ~vagrant/.ssh/id_rsa* /vagrant
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we&amp;rsquo;ll add a script so Vagrant will automatically configure all VMs. It will set the ssh keys, install required packages, and remove unattended-upgrades (this daemon has a habit of getting in the way of package installation). In the same directory where you placed Vagrantfile, add file boot-tasks.sh with the following contents:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p ~vagrant/.ssh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd ~vagrant/.ssh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp /vagrant/hosts /etc
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp /vagrant/id_rsa* .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat id_rsa.pub &amp;gt;&amp;gt; authorized_keys
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chown -R vagrant:vagrant ~vagrant/.ssh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd /root/.ssh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp ~vagrant/.ssh/* .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chown root:root *
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apt -y remove unattended-upgrades
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apt update
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apt -y install g++ make
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;. /vagrant/time.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Restart machines with &lt;code&gt;vagrant reload&lt;/code&gt;. Then try to ssh from root@sr1 to all VMs, including sr1. It should work.&lt;/p&gt;
&lt;h2 id="installing-storage-scale"&gt;Installing Storage Scale
&lt;/h2&gt;&lt;p&gt;First thing is to prepare the installer node. All commands below require root privileges:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd /usr/lpp/mmfs/5.1.9.0/ansible-toolkit
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale setup -s 192.168.56.101
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First server will have a GUI and an admin role (&lt;code&gt;-a -g&lt;/code&gt;). All servers will have a manager role, NSD role and will form quorum (&lt;code&gt;-m -n -q&lt;/code&gt;) . Client is a node without any role (no extra arguments).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale node add sr1 -m -q -n -a -g 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale node add sr2 -m -q -n
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale node add sr3 -m -q -n
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale node add client
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale node list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;NSD means Network Shared Disk. There are several possible cluster topologies for Storage Scale, many of them require some kind of shared storage. We&amp;rsquo;re going to use the simplest form, where each NSD node will use its local disks. Let&amp;rsquo;s define the disks now. And at the same time, define the filesystem that uses all these disks.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale nsd add -p sr1 /dev/sdc /dev/sdd -fs filesystem1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale nsd add -p sr2 /dev/sdc /dev/sdd -fs filesystem1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale nsd add -p sr3 /dev/sdc /dev/sdd -fs filesystem1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, check the filesystem configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale nsd list
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./spectrumscale filesystem list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="Filesystem configuration" class="gallery-image" data-flex-basis="555px" data-flex-grow="231" height="457" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://random.too-many-machines.com/posts/ibm-storage-scale/gpfs-fs.png" srcset="https://random.too-many-machines.com/posts/ibm-storage-scale/gpfs-fs_hu_39f2d6eefca7050.png 800w, https://random.too-many-machines.com/posts/ibm-storage-scale/gpfs-fs.png 1057w" width="1057"&gt;&lt;/p&gt;
&lt;p&gt;Last thing to configure. By default, Spectrum Scale will send information to IBM, but this function is not configured. We need to either provide information about the customer, country etc. or simply turn it off with &lt;code&gt;./spectrumscale callhome disable&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve got nodes, disks and filesystem, ready for deployment. But first, let&amp;rsquo;s save VM snapshots in case we mess up something and need to revert, by running this command on the host: &lt;code&gt;vagrant snapshot save before-installation&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Finally, run &lt;code&gt;./spectrumscale install&lt;/code&gt;. If all goes well, you might go for lunch at this point as the whole process will take at least 30 minutes. More likely, it will fail at some point. IBM Storage Scale Installation Toolkit runs some pre-checks and creates a temporary repo during installation, unfortunately it needs to repeat it during every attempt and it takes (on my slow inadequate hardware) about 10 minutes. Very annoying. Further tasks are more Ansible-style: if something fails, fix the problem and run the installer again, tasks already done will be checked and skipped, failed tasks will be attempted again.&lt;/p&gt;</description></item></channel></rss>