<?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>DEV Community: Franklin Yu</title>
    <description>The latest articles on DEV Community by Franklin Yu (@franklinyu).</description>
    <link>https://dev.to/franklinyu</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%2F220803%2F79deb364-9022-4ece-bce4-71bf98a209f2.jpeg</url>
      <title>DEV Community: Franklin Yu</title>
      <link>https://dev.to/franklinyu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/franklinyu"/>
    <language>en</language>
    <item>
      <title>How the shell aliases affect shell functions: two pitfalls</title>
      <dc:creator>Franklin Yu</dc:creator>
      <pubDate>Fri, 04 Oct 2024 05:59:58 +0000</pubDate>
      <link>https://dev.to/franklinyu/how-the-shell-aliases-affect-shell-functions-two-pitfalls-2ao9</link>
      <guid>https://dev.to/franklinyu/how-the-shell-aliases-affect-shell-functions-two-pitfalls-2ao9</guid>
      <description>&lt;p&gt;If you have this in your &lt;code&gt;.bashrc&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;alias &lt;/span&gt;&lt;span class="nv"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bar
foo&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;echo &lt;/span&gt;1
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You would expect the alias to “shadow” the function, so when you execute &lt;code&gt;foo&lt;/code&gt; you think it is executing &lt;code&gt;bar&lt;/code&gt; instead of &lt;code&gt;echo 1&lt;/code&gt;. Right?&lt;/p&gt;

&lt;p&gt;Wrong! The alias takes immediate effect, so when Bash sees the function definition, it actually regard it as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bar&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;echo &lt;/span&gt;1
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which defines a function named &lt;code&gt;bar&lt;/code&gt;. So you end up with &lt;code&gt;foo&lt;/code&gt; as an alias, and &lt;code&gt;bar&lt;/code&gt; as a function. Zsh is a bit better in this case; if Zsh sees the same snippet trying to define a function after alias, the function-definition command will fail (since defining &lt;code&gt;bar&lt;/code&gt; as a function is almost never intended anyway). To fix it, define the function with the &lt;code&gt;function&lt;/code&gt; keyword instead, whenever POSIX-compliance isn’t needed. This fix works both in Bash and in Zsh.&lt;/p&gt;

&lt;p&gt;Another interesting behavior is how Bash and Zsh expand aliases in function bodies. 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;&lt;span class="nb"&gt;alias ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ls --color'&lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;ls_repos&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;ls&lt;/span&gt; ~/repos  &lt;span class="c"&gt;# expands to "ls --color ~/repos"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The order between the alias and the function is important, because aliases are expanded when the function is &lt;em&gt;defined&lt;/em&gt;, not when it is &lt;em&gt;called&lt;/em&gt;. The &lt;code&gt;ls&lt;/code&gt; in the function body is expanded &lt;em&gt;only if&lt;/em&gt; the alias exists &lt;em&gt;before&lt;/em&gt; the function is defined. When you query the function definition with &lt;code&gt;type -f&lt;/code&gt; you actually see the one &lt;em&gt;after&lt;/em&gt; the expansion.&lt;/p&gt;

&lt;p&gt;This behavior is actually well-documented. In &lt;a href="https://www.gnu.org/software/bash/manual/html_node/Aliases.html" rel="noopener noreferrer"&gt;Bash documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Aliases are expanded when a function definition is read, not when the function is executed, because a function definition is itself a command.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://zsh.sourceforge.io/Intro/intro_4.html" rel="noopener noreferrer"&gt;Zsh documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that aliases are expanded when the function definition is parsed, not when the function is executed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On the plus side, one can make use of this behavior to avoid some annoyance. For example, if one of your alias in your &lt;code&gt;.bashrc&lt;/code&gt; breaks some external script (such as &lt;code&gt;nvm.sh&lt;/code&gt;), you can simply move the alias around in your &lt;code&gt;.bashrc&lt;/code&gt;, defining them &lt;em&gt;after&lt;/em&gt; sourcing &lt;code&gt;nvm&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>bash</category>
    </item>
    <item>
      <title>signify: replacement for PGP signing?</title>
      <dc:creator>Franklin Yu</dc:creator>
      <pubDate>Mon, 24 Jun 2024 08:36:10 +0000</pubDate>
      <link>https://dev.to/franklinyu/signify-replacement-for-pgp-signing-25he</link>
      <guid>https://dev.to/franklinyu/signify-replacement-for-pgp-signing-25he</guid>
      <description>&lt;div class="ltag__wikipedia--container"&gt;
  &lt;div class="ltag__wikipedia--header"&gt;
    &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fwikipedia-logo-0a3e76624c7b1c3ccdeb9493ea4add6ef5bd82d7e88d102d5ddfd7c981efa2e7.svg" class="ltag__wikipedia--logo" alt="Wikipedia Logo"&gt;
    &lt;a href="https://en.wikipedia.org/wiki/OpenBSD" rel="noopener noreferrer"&gt;OpenBSD&lt;/a&gt;
  &lt;/div&gt;
  &lt;div class="ltag__wikipedia--extract"&gt;&lt;p&gt;&lt;b&gt;OpenBSD&lt;/b&gt; is a security-focused, free and open-source, Unix-like operating system based on the Berkeley Software Distribution (BSD). Theo de Raadt created OpenBSD in 1995 by forking NetBSD 1.0. The OpenBSD project emphasizes portability, standardization, correctness, proactive security, and integrated cryptography.&lt;/p&gt;&lt;/div&gt;
  &lt;div class="ltag__wikipedia--btn--container"&gt;
      &lt;a class="ltag__wikipedia--btn" href="https://en.wikipedia.org/wiki/OpenBSD" rel="noopener noreferrer"&gt;View on Wikipedia&lt;/a&gt;&amp;gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;OpenBSD is a Unix-like operating system focusing on security. Like all other unix-like open-sourced operating system, OpenBSD has its package manager, and packages are signed. However, all other Unix-like open-sourced operating systems sign their packages with GnuPG:&lt;/p&gt;


