<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Peek Read Info (Technology)</title><link>https://peekread.info/</link><description>As I Tinker I Learn, Somtimes I Even Write It Down.</description><atom:link href="https://peekread.info/tech.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2024 &lt;a href="mailto:dugite-code@peekread.info"&gt;Dugite-Code&lt;/a&gt; 
&lt;a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"&gt;
&lt;img alt="Creative Commons License BY-SA"
width="88px" height="31px" style="border-width:0; margin-bottom:12px;"
src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Wed, 14 Feb 2024 06:35:19 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>The Hugo Switch</title><link>https://peekread.info/blog/20240214-the-hugo-switch/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;I've decided to shake things up a bit, and I'm switching my blog over from &lt;a href="https://www.getnikola.com/"&gt;Nikola&lt;/a&gt; to &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Page Bundles and Obsidian&lt;/h2&gt;
&lt;p&gt;Page bundles offer great convenience for storing my blog posts in Obsidian. With Hugo, they group content along with associated resources like images and files. With this portability, I can store my posts within my note structure. While Nikola could provide similar capabilities to some extent, it's worth exploring alternatives, especially as I would have to rebuild my site anyway.&lt;/p&gt;
&lt;h2&gt;Better Asset Pipelines&lt;/h2&gt;
&lt;p&gt;One of the things that really drew me to Hugo is its asset pipeline. With image scaling, format conversion (hello, webp! Everyone hates you, but Google's bots sure don't), CSS and JS minification, Hugo makes my life easier. Plus, Hugo plays nice with deployment tools like purgecss, reducing the chances of mistakes with automation.&lt;/p&gt;
&lt;p&gt;I'm even using the &lt;code&gt;module.mounts&lt;/code&gt; feature to import my CSS and JS from a &lt;code&gt;node_modules&lt;/code&gt; folder, making it easier to keep them up to date.&lt;/p&gt;
&lt;h2&gt;I've Just Learned a Lot&lt;/h2&gt;
&lt;p&gt;I'll admit it—I've made my fair share of mistakes along the way with this blog. From opting for a basic Bootstrap theme with little to no dark mode support, to not optimizing my HTML as thoroughly as I could have, I've certainly had some learning moments. But it's all part of the learning experience, so I'll take this opportunity to start fresh.&lt;/p&gt;</description><category>quick post</category><guid>https://peekread.info/blog/20240214-the-hugo-switch/</guid><pubDate>Tue, 13 Feb 2024 16:00:00 GMT</pubDate></item><item><title>Using fdupes to cleanup my file server</title><link>https://peekread.info/tech/20230706-using-fdupes-to-cleanup-my-file-server/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;h4&gt;The overall problem:&lt;/h4&gt;
&lt;p&gt;Like many of us, I am guilty of copying files haphazardly, promising myself that I'll organize them later. This has built up to a significant problem over the years, particularly with old smartphone backups. I had a bad habit of dumping photo folder backups onto my server, with each dump containing even more dumps of old photos, resulting in multiple levels of duplication. Using the command-line tool called &lt;code&gt;fdupes&lt;/code&gt; I've only just managed to get some of it under control.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fdupes&lt;/code&gt; is a command-line application designed to find and identify duplicate files within a directory or a set of directories. It employs various techniques to compare file contents and determine duplicates, enabling efficient cleanup and reclamation of storage space.&lt;/p&gt;
&lt;p&gt;To streamline the review process and make sure I know what's about to happen before deleting any files, I created a simple bash wrapper script. This script acts as a nice safety belt, preventing accidental fat finger deletions.&lt;/p&gt;
&lt;h4&gt;Avoiding the &lt;code&gt;rm -rf&lt;/code&gt; Pitfall:&lt;/h4&gt;
&lt;p&gt;As many of us have learned the hard way, the &lt;code&gt;rm -rf&lt;/code&gt; command can have disastrous consequences if misused (goodbye email server with 2000 emails). A simple typo or a wrong path can result in irreversible data loss. To mitigate this risk, the bash wrapper script avoids using &lt;code&gt;rm -rf&lt;/code&gt; altogether. Instead, it leverages the safer alternative of moving duplicate files to a temporary trash directory for review and then subsequent manual deletion.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;TRASH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/tmp/trash"&lt;/span&gt;

find_files&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;fdupes&lt;span class="w"&gt; &lt;/span&gt;-rn&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Duplicate files have listed in &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

