<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Howto on WormBytes</title><link>https://www.wormbytes.ca/categories/howto/</link><description>Recent content in Howto on WormBytes</description><generator>Hugo -- gohugo.io</generator><language>en-ca</language><managingEditor>Robert James Kaes</managingEditor><copyright>Robert James Kaes. All Rights Reserved.</copyright><lastBuildDate>Thu, 04 May 2023 11:40:56 -0400</lastBuildDate><atom:link href="https://www.wormbytes.ca/categories/howto/index.xml" rel="self" type="application/rss+xml"/><item><title>Yggdrasil VPN</title><link>https://www.wormbytes.ca/2023/05/04/yggdrasil-vpn/</link><pubDate>Thu, 04 May 2023 11:40:56 -0400</pubDate><author>Robert James Kaes</author><guid>https://www.wormbytes.ca/2023/05/04/yggdrasil-vpn/</guid><description>&lt;p&gt;I&amp;rsquo;m trying to work outside my home office more, but all my email is hosted on
my home server. While disconnecting is nice, not having access when I need it
has sucked.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href="https://yggdrasil-network.github.io/"&gt;yggdrasil&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;After installing on my laptop (MacOS) and my desktop (Ubuntu) I updated
&lt;code&gt;.ssh/config&lt;/code&gt; with my desktop&amp;rsquo;s IPv6 address and was able to SSH via IPv6 over
my local network. Perfect!&lt;/p&gt;
&lt;p&gt;Step two: install on a server with a public IP. One more service running on
my &lt;a href="https://www.digitalocean.com/"&gt;Digital Ocean&lt;/a&gt; instance.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not interested, at the moment, with joining the full yggdrasil network, so
I configured my public instance to only allow peering from my laptop and
desktop&amp;rsquo;s public keys:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; AllowedPublicKeys: [
&amp;#34;desktop-public-key&amp;#34;
&amp;#34;laptop-public-key&amp;#34;
]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On the public server, I listen via TLS rather than plain TCP. It&amp;rsquo;s slightly
slower, but also slightly more secure. Since I&amp;rsquo;m not moving a lot of traffic
over the connection, the extra security is worth it to me:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; Listen: [
tls://PUBLIC-IP-ADDRESS:56603
]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I couldn&amp;rsquo;t find a recommended port to listen on, so I picked a random number. 🤣&lt;/p&gt;
&lt;p&gt;(The only &amp;ldquo;gotcha&amp;rdquo; was remembering to open the firewall for
yggdrasil.)&lt;/p&gt;
&lt;p&gt;Ramces Red&amp;rsquo;s &lt;a href="https://www.maketecheasier.com/install-yggdrasil-network"&gt;article about
yggdrasil&lt;/a&gt; has more
information about installing and configuring a basic VPN.&lt;/p&gt;</description></item><item><title>Function Key Snipping with Raycast</title><link>https://www.wormbytes.ca/2023/01/08/function-key-snipping-with-raycast/</link><pubDate>Sun, 08 Jan 2023 08:52:34 -0500</pubDate><author>Robert James Kaes</author><guid>https://www.wormbytes.ca/2023/01/08/function-key-snipping-with-raycast/</guid><description>&lt;p&gt;&lt;a href="https://mxgrn.com/pages/about"&gt;Max Gorin&lt;/a&gt; posted
&lt;a href="https://mxgrn.com/blog/function-keys-productivity-trick"&gt;You&amp;rsquo;re using function keys
wrong&lt;/a&gt; where he
describes using function keys as a quick launcher!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So, here’s the trick: assign each of your top-12 most used apps to an F-key.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Max uses KeyboardMaestro to show/hide the apps, but we can do the same
with &lt;a href="https://www.raycast.com/"&gt;Raycast&lt;/a&gt; (which I already use, and
it&amp;rsquo;s &lt;em&gt;free&lt;/em&gt;.)&lt;/p&gt;
&lt;h2 id="step-1"&gt;Step 1&lt;/h2&gt;
&lt;p&gt;I have a &lt;a href="https://support.apple.com/kb/SP794"&gt;2019 MacBook Pro with Touchbar&lt;/a&gt;
so the first change is to always display the function keys.&lt;/p&gt;
&lt;p&gt;Within &lt;strong&gt;System Settings/Keyboard&lt;/strong&gt; and &lt;strong&gt;Touch Bar Settings&lt;/strong&gt; change:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Touch Bar Shows to &amp;ldquo;F1, F2, etc. Keys&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Press and hold fn key to &amp;ldquo;Show Expanded Control Strip&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;img srcset="https://www.wormbytes.ca/2023/01/08/function-key-snipping-with-raycast/touch-bar-settings_hu_cf92f88f97e2b558.webp 1438w,/2023/01/08/function-key-snipping-with-raycast/touch-bar-settings_hu_bc4f92b338b21232.webp 1078w,/2023/01/08/function-key-snipping-with-raycast/touch-bar-settings_hu_ba10414d4e84ece9.webp 719w,/2023/01/08/function-key-snipping-with-raycast/touch-bar-settings_hu_6961cc61e6c645c0.webp 359w"
sizes="(max-width: 500px) 100vw, 70vw"
src="https://www.wormbytes.ca/2023/01/08/function-key-snipping-with-raycast/touch-bar-settings.png" width="1438" height="1254" alt="Screenshot of macOS Touch Bar Preferences" /&gt;
&lt;h2 id="step-2"&gt;Step 2&lt;/h2&gt;
&lt;p&gt;Install &lt;a href="https://www.raycast.com/"&gt;Raycast&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="step-3"&gt;Step 3&lt;/h2&gt;
&lt;p&gt;Open Raycast (I use &lt;code&gt;⌘Space&lt;/code&gt;), find the application you want to assign to a function key,
and go into application configuration (using &lt;code&gt;⌘⇧,&lt;/code&gt;)&lt;/p&gt;
&lt;img srcset="https://www.wormbytes.ca/2023/01/08/function-key-snipping-with-raycast/raycast-application-settings_hu_f00d4c432a568e0f.webp 1990w,/2023/01/08/function-key-snipping-with-raycast/raycast-application-settings_hu_e1de45f4135b9e96.webp 1492w,/2023/01/08/function-key-snipping-with-raycast/raycast-application-settings_hu_1f508b18df0cd827.webp 995w,/2023/01/08/function-key-snipping-with-raycast/raycast-application-settings_hu_c62e820d62fe6986.webp 497w"
sizes="(max-width: 500px) 100vw, 70vw"
src="https://www.wormbytes.ca/2023/01/08/function-key-snipping-with-raycast/raycast-application-settings.png" width="1990" height="1230" alt="Raycast Application Settings Screen" /&gt;
&lt;p&gt;Hit &lt;code&gt;Record Hotkey&lt;/code&gt; and assign it to whatever &lt;code&gt;Fn&lt;/code&gt; you want!&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;F1&lt;/code&gt; &lt;a href="https://sw.kovidgoyal.net/kitty/"&gt;Kitty Terminal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;F2&lt;/code&gt; &lt;a href="https://slack.com/"&gt;Slack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;F3&lt;/code&gt; &lt;a href="https://support.apple.com/en-ca/guide/messages/welcome/mac"&gt;Messages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;F4&lt;/code&gt; &lt;a href="https://www.mozilla.org/en-CA/firefox/products/"&gt;Firefox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;F5&lt;/code&gt; &lt;a href="https://getdrafts.com/"&gt;Drafts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;F9&lt;/code&gt; Music&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Managing Site Content with Sub</title><link>https://www.wormbytes.ca/2017/08/13/managing-site-content-with-sub/</link><pubDate>Sun, 13 Aug 2017 11:40:35 +0000</pubDate><author>Robert James Kaes</author><guid>https://www.wormbytes.ca/2017/08/13/managing-site-content-with-sub/</guid><description>&lt;p&gt;No self respecting developer will tolerate writing out the same commands over
and over.&lt;/p&gt;
&lt;img srcset="https://www.wormbytes.ca/2017/08/13/managing-site-content-with-sub/automate-all-the-things_hu_77b221da8adb833a.webp 946w,/2017/08/13/managing-site-content-with-sub/automate-all-the-things_hu_9e3f705edf5aa5d0.webp 709w,/2017/08/13/managing-site-content-with-sub/automate-all-the-things_hu_f0f4dedeb81758da.webp 473w,/2017/08/13/managing-site-content-with-sub/automate-all-the-things_hu_6667f62925f77f7f.webp 236w"
sizes="(max-width: 500px) 100vw, 70vw"
src="https://www.wormbytes.ca/2017/08/13/managing-site-content-with-sub/automate-all-the-things.png" width="946" height="660" alt="Automate All the Things!" /&gt;
&lt;p&gt;With &lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; building the static files, I needed a way
to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;create draft posts&lt;/li&gt;
&lt;li&gt;serve drafts via localhost to review&lt;/li&gt;
&lt;li&gt;publish a draft as a full post&lt;/li&gt;
&lt;li&gt;build the site&lt;/li&gt;
&lt;li&gt;deploy to &lt;a href="https://www.digitalocean.com/"&gt;DigitalOcean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After manually running shell commands and manually editing files, I &lt;em&gt;had&lt;/em&gt; to
automate the workflow.&lt;/p&gt;
&lt;p&gt;I use &lt;a href="https://github.com/basecamp/sub"&gt;sub&lt;/a&gt; to organize the various scripts
that handle each part of the process.&lt;/p&gt;
&lt;h1 id="create-draft-posts"&gt;Create Draft Posts&lt;/h1&gt;
&lt;p&gt;First step was to create a &lt;code&gt;template.md&lt;/code&gt; file with all the optional
&lt;a href="https://jekyllrb.com/docs/frontmatter/"&gt;Front Matter&lt;/a&gt; a post might need.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#00f;font-weight:bold"&gt;---&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#008000;font-weight:bold"&gt;title&lt;/span&gt;:&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# # Rest are optional&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# categories:&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# tags:&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# permalink:&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# excerpt: # Markdown description before the story&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# description: # SEO `&amp;lt;meta&amp;gt;` description (requires an `excerpt`)&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# header:&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# image: # Path to the full image for the size (1280x...)&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# image_description: # Custom `alt` tag&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# caption: # Photo credit (can be written in markdown)&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# teaser: # Path to teaser image (roughly 500x300)&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;#&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# # Hero video image&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# video:&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# id: &lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# provider:&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;#&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# # An image with text overlay and call to action button&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# overlay_image: # Path to the full image size&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# overlay_filter: 0.5 # opacity between 0.0 and 1.0 (or full `rgba(255, 0, 0, 0.5)`)&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# cta_label: # Call to action button label&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# cta_url: # URL the call to action button goes to&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# overlay_color: # Can be used rather than `overlay_image` as #ccc&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;#&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# NOTE: https://mmistakes.github.io/minimal-mistakes/docs/helpers/&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# https://mmistakes.github.io/minimal-mistakes/docs/utility-classes/&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#00f;font-weight:bold"&gt;---&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You&amp;rsquo;ll notice that only &lt;code&gt;title&lt;/code&gt; is required. Everything is commented out.
Also, there&amp;rsquo;s no &lt;code&gt;date&lt;/code&gt; attribute since this is a draft.&lt;/p&gt;
&lt;p&gt;When I begin writing a draft I run:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;site draft whatever-the-post-slug-will-be
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;which runs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f"&gt;set&lt;/span&gt; -u
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f"&gt;set&lt;/span&gt; -e
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp _drafts/template.md _drafts/&lt;span style="color:#b68;font-weight:bold"&gt;${&lt;/span&gt;&lt;span style="color:#b8860b"&gt;1&lt;/span&gt;&lt;span style="color:#b68;font-weight:bold"&gt;}&lt;/span&gt;.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f"&gt;exec&lt;/span&gt; &lt;span style="color:#b8860b"&gt;$EDITOR&lt;/span&gt; _drafts/&lt;span style="color:#b68;font-weight:bold"&gt;${&lt;/span&gt;&lt;span style="color:#b8860b"&gt;1&lt;/span&gt;&lt;span style="color:#b68;font-weight:bold"&gt;}&lt;/span&gt;.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A simple script to copy the template into the &lt;code&gt;_drafts/&lt;/code&gt; folder with the slug
name and then fire up my editor (&lt;a href="https://neovim.io/"&gt;NeoVim&lt;/a&gt;.)&lt;/p&gt;
&lt;h1 id="previewing-drafts-on-localhost"&gt;Previewing Drafts on Localhost&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://jekyllrb.org/"&gt;Jekyll&lt;/a&gt; can preview drafts on the localhost. I run:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;site serve
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;which executes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f"&gt;set&lt;/span&gt; -x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f"&gt;set&lt;/span&gt; -e
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jekyll serve -D --watch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;in a separate &lt;a href="https://tmux.github.io/"&gt;tmux&lt;/a&gt; pane. &lt;a href="https://jekyllrb.org/"&gt;Jekyll&lt;/a&gt; is configured to
watch for changes and rebuild the draft for preview.&lt;/p&gt;
&lt;h1 id="publishing"&gt;Publishing&lt;/h1&gt;
&lt;p&gt;Once I&amp;rsquo;m happy with a draft it&amp;rsquo;s time to publish it (meaning promoting it from
&lt;code&gt;_drafts/&lt;/code&gt; into &lt;code&gt;_posts/&lt;/code&gt;.)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;site publish whatever-the-post-slug-will-be
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which runs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;#! /usr/bin/env ruby&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# Copy the file from the drafts folder, add the current date, and update the&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# filename. Remove any commented out lines from the front matter.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;now &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#800"&gt;Time&lt;/span&gt;&lt;span style="color:#666"&gt;.&lt;/span&gt;now
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;draft &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#800"&gt;File&lt;/span&gt;&lt;span style="color:#666"&gt;.&lt;/span&gt;basename(&lt;span style="color:#800"&gt;ARGV&lt;/span&gt;&lt;span style="color:#666"&gt;[&lt;/span&gt;&lt;span style="color:#666"&gt;0&lt;/span&gt;&lt;span style="color:#666"&gt;]&lt;/span&gt;, &lt;span style="color:#b44"&gt;&amp;#39;.md&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;draft_filename &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#800"&gt;File&lt;/span&gt;&lt;span style="color:#666"&gt;.&lt;/span&gt;join(&lt;span style="color:#b44"&gt;&amp;#39;_drafts&amp;#39;&lt;/span&gt;, &lt;span style="color:#b44"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#b68;font-weight:bold"&gt;#{&lt;/span&gt;draft_filename&lt;span style="color:#b68;font-weight:bold"&gt;}&lt;/span&gt;&lt;span style="color:#b44"&gt;.md&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;post_filename &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#800"&gt;File&lt;/span&gt;&lt;span style="color:#666"&gt;.&lt;/span&gt;join(&lt;span style="color:#b44"&gt;&amp;#39;_posts&amp;#39;&lt;/span&gt;, &lt;span style="color:#b44"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#b68;font-weight:bold"&gt;#{&lt;/span&gt;now&lt;span style="color:#666"&gt;.&lt;/span&gt;strftime(&lt;span style="color:#b44"&gt;&amp;#39;%Y-%m-%d&amp;#39;&lt;/span&gt;)&lt;span style="color:#b68;font-weight:bold"&gt;}&lt;/span&gt;&lt;span style="color:#b44"&gt;-&lt;/span&gt;&lt;span style="color:#b68;font-weight:bold"&gt;#{&lt;/span&gt;draft&lt;span style="color:#b68;font-weight:bold"&gt;}&lt;/span&gt;&lt;span style="color:#b44"&gt;.md&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;post &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#800"&gt;File&lt;/span&gt;&lt;span style="color:#666"&gt;.&lt;/span&gt;open(post_filename, &lt;span style="color:#b44"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;state &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#b8860b"&gt;:start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f"&gt;open&lt;/span&gt;(draft_filename)&lt;span style="color:#666"&gt;.&lt;/span&gt;readlines&lt;span style="color:#666"&gt;.&lt;/span&gt;each &lt;span style="color:#a2f;font-weight:bold"&gt;do&lt;/span&gt; &lt;span style="color:#666"&gt;|&lt;/span&gt;line&lt;span style="color:#666"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; (state &lt;span style="color:#666"&gt;==&lt;/span&gt; &lt;span style="color:#b8860b"&gt;:start&lt;/span&gt; &lt;span style="color:#666"&gt;||&lt;/span&gt; state &lt;span style="color:#666"&gt;==&lt;/span&gt; &lt;span style="color:#b8860b"&gt;:in_front_matter&lt;/span&gt;) &lt;span style="color:#666"&gt;&amp;amp;&amp;amp;&lt;/span&gt; line &lt;span style="color:#666"&gt;=~&lt;/span&gt; &lt;span style="color:#b68"&gt;/^---/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; post&lt;span style="color:#666"&gt;.&lt;/span&gt;puts line
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; state &lt;span style="color:#666"&gt;==&lt;/span&gt; &lt;span style="color:#b8860b"&gt;:start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; post&lt;span style="color:#666"&gt;.&lt;/span&gt;puts &lt;span style="color:#b44"&gt;&amp;#34;date: &lt;/span&gt;&lt;span style="color:#b68;font-weight:bold"&gt;#{&lt;/span&gt;now&lt;span style="color:#666"&gt;.&lt;/span&gt;strftime(&lt;span style="color:#b44"&gt;&amp;#39;%Y-%m-%d %H:%M:%S %:z&amp;#39;&lt;/span&gt;)&lt;span style="color:#b68;font-weight:bold"&gt;}&lt;/span&gt;&lt;span style="color:#b44"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; state &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#b8860b"&gt;:in_front_matter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; state &lt;span style="color:#666"&gt;=&lt;/span&gt; &lt;span style="color:#b8860b"&gt;:body&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;elsif&lt;/span&gt; state &lt;span style="color:#666"&gt;==&lt;/span&gt; &lt;span style="color:#b8860b"&gt;:in_front_matter&lt;/span&gt; &lt;span style="color:#666"&gt;&amp;amp;&amp;amp;&lt;/span&gt; (line &lt;span style="color:#666"&gt;=~&lt;/span&gt; &lt;span style="color:#b68"&gt;/^#/&lt;/span&gt; &lt;span style="color:#666"&gt;||&lt;/span&gt; line &lt;span style="color:#666"&gt;=~&lt;/span&gt; &lt;span style="color:#b68"&gt;/^\s$/&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#080;font-style:italic"&gt;# Skip all the comment lines in the front matter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;next&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; post&lt;span style="color:#666"&gt;.&lt;/span&gt;puts line
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a2f;font-weight:bold"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f;font-weight:bold"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;post&lt;span style="color:#666"&gt;.&lt;/span&gt;close
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#800"&gt;File&lt;/span&gt;&lt;span style="color:#666"&gt;.&lt;/span&gt;unlink(draft_filename) &lt;span style="color:#a2f;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#800"&gt;File&lt;/span&gt;&lt;span style="color:#666"&gt;.&lt;/span&gt;exist?(post_filename)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt; script:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Adds the current &lt;code&gt;date&lt;/code&gt; attribute to the &lt;a href="https://jekyllrb.com/docs/frontmatter/"&gt;Front Matter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Removes all the commented out lines in the &lt;a href="https://jekyllrb.com/docs/frontmatter/"&gt;Front Matter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Moves the file from the &lt;code&gt;_drafts&lt;/code&gt; folder to the &lt;code&gt;_posts&lt;/code&gt; folder and
prefixes the current date to the file.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="deploy-updates-to-production"&gt;Deploy Updates to Production&lt;/h1&gt;
&lt;p&gt;With everything ready, it&amp;rsquo;s time to deploy the changes to the
[site]({{ .Site.BaseURL }}). One last script:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;site deploy
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;running:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#b8860b"&gt;$_SITE_ROOT&lt;/span&gt;/bin/site build
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rsync -crvz --delete-after --delete-excluded _site/ wormbytes:/var/www/wormbytes.ca/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First we build the site:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f"&gt;set&lt;/span&gt; -u
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f"&gt;set&lt;/span&gt; -e
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jekyll build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and then copy the &lt;code&gt;_site/&lt;/code&gt; directory up to the &lt;a href="https://www.digitalocean.com/"&gt;DigitalOcean&lt;/a&gt; production
server, deleting any files that have been removed and updating any new files.&lt;/p&gt;</description></item><item><title>Let's Encrypt and Nginx on Ubuntu</title><link>https://www.wormbytes.ca/2017/08/11/letsencrypt-and-nginx-on-ubuntu/</link><pubDate>Fri, 11 Aug 2017 19:09:53 +0000</pubDate><author>Robert James Kaes</author><guid>https://www.wormbytes.ca/2017/08/11/letsencrypt-and-nginx-on-ubuntu/</guid><description>
&lt;img srcset="https://www.wormbytes.ca/2017/08/11/letsencrypt-and-nginx-on-ubuntu/banner_hu_3dae94396171d6b1.webp 949w,/2017/08/11/letsencrypt-and-nginx-on-ubuntu/banner_hu_412871d6f2a91afe.webp 711w,/2017/08/11/letsencrypt-and-nginx-on-ubuntu/banner_hu_399c383d911b0cff.webp 474w,/2017/08/11/letsencrypt-and-nginx-on-ubuntu/banner_hu_d1c2c8c20cd87aa8.webp 237w"
sizes="(max-width: 500px) 100vw, 70vw"
src="https://www.wormbytes.ca/2017/08/11/letsencrypt-and-nginx-on-ubuntu/banner.jpg" width="949" height="400" alt="A combination lock resting on a laptop keyboard" /&gt;
&lt;p&gt;Configuring &lt;a href="https://wiki.nginx.org/"&gt;nginx&lt;/a&gt; to use SSL certificates from &lt;a href="https://letsencrypt.org/"&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; using the
&lt;a href="https://certbot.eff.org/docs/using.html#webroot"&gt;Webroot&lt;/a&gt; method
isn&amp;rsquo;t hard, but
there are a few steps to make it all work. We assume:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you have only one website setup in nginx and that any additional sites will
also use &lt;a href="https://letsencrypt.org/"&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; for their SSL certificates.&lt;/li&gt;
&lt;li&gt;HTML is served from &lt;code&gt;/var/www/example.com&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="prerequisites"&gt;Prerequisites&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://releases.ubuntu.com/16.04/"&gt;Ubuntu 16.04&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.nginx.org/"&gt;nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;You must own or control the registered domain name that you wish to use the
certificate with.&lt;/li&gt;
&lt;li&gt;A DNS &lt;strong&gt;A Record&lt;/strong&gt; that points your domain to the public IP address of your
server. &lt;a href="https://letsencrypt.org/"&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; requires this to validate that you own the domain.
You will need an &lt;strong&gt;A Record&lt;/strong&gt; for both &lt;code&gt;www.example.com&lt;/code&gt; and &lt;code&gt;example.com&lt;/code&gt;
if you want to support both domains.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="step-1---installing-certbot"&gt;Step 1 - Installing Certbot&lt;/h1&gt;
&lt;p&gt;The easiest way to request a SSL certificate from &lt;a href="https://letsencrypt.org/"&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; is to use
the &lt;code&gt;certbot&lt;/code&gt;. The &lt;a href="https://certbot.eff.org/"&gt;Certbot&lt;/a&gt; developers have their own [Ubuntu] software
repository with update-to-date versions of the software.&lt;/p&gt;
&lt;p&gt;First add the repository:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You&amp;rsquo;ll need to press &lt;code&gt;ENTER&lt;/code&gt; to accept the &lt;code&gt;certbot&lt;/code&gt; repository.&lt;/p&gt;
&lt;p&gt;Now install &lt;a href="https://certbot.eff.org/"&gt;Certbot&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt-get install certbot
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;certbot&lt;/code&gt; &lt;a href="https://letsencrypt.org/"&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; client is now ready.&lt;/p&gt;
&lt;h1 id="step-2---create-nginx-configs"&gt;Step 2 - Create Nginx Configs&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://letsencrypt.org/"&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; uses a challenge system to ensure the domain for which the SSL
certificate is about to be issued is controlled by the requester. To avoid
duplicating the logic in every virtual host configuration (as we&amp;rsquo;re setting up
both &lt;code&gt;example.com&lt;/code&gt; and &lt;code&gt;www.example.com&lt;/code&gt;) we&amp;rsquo;ll create a snippet.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo mkdir -p /etc/nginx/snippets/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Create &lt;code&gt;/etc/nginx/snippets/letsencrypt.conf&lt;/code&gt; containing:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;location ^~ /.well-known/acme-challenge/ {
default_type &amp;#34;text/plain&amp;#34;;
root /var/www/letsencrypt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Create the &lt;a href="https://ietf-wg-acme.github.io/acme/"&gt;ACME&lt;/a&gt; challenge folder (as referenced above):&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We need to create the server specific &lt;code&gt;dhparam.pem&lt;/code&gt; file. This will take
a while:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt-get install openssl
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, within &lt;code&gt;/etc/nginx/conf.d&lt;/code&gt; we&amp;rsquo;ll create the global SSL settings. Create
&lt;code&gt;/etc/nginx/conf.d/ssl.conf&lt;/code&gt; containing:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.2;
# Use the &amp;#34;Modern&amp;#34; cipher suite recommended by Mozilla
# https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
ssl_ciphers
&amp;#39;ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256&amp;#39;;
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
# Enable HTST to ensure communication is only over SSL
add_header Strict-Transport-Security &amp;#34;max-age=15768000; includeSubdomains;
preload&amp;#34;;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="step-3---configure-domain-to-respond-to-acme-challenge"&gt;Step 3 - Configure Domain to Respond to ACME Challenge&lt;/h1&gt;
&lt;p&gt;As we don&amp;rsquo;t have any SSL certificates yet, we need to configure our domain to
respond to the &lt;a href="https://ietf-wg-acme.github.io/acme/"&gt;ACME&lt;/a&gt; challenges. Assuming your &lt;a href="https://wiki.nginx.org/"&gt;nginx&lt;/a&gt; virtual server
configuration is at &lt;code&gt;/etc/nginx/sites-available/example.com.conf&lt;/code&gt; add:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;include /etc/nginx/snippets/letsencrypt.conf;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;between your &lt;code&gt;server { ... }&lt;/code&gt; blocks.&lt;/p&gt;
&lt;p&gt;Enable the site:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.conf
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then reload &lt;a href="https://wiki.nginx.org/"&gt;nginx&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="step-4---obtaining-an-ssl-certificate"&gt;Step 4 - Obtaining an SSL Certificate&lt;/h1&gt;
&lt;p&gt;Request the certificate (&lt;em&gt;don&amp;rsquo;t forget to replace with your own email
address&lt;/em&gt;):&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;certbot certonly --webroot --agree-tos --no-eff-email --email YOUR@EMAIL.COM -w /var/www/letsencrypt -d www.example.com -d example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It will save the files into &lt;code&gt;/etc/letsencrypt/live/www.example.com/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: The &lt;code&gt;--no-eff-flag&lt;/code&gt; opts out of signing up for the &lt;a href="https://lists.eff.org/cgi-bin/mailman/listinfo"&gt;EFF mailing
list&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="step-5---setup-https-only-virtual-hosts"&gt;Step 5 - Setup HTTPS-Only Virtual Hosts&lt;/h1&gt;
&lt;p&gt;Now that we have the SSL certificates, switch your domain to HTTPS. Edit
&lt;code&gt;/etc/nginx/sites-available/domain.com.conf&lt;/code&gt; and replace the HTTP server
configs with:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;## http://example.com redirects to https://example.com
server {
listen 80;
listen [::]:80;
server_name example.com;
include /etc/nginx/snippets/letsencrypt.conf;
location / {
return 301 https://example.com$request_uri;
}
}
## http://www.example.com redirects to https://www.example.com
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name www.example.com;
include /etc/nginx/snippets/letsencrypt.conf;
location / {
return 301 https://www.example.com$request_uri;
}
}
## https://example.com redirects to https://www.example.com
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
location / {
return 301 https://www.example.com$request_uri;
}
}
## Serves https://www.example.com
server {
server_name www.example.com;
listen 443 ssl default_server;
listen [::]:443 ssl default_server ipv6only=on;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
# The rest of your previous HTTP virtual server configuration. Below is an
# example:
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally, reload nginx:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;Note that &lt;code&gt;http://example.com&lt;/code&gt; redirects to &lt;code&gt;https://example.com&lt;/code&gt; (which
redirects to &lt;code&gt;https://www.example.com&lt;/code&gt;) because redirecting to
&lt;code&gt;https://www.example.com&lt;/code&gt; directly would be incompatible with HSTS.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id="step-6---automatic-renewal-using-cron"&gt;Step 6 - Automatic Renewal using Cron&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://certbot.eff.org/"&gt;Certbot&lt;/a&gt; can renew all certificates that expire within 30 days. We&amp;rsquo;ll create
a cronjob that automatically updates the certificates (and restarts &lt;a href="https://wiki.nginx.org/"&gt;nginx&lt;/a&gt; to
pick up the changes.)&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try a dry-run to ensure that everything is working:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo certbot renew --dry-run
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Create &lt;code&gt;/usr/local/sbin/letsencrypt.sh&lt;/code&gt; containing:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemctl reload nginx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#080;font-style:italic"&gt;# If you have other services that use the certificates add reloads here:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Make it executable:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo chmod +x /usr/local/sbin/letsencrypt.sh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Edit the root&amp;rsquo;s cron:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo crontab -e
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And add:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;20 3 * * * certbot renew --noninteractive --renew-hook /usr/local/sbin/letsencrypt.sh
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;And that&amp;rsquo;s it! If all went well you should see your site at
&lt;code&gt;https://www.example.com/&lt;/code&gt;!&lt;/p&gt;</description></item><item><title>Relaying Mail through Sympatico Using Postfix</title><link>https://www.wormbytes.ca/articles/postfix-with-sympatico-relay/</link><pubDate>Mon, 15 May 2006 00:21:09 +0000</pubDate><author>Robert James Kaes</author><guid>https://www.wormbytes.ca/articles/postfix-with-sympatico-relay/</guid><description>&lt;p&gt;Customers of &lt;a href="http://www.sympatico.ca/"&gt;Sympatico&lt;/a&gt;&amp;rsquo;s high-speed Internet service receive
instructions on how to set up their email; however, these settings
are aimed at people using Outlook, Netscape, or Eudora.
What I needed were instructions on how to configure my local SMTP
server, &lt;a href="http://www.postfix.org/"&gt;Postfix&lt;/a&gt;, with &lt;a href="http://www.sympatico.ca/"&gt;Sympatico&lt;/a&gt;. Of course, that
information is not available. This document details how I figured
out the settings required to make &lt;tt&gt;smtphm.sympatico.ca&lt;/tt&gt; happy.&lt;/p&gt;
&lt;h2 id="installation"&gt;Installation&lt;/h2&gt;
&lt;p&gt;You need a version of &lt;a href="http://www.postfix.org/"&gt;Postfix&lt;/a&gt; built with TLS and SASL
support enabled. If your distribution doesn&amp;rsquo;t come with it pre-built
follow the instructions at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.postfix.org/TLS_README.html#build_tls"&gt;Building Postfix with TLS support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.postfix.org/SASL_README.html#build_sasl"&gt;Building Postfix with SASL authentication support&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On my Debian unstable system I simply did:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apt-get install postfix libsasl2-modules&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="configuration"&gt;Configuration&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m assuming that your &lt;a href="http://www.postfix.org/"&gt;Postfix&lt;/a&gt; configuration directory it
&lt;tt&gt;/etc/postfix&lt;/tt&gt;. Adjust appropriately to accommodate your
system.&lt;/p&gt;
&lt;p&gt;To use SASL we need a password file containing our user name
and password for the server we are connecting to. Per
&lt;a href="http://www.sympatico.ca/"&gt;Sympatico&lt;/a&gt;&amp;rsquo;s instructions the server is
&lt;tt&gt;smtphm.sympatico.ca&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f"&gt;cd&lt;/span&gt; /etc/postfix
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir sasl &lt;span style="color:#666"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a2f"&gt;cd&lt;/span&gt; sasl
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a2f"&gt;echo&lt;/span&gt; &lt;span style="color:#b44"&gt;&amp;#34;[smtphm.sympatico.ca] USERNAME@symaptico.ca:PASSWORD&amp;#34;&lt;/span&gt; &amp;gt; passwd
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;postmap hash:passwd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above creates the password file and the hash-based database file
that &lt;a href="http://www.postfix.org/"&gt;Postfix&lt;/a&gt; uses. Of course replace
&lt;tt&gt;USERNAME&lt;/tt&gt; with your [% symaptico %] user name, and
&lt;tt&gt;PASSWORD&lt;/tt&gt; with your password (the email password, not the b1
password to access the Internet.)&lt;/p&gt;
&lt;p&gt;Make sure in your &lt;tt&gt;main.cf&lt;/tt&gt; you have configured your
relayhost as: &lt;tt&gt;relayhost = [smtphm.sympatico.ca]&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Finally, add the following lines to your &lt;tt&gt;main.cf&lt;/tt&gt; file:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-conf" data-lang="conf"&gt;# Enable TLS/SASL for the smtphm.sympatico.ca server
smtp_use_tls = yes
smtp_tls_note_starttls_offer = yes
tls_random_source = dev:/dev/urandom
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl/passwd
smtp_sasl_security_options = &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restart &lt;a href="http://www.postfix.org/"&gt;Postfix&lt;/a&gt; and send a test message. If all
went well you should see the successful sending of the message in the
&lt;a href="http://www.postfix.org/"&gt;Postfix&lt;/a&gt; log file.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Good luck!&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>