&lt;div class="ltag__wikipedia--container"&gt;
  &lt;div class="ltag__wikipedia--header"&gt;
    &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fwikipedia-logo-0a3e76624c7b1c3ccdeb9493ea4add6ef5bd82d7e88d102d5ddfd7c981efa2e7.svg" class="ltag__wikipedia--logo" alt="Wikipedia Logo"&gt;
    &lt;a href="https://en.wikipedia.org/wiki/GNU_Privacy_Guard" rel="noopener noreferrer"&gt;GNU Privacy Guard&lt;/a&gt;
  &lt;/div&gt;
  &lt;div class="ltag__wikipedia--extract"&gt;&lt;p&gt;&lt;b&gt;GNU Privacy Guard&lt;/b&gt; is a free-software replacement for Symantec's cryptographic software suite PGP. The software is compliant with RFC &lt;span class="external text"&gt;4880&lt;/span&gt;, the IETF standards-track specification of OpenPGP. Modern versions of PGP are interoperable with GnuPG and other OpenPGP v4-compliant systems.&lt;/p&gt;&lt;/div&gt;
  &lt;div class="ltag__wikipedia--btn--container"&gt;
      &lt;a class="ltag__wikipedia--btn" href="https://en.wikipedia.org/wiki/GNU_Privacy_Guard" rel="noopener noreferrer"&gt;View on Wikipedia&lt;/a&gt;&amp;gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;In contrast, OpenBSD wrote their own tool for it: &lt;a href="https://flak.tedunangst.com/post/signify" rel="noopener noreferrer"&gt;signify&lt;/a&gt;. As mentioned in the blog, it focuses on one thing, and does it well: sign a piece of data. It is much simpler than GnuPG (or OpenPGP in general), therefore a smaller attack surface, and therefore more secure.&lt;/p&gt;

&lt;p&gt;Unfortunately, the tool is only for OpenBSD, not portable. There is a port to macOS (packaged in Homebrew and MacPorts):&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jpouellet" rel="noopener noreferrer"&gt;
        jpouellet
      &lt;/a&gt; / &lt;a href="https://github.com/jpouellet/signify-osx" rel="noopener noreferrer"&gt;
        signify-osx
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      OS X port of OpenBSD's signify(1)
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;macOS port of OpenBSD's &lt;a href="https://man.openbsd.org/signify.1" rel="nofollow noopener noreferrer"&gt;signify(1)&lt;/a&gt;
&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;This macOS port of OpenBSD's &lt;code&gt;signify&lt;/code&gt; utility intentionally tracks upstream
OpenBSD sources directly, keeping only the smallest portability layer possible
with the explicit #1 goal of making it as easy to audit as possible.&lt;/p&gt;
&lt;p&gt;The latest version was tested on macOS 10.14.2 with Apple LLVM 9.1.0.&lt;/p&gt;
&lt;p&gt;Older versions were previously tested as far back as OS X 10.6.8 with GCC 4.2.1.&lt;/p&gt;
&lt;p&gt;Some of the OpenBSD-specific functions used by signify that previously required
portability shims were introduced in macOS 10.12(.1), and the corresponding
portability shims have been removed to keep the code as lean and easily
auditable as possible. If you need support for a newer signify on an older
macOS, feel free to open an issue.&lt;/p&gt;
&lt;p&gt;Man page at &lt;a href="https://man.openbsd.org/signify.1" rel="nofollow noopener noreferrer"&gt;https://man.openbsd.org/signify.1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/&lt;/code&gt; is the result of &lt;code&gt;make fetch&lt;/code&gt; (cvs get) and &lt;code&gt;make hash-helpers&lt;/code&gt; (sed) as
of the time of the last commit.&lt;/p&gt;
&lt;p&gt;If you don't trust…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/jpouellet/signify-osx" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;There is another portable version, more popular and apparently better maintained:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/aperezdc" rel="noopener noreferrer"&gt;
        aperezdc
      &lt;/a&gt; / &lt;a href="https://github.com/aperezdc/signify" rel="noopener noreferrer"&gt;
        signify
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      OpenBSD tool to sign and verify signatures on files. Portable version.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Signify - Sign and Verify&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://actions-badge.atrox.dev/aperezdc/signify/goto" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5aa9aaf1820186ded426d1dc2c42459e06ed47888b618237281673381d0ae3e3/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e742e7376673f75726c3d6874747073253341253246253246616374696f6e732d62616467652e6174726f782e64657625324661706572657a64632532467369676e6966792532466261646765267374796c653d666c6174" alt="Build Status"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;OpenBSD tool to sign and verify signatures on files. This is a portable
version which uses &lt;a href="http://libbsd.freedesktop.org/wiki/" rel="nofollow noopener noreferrer"&gt;libbsd&lt;/a&gt; (version
0.11 or newer is required).&lt;/p&gt;
&lt;p&gt;See &lt;a href="https://www.tedunangst.com/flak/post/signify" rel="nofollow noopener noreferrer"&gt;https://www.tedunangst.com/flak/post/signify&lt;/a&gt; for more information.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;License&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Signify is distributed under the terms of the &lt;a href="https://opensource.org/licenses/isc-license.txt" rel="nofollow noopener noreferrer"&gt;ISC
license&lt;/a&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Some GNU/Linux distributions have readily available packages in their
repositories. It is recommended to use these, unless you absolutely need to
build from source code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Alpine Linux: &lt;code&gt;apk add signify&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Arch Linux: &lt;code&gt;pacman -S signify&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Debian/Ubuntu: &lt;code&gt;apt install signify-openbsd&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CentOS/RHEL/Rocky: &lt;code&gt;dnf install epel-release&lt;/code&gt; then &lt;code&gt;dnf install signify&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Fedora: &lt;code&gt;dnf install signify&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Building&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Dependencies&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;GNU Make (any version above 3.70).&lt;/li&gt;
&lt;li&gt;C compiler. Both GCC and Clang are tested and supported.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://libbsd.freedesktop.org/wiki/" rel="nofollow noopener noreferrer"&gt;libbsd&lt;/a&gt; 0.11 or newer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your system does not provide a package for &lt;code&gt;libbsd&lt;/code&gt;, it is possible to use
a bundled copy, check the &lt;a href="https://github.com/aperezdc/signify#options" rel="noopener noreferrer"&gt;build options&lt;/a&gt; section for more details.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Options&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;The following options…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/aperezdc/signify" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;However, two concerns are still mentioned in this Whonix forum post:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://forums.whonix.org/t/signify-openbsd/7842" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fforums.whonix.org%2Fuploads%2Fdefault%2Foriginal%2F2X%2F5%2F5ac973ff4302e69269667e09e67d850c0b628c7a.jpeg" height="auto" class="m-0"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://forums.whonix.org/t/signify-openbsd/7842" rel="noopener noreferrer" class="c-link"&gt;
          signify-openbsd - Development - Whonix Forum
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          https://www.openbsd.org/papers/bsdcan-signify.html  https://kushaldas.in/posts/using-signify-tool-for-sign-and-verification.html  https://manpages.debian.org/signify-openbsd
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fforums.whonix.org%2Fuploads%2Fdefault%2Foptimized%2F2X%2F3%2F37fe81e592143b0c01c9656c44069b4bfdd3990e_2_32x32.ico"&gt;
        forums.whonix.org
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;First, the signature format doesn’t support embedding filename or timestamp; second, &lt;code&gt;signify&lt;/code&gt; only signs files that fit in RAM (1 GiB by default). The second concern is also mentioned in GitHub:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/aperezdc/signify/issues/42" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        large file support
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#42&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/adrelanos" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F1985040%3Fv%3D4" alt="adrelanos avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/adrelanos" rel="noopener noreferrer"&gt;adrelanos&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/aperezdc/signify/issues/42" rel="noopener noreferrer"&gt;&lt;time&gt;Jul 25, 2023&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Created a 2G file for test purposes.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fallocate -l 2G test.img
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tried to sign it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;signify-openbsd -S -s ./keyname.sec -m ./test.img -x ./test.img.sig
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;result:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;signify-openbsd: msg too large in ./test.img&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Could you please add support for signing arbitrarily large files?&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/aperezdc/signify/issues/42" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The Whonix forum post mentioned that a partially-compatible project &lt;code&gt;minisign&lt;/code&gt; can help:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jedisct1" rel="noopener noreferrer"&gt;
        jedisct1
      &lt;/a&gt; / &lt;a href="https://github.com/jedisct1/minisign" rel="noopener noreferrer"&gt;
        minisign
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A dead simple tool to sign files and verify digital signatures.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/jedisct1/minisign/workflows/CodeQL%20scan/badge.svg"&gt;&lt;img src="https://github.com/jedisct1/minisign/workflows/CodeQL%20scan/badge.svg" alt="CodeQL scan"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Minisign&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Minisign is a dead simple tool to sign files and verify signatures.&lt;/p&gt;
&lt;p&gt;For more information, please refer to the
&lt;a href="https://jedisct1.github.io/minisign/" rel="nofollow noopener noreferrer"&gt;Minisign documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Tarballs and pre-compiled binaries can be verified with the following
public key:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Compilation / installation&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Using &lt;a href="https://ziglang.org" rel="nofollow noopener noreferrer"&gt;Zig&lt;/a&gt;:&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Dependencies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://libsodium.org/" rel="nofollow noopener noreferrer"&gt;libsodium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compilation:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ zig build -Drelease
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Using cmake and gcc or clang:&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://libsodium.org/" rel="nofollow noopener noreferrer"&gt;libsodium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;cmake&lt;/li&gt;
&lt;li&gt;pkg-config&lt;/li&gt;
&lt;li&gt;gcc or clang&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compilation:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ mkdir build
$ cd build
$ cmake ..
$ make
# make install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alternative configuration for static binaries:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ cmake -D STATIC_LIBSODIUM=1 ..
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ cmake -D BUILD_STATIC_EXECUTABLES=1 ..
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Minisign is also available in Homebrew:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ brew install minisign
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Minisign is also available in Scoop on Windows:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ scoop install minisign
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Minisign is also available in chocolatey on Windows:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ choco install minisign
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Minisign is also available with docker:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ docker run -i --rm jedisct1/minisign
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The image can be verified with the following cosign public key:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;-----BEGIN PUBLIC&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/jedisct1/minisign" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Its “trusted comments” feature addresses the first concern; for example, projects can define machine-readable format for the trusted comment. It addresses the second concern by pre-hashing the file with BLAKE:&lt;/p&gt;