remove_files&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Reading from &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Type yes to continue"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;choice
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$choice&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;yes&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TRASH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;line&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TRASH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Duplicate files have been moved to &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TRASH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Exiting"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;getopts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rf:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;option&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;option&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;r&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;f&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPTARG&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;dupes&lt;/span&gt;&lt;span class="p"&gt;.txt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="nv"&gt;OPTIND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$remove&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;remove_files
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;find_files&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Understanding the Script:&lt;/h4&gt;
&lt;p&gt;The script utilizes the &lt;code&gt;fdupes&lt;/code&gt; command-line tool to identify duplicate files within a given directory or set of directories. Here's how it works:&lt;/p&gt;
&lt;h5&gt;Finding Duplicate Files:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;find_files&lt;/code&gt; function invokes the &lt;code&gt;fdupes&lt;/code&gt; command with the &lt;code&gt;-rn&lt;/code&gt; flags, instructing it to recursively search for duplicates and list the results in a specified file.&lt;/li&gt;
&lt;li&gt;If no file name is provided as an argument, the script will use the default file name &lt;code&gt;dupes.txt&lt;/code&gt; to store the duplicate file list.&lt;/li&gt;
&lt;li&gt;After the duplicates are found, the script informs us that the duplicate files have been listed in the &lt;code&gt;dupes.txt&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Removing Duplicate Files:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;remove_files&lt;/code&gt; function allows us to decide whether to remove the duplicates. Make sure to review the &lt;code&gt;dupes.txt&lt;/code&gt; file before running.&lt;/li&gt;
&lt;li&gt;If no file name is provided as an argument, the script will still refer to the default &lt;code&gt;dupes.txt&lt;/code&gt; file to read the duplicate file list.&lt;/li&gt;
&lt;li&gt;After printing the file listing the duplicates, the script prompts us to confirm our decision by typing "yes."&lt;/li&gt;
&lt;li&gt;If confirmed, the script creates a temporary trash directory and proceeds to move the duplicate files to it.&lt;/li&gt;
&lt;li&gt;Finally, it provides a message confirming that the duplicate files have been successfully moved to the trash directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Using the Script:&lt;/h4&gt;
&lt;p&gt;To utilize the script effectively, follow these steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy the script into a text editor and save it as &lt;code&gt;ddup.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open a terminal and navigate to the directory containing the script.&lt;/li&gt;
&lt;li&gt;Make the script executable by running the command: &lt;code&gt;chmod +x ddup.sh&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Execute the script with appropriate options:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;To find duplicate files: &lt;code&gt;./ddup.sh &amp;lt;directory&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;To remove duplicate files: &lt;code&gt;./ddup.sh -r&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: If you don't specify a file name using the &lt;code&gt;-f&lt;/code&gt; argument, it will default to using the &lt;code&gt;dupes.txt&lt;/code&gt; file for listing duplicate files.&lt;/p&gt;</description><category>fdupes</category><category>nextcloud</category><category>quick post</category><guid>https://peekread.info/tech/20230706-using-fdupes-to-cleanup-my-file-server/</guid><pubDate>Wed, 05 Jul 2023 16:00:00 GMT</pubDate></item><item><title>Making a Lazy Dark Theme with Darkreader</title><link>https://peekread.info/tech/20230414-lazy-dark-themes/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/services/darkreader.png" alt="Dark Reader is a web browser plugin the analyzes web pages and aims to reduce eyestrain while browsing the web."&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;I have been using the Dark Reader plugin in firefox for quite some time now and I quite like it. However, there is one drawback - it has made me procrastinate building a dark theme for my blog. As it turns out, exporting and using the Dark Reader generated theme for your website is pretty damn easy.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Frist you need the plugin installed in your browser, you can get it from the &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/darkreader/"&gt;Firefox Add-ons page here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next You have to switch darkreader to the "new design" (the old design looks more modern IMHO) from the dev tools popup in order to access the export button found in the settings dialogue.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Click Dark Reader icon.&lt;/li&gt;
&lt;li&gt;Click Dev tools (in the bottom-right corner).&lt;/li&gt;
&lt;li&gt;Click Preview new design.&lt;/li&gt;
&lt;li&gt;Click on settings in the popup&lt;/li&gt;
&lt;li&gt;Click on Manage Settings&lt;/li&gt;
&lt;li&gt;Click on Export Dynamic Theme&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Source: &lt;a href="https://github.com/darkreader/darkreader/issues/13#issuecomment-661107975"&gt;Question: Export CSS?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Instructions" class="dark-image mx-auto" loading="lazy" max-height="228" max-width="800" src="https://peekread.info/images/2023/0414-lazy-dark-themes/image01.png"&gt;&lt;/p&gt;
&lt;p&gt;Once you have the css, oen it up in an editor and wrap it in the css media rule for the dark perferd color scheme. Then it's a simple matter of adding it to your webpage as you would any other css file, boom a dark theme for your website with little to no effort.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dark&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c"&gt;/*&lt;/span&gt;
&lt;span class="c"&gt;                         _______&lt;/span&gt;
&lt;span class="c"&gt;                        /       \&lt;/span&gt;
&lt;span class="c"&gt;                       .==.    .==.&lt;/span&gt;
&lt;span class="c"&gt;                      ((  ))==((  ))&lt;/span&gt;
&lt;span class="c"&gt;                     / "=="    "=="\&lt;/span&gt;
&lt;span class="c"&gt;                    /____|| || ||___\&lt;/span&gt;
&lt;span class="c"&gt;        ________     ____    ________  ___    ___&lt;/span&gt;
&lt;span class="c"&gt;        |  ___  \   /    \   |  ___  \ |  |  /  /&lt;/span&gt;
&lt;span class="c"&gt;        |  |  \  \ /  /\  \  |  |  \  \|  |_/  /&lt;/span&gt;
&lt;span class="c"&gt;        |  |   )  /  /__\  \ |  |__/  /|  ___  \&lt;/span&gt;
&lt;span class="c"&gt;        |  |__/  /  ______  \|  ____  \|  |  \  \&lt;/span&gt;
&lt;span class="c"&gt;     ___|_______/__/ ____ \__\__|___\__\__|___\__\_______&lt;/span&gt;
&lt;span class="c"&gt;    |  ___  \ |  ____/ /    \   |  ___  \ |  ____|  ___  \&lt;/span&gt;
&lt;span class="c"&gt;    |  |  \  \|  |___ /  /\  \  |  |  \  \|  |___|  |  \  \&lt;/span&gt;
&lt;span class="c"&gt;    |  |__/  /|  ____/  /__\  \ |  |   )  |  ____|  |__/  /&lt;/span&gt;
&lt;span class="c"&gt;    |  ____  \|  |__/  ______  \|  |__/  /|  |___|  ____  \&lt;/span&gt;
&lt;span class="c"&gt;    |__|   \__\____/__/      \__\_______/ |______|__|   \__\&lt;/span&gt;
&lt;span class="c"&gt;                    https://darkreader.org&lt;/span&gt;
&lt;span class="c"&gt;    */&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c"&gt;/*! Dark reader generated CSS | Licensed under MIT https://github.com/darkreader/darkreader/blob/main/LICENSE */&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;[...]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>css</category><category>darkreader</category><category>meta</category><category>website</category><guid>https://peekread.info/tech/20230414-lazy-dark-themes/</guid><pubDate>Thu, 13 Apr 2023 16:00:00 GMT</pubDate></item><item><title>Playing with chatGTP</title><link>https://peekread.info/tech/20230214-playing-with-chatgtp/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2023/0214-playing-with-chatgtp/image01.png" alt="ChatGTP, impressive if a bit dumb"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;ChatGTP has been taking the internet by storm with its impressive ability to spit out reasonable sounding text, but it is all that great? is it clippy back from the dead to take revenge on us all?&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Key take-aways:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;It takes all character out of your sentences.&lt;/li&gt;
&lt;li&gt;It has a habit of dropping key details for a more generic sentence.&lt;/li&gt;
&lt;li&gt;The longer your inputs are the more likely it's spit out nonsense. Giving it small sections at a time to work on is better.&lt;/li&gt;
&lt;li&gt;Everything it produces need to be proofread.&lt;/li&gt;
&lt;li&gt;It really, really likes the work additionally for some reason.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Biggest criticism&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;&lt;div&gt;test&lt;/div&gt;
&lt;p&gt;ChatGTP has a very strange ability to "corporatize" just about just about anything and remove everything remotely human about a sentence.&lt;/p&gt;
&lt;p&gt;Take this for example:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Me: reword and expand: chat gtp is able to produce quite good sentences but has all the contextual intelligence of a flat worm.&lt;/p&gt;
&lt;p&gt;ChatGTP: While ChatGPT is capable of generating high-quality sentences through natural language processing, its contextual understanding is still limited compared to human intelligence. In other words, while ChatGPT can produce coherent and grammatically correct responses, it lacks the depth of understanding and nuance that humans possess. This is because ChatGPT relies on a vast database of pre-existing text to generate its responses, rather than having the ability to truly comprehend the meaning behind language like a human brain can. Therefore, while ChatGPT can provide helpful information and engage in conversation, it should be used as a tool to assist human intelligence, rather than a replacement for it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If that paragraph doesn’t scream corporate press release maybe you need to take a day off from work and let your brain detox.&lt;/p&gt;
&lt;h3&gt;Final thoughts&lt;/h3&gt;
&lt;p&gt;ChatGTP is a tool, that, while amazing a first glance has it's issues and bugs. It's certainly a step above clippy and has it's place helping to flesh out emails, memos and cover letters but it's formal and stiff. An article on New Yorker titled "ChatGPT Is a Blurry JPEG of the Web" was close, Chat GTP is actually a smudge tool for text.&lt;/p&gt;
&lt;p&gt;Now let's see Chat GTP's take on this article:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Me: write a article regarding the pros and cons of chatgtp in this style: [...]&lt;/p&gt;
&lt;p&gt;ChatGTP: ChatGTP has been making waves on the internet with its ability to produce coherent and grammatically correct sentences through natural language processing. However, is it really as impressive as it appears to be? This article will take a closer look at the pros and cons of ChatGTP.&lt;/p&gt;
&lt;p&gt;One of the most significant drawbacks of ChatGTP is its tendency to remove all character from your sentences. It has a habit of dropping key details to produce more generic responses, which can result in it missing the point entirely. Additionally, the longer the input, the more likely it is to produce nonsense. Therefore, giving it smaller sections to work on is generally more effective.&lt;/p&gt;
&lt;p&gt;Another major drawback of ChatGTP is that everything it produces needs to be proofread. While it can generate coherent and grammatically correct sentences, it can also produce awkward phrasing or sentences that don't quite make sense. This means that anything produced by ChatGTP should always be double-checked to ensure accuracy and clarity.&lt;/p&gt;
&lt;p&gt;The biggest criticism of ChatGTP, however, is its tendency to "corporatize" just about anything and remove all human qualities from a sentence. It has a knack for producing sentences that sound like corporate press releases, which can make it difficult to engage in a natural conversation.&lt;/p&gt;
&lt;p&gt;In conclusion, while ChatGTP is an impressive tool, it is not as impressive as it initially appears to be. It has some significant drawbacks, including removing character from sentences, producing generic responses, and its tendency to "corporatize" language. Therefore, it should be used as a tool to assist human intelligence, rather&lt;/p&gt;
&lt;/blockquote&gt;</description><category>ai</category><category>chatgtp</category><category>thoughts</category><guid>https://peekread.info/tech/20230214-playing-with-chatgtp/</guid><pubDate>Mon, 13 Feb 2023 16:00:00 GMT</pubDate></item><item><title>Readable Nginx configs</title><link>https://peekread.info/tech/20220907-readable-nginx-configs/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2019/0625-server-set-up-checklist/image01.png" alt="Configure your linux server"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;A recent project announcement on the subredit &lt;a href="https://www.reddit.com/r/selfhosted/comments/x7gpwd/making_nginx_easier_to_use_like_caddy/"&gt;/r/selfhosted&lt;/a&gt; reminded me to post about a simple trick I've started using to make the configuration of the webserver Nginx a little more ergonomic.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Nginx allows you to include files inline in your configs to make re-using code simple. An example would be all your ssl proxy settings as per generated using the &lt;a href="https://ssl-config.mozilla.org/#server=nginx&amp;amp;version=1.17.7&amp;amp;config=modern&amp;amp;openssl=1.1.1k&amp;amp;guideline=5.6"&gt;Mozilla ssl-config&lt;/a&gt; generator.&lt;/p&gt;
&lt;p&gt;simply add this config to a file like &lt;code&gt;/etc/nginx/include.d/include.ssl_sec&lt;/code&gt; with your cert paths modified and include it in your config:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;upstream&lt;span class="w"&gt; &lt;/span&gt;example_service&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.1:8080&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;keepalive&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

