<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>@jnoxon&#39;s thoughts</title><link>https://jeff.noxon.cc/</link><description>Recent content on @jnoxon&#39;s thoughts</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><managingEditor>jeff@noxon.cc (Jeff Noxon)</managingEditor><webMaster>jeff@noxon.cc (Jeff Noxon)</webMaster><copyright>Copyright &amp;#169; 2000-2019 Jeff Noxon. All Rights Reserved.</copyright><lastBuildDate>Thu, 17 Sep 2020 00:00:00 +0000</lastBuildDate><atom:link href="https://jeff.noxon.cc/feed.xml" rel="self" type="application/rss+xml"/><item><title>Using custom DNS-over-HTTPS with CoreDNS and Google Chrome</title><link>https://jeff.noxon.cc/2020/09/17/using-custom-dns-over-https-with-coredns-and-chrome/</link><pubDate>Thu, 17 Sep 2020 00:00:00 +0000</pubDate><author>jeff@noxon.cc (Jeff Noxon)</author><guid>https://jeff.noxon.cc/2020/09/17/using-custom-dns-over-https-with-coredns-and-chrome/</guid><description>&lt;p&gt;I&amp;rsquo;ve been using &lt;a href=&#34;https://coredns.io&#34; target=&#34;_blank&#34;&gt;CoreDNS&lt;/a&gt; on my home network infrastructure for a few
years, and it&amp;rsquo;s worked really well. One of the things I use it for
is translating local DNS queries into DNS-over-TLS queries, which
keeps my ISP from inspecting and manipulating DNS lookups. That use
case is well documented and works well.&lt;/p&gt;
&lt;p&gt;Today I found myself wanting to override the DNS provider used by
just one browser on my computer. I&amp;rsquo;m often connected to a corporate VPN
that hijacks DNS and makes it difficult to connect to sites on my home
network. Having a dedicated browser for these sites means I don&amp;rsquo;t need to
disconnect from the VPN or mess with &lt;code&gt;/etc/hosts&lt;/code&gt; to reach them.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t think any browsers allow overriding normal DNS resolvers
anymore, but both Chrome and Firefox support DNS-over-HTTPS
with custom resolvers.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how to make that work with Chrome and CoreDNS:&lt;/p&gt;
&lt;p&gt;First, you&amp;rsquo;ll need a valid TLS certificate for your resolver. I
used the awesome &lt;a href=&#34;https://github.com/go-acme/lego&#34; target=&#34;_blank&#34;&gt;LEGO&lt;/a&gt; client for &lt;a href=&#34;https://letsencrypt.org&#34; target=&#34;_blank&#34;&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt; to generate one, along with some simple automation
to keep it fresh. It might be possible to create your own CA and
add it to your computer&amp;rsquo;s trust store; I haven&amp;rsquo;t tried that. The
CN for the cert must be a valid DNS name.&lt;/p&gt;
&lt;p&gt;The CoreDNS config should look something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://.:853 {
tls /etc/coredns/ssl/coredns.crt /etc/coredns/ssl/coredns.key {
client_auth nocert
}
forward . 127.0.0.1:53
# log
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells CoreDNS to listen on port 853 using the DNS-over-HTTPS
protocol, and to resolve anything using the &lt;code&gt;.&lt;/code&gt; wildcard. It
then forwards those queries to itself using standard DNS. That&amp;rsquo;s
it! I suggest enabling logging at first but turn it off once
everything works.&lt;/p&gt;
&lt;p&gt;Note: CoreDNS supports &lt;a href=&#34;https://tools.ietf.org/html/rfc8484&#34; target=&#34;_blank&#34;&gt;RFC 8484&lt;/a&gt; queries only, not Google&amp;rsquo;s JSON query language.&lt;/p&gt;
&lt;p&gt;You can test that it works with cURL:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -i &#39;https://you-resolver-fqdn:853/dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB&#39;
HTTP/1.1 200 OK
Cache-Control: max-age=3455.000000
Content-Length: 64
Content-Type: application/dns-message
Date: Thu, 17 Sep 2020 16:56:23 GMT
Warning: Binary output can mess up your terminal. Use &amp;quot;--output -&amp;quot; to tell
Warning: curl to output it to your terminal anyway, or consider &amp;quot;--output
Warning: &amp;lt;FILE&amp;gt;&amp;quot; to save to a file.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;200 OK&lt;/code&gt; response is what you&amp;rsquo;re looking for.&lt;/p&gt;
&lt;p&gt;If you get a certificate validation problem, don&amp;rsquo;t ignore it with &lt;code&gt;-k&lt;/code&gt;. Fix that before you continue.&lt;/p&gt;
&lt;p&gt;The query above will resolve &lt;code&gt;example.com&lt;/code&gt;. (The base64 is an encoded DNS query.) If you have logging
enabled in CoreDNS, you should see that query in your logs.&lt;/p&gt;
&lt;p&gt;Now you can configure it in Chrome:&lt;/p&gt;
&lt;p&gt;In Chrome 85, the setting lives in &lt;code&gt;Preferences&lt;/code&gt; under &lt;code&gt;Privacy and security&lt;/code&gt;, &lt;code&gt;Security&lt;/code&gt;, &lt;code&gt;Advanced&lt;/code&gt;, &lt;code&gt;Use secure DNS&lt;/code&gt;.
Turn it on, select the custom provider, and enter your resolver like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://your-resolver-fqdn:853/dns-query
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&amp;rsquo;s the last bit that took me forever to figure out. RFC 8484 specifies the &lt;code&gt;/dns-query&lt;/code&gt; path, but
Chrome doesn&amp;rsquo;t append it implicitly.&lt;/p&gt;
&lt;p&gt;If Chrome is satisfied, that&amp;rsquo;s it. If it isn&amp;rsquo;t, you&amp;rsquo;ll see &lt;code&gt;Please verify that this is a valid provider or try again later&lt;/code&gt;.
If you see that after following the advice here, I&amp;rsquo;m not sure what to suggest, but it&amp;rsquo;s most likely a problem with the cert,
or Chrome can&amp;rsquo;t resolve the resolver itself (try using /etc/hosts), or CoreDNS isn&amp;rsquo;t resolving correctly (check the logs, try cURL).&lt;/p&gt;
&lt;p&gt;Since DoH uses standard HTTPS, you can do further troubleshooting with mitmproxy in reverse proxy mode, using the same cert/key as
your resolver.&lt;/p&gt;
&lt;p&gt;I tried this with Firefox and I never got it working. Firefox 80.0
accepts a custom DoH config and then silently refuses to use it.
I didn&amp;rsquo;t put Firefox under the mitmproxy microscope, however, since
getting it to work with Chrome was enough for me.&lt;/p&gt;</description></item><item><title>Expanding btrfs filesystems</title><link>https://jeff.noxon.cc/2019/03/17/expanding-btrfs-filesystems/</link><pubDate>Sun, 17 Mar 2019 19:29:06 -0500</pubDate><author>jeff@noxon.cc (Jeff Noxon)</author><guid>https://jeff.noxon.cc/2019/03/17/expanding-btrfs-filesystems/</guid><description>&lt;p&gt;A few months ago, I migrated a bunch of media from a ZFS mirror on
my Mac to my home server VM. I used mismatched drives that I happened
to have on hand, and while it works fine, I might as well replace
the disks with the ones from the ZFS pool that I&amp;rsquo;m not using any more.&lt;/p&gt;
&lt;p&gt;While ZFS works reasonably well, it carries a ton of technical and
political debt, particularly on Linux. Since btrfs has matured
significantly in the last few years, I&amp;rsquo;m using it on my Linux servers
now. I like btrfs a lot. It has good performance, and offers advanced
features like data and metadata checksumming, snapshots, RAID, and
compression.&lt;/p&gt;
&lt;p&gt;What follows is mostly for my own notes, but maybe it&amp;rsquo;ll help someone.&lt;/p&gt;
&lt;p&gt;Note that &lt;code&gt;/var/lib/plex/data&lt;/code&gt; is just one of the subvolumes that
belongs to the btrfs filesystem I&amp;rsquo;m working on.&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s identify the existing devices in the filesystem:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proteus:~# btrfs filesystem show /var/lib/plex/data
Label: &#39;Media&#39; uuid: 290c5b77-9bff-47d5-9f82-3d7576f134f5
Total devices 2 FS bytes used 1.62TiB
devid 1 size 5.46TiB used 1.62TiB path /dev/sdd2
devid 2 size 3.64TiB used 1.62TiB path /dev/sdc2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br&gt;
&lt;code&gt;/dev/sdd2&lt;/code&gt;, which btrfs regards as &lt;code&gt;devid 2&lt;/code&gt;, is the disk I&amp;rsquo;ll
replace first. I&amp;rsquo;ve already partitioned a replacement disk, &lt;code&gt;/dev/sde2&lt;/code&gt;
&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start the replacement:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proteus:~# btrfs replace start -B 2 /dev/sde2 /var/lib/plex/data
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;-B&lt;/code&gt; option makes the command block until it&amp;rsquo;s completed, so
it&amp;rsquo;s completely optional. &lt;code&gt;2&lt;/code&gt; is the &lt;code&gt;devid&lt;/code&gt; we&amp;rsquo;re replacing. The
filesystem will remain online and read/write during the migration.
Btrfs doesn&amp;rsquo;t appear to prioritize regular filesystem I/O during
the migration, so expect performance to suffer until the migration
is done.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also possible to monitor the status in a blocking way:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proteus:~# btrfs replace status /var/lib/plex/data
7.4% done, 0 write errs, 0 uncorr. read errs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the migration in progress, you can also see that the mirror has three
devices attached:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proteus:~# btrfs filesystem show /var/lib/plex/data/
Label: &#39;Media&#39; uuid: 290c5b77-9bff-47d5-9f82-3d7576f134f5
Total devices 3 FS bytes used 1.63TiB
devid 0 size 3.64TiB used 1.62TiB path /dev/sde2
devid 1 size 5.46TiB used 1.64TiB path /dev/sdd2
devid 2 size 3.64TiB used 1.64TiB path /dev/sdc2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The new disk, &lt;code&gt;devid 0&lt;/code&gt;, is only reporting 3.64TiB, even though
it&amp;rsquo;s an 8TB disk. We&amp;rsquo;ll fix that once the migration is done.&lt;/p&gt;
&lt;p&gt;Hours later, the process is done:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proteus:~# btrfs filesystem show /var/lib/plex/data/
Label: &#39;Media&#39; uuid: 290c5b77-9bff-47d5-9f82-3d7576f134f5
Total devices 2 FS bytes used 1.62TiB
devid 1 size 5.46TiB used 1.63TiB path /dev/sdd2
devid 2 size 3.64TiB used 1.63TiB path /dev/sde2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note how &lt;code&gt;devid 2&lt;/code&gt; is the new disk on &lt;code&gt;/dev/sde2&lt;/code&gt;, but it still
shows the wrong capacity. It&amp;rsquo;s unclear why resizing is not automatic,
but it can be done manually:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proteus:~# btrfs filesystem resize 2:max /var/lib/plex/data
Resize &#39;/var/lib/plex/data&#39; of &#39;2:max&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The resize operation completes almost instantly, and now we have:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proteus:~# btrfs filesystem show /var/lib/plex/data/
Label: &#39;Media&#39; uuid: 290c5b77-9bff-47d5-9f82-3d7576f134f5
Total devices 2 FS bytes used 1.62TiB
devid 1 size 5.46TiB used 1.63TiB path /dev/sdd2
devid 2 size 7.28TiB used 1.63TiB path /dev/sde2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we can see that full redundancy is maintained:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proteus:~# btrfs device usage /var/lib/plex/data
/dev/sdd2, ID: 1
Device size: 5.46TiB
Device slack: 0.00B
Data,RAID1: 1.63TiB
Metadata,RAID1: 3.00GiB
System,RAID1: 64.00MiB
Unallocated: 3.83TiB
/dev/sde2, ID: 2
Device size: 7.28TiB
Device slack: 3.50KiB
Data,RAID1: 1.63TiB
Metadata,RAID1: 3.00GiB
System,RAID1: 64.00MiB
Unallocated: 5.65TiB
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are some relevant messages in the kernel log:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[1987714.818696] BTRFS info (device sdd2): dev_replace from /dev/sdc2 (devid 2) to /dev/sde2 started
[1998011.747252] BTRFS info (device sdd2): dev_replace from /dev/sdc2 (devid 2) to /dev/sde2 finished
[1999100.104284] BTRFS info (device sdd2): resizing devid 2
[1999100.104289] BTRFS info (device sdd2): new size for /dev/sde2 is 8001352437760
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now &lt;code&gt;/dev/sdc&lt;/code&gt; can be removed from the system.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@proteus:~# lsblk -S /dev/sdc
NAME HCTL TYPE VENDOR MODEL REV TRAN
sdc 4:0:0:0 disk Mercury Elite Pro Quad C 0 usb
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above command shows that the disk occupies bay &lt;code&gt;C&lt;/code&gt; in the disk
enclosure.&lt;/p&gt;
&lt;p&gt;After removing the disk and replacing it with another 8TB disk, the entire process was repeated to replace &lt;code&gt;/dev/sdd2&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Using Commento with Hugo</title><link>https://jeff.noxon.cc/2019/03/17/using-commento-with-hugo/</link><pubDate>Sun, 17 Mar 2019 19:29:06 -0500</pubDate><author>jeff@noxon.cc (Jeff Noxon)</author><guid>https://jeff.noxon.cc/2019/03/17/using-commento-with-hugo/</guid><description>
&lt;p&gt;Although this site has never received much comment volume, there have been occasions where comments have been quite valuable. One popular solution for static sites is to use Disqus, which is a fully hosted comment system that many Hugo themes support right out of the box. Disqus is free, but you pay for it with lost privacy, third-party trackers, and bloat.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve decided instead to use &lt;a href=&#34;https://commento.io&#34; target=&#34;_blank&#34;&gt;Commento&lt;/a&gt;. There&amp;rsquo;s a cheap hosted version of Commento, but why not try out the fully self-hosted version?&lt;/p&gt;
&lt;p&gt;What follows are some notes on how I got Commento working and integrated with Hugo.&lt;/p&gt;
&lt;h3 id=&#34;setting-up-a-dedicated-database&#34;&gt;Setting up a dedicated database&lt;/h3&gt;
&lt;p&gt;Even though Commento is small, it requires a &lt;a href=&#34;https://postgresql.org&#34; target=&#34;_blank&#34;&gt;PostgreSQL&lt;/a&gt; database. That&amp;rsquo;s a bit of overkill for a small blog like this one, but considering a single Commento server could potentially handle dozens if not thousands of domains, it&amp;rsquo;s not an unreasonable choice.&lt;/p&gt;
&lt;p&gt;I decided to use &lt;a href=&#34;https://docker.com&#34; target=&#34;_blank&#34;&gt;Docker&lt;/a&gt; to run a PostgreSQL database dedicated to this purpose. First, I installed &lt;code&gt;postgresql-client&lt;/code&gt; and &lt;code&gt;postgresql-common&lt;/code&gt; on my host, and took advantage of that creating a &lt;code&gt;postgres&lt;/code&gt; user and group for me.&lt;/p&gt;
&lt;p&gt;The initial startup looked like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -e POSTGRES_PASSWORD=censored -it --rm -v commento-postgres:/var/lib/postgresql/data postgres
.. wait for the container to settle down ..
^C
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This created a docker volume called &lt;code&gt;commento-postgres&lt;/code&gt; to hold the database and initialized a &lt;code&gt;postgres&lt;/code&gt; user in the database engine.&lt;/p&gt;
&lt;p&gt;I then changed the permissions on the data, where &lt;code&gt;113:120&lt;/code&gt; is the user:group of my host&amp;rsquo;s &lt;code&gt;postgres&lt;/code&gt; user:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -it --rm -v commento-postgres:/var/lib/postgresql/data bash chown -R 113:120 /var/lib/postgresql/data
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;commento-wants-tls&#34;&gt;Commento wants TLS&lt;/h4&gt;
&lt;p&gt;I&amp;rsquo;ll save you a bit of trial-and-error here. It turns out Commento expects to connect to the database using TLS. It doesn&amp;rsquo;t care if the cert is self-signed or not, so I made one and stuffed it into my &lt;code&gt;commento-postgres&lt;/code&gt; volume:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;openssl req -x509 -newkey rsa:1024 -nodes -keyout key.pem -out cert.pem -days 3650
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Use &lt;code&gt;docker volume inspect commento-postgres&lt;/code&gt; if you&amp;rsquo;re not sure where the volume is mounted.)&lt;/p&gt;
&lt;p&gt;While I was there, I edited &lt;code&gt;postgresql.conf&lt;/code&gt; to enable TLS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssl = on
ssl_cert_file = &#39;cert.pem&#39;
ssl_key_file = &#39;key.pem&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that this database isn&amp;rsquo;t accessible over the Internet or even the LAN, thanks to iptables rules that aren&amp;rsquo;t shown here.&lt;/p&gt;
&lt;h4 id=&#34;starting-the-database&#34;&gt;Starting the database&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;docker run -d \
--restart=always \
--name=commento-postgres \
--user 113:120 \
-p5432:5432/tcp \
-v commento-postgres:/var/lib/postgresql/data \
postgres
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&#34;testing-the-connection-and-creating-a-commento-database&#34;&gt;Testing the connection and creating a commento database&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# psql -h localhost -p 5432 -U postgres
Password for user postgres:
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 11.2 (Debian 11.2-1.pgdg90+1))
WARNING: psql major version 10, server major version 11.
Some psql features might not work.
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type &amp;quot;help&amp;quot; for help.
postgres=# create database commento;
CREATE DATABASE
^D
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see above that the connection used TLS, which is good. I also created the database.&lt;/p&gt;
&lt;h3 id=&#34;starting-commento&#34;&gt;Starting commento&lt;/h3&gt;
&lt;p&gt;First, I created a system user and group for commento.&lt;/p&gt;
&lt;p&gt;I went through a ton of trial-and-error here as well, and the details aren&amp;rsquo;t that interesting, so here is what I ended up with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -d \
-p 8080:8080 \
-e COMMENTO_ORIGIN=https://commento.noxon.cc \
-e COMMENTO_POSTGRES=postgres://postgres:censored@docker_host_ip:5432/commento \
-e COMMENTO_SMTP_USERNAME=nobody \
-e COMMENTO_SMTP_PASSWORD=nopass \
-e COMMENTO_SMTP_HOST=my_mail_host.example.com \
-e COMMENTO_SMTP_PORT=25 \
-e COMMENTO_FORBID_NEW_OWNERS=true \
-e COMMENTO_SMTP_FROM_ADDRESS=no-reply@noxon.cc \
-e COMMENTO_GOOGLE_KEY=censored \
-e COMMENTO_GOOGLE_SECRET=censored \
-e COMMENTO_TWITTER_KEY=censored \
-e COMMENTO_TWITTER_SECRET=censored \
--dns=my_dns_server_ip \
--user=122:122 \
--name commento \
--restart=always \
registry.gitlab.com/commento/commento
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Some important notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I published a DNS record for &lt;code&gt;COMMENTO_ORIGIN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;I configured an NGINX reverse proxy to add TLS and expose Commento on port 443.&lt;/li&gt;
&lt;li&gt;The first time running this, don&amp;rsquo;t set &lt;code&gt;COMMENTO_FORBID_NEW_OWNERS&lt;/code&gt;. Register a user through the web portal, then restart it with new owners disabled.&lt;/li&gt;
&lt;li&gt;To test SMTP, use the &amp;ldquo;forgot password&amp;rdquo; workflow, and &lt;code&gt;docker logs commento&lt;/code&gt; to check for errors (and, obviously, look for the email.)&lt;/li&gt;
&lt;li&gt;All of the SMTP parameters are necessary. If your SMTP relay doesn&amp;rsquo;t use SASL authentication, make sure it doesn&amp;rsquo;t offer it, and just use a bogus SMTP username and password. If your relay is Postfix, take a look at &lt;code&gt;smtpd_sasl_exceptions_networks&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I highly recommend using a local SMTP relay to store and forward emails.&lt;/li&gt;
&lt;li&gt;You can get OAuth keys from Google and Twitter pretty easily. The callbacks are &lt;code&gt;/api/oauth/google/callback&lt;/code&gt; and &lt;code&gt;/api/oauth/twitter/callback&lt;/code&gt;. Github and Gitlab are also supported using the same pattern.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;putting-the-pieces-together&#34;&gt;Putting the pieces together&lt;/h3&gt;
&lt;p&gt;Create &lt;code&gt;layouts/partials/commento.html&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;p/&amp;gt;
&amp;lt;div id=&amp;quot;commento&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script defer
src=&amp;quot;https://commento.noxon.cc/js/commento.js&amp;quot;
data-div=&amp;quot;#commento&amp;quot;&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Copy &lt;code&gt;themes/&amp;lt;your-theme&amp;gt;/layouts/_default/single.html&lt;/code&gt; to &lt;code&gt;layouts/_default/single.html&lt;/code&gt; and add &lt;code&gt;{{ partial &amp;quot;commento.html&amp;quot; . }}&lt;/code&gt; right around where the Disqus comment code is.&lt;/p&gt;
&lt;h3 id=&#34;what-s-left-to-figure-out&#34;&gt;What&amp;rsquo;s left to figure out?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;How to automate database dumps for backups&lt;/li&gt;
&lt;li&gt;Investigate ways to import old WordPress comments&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ll come back and update this post as I make progress.&lt;/p&gt;
&lt;h3 id=&#34;enjoy-some-comment-spam&#34;&gt;Enjoy some comment spam.&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s roughly it. I&amp;rsquo;d like to thank oct8l for his &lt;a href=&#34;https://oct8l.gitlab.io/posts/2018/129/setting-up-commento-with-hugo/&#34; target=&#34;_blank&#34;&gt;helpful blog post&lt;/a&gt; on the same subject!&lt;/p&gt;
&lt;p&gt;Feedback is welcome. Add a comment below!&lt;/p&gt;</description></item><item><title>Migrated From WordPress to Hugo</title><link>https://jeff.noxon.cc/2019/03/14/migrated-from-wordpress-to-hugo/</link><pubDate>Thu, 14 Mar 2019 13:17:12 -0500</pubDate><author>jeff@noxon.cc (Jeff Noxon)</author><guid>https://jeff.noxon.cc/2019/03/14/migrated-from-wordpress-to-hugo/</guid><description>&lt;p&gt;I&amp;rsquo;ve migrated this blog from WordPress to &lt;a href=&#34;https://gohugo.io/&#34; target=&#34;_blank&#34;&gt;Hugo&lt;/a&gt;. It&amp;rsquo;s something I&amp;rsquo;ve wanted to do for a long time. WordPress is a bit of a security nightmare, and although I&amp;rsquo;ve somehow never had my server owned, I did notice a couple of successful exfiltration attacks against WordPress while reviewing logs. Thankfully, the attacks were harmless.&lt;/p&gt;
&lt;p&gt;If you subscribe to my RSS feed, you&amp;rsquo;ll notice some repeated content. It wasn&amp;rsquo;t worth the effort to match the content GUIDs.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m still not sure about this theme, but it will do for now.&lt;/p&gt;
&lt;p&gt;As part of this migration, I&amp;rsquo;ve finally made the site HTTPS-only. HTTPS has been enabled for years with HSTS, but now HTTP is permanently redirected to HTTPS.&lt;/p&gt;
&lt;p&gt;There are still a bunch of tweaks I&amp;rsquo;d like to make, particularly with responsive image sizes and re-enabling the CDN.&lt;/p&gt;
&lt;p&gt;Last but not least, comments are gone, at least temporarily. I&amp;rsquo;d like to add &lt;a href=&#34;https://commento.io/&#34; target=&#34;_blank&#34;&gt;Commento&lt;/a&gt; or another open-source comment engine at some point, but for now, I&amp;rsquo;m exhaused.&lt;/p&gt;
&lt;p&gt;If you encounter any issues or have any feedback, send me an email!&lt;/p&gt;</description></item></channel></rss>