&lt;div class="ltag__wikipedia--container"&gt;
  &lt;div class="ltag__wikipedia--header"&gt;
    &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fwikipedia-logo-0a3e76624c7b1c3ccdeb9493ea4add6ef5bd82d7e88d102d5ddfd7c981efa2e7.svg" class="ltag__wikipedia--logo" alt="Wikipedia Logo"&gt;
    &lt;a href="https://en.wikipedia.org/wiki/BLAKE_(hash_function)" rel="noopener noreferrer"&gt;BLAKE (hash function)&lt;/a&gt;
  &lt;/div&gt;
  &lt;div class="ltag__wikipedia--extract"&gt;&lt;p&gt;&lt;b&gt;BLAKE&lt;/b&gt; is a cryptographic hash function based on Daniel J. Bernstein's ChaCha stream cipher, but a permuted copy of the input block, XORed with round constants, is added before each ChaCha round. Like SHA-2, there are two variants differing in the word size. ChaCha operates on a 4×4 array of words. BLAKE repeatedly combines an 8-word hash value with 16 message words, truncating the ChaCha result to obtain the next hash value. &lt;b&gt;BLAKE-256&lt;/b&gt; and &lt;b&gt;BLAKE-224&lt;/b&gt; use 32-bit words and produce digest sizes of 256 bits and 224 bits, respectively, while &lt;b&gt;BLAKE-512&lt;/b&gt; and &lt;b&gt;BLAKE-384&lt;/b&gt; use 64-bit words and produce digest sizes of 512 bits and 384 bits, respectively.&lt;/p&gt;&lt;/div&gt;
  &lt;div class="ltag__wikipedia--btn--container"&gt;
      &lt;a class="ltag__wikipedia--btn" href="https://en.wikipedia.org/wiki/BLAKE_(hash_function)" rel="noopener noreferrer"&gt;View on Wikipedia&lt;/a&gt;&amp;gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This project also seems to be more active than the previous two ports, so it makes sense to sign binary releases (especially big files like disk images) with &lt;code&gt;minisign&lt;/code&gt; instead of &lt;code&gt;signify&lt;/code&gt;. &lt;code&gt;signify&lt;/code&gt; remains feasible for small files like emails or plain text files.&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;minisign&lt;/code&gt; is only one-way compatible with &lt;code&gt;signify&lt;/code&gt; in that &lt;code&gt;minisign&lt;/code&gt; &lt;em&gt;legacy&lt;/em&gt; signatures (i.e. signed with the &lt;code&gt;-l&lt;/code&gt; switch) can be verified by &lt;code&gt;signify&lt;/code&gt;. See:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/jedisct1/minisign/issues/59" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Can't verify Signify signatures
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#59&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/Macil" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F577345%3Fv%3D4" alt="Macil avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/Macil" rel="noopener noreferrer"&gt;Macil&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/jedisct1/minisign/issues/59" rel="noopener noreferrer"&gt;&lt;time&gt;Jul 23, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Minisign gives me an error when I try to use it to verify a signature made by Signify. From the docs it seems like this is intended to work.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ echo VGhpcyBpcyBhIHRlc3QgbWVzc2FnZS4K | base64 --decode &amp;gt; message.txt
$ signify -G -p sign.pub -s sign.sec
passphrase: (z)
confirm passphrase: (z)
$ cat sign.sec
untrusted comment: signify secret key
RWRCSwAAACrVwvFk3aEyZFmPQ3kkX8eVAXYt/DvCvS3JD4o2QgWw5dPT1GwM0/u9lgqB03XQqr5yJJx9f49kmX5vd6NBBHa0rk4e9XC8mVs6Q1jWMCmO6aQTjcLOHFhLr9Vxc+W+NSw=
$ signify -S -s sign.sec -m message.txt
passphrase: (z)
$ cat message.txt.sig
untrusted comment: verify with sign.pub
RWTJD4o2QgWw5Yl4xS5JBgxC4Zv+KnDXYfDJzpE6LU/FZbs5vHq2kVJ5E7ruNvUUL+sg1/OSOvnI6N6A57wpc2VrWwujA/m8mwU=
$ ls
message.txt     message.txt.sig sign.pub        sign.sec
$ signify -V -p sign.pub -m message.txt -x message.txt.sig
Signature Verified
$ minisign -V -p sign.pub -m message.txt -x message.txt.sig
message.txt.sig: Undefined error: 0
$ minisign -v
minisign 0.8
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The other way around works okay. Signify can verify minisign signatures:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ rm sign.pub sign.sec
$ minisign -G -p sign.pub -s sign.sec
Please enter a password to protect the secret key.