server&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;server_name&lt;span class="w"&gt; &lt;/span&gt;example.tld&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;#Mozilla modern tls config&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;include&lt;span class="w"&gt; &lt;/span&gt;/etc/nginx/include.d/include.ssl_sec&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;location&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#Common Proxy settings&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;include&lt;span class="w"&gt; &lt;/span&gt;/etc/nginx/include.d/include.proxy_settings&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;proxy_pass&lt;span class="w"&gt; &lt;/span&gt;http://example_service/&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you have a nice easy config file that can be easily used as a template for new services. Adding additional configurations to files really makes it quick and easy to deploy new services without needing complicated projects like Nginx Proxy Manager&lt;/p&gt;</description><category>nginx</category><category>quick post</category><guid>https://peekread.info/tech/20220907-readable-nginx-configs/</guid><pubDate>Tue, 06 Sep 2022 16:00:00 GMT</pubDate></item><item><title>Eking out some Nextcloud performance</title><link>https://peekread.info/tech/20220618-eking-out-some-nextcloud-performance/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/services/nextcloud.png" alt="Tweeking my linux server"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;Nextcloud is notorious in the selfhosted community of being difficult for some people to achieve a decent level of performance. After enabling the basic caching with both APCu and Redis there are several options to trim some fat. Once all the easy stuff is taken care of the hidden bottlenecks is where I am focusing my efforts. So far I have had some success by switching to UNIX sockets in my dockerised Nextcloud deployment.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Generally I've found:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Shipping file logging off to syslog made a noticeable visual difference over logging to the &lt;code&gt;nextcloud.log&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Using postgresql has been &lt;a href="https://np.reddit.com/r/NextCloud/comments/vdl309/result_of_switching_from_mariadb_to_postgresql/"&gt;often touted&lt;/a&gt; as a decent option for easy performance gains.&lt;/li&gt;
&lt;li&gt;Using the &lt;a href="https://apps.nextcloud.com/apps/previewgenerator"&gt;preview generator&lt;/a&gt; app alongside using &lt;a href="https://docs.nextcloud.com/server/latest/admin_manual/installation/server_tuning.html#previews"&gt;Imaginary&lt;/a&gt; makes images less of an issue for general browsing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But what else can you do after that? Trying to find bottlenecks in your setup. Be it spinning rust vs SSD vs M.2 drives there are usually some form of low hanging fruit you can find that is causing issues. A big potential issue is of course your abstraction layer, in my case docker. Docker adds some minor overheads to any service, a trade off for simplifying deployment and replication, one of these overheads is the networking stack. My understanding is that Docker's networking when not in host mode acts as a NAT, even when one container is talking to another. One method of bypass networking overhead between local services is the use of unix sockets.&lt;/p&gt;
&lt;p&gt;In researching how to achieve this I found &lt;a href="https://medium.com/@jonbaldie/"&gt;@jonbaldie's&lt;/a&gt; post on &lt;a href="https://medium.com/@jonbaldie/how-to-connect-to-redis-with-unix-sockets-in-docker-9e94e01b7acd"&gt;How to Connect to Redis with Unix Sockets in Docker&lt;/a&gt;. A few modifications and I was ready to test and verify that this made a difference.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;These are the modifications done to my docker-compose file. Note that I have made a few modifications to avoid the need to set the folders and sockets permissions as &lt;code&gt;777&lt;/code&gt;. This is mainly handled by modifying the container user group id to the &lt;code&gt;www-data&lt;/code&gt; group from the Nextcloud app container.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'2'&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#Temporary busybox container to set correct permissions to shared socket folder&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;busybox&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sh -c "chown -R 33:33 /tmp/docker/ &amp;amp;&amp;amp; chmod -R 770 /tmp/docker/"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/tmp/docker/&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud_db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres:14-alpine&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./volumes/postgresql:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/timezone:/etc/timezone:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db.env&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Unix socket modifications&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Run as a member of the www-data GID 33 group but keep postgres uid as 70&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"70:33"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Add the /tmp/docker/ socket folder to postgres&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres -c unix_socket_directories='/var/run/postgresql/,/tmp/docker/'&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tmp&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Add shared volume from Temporary busybox container&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes_from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tmp&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud_redis&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:alpine&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/timezone:/etc/timezone:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Unix socket modifications&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./volumes/redis.conf:/etc/redis.conf&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Run redis with custom config&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis-server /etc/redis.conf&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Run as a member of the www-data GID 33 group but keep redis uid as 999&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"999:33"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tmp&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Add shared volume from Temporary busybox container&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes_from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tmp&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud_app&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:apache&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;127.0.0.1:9001:80&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./volumes/nextcloud:/var/www/html&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./volumes/php.ini:/usr/local/etc/php/conf.d/zzz-custom.ini&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/timezone:/etc/timezone:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Unix socket modifications&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Add shared volume from Temporary busybox container&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes_from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tmp&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the redis.conf file that tells it to only listen to the unix socket, and what permissions to use on said socket. Note I have a password enabled here, this is not really need it if not exposed publicly but I've used it just for best practice.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;
&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;only&lt;/span&gt;
&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;127.0.0.1&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;domain&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;
&lt;span class="n"&gt;unixsocket&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;permissions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;
&lt;span class="n"&gt;unixsocketperm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;770&lt;/span&gt;