Password: (z)
Password (one more time):
Deriving a key from the password in order to encrypt the secret key... done

The secret key was saved as sign.sec - Keep it secret!
The public key was saved as sign.pub - That one can be public.

Files signed using this key pair can be verified with the following command:

minisign -Vm &amp;lt;file&amp;gt; -P RWSaFhePk+tC9vTTi+yeIO4Wl6ncKXi9+ic+Rj0nohuwNC/ZWZLgBoEx
$ cat sign.sec
untrusted comment: minisign encrypted secret key
RWRTY0Iy8Ih0p+rQl2n6xucscPJOdSK48PM+Un6uFrhB74CZR/oAAAACAAAAAAAAAEAAAAAAXEf+5XzHb5GZ0vHG9ToGyICcgqEyB6kj1FAX0o/rO5o6bjIPvf3dJYo9qbOUYhWCv+56u9rnEywSGLzL9+XFmp3B2wwh14cw2+VsVe6saQG/fjrI2/C3vjUbpX1pKzGhGO391w6IawQ=
$ minisign -S -s sign.sec -m message.txt
Password: (z)
Deriving a key from the password and decrypting the secret key... done
$ cat message.txt.minisig
untrusted comment: signature from minisign secret key
RWSaFhePk+tC9snG7mzd/58ED3RdUFmO3KkyR5K8Vx/4WJCkRqHKBtUAVe4zSkoG2TgDGAImnjKBmHChbbjAxoD+TaY81Owx6AE=
trusted comment: timestamp:1563858228   file:message.txt
D1HGUOIL0Qc9OqibpK7QwMO3crzhoUdaur25n1eyMBL2q4r0loThMZycevcN1bMOg61h6cA5+PuBY8kE6MxFAw==
$ minisign -V -p sign.pub -m message.txt -x message.txt.minisig
Signature and comment signature verified
Trusted comment: timestamp:1563858228   file:message.txt
$ signify -V -p sign.pub -m message.txt -x message.txt.minisig
Signature Verified
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just in case this is somehow system-specific, I'm on MacOS with minisign and signify installed from Homebrew.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ brew info signify-osx
signify-osx: stable 1.4 (bottled), HEAD
Cryptographically sign and verify files
https://man.openbsd.org/signify.1
/usr/local/Cellar/signify-osx/1.4 (6 files, 174.8KB) *
  Poured from bottle on 2019-07-22 at 14:46:59
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/signify-osx.rb
==&amp;gt; Options
--HEAD
    Install HEAD version
==&amp;gt; Analytics
install: 28 (30 days), 59 (90 days), 221 (365 days)
install_on_request: 28 (30 days), 58 (90 days), 208 (365 days)
build_error: 0 (30 days)
$ brew info minisign
minisign: stable 0.8 (bottled)
Sign files &amp;amp; verify signatures. Works with signify in OpenBSD
https://jedisct1.github.io/minisign/
/usr/local/Cellar/minisign/0.8 (6 files, 38.1KB) *
  Poured from bottle on 2019-07-22 at 13:40:52
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/minisign.rb
==&amp;gt; Dependencies
Build: cmake ✔
Required: libsodium ✔
==&amp;gt; Analytics
install: 85 (30 days), 172 (90 days), 644 (365 days)
install_on_request: 63 (30 days), 116 (90 days), 420 (365 days)
build_error: 0 (30 days)
&lt;/code&gt;&lt;/pre&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/jedisct1/minisign/issues/59" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Also note that the size-limitation of &lt;code&gt;signify&lt;/code&gt; also affects signature verification, so the “legacy switch” doesn’t make sense for large files (since you can’t verify with &lt;code&gt;signify&lt;/code&gt; anyway).&lt;/p&gt;

</description>
      <category>cryptography</category>
      <category>digitalsignature</category>
      <category>openbsd</category>
      <category>linux</category>
    </item>
    <item>
      <title>Redis license change, and Rails Solid Cache</title>
      <dc:creator>Franklin Yu</dc:creator>
      <pubDate>Mon, 13 May 2024 07:10:04 +0000</pubDate>
      <link>https://dev.to/franklinyu/redis-license-change-and-rails-solid-cache-458n</link>
      <guid>https://dev.to/franklinyu/redis-license-change-and-rails-solid-cache-458n</guid>
      <description>&lt;p&gt;Redis switched the license of the main repository from BSD to dual license of SSPLv1 + RSALv2 in March. This was &lt;a href="https://www.theregister.com/2024/03/22/redis_changes_license/" rel="noopener noreferrer"&gt;reported by The Register&lt;/a&gt;, and got &lt;a href="https://news.ycombinator.com/item?id=39772562" rel="noopener noreferrer"&gt;heavily discussed on Hacker News&lt;/a&gt;. The GitHub pull request also received many comments:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/redis/redis/pull/13157" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Change license from BSD-3 to dual RSALv2+SSPLv1
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#13157&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/K-Jo" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F4069725%3Fv%3D4" alt="K-Jo avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/K-Jo" rel="noopener noreferrer"&gt;K-Jo&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/redis/redis/pull/13157" rel="noopener noreferrer"&gt;&lt;time&gt;Mar 20, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Read more about the license change here: &lt;a href="https://redis.com/blog/redis-adopts-dual-source-available-licensing/" rel="nofollow noopener noreferrer"&gt;Redis Adopts Dual Source-Available Licensing&lt;/a&gt;
Live long and prosper 🖖&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/redis/redis/pull/13157" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The comments mentioned several alternatives, including forks, and some competitors. Among those is a wire-format-compatible implementation from Microsoft:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/microsoft" rel="noopener noreferrer"&gt;
        microsoft
      &lt;/a&gt; / &lt;a href="https://github.com/microsoft/garnet" rel="noopener noreferrer"&gt;
        garnet
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Garnet is a remote cache-store from Microsoft Research that offers strong performance (throughput and latency), scalability, storage, recovery, cluster sharding, key migration, and replication features. Garnet can work with existing Redis clients.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Garnet&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/microsoft/garnet/actions/workflows/ci.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/microsoft/garnet/actions/workflows/ci.yml/badge.svg?branch=main" alt=".NET CI"&gt;&lt;/a&gt;
&lt;a href="https://github.com/microsoft/garnet/releases/latest" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6d76048391b15024f09cb081c5028930aff65d6fa77f48f4a8d462e757284e0b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f6d6963726f736f66742f6761726e65742e7376673f6c6162656c3d6c617465737425323072656c6561736526636f6c6f723d303037656466" alt=""&gt;&lt;/a&gt;
&lt;a href="https://www.nuget.org/packages/microsoft.garnet" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/d142befbc323049eb203dc99be128af3a64e7346f03acaadcc7c5e23126d6d0a/68747470733a2f2f696d672e736869656c64732e696f2f6e756765742f64742f6d6963726f736f66742e6761726e65742e7376673f6c6162656c3d646f776e6c6f61647326636f6c6f723d303037656466266c6f676f3d6e75676574" alt=""&gt;&lt;/a&gt;
&lt;a href="https://aka.ms/garnet-discord" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2459fc61669272fa4b44a3acebdcb8828116449ca23027580af4d507d48ba31c/68747470733a2f2f646973636f72646170702e636f6d2f6170692f6775696c64732f313231333933373435323237323538323637362f7769646765742e706e673f7374796c653d736869656c64" alt="Discord Shield"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Garnet is a new remote cache-store from Microsoft Research, that offers several unique benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Garnet adopts the popular &lt;a href="https://redis.io/docs/reference/protocol-spec/" rel="nofollow noopener noreferrer"&gt;RESP&lt;/a&gt; wire protocol as a starting point, which makes it possible to use Garnet from unmodified Redis clients available in
most programming languages of today, such as &lt;a href="https://github.com/StackExchange/StackExchange.Redis" rel="noopener noreferrer"&gt;StackExchange.Redis&lt;/a&gt; in C#.&lt;/li&gt;
&lt;li&gt;Garnet offers much better throughput and scalability with many client connections and small batches, relative to comparable open-source cache-stores, leading to cost savings for large apps and services.&lt;/li&gt;
&lt;li&gt;Garnet demonstrates extremely low client latencies (often less than 300 microseconds at the 99.9th percentile) using commodity cloud (Azure) VMs with Accelerated Networking enabled, which is critical to real-world scenarios.&lt;/li&gt;
&lt;li&gt;Based on the latest .NET technology, Garnet is cross-platform, extensible, and modern. It is designed to be easy to develop for and evolve, without sacrificing performance in the
common case. We leveraged the rich library ecosystem of .NET for API breadth, with open…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/microsoft/garnet" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Coincidentally, the Rails team &lt;a href="https://fly.io/ruby-dispatch/the-plan-for-rails-8/" rel="noopener noreferrer"&gt;planned their next release&lt;/a&gt; earlier this year, where they intended to provide Solid Cache, a cache store backed by a SQL database, as an alternative to Redis-based cache store:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/rails" rel="noopener noreferrer"&gt;
        rails
      &lt;/a&gt; / &lt;a href="https://github.com/rails/solid_cache" rel="noopener noreferrer"&gt;
        solid_cache
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A database-backed ActiveSupport::Cache::Store
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Solid Cache&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Solid Cache is a database-backed Active Support cache store that let's you keep a much larger cache than is typically possible with traditional memory-only Redis or Memcached stores. This is thanks to the speed of modern SSD drives, which make the access-time penalty of using disk vs RAM insignificant for most caching purposes. Simply put, you're now usually better off keeping a huge cache on disk rather than a small cache in memory.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Solid Cache is configured by default in new Rails 8 applications. But if you're running an earlier version, you can add it manually following these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;bundle add solid_cache&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bin/rails solid_cache:install&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This will configure Solid Cache as the production cache store, create &lt;code&gt;config/cache.yml&lt;/code&gt;, and create &lt;code&gt;db/cache_schema.rb&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You will then have to add the configuration for the queue database in &lt;code&gt;config/database.yml&lt;/code&gt;. If you're using sqlite, it'll look like this:&lt;/p&gt;
&lt;div class="highlight highlight-source-yaml notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;production&lt;/span&gt;
  &lt;span class="pl-ent"&gt;primary&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/rails/solid_cache" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://discuss.rubyonrails.org/t/explaning-solid-cache-rails-new-cache-store/83970" rel="noopener noreferrer"&gt;This announcement thread in Rails forum&lt;/a&gt; mentioned some caveat (which is also on the GitHub ReadMe), &lt;a href="https://dev.37signals.com/solid-cache/" rel="noopener noreferrer"&gt;a blog post&lt;/a&gt;, and a video for the talk:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/wYeVne3aRow"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Actually DHH &lt;a href="https://world.hey.com/dhh/five-big-open-source-gifts-from-us-c1b42c1b" rel="noopener noreferrer"&gt;blogged about this gem&lt;/a&gt; in December, before the plan of Rails 8 was announced. Overall it sounds like a feasible solution, given the recent performance improvements of NVMe SSD.&lt;/p&gt;

</description>
      <category>redis</category>
      <category>rails</category>
      <category>cache</category>
    </item>
    <item>
      <title>Error of “RUBY_FUNCTION_NAME_STRING” when compiling Ruby</title>
      <dc:creator>Franklin Yu</dc:creator>
      <pubDate>Sat, 02 Dec 2023 07:19:17 +0000</pubDate>
      <link>https://dev.to/franklinyu/error-of-rubyfunctionnamestring-when-compiling-ruby-32b8</link>
      <guid>https://dev.to/franklinyu/error-of-rubyfunctionnamestring-when-compiling-ruby-32b8</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;An unintended behavior when using &lt;code&gt;ruby-install&lt;/code&gt; when both MacPorts and Homebrew are installed, a.k.a. “three hours lost in my life”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation failure
&lt;/h2&gt;

&lt;p&gt;It has been a few weeks since I last wrote some Ruby code, and my Ruby (installed with &lt;code&gt;ruby-install&lt;/code&gt;) doesn’t work, because MacPorts were updated. This is pretty expected, and I went ahead to reinstall the version of Ruby. When I run &lt;code&gt;ruby-install&lt;/code&gt; for that, I hit an compilation error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;compiling compile.c
In file included from compile.c:40:
./vm_callinfo.h:175:9: error: use of undeclared identifier 'RUBY_FUNCTION_NAME_STRING'
        rp(ci);
        ^
./internal.h:94:72: note: expanded from macro 'rp'
#define rp(obj) rb_obj_info_dump_loc((VALUE)(obj), __FILE__, __LINE__, RUBY_FUNCTION_NAME_STRING)

In file included from compile.c:40:
./vm_callinfo.h:216:16: error: use of undeclared identifier 'RUBY_FUNCTION_NAME_STRING'
    if (debug) rp(ci);
               ^