&lt;span class="n"&gt;requirepass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally the Nextcloud config I updated to reflect the connection changes&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="x"&gt;'dbtype' =&amp;gt; 'pgsql',&lt;/span&gt;
&lt;span class="x"&gt;'dbhost' =&amp;gt; '/tmp/docker/',&lt;/span&gt;
&lt;span class="x"&gt;'dbname' =&amp;gt; 'nextcloud',&lt;/span&gt;
&lt;span class="x"&gt;'dbuser' =&amp;gt; 'nextcloud',&lt;/span&gt;
&lt;span class="x"&gt;'dbpassword' =&amp;gt; '{password}',&lt;/span&gt;

&lt;span class="x"&gt;'memcache.local' =&amp;gt; '\\OC\\Memcache\\APCu',&lt;/span&gt;
&lt;span class="x"&gt;'memcache.distributed' =&amp;gt; '\\OC\\Memcache\\Redis',&lt;/span&gt;
&lt;span class="x"&gt;'memcache.locking' =&amp;gt; '\\OC\\Memcache\\Redis',&lt;/span&gt;
&lt;span class="x"&gt;'redis' =&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;array (&lt;/span&gt;
&lt;span class="x"&gt;  'host' =&amp;gt; '/tmp/docker/redis.sock',&lt;/span&gt;
&lt;span class="x"&gt;  'port' =&amp;gt; 0,&lt;/span&gt;
&lt;span class="x"&gt;  'dbindex' =&amp;gt; 0,&lt;/span&gt;
&lt;span class="x"&gt;  'password' =&amp;gt; '{password}',&lt;/span&gt;
&lt;span class="x"&gt;  'timeout' =&amp;gt; 1.5,&lt;/span&gt;
&lt;span class="x"&gt;),&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Verifying the changes made a difference.&lt;/h2&gt;
&lt;p&gt;There is not much point in doing this without verification, otherwise we are all just participating in a cargo cult seeking performance enlightenment. With that in mind I set out to do some very basic benchmarks to ensure the performance gain I felt when navigating my Nextcloud install was in fact happening.&lt;/p&gt;
&lt;p&gt;I did all my testing inside my Nextcloud container to better simulate a real-world result. I modified the &lt;code&gt;redis.conf&lt;/code&gt; temporarily to allow both socket connections and TCP IP connections, then I had to install the &lt;code&gt;redis-tools&lt;/code&gt; and &lt;code&gt;postgresql-contrib&lt;/code&gt; packages to get the tools required.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;port&lt;/span&gt;
#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;

#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;only&lt;/span&gt;
#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;127&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="nv"&gt;bind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;nextcloud_app&lt;span class="w"&gt; &lt;/span&gt;bash

apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;redis-tools&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;postgresql-contrib
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I then performed the same tests as &lt;a href="https://medium.com/@jonbaldie/"&gt;@jonbaldie's&lt;/a&gt; using the commands &lt;code&gt;time redis-benchmark -a [password] -h redis -p 6379&lt;/code&gt; and &lt;code&gt;time redis-benchmark -a [password] -s /tmp/docker/redis.sock&lt;/code&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;REDIS&lt;/th&gt;
&lt;th&gt;TCP (s)&lt;/th&gt;
&lt;th&gt;UNIX (s)&lt;/th&gt;
&lt;th&gt;% Diff&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Real&lt;/td&gt;
&lt;td&gt;242.8&lt;/td&gt;
&lt;td&gt;165.5&lt;/td&gt;
&lt;td&gt;32%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;63.4&lt;/td&gt;
&lt;td&gt;60.9&lt;/td&gt;
&lt;td&gt;4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sys&lt;/td&gt;
&lt;td&gt;132.1&lt;/td&gt;
&lt;td&gt;70.6&lt;/td&gt;
&lt;td&gt;47%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;438.4&lt;/td&gt;
&lt;td&gt;297.1&lt;/td&gt;
&lt;td&gt;32%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As you can see on my system I saw a staggering 32% difference compared to &lt;a href="https://medium.com/@jonbaldie/"&gt;@jonbaldie's&lt;/a&gt; 13%. Clearly the Redis socket is a very worthwhile modification.&lt;/p&gt;
&lt;p&gt;Using some of what I learned from reading &lt;a href="https://www.enterprisedb.com/blog/pgbench-performance-benchmark-postgresql-12-and-edb-advanced-server-12"&gt;this article&lt;/a&gt; I now wanted to test my Postgres database using it's benchmarking tool &lt;code&gt;pgbench&lt;/code&gt;. I did a quick database backup just in case, but it shouldn't harm the Nextcloud db as it's only adding the tables pgbench_accounts, pgbench_branches, pgbench_tellers and pgbench_history to perform the tests.&lt;/p&gt;
&lt;p&gt;First test the testing tables initialisation&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;pgbench&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;db&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5432&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;nextcloud&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;nextcloud

...

&lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.85&lt;span class="w"&gt; &lt;/span&gt;s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;drop&lt;span class="w"&gt; &lt;/span&gt;tables&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.00&lt;span class="w"&gt; &lt;/span&gt;s,&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;tables&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.13&lt;span class="w"&gt; &lt;/span&gt;s,&lt;span class="w"&gt; &lt;/span&gt;client-side&lt;span class="w"&gt; &lt;/span&gt;generate&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.60&lt;span class="w"&gt; &lt;/span&gt;s,&lt;span class="w"&gt; &lt;/span&gt;vacuum&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.60&lt;span class="w"&gt; &lt;/span&gt;s,&lt;span class="w"&gt; &lt;/span&gt;primary&lt;span class="w"&gt; &lt;/span&gt;keys&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.51&lt;span class="w"&gt; &lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then I Ran 3 tests using the command &lt;code&gt;pgbench -h db -c 10 -p 5432 -U nextcloud -d nextcloud&lt;/code&gt; simulating 10 clients.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Postgres TCP&lt;/th&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;th&gt;2&lt;/th&gt;
&lt;th&gt;3&lt;/th&gt;
&lt;th&gt;Average&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;latency average&lt;/td&gt;
&lt;td&gt;265.887&lt;/td&gt;
&lt;td&gt;333.644&lt;/td&gt;
&lt;td&gt;280.873&lt;/td&gt;
&lt;td&gt;293.468&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tps (including connections establishing)&lt;/td&gt;
&lt;td&gt;37.60993&lt;/td&gt;
&lt;td&gt;29.972067&lt;/td&gt;
&lt;td&gt;35.603308&lt;/td&gt;
&lt;td&gt;34.3951016666667&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tps (excluding connections establishing)&lt;/td&gt;
&lt;td&gt;38.089613&lt;/td&gt;
&lt;td&gt;30.24576&lt;/td&gt;
&lt;td&gt;35.997626&lt;/td&gt;
&lt;td&gt;34.7776663333333&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Clean up inbeteween tests&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;psql&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;/tmp/docker/&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;nextcloud&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;nextcloud

DROP&lt;span class="w"&gt; &lt;/span&gt;TABLE&lt;span class="w"&gt; &lt;/span&gt;pgbench_accounts,&lt;span class="w"&gt; &lt;/span&gt;pgbench_branches,&lt;span class="w"&gt; &lt;/span&gt;pgbench_tellers,&lt;span class="w"&gt; &lt;/span&gt;pgbench_history&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;First test the testing tables initialisation&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;pgbench&lt;span class="w"&gt; &lt;/span&gt;-h&lt;span class="w"&gt; &lt;/span&gt;/tmp/docker/&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;nextcloud&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;nextcloud