./internal.h:94:72: note: expanded from macro 'rp'
#define rp(obj) rb_obj_info_dump_loc((VALUE)(obj), __FILE__, __LINE__, RUBY_FUNCTION_NAME_STRING)
                                                                       ^
2 errors generated.
make: *** [compile.o] Error 1
!!! Compiling ruby 3.1.2 failed!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My quick reaction was to Google this error message. &lt;a href="https://github.com/rbenv/ruby-build/discussions/1938"&gt;Everyone&lt;/a&gt; said that their issue were fixed by reinstall the Xcode CLT (Command Line Tool). Tried it, didn’t help; so I had to actually dig into the issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Ruby configuration
&lt;/h2&gt;

&lt;p&gt;From the affected C code, &lt;code&gt;RUBY_FUNCTION_NAME_STRING&lt;/code&gt; looks like a macro. I searched the source code for the macro, and found that it was defined &lt;a href="https://github.com/ruby/ruby/blob/4491bb740a9506d76391ac44bb2fe6e483fec952/configure.ac#L1684-L1701"&gt;here&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AC_CACHE_CHECK(for function name string predefined identifier,
    rb_cv_function_name_string,
    [AS_CASE(["$target_os"],[openbsd*],[
      rb_cv_function_name_string=__func__
     ],[
     rb_cv_function_name_string=no
      RUBY_WERROR_FLAG([
        for func in __func__ __FUNCTION__; do
            AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include &amp;lt;stdio.h&amp;gt;]],
                        [[puts($func);]])],
            [rb_cv_function_name_string=$func
            break])
        done
      ])])]
)
AS_IF([test "$rb_cv_function_name_string" != no], [
    AC_DEFINE_UNQUOTED(RUBY_FUNCTION_NAME_STRING, [$rb_cv_function_name_string])
])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file (&lt;code&gt;configure.ac&lt;/code&gt;) is a GNU Autoconf script. This section of the script sets the value of the macro:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If compiling for OpenBSD, set it to &lt;code&gt;__func__&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Otherwise, check whether the compiler supports the magic &lt;code&gt;__func__&lt;/code&gt;, by compiling a minimal C program with it. If it does, set the macro to &lt;code&gt;__func__&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Otherwise, do the same with &lt;code&gt;__FUNCTION__&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If none of the above works, then leave the macro unset.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Indeed the output of &lt;code&gt;ruby-install&lt;/code&gt; (actually &lt;code&gt;./configure&lt;/code&gt;) contains&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;checking for function name string predefined identifier... no&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So it did fall into the last branch, leaving the macro unset. I tried compiling the same piece of C code; my compiler do support &lt;code&gt;__func__&lt;/code&gt;. My next thoughts were: anyway for me to force it skipping the detection and use &lt;code&gt;__func__&lt;/code&gt; anyway?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;./configure --help&lt;/code&gt; gives the answer: it supports &lt;code&gt;--enable-FLAG=VALUE&lt;/code&gt; to override any feature detection. So I ran&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./configure --enable-rb_cv_function_name_string=__func__
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And indeed that line of log became&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;checking for function name string predefined identifier... &lt;code&gt;__func__&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In addition, subsequent &lt;code&gt;make compiler.o&lt;/code&gt; succeeded without complaint. So the workaround sounds simple: just pass this flag as a “configure option” to &lt;code&gt;ruby-install&lt;/code&gt;, like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruby-install ruby-3.1.2 &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--enable-rb_cv_function_name_string&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;__func__
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;right?&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the next (real) broken thing
&lt;/h2&gt;

&lt;p&gt;Nope, it didn’t work; the feature was set back to “no”. After scratching my head and reading the source code of &lt;code&gt;ruby-install&lt;/code&gt;, I noticed that it supports a flag: &lt;code&gt;-D&lt;/code&gt;/&lt;code&gt;--debug&lt;/code&gt;, which prints the command it runs. I ran &lt;code&gt;ruby-install&lt;/code&gt; again with that flag, and it printed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[DEBUG] ./configure --prefix=/Users/franklinyu/.rubies/ruby-3.1.2 --with-opt-dir=/Users/franklinyu/.local/opt/openssl@1.1:/Users/franklinyu/.local/opt/readline:/Users/franklinyu/.local/opt/libyaml:/Users/franklinyu/.local/opt/gdbm --enable-rb_cv_function_name_string=__func__
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So it did have the &lt;code&gt;--enable-xxx&lt;/code&gt; flags that I wanted; the &lt;code&gt;--prefix&lt;/code&gt; looks legit. But the &lt;code&gt;--with-opt-dir&lt;/code&gt; looks suspicious, because those paths didn’t actually exist on my system. I tried running this &lt;code&gt;./configure&lt;/code&gt; command, and I could reproduce the problem of feature set to “no”. I tried running with only the &lt;code&gt;--prefix&lt;/code&gt; flag, and the feature was set to &lt;code&gt;__func__&lt;/code&gt; even without my &lt;code&gt;--enable-xxx&lt;/code&gt; hack. So the root cause was actually the &lt;code&gt;--with-opt-dir&lt;/code&gt;. Why was it set?&lt;/p&gt;

&lt;p&gt;Reading the source code again, the relevant part is &lt;a href="https://github.com/postmodern/ruby-install/blob/638253aa325aa6a40e5546d37555d046e057158b/share/ruby-install/ruby/functions.sh#L30-L43"&gt;this&lt;/a&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="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$package_manager&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in
    &lt;/span&gt;brew&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;opt_dir&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;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; readline&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; libyaml&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; gdbm&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nv"&gt;openssl_dir&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;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; openssl@1.1&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;;;&lt;/span&gt;
    port&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;opt_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/opt/local"&lt;/span&gt;
        &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;

run ./configure &lt;span class="nt"&gt;--prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$install_dir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;opt_dir&lt;/span&gt;:+--with-opt-dir&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$opt_dir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;openssl_dir&lt;/span&gt;:+--with-openssl-dir&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$openssl_dir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;configure_opts&lt;/span&gt;&lt;span class="p"&gt;[@]&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="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn’t set &lt;code&gt;--package_manager&lt;/code&gt; for &lt;code&gt;ruby-install&lt;/code&gt; because I did set &lt;code&gt;--no-install-deps&lt;/code&gt;, and I thought it is sufficient. The problem was finally resolved by replacing &lt;code&gt;--no-install-deps&lt;/code&gt; with &lt;code&gt;--package_manager port&lt;/code&gt;. (Note: &lt;code&gt;ruby-install&lt;/code&gt; doesn’t support the flag format &lt;code&gt;--key=val&lt;/code&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I use MacPorts to manage FOSS on my Mac. I switched from Homebrew to MacPorts because Homebrew doesn’t record whether a package is “explicitly installed” or pulled in as dependencies; also Homebrew doesn’t support “virtual packages”. However, MacPorts seems to be mainly (only?) for FOSS, and is not interested in distributing binaries compiled upstream. This is includes &lt;a href="https://docs.docker.com/desktop/install/mac-install/"&gt;Docker for Mac&lt;/a&gt;, &lt;a href="https://www.coconut-flavour.com/coconutbattery/"&gt;coconutBattery&lt;/a&gt;, Acrobat Reader, Vagrant, and VirtualBox. Managing them via Homebrew Cask allows clean uninstallation, which is important for me, so I’d keep them coexist for a while.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>macports</category>
      <category>autotools</category>
    </item>
    <item>
      <title>Monitor home Internet connectivity with Cloudprober</title>
      <dc:creator>Franklin Yu</dc:creator>
      <pubDate>Sat, 07 Oct 2023 03:49:00 +0000</pubDate>
      <link>https://dev.to/franklinyu/monitor-home-internet-connectivity-with-cloudprober-ejk</link>
      <guid>https://dev.to/franklinyu/monitor-home-internet-connectivity-with-cloudprober-ejk</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;From time to time, my home is disconnected from the Internet, typically due to an outage of the Internet Service Provider. I do receive notification about my cameras going offline, but I have no idea how long it lasts; it can range from 10 minutes to 12 hours, and Comcast won’t tell you how long (you don’t even have access to the outage information unless you log in with the Comcast account). In addition, sometimes the Internet isn’t fully down, but the quality drops, so I’d like to set up something to monitor my Internet connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey of solution-hunting
&lt;/h2&gt;

&lt;p&gt;The principle is simple: I set up something to ping (or cURL) &lt;a href="https://google.com"&gt;https://google.com&lt;/a&gt;. Given the historical availability of that page, this probe is going to tell me whether I can reach Internet. Now the real question is, what tool can do the queries, save the data, and visualize the latency for me.&lt;/p&gt;