...

&lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.42&lt;span class="w"&gt; &lt;/span&gt;s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;drop&lt;span class="w"&gt; &lt;/span&gt;tables&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.00&lt;span class="w"&gt; &lt;/span&gt;s,&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;tables&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.11&lt;span class="w"&gt; &lt;/span&gt;s,&lt;span class="w"&gt; &lt;/span&gt;client-side&lt;span class="w"&gt; &lt;/span&gt;generate&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.68&lt;span class="w"&gt; &lt;/span&gt;s,&lt;span class="w"&gt; &lt;/span&gt;vacuum&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.25&lt;span class="w"&gt; &lt;/span&gt;s,&lt;span class="w"&gt; &lt;/span&gt;primary&lt;span class="w"&gt; &lt;/span&gt;keys&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.38&lt;span class="w"&gt; &lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then I Ran 3 tests using the command &lt;code&gt;pgbench -h /tmp/docker/ -c 10 -U nextcloud -d nextcloud&lt;/code&gt; simulating 10 clients.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Postgres UNIX&lt;/th&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;th&gt;2&lt;/th&gt;
&lt;th&gt;3&lt;/th&gt;
&lt;th&gt;Average&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;latency average&lt;/td&gt;
&lt;td&gt;291.566&lt;/td&gt;
&lt;td&gt;290.129&lt;/td&gt;
&lt;td&gt;222.446&lt;/td&gt;
&lt;td&gt;268.047&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tps (including connections establishing)&lt;/td&gt;
&lt;td&gt;34.297528&lt;/td&gt;
&lt;td&gt;34.467479&lt;/td&gt;
&lt;td&gt;44.954712&lt;/td&gt;
&lt;td&gt;37.906573&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tps (excluding connections establishing)&lt;/td&gt;
&lt;td&gt;34.397523&lt;/td&gt;
&lt;td&gt;34.570084&lt;/td&gt;
&lt;td&gt;45.137941&lt;/td&gt;
&lt;td&gt;38.0351826666667&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;My results show a much more modest performance difference with the database. But it's still an unambiguous improvement so well worth the minor amount of effort.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;% Diff&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;latency average&lt;/td&gt;
&lt;td&gt;9.00%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tps (including connections establishing)&lt;/td&gt;
&lt;td&gt;10.00%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tps (excluding connections establishing)&lt;/td&gt;
&lt;td&gt;9.00%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;testing tables initialisation&lt;/td&gt;
&lt;td&gt;23.00%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Finding, testing and minimising bottlenecks is possibly the most difficult task for any selfhosting admin. I hope you found this of use in your own bottleneck hunting journey.&lt;/p&gt;</description><category>nextcloud</category><category>performance</category><category>sysadmin</category><category>tweeks</category><guid>https://peekread.info/tech/20220618-eking-out-some-nextcloud-performance/</guid><pubDate>Fri, 17 Jun 2022 16:00:00 GMT</pubDate></item><item><title>Authentik Gotifiy Login Notifications</title><link>https://peekread.info/tech/20220506-authentik-gotifiy-login-notifications/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2022/0428-sso-with-authentik/image01.png" alt="SSO all the things"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;Continuing with my journy of utilising Authentik for my SSO. After reading a rather good comment by &lt;a href="https://www.reddit.com/r/selfhosted/comments/ub7dvb/authentik_or_keycloak/i62o6hf/"&gt;/u/internallogictv&lt;/a&gt; over on the reddit &lt;a href="https://www.reddit.com/r/selfhosted/"&gt;/r/selfhosted&lt;/a&gt;, I wanted to add a few more protections. The simplest of which is to send myself a notification whenever a login or a failed login occurs.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Step 1&lt;/h2&gt;
&lt;p&gt;First things first we create a new application in gotify in order to generate a token for authentik use. Select the &lt;code&gt;Apps&lt;/code&gt; tab and press the &lt;code&gt;Create Application&lt;/code&gt; button.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Gotify create an application" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="185" max-width="800" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image01.png"&gt;&lt;/p&gt;
&lt;h2&gt;Step 2&lt;/h2&gt;
&lt;p&gt;Create a new gotify property mapping in the &lt;code&gt;Admin Interface -&amp;gt; Customisation -&amp;gt; Property Mappings&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="426" max-width="800" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image02.png"&gt;&lt;/p&gt;
&lt;p&gt;I've built this so a login failed is set to the maximum gotify priority level regardless of the user group. For successful logins I divide the levels based on the group gotify-users. I algo create a geo uri for mapping applications on android. You will be able to click the notification and it will open the city co-ordinates, although you may have to skip this if you don't have the &lt;code&gt;geoipupdate&lt;/code&gt; container configured.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Get the login failed username&lt;/span&gt;
    &lt;span class="n"&gt;event_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Get the login succeeded username&lt;/span&gt;
    &lt;span class="n"&gt;event_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"login_failed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
    &lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"warning"&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;ak_is_group_member&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;ak_user_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;event_user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"gotify-users"&lt;/span&gt; &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;# Check if the user belongs to group&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# default notification settings&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;