&lt;p&gt;I did some research, and asked around. Most people don’t care; the ones who care typically uses SmokePing:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/oetiker"&gt;
        oetiker
      &lt;/a&gt; / &lt;a href="https://github.com/oetiker/SmokePing"&gt;
        SmokePing
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The Active Monitoring System
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;____                  _        ____  _             
/ ___| _ __ ___   ___ | | _____|  _ \(_)_ __   __ _ 
\___ \| '_ ` _ \ / _ \| |/ / _ \ |_) | | '_ \ / _` |
 ___) | | | | | | (_) |   &amp;lt;  __/  __/| | | | | (_| |
|____/|_| |_| |_|\___/|_|\_\___|_|   |_|_| |_|\__, |
                                              |___/ 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Original Authors:  Tobias Oetiker  and Niko Tyni &lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/oetiker/SmokePing/actions/workflows/build-test.yaml"&gt;&lt;img src="https://github.com/oetiker/SmokePing/actions/workflows/build-test.yaml/badge.svg" alt="Build Test"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SmokePing is a latency logging and graphing and
alerting system. It consists of a daemon process which
organizes the latency measurements and a CGI which
presents the graphs.&lt;/p&gt;
&lt;h1 id="user-content-smokeping-is-"&gt;&lt;a class="heading-link" href="https://github.com/oetiker/SmokePing#smokeping-is-"&gt;SmokePing is ...&lt;/a&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;extensible through plug-in modules&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;easy to customize through a webtemplate and an extensive
configuration file.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;written in perl and should readily port to any unix system&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;an RRDtool frontend&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;able to deal with DYNAMIC IP addresses as used with
Cable and ADSL internet.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;cheers
tobi&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/oetiker/SmokePing"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;SmokePing has its own web UI to show the data. The UI looks good enough for most users, but I’m not an average user, but this is insufficient for an SRE-SWE. I’m more of a backend guy, so not very good at implementing the interactive features myself. Another option I found was Nagios:&lt;/p&gt;


&lt;div class="ltag__wikipedia--container"&gt;
  &lt;div class="ltag__wikipedia--header"&gt;
    &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Y-xY3vU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/wikipedia-logo-0a3e76624c7b1c3ccdeb9493ea4add6ef5bd82d7e88d102d5ddfd7c981efa2e7.svg" class="ltag__wikipedia--logo" alt="Wikipedia Logo" width="128" height="128"&gt;
    &lt;a href="https://en.wikipedia.org/wiki/Nagios" rel="noopener noreferrer"&gt;Nagios&lt;/a&gt;
  &lt;/div&gt;
  &lt;div class="ltag__wikipedia--extract"&gt;&lt;p&gt;&lt;b&gt;Nagios Core&lt;/b&gt;, formerly known as &lt;b&gt;Nagios&lt;/b&gt;, is a free and open-source computer-software application that monitors systems, networks and infrastructure. Nagios offers monitoring and alerting services for servers, switches, applications and services. It alerts users when things go wrong and alerts them a second time when the problem has been resolved.&lt;/p&gt;&lt;/div&gt;
  &lt;div class="ltag__wikipedia--btn--container"&gt;
    
      &lt;a href="https://en.wikipedia.org/wiki/Nagios" rel="noopener noreferrer"&gt;View on Wikipedia&lt;/a&gt;
    
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I tried it briefly, before I had another idea: simply make a daemon (or a scheduled task) to post to some data-hosting service, such as &lt;a href="https://cloud.google.com/monitoring"&gt;Google Cloud Monitoring&lt;/a&gt; (also known as “StackDriver”. (Disclaimer: I’m a Googler.) I did some more research, and summarized my options in a GitHub issue:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/FranklinYu/snippets/issues/23"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Create a prober for connectivity of home Internet
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#23&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/FranklinYu"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--NEh5y_1a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://avatars.githubusercontent.com/u/3153452%3Fv%3D4" alt="FranklinYu avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/FranklinYu"&gt;FranklinYu&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/FranklinYu/snippets/issues/23"&gt;&lt;time&gt;Oct 07, 2022&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Need to know how good the connection is.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/FranklinYu/snippets/issues/23"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;When I was collecting libraries for this idea, I found Cloudprober.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloudprober
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/cloudprober"&gt;
        cloudprober
      &lt;/a&gt; / &lt;a href="https://github.com/cloudprober/cloudprober"&gt;
        cloudprober
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An active monitoring software to detect failures before your customers do.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a href="https://hub.docker.com/v2/repositories/cloudprober/cloudprober/" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/cf8352281c15bd7cc2b537bd9f10af11c0752b6c3a4a94ba348dc9faccc303db/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f70756c6c732f636c6f756470726f6265722f636c6f756470726f6265722e737667" alt="Docker Pulls"&gt;&lt;/a&gt;
&lt;a href="https://github.com/cloudprober/cloudprober/actions/workflows/go.yml"&gt;&lt;img src="https://github.com/cloudprober/cloudprober/actions/workflows/go.yml/badge.svg" alt="Go Build and Test"&gt;&lt;/a&gt;
&lt;a href="https://sonarcloud.io/summary/new_code?id=cloudprober_cloudprober" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/a778229c3e2d3aeeec82da6414881655faac077962efe7ccaa3507a4f957620f/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d636c6f756470726f6265725f636c6f756470726f626572266d65747269633d73656375726974795f726174696e67" alt="Security Rating"&gt;&lt;/a&gt;
&lt;a href="https://sonarcloud.io/summary/new_code?id=cloudprober_cloudprober" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/e10267f3a54c1632b7903c91fc41f2f33e36e9acba5b582ecc67de1e8b689afc/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d636c6f756470726f6265725f636c6f756470726f626572266d65747269633d7371616c655f726174696e67" alt="Maintainability Rating"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;NOTE: Cloudprober's active development has moved to
&lt;a href="https://github.com/cloudprober/cloudprober"&gt;github.com/cloudprober/cloudprober&lt;/a&gt;
from &lt;del&gt;&lt;a href="https://github.com/google/cloudprober"&gt;github.com/google/cloudprober&lt;/a&gt;&lt;/del&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Cloudprober is a monitoring software that makes it super-easy to monitor
availability and performance of various components of your system. Cloudprober
employs the "active" monitoring model. It runs probes against (or on) your
components to verify that they are working as expected. For example, it can run
a probe to verify that your frontends can reach your backends. Similarly it can
run a probe to verify that your in-Cloud VMs can actually reach your on-premise
systems. This kind of monitoring makes it possible to monitor your systems'
interfaces regardless of the implementation and helps you quickly pin down
what's broken in your system.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/9980c452ea9ce1bb98b0c7f57b0ebd264939f906c5b86dafb3e6b026263f87ac/687474703a2f2f636c6f756470726f6265722e6f72672f6469616772616d732f636c6f756470726f6265725f7573655f636173652e737667"&gt;&lt;img src="https://camo.githubusercontent.com/9980c452ea9ce1bb98b0c7f57b0ebd264939f906c5b86dafb3e6b026263f87ac/687474703a2f2f636c6f756470726f6265722e6f72672f6469616772616d732f636c6f756470726f6265725f7573655f636173652e737667" alt="Cloudprober Use Case"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="user-content-features"&gt;&lt;a class="heading-link" href="https://github.com/cloudprober/cloudprober#features"&gt;Features&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Out of the box, config based, integration with many popular monitoring systems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://prometheus.io" rel="nofollow"&gt;Prometheus/Grafana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.datadoghq.com/" rel="nofollow"&gt;DataDog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/" rel="nofollow"&gt;PostgreSQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/cloudwatch/" rel="nofollow"&gt;AWS CloudWatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/stackdriver/" rel="nofollow"&gt;StackDriver / Google Cloud Monitoring&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Multiple options for checks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Efficient, highly scalable&lt;/em&gt;, built-in probes
&lt;a href="https://github.com/cloudprober/cloudprober/blob/master/probes/http/proto/config.proto"&gt;HTTP&lt;/a&gt;
&lt;a href="https://github.com/cloudprober/cloudprober/blob/master/probes/ping/proto/config.proto"&gt;PING&lt;/a&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/cloudprober/cloudprober"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Cloudprober was created by Googlers (probably as a side project), and it supports uploading data to Google Cloud Monitoring (exactly what I needed). The tool was designed for black-box service monitoring of owned services, but it can actually be pointed to any service. For example, I monitor the Google homepage with this configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# proto-file: https://github.com/cloudprober/cloudprober/blob/master/config/proto/config.proto
# proto-message: cloudprober.ProberConfig

probe: {
  name: "google_homepage"
  type: HTTP
  targets: {
    host_names: "www.google.com"
  }
  interval: "30s"
  timeout: "1s"
  latency_distribution: {
    exponential_buckets: {
      scale_factor: 100
      base: 1.1
      num_buckets: 25
      # last bucket starts at: 100 * 1.1^24 = 985 ms
    }
  }
  latency_unit: "ms"
  http_probe: {
    protocol: HTTPS
  }
}

surfacer: {
  type: STACKDRIVER
  stackdriver_surfacer: {
    project: "franklinyu-home"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This creates nice charts on Google Cloud console like&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bGUdZL9D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/21ug1v2ccf6uvfvl6b9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bGUdZL9D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/21ug1v2ccf6uvfvl6b9j.png" alt="heatmap of latency" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Starting Cloudprober yourself
&lt;/h2&gt;

&lt;p&gt;First, of course you need to download Cloudprober. You can follow &lt;a href="https://cloudprober.org/docs/overview/getting-started/"&gt;the official guide&lt;/a&gt; to download the pre-built binary, or (if you are using Arch Linux) use &lt;a href="https://aur.archlinux.org/packages/cloudprober"&gt;my AUR package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then you need a Google Cloud project, and &lt;a href="https://cloud.google.com/docs/authentication/provide-credentials-adc#local-key"&gt;create a service account key&lt;/a&gt;. Follow the Google Cloud documentation to set the environment variable.&lt;/p&gt;

&lt;p&gt;Now save the configuration file somewhere, for example in &lt;code&gt;~/Desktop/cloudprober.textproto&lt;/code&gt;, and run Cloudprober like&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudprober &lt;span class="nt"&gt;--config_file&lt;/span&gt; ~/Desktop/cloudprober.textproto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Wait for a while, and the metric should appear in Google Cloud Console as&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;custom/cloudprober/http/google_homepage/latency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And you can see the data in &lt;a href="https://console.cloud.google.com/monitoring/metrics-explorer"&gt;Metric Explorer&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;The configuration file is specified in &lt;a href="https://protobuf.dev/reference/protobuf/textformat-spec/"&gt;the text format of Procotol Buffer&lt;/a&gt;, also known (in Google) as “Text-Proto”. Most parts are straight forward; the &lt;code&gt;latency_distribution&lt;/code&gt; stanza is explained in &lt;a href="https://cloud.google.com/monitoring/api/v3/distribution-metrics"&gt;Google Cloud documentation&lt;/a&gt;. If we denote the scale-factor as “k” and base as “a”, then basically the buckets are the right-open intervals&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;[kai,kai+1)
[k a^i, k a^{i+1})
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;[&lt;/span&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mbin mtight"&gt;+&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;except the first and last bucket (which has to cover the minimum and maximum). My strategy of choosing the base and the scale factor boils down to the “target interval”, which is the interval of latency that I care about. If we denote the number of buckets as “n”, then my strategy is that the entire “target interval” should be covered by buckets from second to the “second to last”. In other words, the “target interval” is supposed to be a subset of&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;[k,kan−2)
[k, k a^{n-2})
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;[&lt;/span&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


</description>
      <category>homelab</category>
    </item>
  </channel>
</rss>