&lt;span class="c1"&gt;# Build a geo uri for opening a mapping applications from the gotify notification.&lt;/span&gt;
&lt;span class="n"&gt;geo_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"geo:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'lat'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'long'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?q=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'lat'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'long'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from authentik &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"New &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event_user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was detected coming from &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'city'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'country'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from the IP address: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client_ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Build the gotify payload&lt;/span&gt;
&lt;span class="n"&gt;gotify_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"extras"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"client::notification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"click"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;geo_uri&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;gotify_payload&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Step 3&lt;/h2&gt;
&lt;p&gt;Create a new notification transport &lt;code&gt;Admin Interface -&amp;gt; Events -&amp;gt;  Notification Transports&lt;/code&gt; using &lt;code&gt;Webhook (generic)&lt;/code&gt; your gotify message url with the token created in step one &lt;code&gt;https://example.tld/gotify/message?token=yourtokenhere&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="360" max-width="799" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image03.png"&gt;&lt;/p&gt;
&lt;h2&gt;Step 4&lt;/h2&gt;
&lt;p&gt;Finally we create the notification rule that actually calls the Notification transport. &lt;code&gt;Admin Interface -&amp;gt; Events -&amp;gt;  Notification Rules&lt;/code&gt; Create a new rule &lt;code&gt;login-notification&lt;/code&gt; sending to the group of your choice (This dosn't really matter but it will display an ugly json string as notification on the web UI). Select the &lt;code&gt;Gotify&lt;/code&gt; notification transport you created and set the Severity to &lt;code&gt;Notice&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="489" max-width="798" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image04.png"&gt;&lt;/p&gt;
&lt;p&gt;Now we have to create the policies &lt;code&gt;authentik-core-login&lt;/code&gt; and &lt;code&gt;authentik-core-login-failed&lt;/code&gt; to the event. Expand the &lt;code&gt;login-notification&lt;/code&gt; event and press &lt;code&gt;Create Policy&lt;/code&gt;. Select &lt;code&gt;Event Matcher Policy&lt;/code&gt;, name it &lt;code&gt;authentik-core-login&lt;/code&gt; enable the &lt;code&gt;Execution Logging&lt;/code&gt; option, select the &lt;code&gt;Login&lt;/code&gt; action and &lt;code&gt;authentik Core&lt;/code&gt; App. Finish and repeat for the &lt;code&gt;Login Failed&lt;/code&gt; action.&lt;/p&gt;
&lt;p&gt;Now you should be receiving Login and Login Failed notifications from your Authentik instance over Gotify. I Hope I'll be able to update this to pull different tokens from the user/group attributes in the future to better separate notifications to individual users/admins.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="294" max-width="797" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image05.png"&gt;&lt;/p&gt;</description><category>authentik</category><category>gotify</category><category>notifications</category><category>security</category><category>SSO</category><guid>https://peekread.info/tech/20220506-authentik-gotifiy-login-notifications/</guid><pubDate>Thu, 05 May 2022 16:00:00 GMT</pubDate></item><item><title>Node-Red SSO with Authentik</title><link>https://peekread.info/tech/20220429-node-red-sso-with-authentik/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2019/1122-node-red-website-alerts/image01.png" alt="Node-RED is a flow-based programming tool, originally developed by IBM’s Emerging Technology Services team and now a part of the JS Foundation."&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;Following my &lt;a href="https://peekread.info/tech/20220325-sso-with-authentik/"&gt;last post regarding SSO with Authentik&lt;/a&gt; I thought I should post my passportjs configuration for Node-Red and OpenidConnect. Currently User accounts work, however I haven't gotten group based permissions setup yet.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note This guide is based off the &lt;a href="https://goauthentik.io/integrations/services/gitea/"&gt;Gitea integration guide from the Authentik docs.&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Preparation&lt;/h3&gt;
&lt;p&gt;The following placeholders will be used:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;authentik.company&lt;/code&gt; is the FQDN of authentik.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nodered.company&lt;/code&gt; is the FQDN of nodered.&lt;/p&gt;
&lt;h3&gt;Step 1&lt;/h3&gt;
&lt;p&gt;In authentik, create an OAuth2/OpenID Provider (under Resources/Providers) with these settings:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;note&lt;/p&gt;
&lt;p&gt;Only settings that have been modified from default have been listed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Protocol Settings&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;
&lt;span class="n"&gt;Signing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;note&lt;/p&gt;
&lt;p&gt;Take note of the Client ID and Client Secret, you'll need to give them to nodered in Step 3.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Step 2&lt;/h3&gt;
&lt;p&gt;In authentik, create an application (under Resources/Applications) which uses this provider. Optionally apply access restrictions to the application using policy bindings.
note&lt;/p&gt;
&lt;p&gt;Only settings that have been modified from default have been listed.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;
&lt;span class="n"&gt;Slug&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;
&lt;span class="n"&gt;Provider&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;note&lt;/p&gt;
&lt;p&gt;We are assuming node-red is installed under docker&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Navigate to the node-red data volume &lt;code&gt;data/node_modules/&lt;/code&gt;. Alternatively enter the docker container &lt;code&gt;sudo docker exec -it nodered bash&lt;/code&gt; and cd &lt;code&gt;/data/node_modules&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Use npm to install passport-openidconnect npm install passport-openidconnect&lt;/p&gt;
&lt;p&gt;Edit the node-red settings.js file &lt;code&gt;/data/settings.js&lt;/code&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nx"&gt;adminAuth&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"strategy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openidconnect"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Sign in with authentik'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"fa-cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"passport-openidconnect"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;issuer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/&amp;lt;application-slug&amp;gt;/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;authorizationURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/authorize/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;tokenURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/token/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;userInfoURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/userinfo/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;clientID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;Client ID (Key): Step 2&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;clientSecret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;Client Secret: Step 2&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;callbackURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://nodered.company/auth/strategy/callback/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'profile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'openid'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;verify&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>authentik</category><category>node-red</category><category>security</category><category>SSO</category><guid>https://peekread.info/tech/20220429-node-red-sso-with-authentik/</guid><pubDate>Thu, 28 Apr 2022 16:00:00 GMT</pubDate></item><item><title>SSO with Authentik</title><link>https://peekread.info/tech/20220325-sso-with-authentik/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2022/0428-sso-with-authentik/image01.png" alt="SSO all the things"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;A while back I wrote about minimising my attack surface by utilising default deny and whitelists in Nginx. Now I've gotten into the weeds with authentication and deployed an SSO (Signle sign-on) service on my selfhosted infrastructure.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;What is Authentik?&lt;/h3&gt;
&lt;p&gt;Authentik is a SSO (Single Sign on) provider, much like with Google's services you sign in once and then you can access all your services. This has been a big bugbear with selfhosted applications, with &lt;a href="https://gitlab.com/dugite-code/rcmail_ttrss"&gt;Roundcubemail TTRSS plugin&lt;/a&gt;, &lt;a href="https://github.com/dugite-code/auth_rcmail"&gt;auto authentication for Tiny Tiny RSS against an IMAP Server&lt;/a&gt; and &lt;a href="https://github.com/dugite-code/codiad-imap_auth"&gt;Codiad External Authentication via IMAP &lt;/a&gt; to name a few work arounds to the issue I have hacked together over the years.&lt;/p&gt;
&lt;p&gt;Most importantly for my use case is the single pane of glass to access my services:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A nice dashboard really brings it all together" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-width="1110" src="https://peekread.info/images/2022/0428-sso-with-authentik/a-nice-dashboard-realy-brings-it-all-together.png"&gt;&lt;/p&gt;
&lt;h3&gt;The Issues&lt;/h3&gt;
&lt;p&gt;Introducing a SSO system introduces complexity and potential problems so it's not all smooth sailing, passwords are a thing still as they are simple and reliable and understandable.&lt;/p&gt;
&lt;h4&gt;New Project new problems, limited reviews&lt;/h4&gt;
&lt;p&gt;Authentik's first beta release was in Jan 2020 so it's very new and has had a few teething issues and quite a few bugs. I highly recommend utilising additional security methods in front of authentik (IDS/IPS, Geo Blocking and ideally using a VPN to access) until it reaches maturity.&lt;/p&gt;
&lt;h4&gt;Poor Documentation&lt;/h4&gt;
&lt;p&gt;Quite frankly the documentation isn't great if you are attempting to figure out &lt;strong&gt;HOW&lt;/strong&gt; it’s supposed to work. Thankfully they have integration guides included in the docs that covers the gaps, so some reading between the lines is needed for a while yet.&lt;/p&gt;
&lt;h4&gt;Limited compatibility&lt;/h4&gt;
&lt;p&gt;Not everything has SSO support (SAML, Oauth/OpenidConnect or reverse Proxy Authentication), thankfully this isn't as hard to deal with as it once was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discourse.nodered.org/t/nextcloud-oauth-2-login/4403/8?u=dugite-code"&gt;My post on adding openidconnect to node-red&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ArchiveBox/ArchiveBox/pull/866#discussion_r839151488"&gt;My minor contribution to the Reverse Proxy authentication pull request for ArchiveBox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main issue I have faced is with HomeAssistant. The developers have been reluctant/resistant to adding additional authentication methods to the project. There is the &lt;a href="https://github.com/BeryJu/hass-auth-header"&gt;hass-auth-header&lt;/a&gt; project created by the developer of Authentik, however the HomeAssistant Android app is frustratingly a &lt;a href="https://github.com/home-assistant/android/issues/1438"&gt;major sticking point&lt;/a&gt;.&lt;/p&gt;</description><category>authentication</category><category>authentik</category><category>rss</category><category>security</category><category>SSO</category><guid>https://peekread.info/tech/20220325-sso-with-authentik/</guid><pubDate>Thu, 24 Mar 2022 16:00:00 GMT</pubDate></item><item><title>New maintainers needed for the Thunderbird Lookout Fix-version add-on</title><link>https://peekread.info/tech/20210817-new-maintainers-needed-for-the-thunderbird-lookout-fix-version-add-on/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2019/0627-lookout-fix-version/image01.png" alt="Lookout!"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;In august 2018 I took over maintenance of the Thunderbird addon &lt;a href="https://addons.thunderbird.net/en-US/thunderbird/addon/lookout-fix-version/"&gt;Lookout-fix-version&lt;/a&gt;. I soon set up a the Github Organization &lt;a href="https://github.com/TB-throwback"&gt;TB-throwback&lt;/a&gt; so that future development can be expanded and transferred easier if I stop work on it.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;LookOut Fix-Version is a plugin which allows Thunderbird to interface with Microsoft’s mail tools by decoding metadata and attachments encapsulated/embedded in a TNEF (Transport Neutral Encapsulation Format) encoded attachment (aka winmail.dat).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Transport Neutral Encapsulation Format or TNEF is a proprietary email attachment format used by Microsoft Outlook and Microsoft Exchange Server. An attached file with TNEF encoding is most often named winmail.dat or win.dat, and has a MIME type of Application/MS-TNEF. The official (IANA) media type, however, is application/vnd.ms-tnef.
Source: https://en.wikipedia.org/wiki/Transport_Neutral_Encapsulation_Format&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Unfortunately I had to stop working on Lookout a while ago because my employer switched us back to Outlook leaving me with no company time to maintain the project any more. The last major release of Thunderbird I received a lot of help from the TB team's John Bieling to bootstrap a workaround to get things rolling again, now Thunderbird 91 is coming and it's another case of the old xul add-ons not working in the webextension world.&lt;/p&gt;
&lt;p&gt;After receiving no takers to my maintainer request over &lt;a href="https://thunderbird.topicbox.com/groups/addons/T263d93db60cf14be-Mb7ce4a3a6ba61fac7cb8f2fb/lookout-fix-version-no-longer-receiving-company-backed-support"&gt;on the mailing list&lt;/a&gt; I have decided if I am unable to locate new maintainers I will archive the project on Github. I hope the Thunderbird devs finally assign &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=77811"&gt;Bug 77811&lt;/a&gt; to someone as I know that proper integration for decoding TNEF emails was &lt;a href="https://developer.thunderbird.net/planning/roadmap-1#investigate-microsoft-tnef-support-tb-2022"&gt;added to the roadmap&lt;/a&gt;, however in the meantime you are interested in updating the project please let me know as I'll actively be monitoring &lt;a href="https://github.com/TB-throwback/LookOut-fix-version"&gt;the Github project&lt;/a&gt; and &lt;a href="https://github.com/TB-throwback/LookOut-fix-version/issues/65"&gt;the issue calling for new maintainers&lt;/a&gt;&lt;/p&gt;</description><category>add-on</category><category>legacy</category><category>thunderbird</category><category>tnef</category><category>winmail.dat</category><guid>https://peekread.info/tech/20210817-new-maintainers-needed-for-the-thunderbird-lookout-fix-version-add-on/</guid><pubDate>Mon, 16 Aug 2021 16:00:00 GMT</pubDate></item></channel></rss>