Recent changes to this wiki:

Comment moderation
diff --git a/posts/setting-up-raid-on-existing/comment_18_f58080e8a92469474b205e9b40eb4374._comment b/posts/setting-up-raid-on-existing/comment_18_f58080e8a92469474b205e9b40eb4374._comment
new file mode 100644
index 0000000..8351d96
--- /dev/null
+++ b/posts/setting-up-raid-on-existing/comment_18_f58080e8a92469474b205e9b40eb4374._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ ip="198.52.147.213"
+ claimedauthor="Dennis Chang"
+ subject="Ubuntu 18.04.3 LTS update"
+ date="2020-01-19T17:27:30Z"
+ content="""
+Hi,
+
+Thanks for the article! I followed it and it was my primary reference. However, I did encounter two issues while following it that I thought I should leave with you here. I'm using Ubuntu 18.04.3 and fdisk does not have 'fd' to convert a Linux partition to a Linux RAID partition. It is now '29' for a Linux RAID partition. Also, after adding the original disk to the RAID array and rebooting I found myself in grub rescue mode. After researching more I discovered that I was required to install a module 'mdraid1x' in order for grub to be able to read the RAID array and find the kernel in order to boot. Therefore, I had to boot a Live USB Ubuntu system to access the RAID array before chroot and grub-install --modules='mdraid1x' /dev/sda (to both drives). And finally, when I test each drive separately to see if it will boot (it does).
+
+Anyway, thanks for the article.
+"""]]

Update article for buster
diff --git a/posts/usual-server-setup.mdwn b/posts/usual-server-setup.mdwn
index c04e271..5f27fc7 100644
--- a/posts/usual-server-setup.mdwn
+++ b/posts/usual-server-setup.mdwn
@@ -207,12 +207,7 @@ and these to `/etc/rkhunter.conf.local`:
 
     apt install apparmor apparmor-profiles apparmor-profiles-extra libpam-tmpdir
 
-While the harden packages are configuration-free, AppArmor must be [manually enabled](https://wiki.debian.org/AppArmor/HowToUse#Enable_AppArmor):
-
-    perl -pi -e 's,GRUB_CMDLINE_LINUX="(.*)"$,GRUB_CMDLINE_LINUX="$1 apparmor=1 security=apparmor",' /etc/default/grub
-    update-grub
-
-In addition, certain kernel security features can be enabled by putting the
+Certain kernel security features can be enabled by putting the
 following in `/etc/sysctl.d/local.conf` to
 [hide kernel pointers and messages](https://www.kernel.org/doc/Documentation/sysctl/kernel.txt)
 from unprivileged processes:
@@ -238,9 +233,9 @@ and the following to harden the TCP stack:
 
 before reloading these settings using `sysctl -p`.
 
-Sandboxing in apt can be enabled by putting the following in `/etc/apt/apt.conf.d/30-seccomp`:
+[Sandboxing in apt](https://www.debian.org/releases/buster/amd64/release-notes/ch-whats-new.en.html#apt-sandboxing) can be enabled by putting the following in `/etc/apt/apt.conf.d/30-seccomp`:
 
-    APT::Sandbox::Seccomp "true";
+    APT::Sandbox::Seccomp "1";
 
 I also restrict the use of cron to the `root` user by putting the following in `/etc/cron.allow`:
 

Add hotspot article
diff --git a/posts/sharing-wifi-connection-with-network-manager-hotspot.mdwn b/posts/sharing-wifi-connection-with-network-manager-hotspot.mdwn
new file mode 100644
index 0000000..e307e52
--- /dev/null
+++ b/posts/sharing-wifi-connection-with-network-manager-hotspot.mdwn
@@ -0,0 +1,96 @@
+[[!meta title="Sharing your WiFi connection with a NetworkManager hotspot"]]
+[[!meta date="2020-01-15T18:15:00.000-08:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+In-flight and hotel WiFi can be quite expensive and often insist on charging
+users extra to connect multiple devices. In order to avoid that, it's
+possible to easily create a WiFi hotspot using
+[NetworkManager](https://wiki.gnome.org/Projects/NetworkManager) and a
+[external USB WiFi
+adapter](https://www.thinkpenguin.com/gnu-linux/penguin-wireless-n-usb-adapter-gnu-linux-tpe-n150usb).
+
+# Creating the hotspot
+
+The main trick is to right-click on the NetworkManager icon in the status
+bar and select "Edit Connections..." (**not** "Create New WiFi Network..."
+despite the promising name).
+
+From there click the "+" button in the lower right then "WiFi" as the
+Connection Type. I like to use the computer name as the "Connection name".
+
+In the *WiFi* tab, set the following:
+
+- SSID: machinename_nomap
+- Mode: hotspot
+- Device: (the device name of the USB WiFi adapter)
+
+The `_nomap` suffix is there to opt out of the
+[Google](https://support.google.com/maps/answer/1725632?hl=en) and
+[Mozilla](https://location.services.mozilla.com/optout) location services
+which could allow anybody to lookup sightings of your device around the
+World.
+
+In the *WiFi Security* tab:
+
+- Security: WPA & WPA2 Personal
+- Password: (a 63-character random password generated using `pwgen -s 63`)
+
+While you may think that such a long password is inconvenient, it's now
+possible to add the network automatically by simply [scanning a QR
+code](https://feeding.cloud.geek.nz/posts/encoding-wifi-access-point-passwords-qr-code/)
+on your phone.
+
+In the *IPv4 Settings* tab:
+
+- Method: Shared to other computers
+
+Finally, in the *IPv6 Settings* tab:
+
+- Method: Ignore
+
+I ended up with the following config in
+`/etc/NetworkManager/system-connections/machinename`:
+
+    [connection]
+    id=machinename
+    uuid=<long UUID string>
+    type=wifi
+    interface-name=wl...
+    permissions=
+    timestamp=1578533792
+    
+    [wifi]
+    mac-address=<MAC>
+    mac-address-blacklist=
+    mode=ap
+    seen-bssids=<BSSID>
+    ssid=machinename_nomap
+    
+    [wifi-security]
+    key-mgmt=wpa-psk
+    psk=<63-character password>
+    
+    [ipv4]
+    dns-search=
+    method=shared
+    
+    [ipv6]
+    addr-gen-mode=stable-privacy
+    dns-search=
+    ip6-privacy=0
+    method=ignore
+
+# Firewall rules
+
+In order for the packets to flow correctly, I opened up the following ports
+on my machine's local firewall:
+
+    -A INPUT -s 10.42.0.0/24 -j ACCEPT
+    -A FORWARD -d 10.42.0.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+    -A FORWARD -s 10.42.0.0/24 -j ACCEPT
+    -A INPUT -d 224.0.0.251 -s 10.42.0.1 -j ACCEPT
+    -A INPUT -d 239.255.255.250 -s 10.42.0.1 -j ACCEPT
+    -A INPUT -d 10.42.0.255 -s 10.42.0.1 -j ACCEPT
+    -A INPUT -d 10.42.0.1 -s 10.42.0.0/24 -j ACCEPT
+
+[[!tag nzoss]] [[!tag gnome]] [[!tag debian]]

Allow builds to be interrupted if ran interactively
diff --git a/posts/seeding-brave-browser-sccache.mdwn b/posts/seeding-brave-browser-sccache.mdwn
index 6ccf30f..5697ea9 100644
--- a/posts/seeding-brave-browser-sccache.mdwn
+++ b/posts/seeding-brave-browser-sccache.mdwn
@@ -52,7 +52,7 @@ and here are the contents of that script:
     echo $(date)
     echo "=> Debug build"
     killall sccache || true
-    ionice nice timeout 4h npm run build || ionice nice timeout 4h npm run build
+    ionice nice timeout --foreground 4h npm run build || ionice nice timeout 4h npm run build
     ionice nice ninja -C src/out/Component brave_unit_tests
     ionice nice ninja -C src/out/Component brave_browser_tests
     echo
@@ -60,7 +60,7 @@ and here are the contents of that script:
     echo $(date)
     echo "=> Release build"
     killall sccache || true
-    ionice nice timeout 5h npm run build Release || ionice nice timeout 5h npm run build Release
+    ionice nice timeout --foreground 5h npm run build Release || ionice nice timeout 5h npm run build Release
     ionice nice ninja -C src/out/Release brave_unit_tests
     ionice nice ninja -C src/out/Release brave_browser_tests
     echo

Debug builds are now in src/out/Component by default
diff --git a/posts/seeding-brave-browser-sccache.mdwn b/posts/seeding-brave-browser-sccache.mdwn
index 423f702..6ccf30f 100644
--- a/posts/seeding-brave-browser-sccache.mdwn
+++ b/posts/seeding-brave-browser-sccache.mdwn
@@ -53,12 +53,12 @@ and here are the contents of that script:
     echo "=> Debug build"
     killall sccache || true
     ionice nice timeout 4h npm run build || ionice nice timeout 4h npm run build
-    ionice nice ninja -C src/out/Debug brave_unit_tests
-    ionice nice ninja -C src/out/Debug brave_browser_tests
+    ionice nice ninja -C src/out/Component brave_unit_tests
+    ionice nice ninja -C src/out/Component brave_browser_tests
     echo
     
     echo $(date)
-    echo "=>Release build"
+    echo "=> Release build"
     killall sccache || true
     ionice nice timeout 5h npm run build Release || ionice nice timeout 5h npm run build Release
     ionice nice ninja -C src/out/Release brave_unit_tests

Upgrade links to HTTPS
diff --git a/posts/getting-involved-in-open-source-project.mdwn b/posts/getting-involved-in-open-source-project.mdwn
index 97c5848..0a32b59 100644
--- a/posts/getting-involved-in-open-source-project.mdwn
+++ b/posts/getting-involved-in-open-source-project.mdwn
@@ -1,13 +1,13 @@
 [[!meta title="Getting involved in an Open Source project"]]
 [[!meta date="2009-02-11T11:30:00.001+13:00"]]
-[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/)"]]
 Contributing to an Open Source project is a fantastic way to learn new skills and gain some real work experience. Unlike most of the work done in the proprietary world, the contributions you make to a Free Software project are generally publicly visible and thus can easily be included in a portfolio you show to prospective employers.
 
 In most cases, getting involved in an existing project is quite easy. Most projects need help and would be very happy to count you on board even if you're not a developer. Good places to start:
 
-  * the operating system you use (e.g. [Ubuntu](http://www.ubuntu.com/community/participate) or [Debian](http://wiki.debian.org/GetInvolved-Beta))
-  * a piece of [Free Software](http://www.fsf.org/about/what-is-free-software) you use every day
+  * the operating system you use (e.g. [Ubuntu](https://discourse.ubuntu.com/t/contribute/26) or [Debian](https://wiki.debian.org/GetInvolved-Beta))
+  * a piece of [Free Software](https://www.fsf.org/about/what-is-free-software) you use every day
 
-Of course, if you can't find a project that solves your own particular problem, you may also want to [start a new one](http://feeding.cloud.geek.nz/2008/09/starting-free-software-project.html). You may be surprised at how many people will find your pet project useful and see a [community grow](http://feeding.cloud.geek.nz/2008/09/growing-community-around-your-new-free.html) around it.
+Of course, if you can't find a project that solves your own particular problem, you may also want to [start a new one](https://feeding.cloud.geek.nz/posts/getting-involved-in-open-source-project/). You may be surprised at how many people will find your pet project useful and see a [community grow](https://feeding.cloud.geek.nz/posts/growing-community-around-your-new-free/) around it.
   
 I gave [a presentation](https://archive.org/details/contributing-to-foss_soc) on this topic for the [New Zealand Summer of Code](https://summeroftech.co.nz/).

Fix dead links
diff --git a/posts/getting-involved-in-open-source-project.mdwn b/posts/getting-involved-in-open-source-project.mdwn
index fd7a8a1..97c5848 100644
--- a/posts/getting-involved-in-open-source-project.mdwn
+++ b/posts/getting-involved-in-open-source-project.mdwn
@@ -10,4 +10,4 @@ In most cases, getting involved in an existing project is quite easy. Most proje
 
 Of course, if you can't find a project that solves your own particular problem, you may also want to [start a new one](http://feeding.cloud.geek.nz/2008/09/starting-free-software-project.html). You may be surprised at how many people will find your pet project useful and see a [community grow](http://feeding.cloud.geek.nz/2008/09/growing-community-around-your-new-free.html) around it.
   
-I gave [a presentation](http://summerofcode.blip.tv/file/1760791/) on this topic for the [New Zealand Summer of Code](http://www.summerofcode.co.nz).
+I gave [a presentation](https://archive.org/details/contributing-to-foss_soc) on this topic for the [New Zealand Summer of Code](https://summeroftech.co.nz/).

Remove unnecessary whitespace
diff --git a/posts/getting-involved-in-open-source-project.mdwn b/posts/getting-involved-in-open-source-project.mdwn
index 70ee512..fd7a8a1 100644
--- a/posts/getting-involved-in-open-source-project.mdwn
+++ b/posts/getting-involved-in-open-source-project.mdwn
@@ -1,15 +1,13 @@
 [[!meta title="Getting involved in an Open Source project"]]
 [[!meta date="2009-02-11T11:30:00.001+13:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
-Contributing to an Open Source project is a fantastic way to learn new skills and gain some real work experience. Unlike most of the work done in the proprietary world, the contributions you make to a Free Software project are generally publicly visible and thus can easily be included in a portfolio you show to prospective employers.  
-  
-In most cases, getting involved in an existing project is quite easy. Most projects need help and would be very happy to count you on board even if you're not a developer. Good places to start:  
+Contributing to an Open Source project is a fantastic way to learn new skills and gain some real work experience. Unlike most of the work done in the proprietary world, the contributions you make to a Free Software project are generally publicly visible and thus can easily be included in a portfolio you show to prospective employers.
+
+In most cases, getting involved in an existing project is quite easy. Most projects need help and would be very happy to count you on board even if you're not a developer. Good places to start:
 
   * the operating system you use (e.g. [Ubuntu](http://www.ubuntu.com/community/participate) or [Debian](http://wiki.debian.org/GetInvolved-Beta))
-  * a piece of [Free Software](http://www.fsf.org/about/what-is-free-software) you use every day  
+  * a piece of [Free Software](http://www.fsf.org/about/what-is-free-software) you use every day
 
-Of course, if you can't find a project that solves your own particular problem, you may also want to [start a new one](http://feeding.cloud.geek.nz/2008/09/starting-free-software-project.html). You may be surprised at how many people will find your pet project useful and see a [community grow](http://feeding.cloud.geek.nz/2008/09/growing-community-around-your-new-free.html) around it.  
+Of course, if you can't find a project that solves your own particular problem, you may also want to [start a new one](http://feeding.cloud.geek.nz/2008/09/starting-free-software-project.html). You may be surprised at how many people will find your pet project useful and see a [community grow](http://feeding.cloud.geek.nz/2008/09/growing-community-around-your-new-free.html) around it.
   
 I gave [a presentation](http://summerofcode.blip.tv/file/1760791/) on this topic for the [New Zealand Summer of Code](http://www.summerofcode.co.nz).
-
-

Update qdisc guidance to fq
This is based on https://www.bufferbloat.net/projects/codel/wiki/#Binary-code-and-kernels-for-Linux-based-operating-systems.
diff --git a/posts/usual-server-setup.mdwn b/posts/usual-server-setup.mdwn
index b048270..c04e271 100644
--- a/posts/usual-server-setup.mdwn
+++ b/posts/usual-server-setup.mdwn
@@ -397,7 +397,7 @@ To [reduce the server's contribution to
 bufferbloat](https://lwn.net/Articles/616241/) I change the default kernel
 queueing discipline (jessie or later) by putting the following in `/etc/sysctl.d/local.conf`:
 
-    net.core.default_qdisc=fq_codel
+    net.core.default_qdisc=fq
 
 and the following to improve congestion control and
 [HTTP/2 prioritization](https://blog.cloudflare.com/http-2-prioritization-with-nginx/):

Add third pass assets
diff --git a/posts/receiving-sstv-images-from-iss/iss_sstv3.png b/posts/receiving-sstv-images-from-iss/iss_sstv3.png
new file mode 100644
index 0000000..dc9a5e8
Binary files /dev/null and b/posts/receiving-sstv-images-from-iss/iss_sstv3.png differ
diff --git a/posts/receiving-sstv-images-from-iss/iss_sstv3.wav b/posts/receiving-sstv-images-from-iss/iss_sstv3.wav
new file mode 100644
index 0000000..3f5178f
Binary files /dev/null and b/posts/receiving-sstv-images-from-iss/iss_sstv3.wav differ

creating tag page tags/anytone
diff --git a/tags/anytone.mdwn b/tags/anytone.mdwn
new file mode 100644
index 0000000..e8d906c
--- /dev/null
+++ b/tags/anytone.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged anytone"]]
+
+[[!inline pages="tagged(anytone)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tags/kenwood
diff --git a/tags/kenwood.mdwn b/tags/kenwood.mdwn
new file mode 100644
index 0000000..fa4e00a
--- /dev/null
+++ b/tags/kenwood.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged kenwood"]]
+
+[[!inline pages="tagged(kenwood)" actions="no" archive="yes"
+feedshow=10]]

Create tags for each of my radios
diff --git a/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox.mdwn b/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox.mdwn
index 1d0463a..953b794 100644
--- a/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox.mdwn
+++ b/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox.mdwn
@@ -75,4 +75,4 @@ since it's much better than the official manual.
 You should be able to use the "Write to radio" menu option without any
 problems once you're done creating your codeplug.
 
-[[!tag ham]]
+[[!tag ham]] [[!tag anytone]]
diff --git a/posts/using-kenwood-th-d72a-with-pat-linux-ax25.mdwn b/posts/using-kenwood-th-d72a-with-pat-linux-ax25.mdwn
index 4ddba68..d97037a 100644
--- a/posts/using-kenwood-th-d72a-with-pat-linux-ax25.mdwn
+++ b/posts/using-kenwood-th-d72a-with-pat-linux-ax25.mdwn
@@ -98,4 +98,4 @@ If you can't connect to `VA7EOC-10` on UHF, you could also try the VHF BCFM
 repeater on Mt Seymour, [VE7LAN](http://www.bcfmca.bc.ca/lanvhf.php) (VECTOR
 channel 65).
 
-[[!tag ham]]
+[[!tag ham]] [[!tag kenwood]]

Add post about SSTV on the ISS
diff --git a/posts/receiving-sstv-images-from-iss.mdwn b/posts/receiving-sstv-images-from-iss.mdwn
new file mode 100644
index 0000000..4375796
--- /dev/null
+++ b/posts/receiving-sstv-images-from-iss.mdwn
@@ -0,0 +1,80 @@
+[[!meta title="Receiving slow-scan television images from the International Space Station"]]
+[[!meta date="2020-01-01T16:00:00.000-08:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+Thanks to a fellow [VECTOR](https://vectorradio.ca) volunteer [Nick
+Doyle](https://www.qrz.com/db/VE7NCD), I found out that the [International
+Space Station](https://en.wikipedia.org/wiki/International_Space_Station)
+would be broadcasting [slow-scan
+television](https://en.wikipedia.org/wiki/Slow-scan_television) images at
+the end of the year. I decided to try and pick those up with my handheld
+radio.
+
+# Planning
+
+From the [official announcement](https://ariss.pzk.org.pl/sstv/), I got the
+frequency (145.800 MHz) and the broadcast times.
+
+Next I had to figure out when the ISS would be passing over my location.
+Most of the ISS tracking websites and applications are aimed at people
+wanting to _see_ the reflection of the sun on the station and so they only
+list the passes during nighttime before the earth casts a shadow that would
+prevent any visual contacts.
+
+Thankfully, Nick found a site which has a option to show all of the passes,
+visible or not and so I was able to get a [list of upcoming passes over
+Vancouver](https://heavens-above.com/PassSummary.aspx?satid=25544&lat=49.2827&lng=-123.1207&loc=Vancouver&alt=0&tz=PST).
+
+# Hardware
+
+From a hardware point-of-view, I didn't have to get any special equipment. I
+used my [Kenwood D72](https://www.kenwood.com/usa/com/amateur/th-d72a/) and
+an external Comet SBB5 mobile antenna.
+
+The only other pieces of equipment I used was a 2.5mm mono adapter which I
+used to connect a 3.5mm male-male audio cable in the speaker port of the
+radio and the microphone input of my computer.
+
+# Software
+
+The software I used for the recording was
+[Audacity](https://www.audacityteam.org/) set to a **sampling rate of 48
+kHz**.
+
+Then I installed
+[qsstv](http://users.telenet.be/on4qz/qsstv/manual/index.html) and
+configured it to [read input from a file instead of the sound
+card](http://users.telenet.be/on4qz/qsstv/faq.html#Audiofile).
+
+# Results
+
+Here is the [audio I
+recorded](/posts/receiving-sstv-images-from-iss/iss_sstv1.wav) from the
+first pass (65 degrees at the highest point) as well as the rendered image:
+
+![](/posts/receiving-sstv-images-from-iss/iss_sstv1.png)
+
+The second pass (60 degrees) was not as successful since I didn't hold the
+squelch open and you can tell from the [audio
+recording](/posts/receiving-sstv-images-from-iss/iss_sstv2.wav) that the
+signal got drowned in noise a couple of times. This is the rendering of that
+second pass:
+
+![](/posts/receiving-sstv-images-from-iss/iss_sstv2.png)
+
+# Tips
+
+The signal came through the squelch for only about a minute at the highest
+point, so I found it best to open the squelch fully (`F`+`Moni`) as soon as
+the bird is visible.
+
+Another thing I did on a third pass (16 degrees at the highest point -- not
+particularly visible) was to plug the speaker out of my radio into a Y
+splitter so that I could connect it to my computer and an external speaker I
+could take outside with me. Since I was able to listen to the audio, I held
+the antenna and tried to **point it** at the [satellite's general
+direction](https://heavens-above.com/orbit.aspx?satid=25544&lat=49.2827&lng=-123.1207&loc=Vancouver&alt=0&tz=PST)
+as well as **varying the orientation** of the antenna to increase the signal
+strength.
+
+[[!tag kenwood]] [[!tag ham]]
diff --git a/posts/receiving-sstv-images-from-iss/iss_sstv1.png b/posts/receiving-sstv-images-from-iss/iss_sstv1.png
new file mode 100644
index 0000000..5026cd0
Binary files /dev/null and b/posts/receiving-sstv-images-from-iss/iss_sstv1.png differ
diff --git a/posts/receiving-sstv-images-from-iss/iss_sstv1.wav b/posts/receiving-sstv-images-from-iss/iss_sstv1.wav
new file mode 100644
index 0000000..173913c
Binary files /dev/null and b/posts/receiving-sstv-images-from-iss/iss_sstv1.wav differ
diff --git a/posts/receiving-sstv-images-from-iss/iss_sstv2.png b/posts/receiving-sstv-images-from-iss/iss_sstv2.png
new file mode 100644
index 0000000..fe0129f
Binary files /dev/null and b/posts/receiving-sstv-images-from-iss/iss_sstv2.png differ
diff --git a/posts/receiving-sstv-images-from-iss/iss_sstv2.wav b/posts/receiving-sstv-images-from-iss/iss_sstv2.wav
new file mode 100644
index 0000000..b9d05c0
Binary files /dev/null and b/posts/receiving-sstv-images-from-iss/iss_sstv2.wav differ

calendar update
diff --git a/archives/2020.mdwn b/archives/2020.mdwn
new file mode 100644
index 0000000..8843a09
--- /dev/null
+++ b/archives/2020.mdwn
@@ -0,0 +1 @@
+[[!calendar type=year year=2020 pages="page(posts/*) and !*/Discussion"]]
diff --git a/archives/2020/01.mdwn b/archives/2020/01.mdwn
new file mode 100644
index 0000000..0577516
--- /dev/null
+++ b/archives/2020/01.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=01 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(01) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/02.mdwn b/archives/2020/02.mdwn
new file mode 100644
index 0000000..189d77c
--- /dev/null
+++ b/archives/2020/02.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=02 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(02) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/03.mdwn b/archives/2020/03.mdwn
new file mode 100644
index 0000000..63a191c
--- /dev/null
+++ b/archives/2020/03.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=03 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(03) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/04.mdwn b/archives/2020/04.mdwn
new file mode 100644
index 0000000..d8be67f
--- /dev/null
+++ b/archives/2020/04.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=04 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(04) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/05.mdwn b/archives/2020/05.mdwn
new file mode 100644
index 0000000..92e59fa
--- /dev/null
+++ b/archives/2020/05.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=05 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(05) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/06.mdwn b/archives/2020/06.mdwn
new file mode 100644
index 0000000..fff6e79
--- /dev/null
+++ b/archives/2020/06.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=06 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(06) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/07.mdwn b/archives/2020/07.mdwn
new file mode 100644
index 0000000..9674bf2
--- /dev/null
+++ b/archives/2020/07.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=07 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(07) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/08.mdwn b/archives/2020/08.mdwn
new file mode 100644
index 0000000..19eec13
--- /dev/null
+++ b/archives/2020/08.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=08 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(08) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/09.mdwn b/archives/2020/09.mdwn
new file mode 100644
index 0000000..282af8d
--- /dev/null
+++ b/archives/2020/09.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=09 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(09) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/10.mdwn b/archives/2020/10.mdwn
new file mode 100644
index 0000000..e459232
--- /dev/null
+++ b/archives/2020/10.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=10 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(10) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/11.mdwn b/archives/2020/11.mdwn
new file mode 100644
index 0000000..b462704
--- /dev/null
+++ b/archives/2020/11.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=11 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(11) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/archives/2020/12.mdwn b/archives/2020/12.mdwn
new file mode 100644
index 0000000..2503185
--- /dev/null
+++ b/archives/2020/12.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=12 year=2020 pages="page(posts/*) and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(12) and creation_year(2020) and page(posts/*) and !*/Discussion" show=0 feeds=no reverse=yes]]

Comment moderation
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code/comment_3_4f23e4f1119d36cafcd927b51bbd82ea._comment b/posts/encoding-wifi-access-point-passwords-qr-code/comment_3_4f23e4f1119d36cafcd927b51bbd82ea._comment
new file mode 100644
index 0000000..937cf88
--- /dev/null
+++ b/posts/encoding-wifi-access-point-passwords-qr-code/comment_3_4f23e4f1119d36cafcd927b51bbd82ea._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="RobIII"
+ avatar="http://cdn.libravatar.org/avatar/f4862f3fb4e7d4570395c294e2c73345"
+ subject="@Martin"
+ date="2019-12-30T15:22:57Z"
+ content="""
+If you're using a phone without a camera then there's no point in using a QR code anyway, is it?
+"""]]

Add escaping for semicolons in passwords.
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code.mdwn b/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
index 1339937..bffca9d 100644
--- a/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
+++ b/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
@@ -19,9 +19,17 @@ package, run the following:
 substituting `<SSID>` for the name of your WiFi network and `<PASSWORD>` for
 the 63-character password you hopefully generated with `pwgen -s 63`.
 
-The only pitfall I ran into is that if you include a trailing newline character (for example piping
-`echo "..."` into `qrencode` as opposed to `echo -n "..."`) then it will
-fail on both iOS and Android.
+If your password includes a semicolon, then escape it like this:
+
+    "WIFI:T:WPA;S:<SSID>;P:pass\:word;;"
+
+since iOS won't support the following (which works fine on Android):
+
+    'WIFI:T:WPA;S:<SSID>;P:"pass:word";;'
+
+The only other pitfall I ran into is that if you include a trailing newline
+character (for example piping `echo "..."` into `qrencode` as opposed to
+`echo -n "..."`) then it will fail on both iOS and Android.
 
 ## Scanning the QR code
 
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code/comment_2_c0110bb414c3c1298fb6b3abb6d897eb._comment b/posts/encoding-wifi-access-point-passwords-qr-code/comment_2_c0110bb414c3c1298fb6b3abb6d897eb._comment
deleted file mode 100644
index 62552ac..0000000
--- a/posts/encoding-wifi-access-point-passwords-qr-code/comment_2_c0110bb414c3c1298fb6b3abb6d897eb._comment
+++ /dev/null
@@ -1,8 +0,0 @@
-[[!comment format=mdwn
- ip="2001:44b8:3191:3b00:7dba:a0e1:1b6a:313e"
- claimedauthor="Jeremy"
- subject="Semicolon in SSID or password"
- date="2019-12-30T02:33:57Z"
- content="""
-How does this handle semicolons in the SSID or password?
-"""]]

Comment moderation
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code/comment_3_e3c73a6fa17265f79283284c80a6d9ac._comment b/posts/encoding-wifi-access-point-passwords-qr-code/comment_3_e3c73a6fa17265f79283284c80a6d9ac._comment
new file mode 100644
index 0000000..08c9356
--- /dev/null
+++ b/posts/encoding-wifi-access-point-passwords-qr-code/comment_3_e3c73a6fa17265f79283284c80a6d9ac._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ ip="85.220.211.78"
+ claimedauthor="Martin"
+ subject="63 characters?"
+ date="2019-12-30T12:58:46Z"
+ content="""
+Neither my current mobile device (GPD Pocket running Debian bullseye), nor my future one, the Pyra (there is still some hope), feature a camera. With a password of 63 characters, I hope to type everything correctly! :-)
+"""]]

Comment moderation
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code/comment_2_c0110bb414c3c1298fb6b3abb6d897eb._comment b/posts/encoding-wifi-access-point-passwords-qr-code/comment_2_c0110bb414c3c1298fb6b3abb6d897eb._comment
new file mode 100644
index 0000000..62552ac
--- /dev/null
+++ b/posts/encoding-wifi-access-point-passwords-qr-code/comment_2_c0110bb414c3c1298fb6b3abb6d897eb._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ ip="2001:44b8:3191:3b00:7dba:a0e1:1b6a:313e"
+ claimedauthor="Jeremy"
+ subject="Semicolon in SSID or password"
+ date="2019-12-30T02:33:57Z"
+ content="""
+How does this handle semicolons in the SSID or password?
+"""]]

Add latest post to aggregators
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code.mdwn b/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
index 4e3f515..1339937 100644
--- a/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
+++ b/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
@@ -45,4 +45,4 @@ If you can't do this locally for some reason, there is also an [in-browser
 QR code generator](https://qifi.org/) with [source code
 available](https://github.com/evgeni/qifi).
 
-[[!tag ios]] [[!tag android]] [[!tag security]]
+[[!tag ios]] [[!tag android]] [[!tag security]] [[!tag debian]] [[!tag nzoss]]

Properly format code block
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code/comment_1_995e478c5b1e90c2a0a00f355f8ac3f7._comment b/posts/encoding-wifi-access-point-passwords-qr-code/comment_1_995e478c5b1e90c2a0a00f355f8ac3f7._comment
index 8337a72..362fe86 100644
--- a/posts/encoding-wifi-access-point-passwords-qr-code/comment_1_995e478c5b1e90c2a0a00f355f8ac3f7._comment
+++ b/posts/encoding-wifi-access-point-passwords-qr-code/comment_1_995e478c5b1e90c2a0a00f355f8ac3f7._comment
@@ -3,8 +3,7 @@
  subject="Script it"
  date="2019-12-29T09:18:22Z"
  content="""
-SSID=SSID_GOES_HERE
-pwgen -s 63 > 00wifi.txt
-qrencode -o 00wifi.png \"WIFI:T:WPA;S:${SSID};P:$(cat 00wifi.txt);;\"
-
+    SSID=SSID_GOES_HERE
+    pwgen -s 63 > 00wifi.txt
+    qrencode -o 00wifi.png \"WIFI:T:WPA;S:${SSID};P:$(cat 00wifi.txt);;\"
 """]]

Comment moderation
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code/comment_1_995e478c5b1e90c2a0a00f355f8ac3f7._comment b/posts/encoding-wifi-access-point-passwords-qr-code/comment_1_995e478c5b1e90c2a0a00f355f8ac3f7._comment
new file mode 100644
index 0000000..8337a72
--- /dev/null
+++ b/posts/encoding-wifi-access-point-passwords-qr-code/comment_1_995e478c5b1e90c2a0a00f355f8ac3f7._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ ip="98.210.73.233"
+ subject="Script it"
+ date="2019-12-29T09:18:22Z"
+ content="""
+SSID=SSID_GOES_HERE
+pwgen -s 63 > 00wifi.txt
+qrencode -o 00wifi.png \"WIFI:T:WPA;S:${SSID};P:$(cat 00wifi.txt);;\"
+
+"""]]

Specify the Android version which supports this feature.
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code.mdwn b/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
index 66a1588..4e3f515 100644
--- a/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
+++ b/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
@@ -6,7 +6,7 @@ Up until recently, it was a pain to defend againt [WPA2 brute-force
 attacks](https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#Weak_password)
 by using a random 63-character password (the maximum in
 [WPA-Personal](https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#Target_users_(authentication_key_distribution))
-mode). Thanks to Android and now iOS 11 supporting reading WiFi passwords
+mode). Thanks to Android 10 and iOS 11 supporting reading WiFi passwords
 from a QR code, this is finally a practical defense.
 
 ## Generating the QR code

Add WiFi QR code post
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code.mdwn b/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
new file mode 100644
index 0000000..66a1588
--- /dev/null
+++ b/posts/encoding-wifi-access-point-passwords-qr-code.mdwn
@@ -0,0 +1,48 @@
+[[!meta title="Encoding your WiFi access point password into a QR code"]]
+[[!meta date="2019-12-28T19:25:00.000-08:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+Up until recently, it was a pain to defend againt [WPA2 brute-force
+attacks](https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#Weak_password)
+by using a random 63-character password (the maximum in
+[WPA-Personal](https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#Target_users_(authentication_key_distribution))
+mode). Thanks to Android and now iOS 11 supporting reading WiFi passwords
+from a QR code, this is finally a practical defense.
+
+## Generating the QR code
+
+After installing the [`qrencode`](https://packages.debian.org/stable/qrencode)
+package, run the following:
+
+    qrencode -o wifi.png "WIFI:T:WPA;S:<SSID>;P:<PASSWORD>;;"
+
+substituting `<SSID>` for the name of your WiFi network and `<PASSWORD>` for
+the 63-character password you hopefully generated with `pwgen -s 63`.
+
+The only pitfall I ran into is that if you include a trailing newline character (for example piping
+`echo "..."` into `qrencode` as opposed to `echo -n "..."`) then it will
+fail on both iOS and Android.
+
+## Scanning the QR code
+
+On iOS, simply open the camera app and scan the QR code to bring up a
+notification which allows you to connect to the WiFi network:
+
+![](/posts/encoding-wifi-access-point-passwords-qr-code/ios_qr_scanner.png)
+
+On Android, go into the WiFi settings and tap on the WiFi network you want
+to join:
+
+![](/posts/encoding-wifi-access-point-passwords-qr-code/android_wifi_settings.png)
+
+then click the QR icon in the password field and scan the code:
+
+![](/posts/encoding-wifi-access-point-passwords-qr-code/android_qr_scanner.png)
+
+## In-browser alternative
+
+If you can't do this locally for some reason, there is also an [in-browser
+QR code generator](https://qifi.org/) with [source code
+available](https://github.com/evgeni/qifi).
+
+[[!tag ios]] [[!tag android]] [[!tag security]]
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code/android_qr_scanner.png b/posts/encoding-wifi-access-point-passwords-qr-code/android_qr_scanner.png
new file mode 100644
index 0000000..49e978d
Binary files /dev/null and b/posts/encoding-wifi-access-point-passwords-qr-code/android_qr_scanner.png differ
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code/android_wifi_settings.png b/posts/encoding-wifi-access-point-passwords-qr-code/android_wifi_settings.png
new file mode 100644
index 0000000..4db83ba
Binary files /dev/null and b/posts/encoding-wifi-access-point-passwords-qr-code/android_wifi_settings.png differ
diff --git a/posts/encoding-wifi-access-point-passwords-qr-code/ios_qr_scanner.png b/posts/encoding-wifi-access-point-passwords-qr-code/ios_qr_scanner.png
new file mode 100644
index 0000000..c69937f
Binary files /dev/null and b/posts/encoding-wifi-access-point-passwords-qr-code/ios_qr_scanner.png differ

Fix IP address thanks to Pedro Bezunartea López.
diff --git a/posts/installing-debian-buster-on-gnubee2.mdwn b/posts/installing-debian-buster-on-gnubee2.mdwn
index 3e80d85..5582f71 100644
--- a/posts/installing-debian-buster-on-gnubee2.mdwn
+++ b/posts/installing-debian-buster-on-gnubee2.mdwn
@@ -22,7 +22,7 @@ On another machine, do the following:
 Then plug a network cable between your laptop and the **black network port**
 and plug the USB stick into the GnuBee before rebooting the GnuBee via ssh:
 
-    ssh 192.68.10.0
+    ssh 192.68.10.1
     reboot
 
 If you have a [USB serial
@@ -43,7 +43,7 @@ Now enable SSH access via the built-in [LibreCMC](https://librecmc.org)
 firmware:
 
 1. Plug a network cable between your laptop and the **black network port**.
-2. Open web-based admin panel at <http://192.168.10.0>.
+2. Open web-based admin panel at <http://192.168.10.1>.
 3. Go to *System | Administration*.
 4. Set a root password.
 5. Disable ssh password auth and root password logins.

Add duplicity tag since I mention ssh config tweak
diff --git a/posts/usual-server-setup.mdwn b/posts/usual-server-setup.mdwn
index 79ca04d..b048270 100644
--- a/posts/usual-server-setup.mdwn
+++ b/posts/usual-server-setup.mdwn
@@ -405,4 +405,4 @@ and the following to improve congestion control and
     net.ipv4.tcp_congestion_control = bbr
     net.ipv4.tcp_notsent_lowat = 16384
 
-[[!tag sysadmin]] [[!tag debian]] [[!tag nzoss]]
+[[!tag sysadmin]] [[!tag debian]] [[!tag nzoss]] [[!tag duplicity]]

creating tag page tags/s3
diff --git a/tags/s3.mdwn b/tags/s3.mdwn
new file mode 100644
index 0000000..1342587
--- /dev/null
+++ b/tags/s3.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged s3"]]
+
+[[!inline pages="tagged(s3)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tags/duplicity
diff --git a/tags/duplicity.mdwn b/tags/duplicity.mdwn
new file mode 100644
index 0000000..b55400d
--- /dev/null
+++ b/tags/duplicity.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged duplicity"]]
+
+[[!inline pages="tagged(duplicity)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tags/aws
diff --git a/tags/aws.mdwn b/tags/aws.mdwn
new file mode 100644
index 0000000..48b9df8
--- /dev/null
+++ b/tags/aws.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged aws"]]
+
+[[!inline pages="tagged(aws)" actions="no" archive="yes"
+feedshow=10]]

Add duplicity S3 post
diff --git a/posts/backing-up-to-s3-with-duplicity.mdwn b/posts/backing-up-to-s3-with-duplicity.mdwn
new file mode 100644
index 0000000..0f698c5
--- /dev/null
+++ b/posts/backing-up-to-s3-with-duplicity.mdwn
@@ -0,0 +1,146 @@
+[[!meta title="Backing up to S3 with Duplicity"]]
+[[!meta date="2019-12-22T12:30:00.000-08:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+Here is how I setup [duplicity](http://duplicity.nongnu.org/) to use S3 as a
+backend while giving duplicity the minimum set of permissions to my Amazon
+Web Services account.
+
+# AWS Security Settings
+
+First of all, I enabled the following [general security
+settings](https://console.aws.amazon.com/iam/home#/security_credentials) in
+my AWS account:
+
+- MFA with a U2F device
+- no root user access keys
+
+Then I set a **password policy** in the [IAM Account
+Settings](https://console.aws.amazon.com/iam/home#/account_settings) and
+**turned off all public access** in the [S3 Account
+Settings](https://s3.console.aws.amazon.com/s3/settings).
+
+# Creating an S3 bucket
+
+As a destination for the backups, I created a new `backup-foobar` [S3
+bucket](https://s3.console.aws.amazon.com/s3/home) keeping all of the
+default options except for the
+[region](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions)
+which I set to `ca-central-1` to ensure that my data would stay in
+Canada.
+
+The bucket name can be anything you want as long as:
+
+- it's not already taken by another AWS user
+- it's a valid hostname (i.e. alphanumeric characters or dashes)
+
+Note that I did _not_ enable S3 server-side encryption since I will be
+encrypting the backups client-side using the support built into duplicity
+instead.
+
+# Creating a restricted user account
+
+Then I went back into the [Identity and Access Managment
+console](https://console.aws.amazon.com/iam/home) and created a new
+`DuplicityBackup` **policy**:
+
+    {
+        "Version": "2012-10-17",
+        "Statement": [
+            {
+                "Sid": "VisualEditor0",
+                "Effect": "Allow",
+                "Action": [
+                    "s3:PutObject",
+                    "s3:GetObject",
+                    "s3:ListBucketMultipartUploads",
+                    "s3:AbortMultipartUpload",
+                    "s3:CreateBucket",
+                    "s3:ListBucket",
+                    "s3:DeleteObject",
+                    "s3:ListMultipartUploadParts"
+                ],
+                "Resource": [
+                    "arn:aws:s3:::backup-foobar",
+                    "arn:aws:s3:::backup-foobar/*"
+                ]
+            },
+            {
+                "Sid": "VisualEditor1",
+                "Effect": "Allow",
+                "Action": "s3:ListAllMyBuckets",
+                "Resource": "*"
+            }
+        ]
+    }
+
+It's unfortunate that the unrestricted `s3:ListAllMyBuckets` permission has
+to be granted, but in my testing, duplicity would error out without it. No
+other permissions were needed.
+
+The next step was to create a new `DuplicityBackupHosts` IAM **group** to which
+I attached the `DuplicityBackup` policy.
+
+Finally, I created a new `machinename` IAM **user**:
+
+- Access: **programmatic only**
+- Group: `DuplicityBackupHosts`
+- Tags: `duplicity=1`
+
+and wrote down the *access key* and the *access key secret*.
+
+# Duplicity settings
+
+Once that's all set, I was able to use duplicity using the following
+options:
+
+- `--s3-use-new-style`: apparently required on non-US regions
+- `--s3-use-ia`: recommended pricing structure for backups
+- `--s3-use-multiprocessing`: speeds up uploading of backup chunks
+
+and used the following remote URL:
+
+    s3://s3.ca-central-1.amazonaws.com/backup-foobar/machinename
+
+which hardcodes the region in order to [work-around the lack of explicit
+region support in
+duplicity](https://bugs.launchpad.net/duplicity/+bug/1003159/comments/7).
+
+I ended up with the following command:
+
+    http_proxy= AWS_ACCESS_KEY_ID=<access_key> AWS_SECRET_ACCESS_KEY=<access_key_secret> PASSPHRASE=<password> duplicity --s3-use-new-style --s3-use-ia --s3-use-multiprocessing --no-print-statistics --verbosity 1 --exclude-device-files --exclude-filelist <exclude_file> --include-filelist <include_file> --exclude '**' / <remote_url>
+
+where `<exclude_file>` is a file which contains the list of paths to keep
+out of my backup:
+
+    /etc/.git
+    /home/francois/.cache
+
+`<include_file>` is a file which contains the list of paths to include
+in the backup:
+
+    /etc
+    /home/francois
+    /usr/local/bin
+    /usr/local/sbin
+    /var/log/apache2
+    /var/www
+
+and `<password>` is a long random string (`pwgen -s 64`) used to encrypt the backups.
+
+# Backup script
+
+Here are two other things I included in my backup script prior to the actual
+backup line listed in the previous section.
+
+The first one deletes files related to failed backups:
+
+    http_proxy= AWS_ACCESS_KEY_ID=<access_key> AWS_SECRET_ACCESS_KEY=<access_key_secret> PASSPHRASE=<password> duplicity cleanup --verbosity 1 --force <remote_url>
+
+and the second deletes old backups (older than 12 days in this example):
+
+    http_proxy= AWS_ACCESS_KEY_ID=<access_key> AWS_SECRET_ACCESS_KEY=<access_key_secret> PASSPHRASE=<password> duplicity remove-older-than 12D --verbosity 1 --force <remote_url>
+
+Feel free to leave a comment if I forgot anything that might be useful!
+
+[[!tag duplicity]] [[!tag sysadmin]] [[!tag backup]] [[!tag aws]] [[!tag s3]]

Disable compression
diff --git a/posts/using-openvpn-on-android-lollipop.mdwn b/posts/using-openvpn-on-android-lollipop.mdwn
index 631c4c8..1c21b8b 100644
--- a/posts/using-openvpn-on-android-lollipop.mdwn
+++ b/posts/using-openvpn-on-android-lollipop.mdwn
@@ -36,6 +36,7 @@ you'll need to use on your phone:
 
 Basic:
 
+- LZO Compression: `NO`
 - Type: `Certificates`
 - CA Certificate: `ca.crt`
 - Client Certificate: `nexus6.crt`

Turn on Reverse Path Filtering as a mitigation for CVE-2019-14899
diff --git a/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn b/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn
index 3f373f3..9cedb93 100644
--- a/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn
+++ b/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn
@@ -117,6 +117,7 @@ Finally, I added the following to these configuration files:
 * `/etc/sysctl.d/openvpn.conf`:
 
       net.ipv4.ip_forward=1
+      net.ipv4.conf.all.rp_filter=1
 
 * `/etc/rc.local` (just before `exit 0`):
 

Need to reconfigure grub-pc too
diff --git a/posts/replacing-a-failed-raid-drive.mdwn b/posts/replacing-a-failed-raid-drive.mdwn
index 9089c9b..84e27b5 100644
--- a/posts/replacing-a-failed-raid-drive.mdwn
+++ b/posts/replacing-a-failed-raid-drive.mdwn
@@ -78,8 +78,9 @@ to re-create it), I had to update two things:
 
 # Ensuring that I can boot with the replacement drive
 
-In order to be able to boot from both drives, I reinstalled the grub boot
-loader onto the replacement drive:
+In order to be able to boot from both drives, I made sure that the
+replacement drive was included in the list from `dpkg-reconfigure grub-pc`
+and then reinstalled the grub boot loader manually onto it:
 
     grub-install /dev/sdb
 

Create a new "testing" heading for the SMART check
diff --git a/posts/replacing-a-failed-raid-drive.mdwn b/posts/replacing-a-failed-raid-drive.mdwn
index 43cf150..9089c9b 100644
--- a/posts/replacing-a-failed-raid-drive.mdwn
+++ b/posts/replacing-a-failed-raid-drive.mdwn
@@ -100,7 +100,10 @@ that everything is fine:
 
     cat /proc/mdstat
 
-Then I ran a full SMART test over the new replacement drive:
+# Testing the new drive
+
+Finally once everything was configured, I ran a full SMART test over the
+new replacement drive:
 
     smartctl -t long /dev/sdb
 

Use referral link for Brave
diff --git a/posts/passwordless-restricted-guest-account-ubuntu.mdwn b/posts/passwordless-restricted-guest-account-ubuntu.mdwn
index d1bcfe4..5ad5b4a 100644
--- a/posts/passwordless-restricted-guest-account-ubuntu.mdwn
+++ b/posts/passwordless-restricted-guest-account-ubuntu.mdwn
@@ -36,7 +36,7 @@ gnome-control-center. I set the following in the privacy section:
 
 ![](/posts/passwordless-restricted-guest-account-ubuntu/privacy-settings.png)
 
-Then I replaced Firefox with [Brave](https://brave.com) in the sidebar,
+Then I replaced Firefox with [Brave](https://brave.com/clo187) in the sidebar,
 set it as the default browser in gnome-control-center:
 
 ![](/posts/passwordless-restricted-guest-account-ubuntu/default-applications.png)

Adjust image contrast
diff --git a/posts/fixing-turris-omnia-wifi-quality/overall.jpg b/posts/fixing-turris-omnia-wifi-quality/overall.jpg
index b36a840..48dfc06 100644
Binary files a/posts/fixing-turris-omnia-wifi-quality/overall.jpg and b/posts/fixing-turris-omnia-wifi-quality/overall.jpg differ
diff --git a/posts/fixing-turris-omnia-wifi-quality/radios.jpg b/posts/fixing-turris-omnia-wifi-quality/radios.jpg
index dd081f8..ce3f594 100644
Binary files a/posts/fixing-turris-omnia-wifi-quality/radios.jpg and b/posts/fixing-turris-omnia-wifi-quality/radios.jpg differ

creating tag page tags/turris
diff --git a/tags/turris.mdwn b/tags/turris.mdwn
new file mode 100644
index 0000000..a0ee205
--- /dev/null
+++ b/tags/turris.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged turris"]]
+
+[[!inline pages="tagged(turris)" actions="no" archive="yes"
+feedshow=10]]

Fix images and tag
diff --git a/posts/fixing-turris-omnia-wifi-quality.mdwn b/posts/fixing-turris-omnia-wifi-quality.mdwn
index 8a1ea52..c4a9b91 100644
--- a/posts/fixing-turris-omnia-wifi-quality.mdwn
+++ b/posts/fixing-turris-omnia-wifi-quality.mdwn
@@ -33,7 +33,7 @@ around inside the unit, as suggested by the poster.
 After opening the case however, I noticed that radios were already laid out
 in the optimal way:
 
-![](/posts/fixing-turris-omnia-wifi-quality/radios.png)
+![](/posts/fixing-turris-omnia-wifi-quality/radios.jpg)
 
 and that USB3 interference wasn't going to be the reason
 for my troubles.
@@ -46,12 +46,12 @@ radio](https://compex.com.sg/shop/wifi-module/802-11ac-wave-1/wle900vx/)
 radio](https://compex.com.sg/shop/wifi-module/802-11n/wle200n2/) (2.4 GHz
 only) was connected to only 2 of the 3 antennas:
 
-![](/posts/fixing-turris-omnia-wifi-quality/overall.png)
+![](/posts/fixing-turris-omnia-wifi-quality/overall.jpg)
 
 To make it possible for antennas 1 and 3 to carry the signal from both
 radios, a duplexer got inserted between the radios and the antenna:
 
-![](/posts/fixing-turris-omnia-wifi-quality/duplexer.png)
+![](/posts/fixing-turris-omnia-wifi-quality/duplexer.jpg)
 
 On one side is the 2.4 antenna port and on the other side is the 5 GHz port.
 
@@ -74,4 +74,4 @@ as I passed my advanced [amateur radio license
 exam](https://launchpad.net/canadian-ham-exam). I guess that was a good way
 to put the course material into practice!
 
-[[!tag nzoss]] [[!turris]]
+[[!tag nzoss]] [[!tag turris]]

Add Turris Omnia article
diff --git a/posts/fixing-turris-omnia-wifi-quality.mdwn b/posts/fixing-turris-omnia-wifi-quality.mdwn
new file mode 100644
index 0000000..8a1ea52
--- /dev/null
+++ b/posts/fixing-turris-omnia-wifi-quality.mdwn
@@ -0,0 +1,77 @@
+[[!meta title="Fixing Turris Omnia WiFi Quality"]]
+[[!meta date="2019-11-24T22:30:00.000-08:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+I was recently hoping to replace an aging proprietary router (upgraded to a
+[Gargoyle](https://www.gargoyle-router.com/) FOSS firmware). After rejecting
+a [popular brand with a disturbing GPL violation
+habit](https://sfconservancy.org/blog/2019/oct/02/cambium-ubiquiti-gpl-violations/),
+I settled on the [Turris Omnia router](https://www.turris.cz/en/omnia/),
+built on free software. Overall, I was pretty satisfied with the fact that
+it is free and comes with automatic updates, but I noticed a problem with
+the WiFi. Specifically, the 5 GHz access point was okay but the 2.4 GHz was
+awful.
+
+## False lead
+
+I initially thought that the 2.4 GHz radio wasn't working, but then I
+realized that putting my phone next to the router would allow it to connect
+and exchange data at a slow-but-steady rate. If I moved the phone more than
+3-4 meters away though, it would disconnect for lack of signal. To be frank,
+the wireless performance was much worse than my original router, even though
+the wired performance was, as expected, amazing:
+
+![](/posts/fixing-turris-omnia-wifi-quality/fast.png)
+
+I looked on the [official support forums](https://forum.turris.cz/) and found this intriguing
+thread about [interference between USB3 and 2.4 GHz
+radios](https://forum.turris.cz/t/slow-wifi-and-bad-signal-finally-solved/7372).
+This sounded a lot like what I was experiencing (working radio but terrible
+signal/interference) and so I decided to see if I could move the radios
+around inside the unit, as suggested by the poster.
+
+After opening the case however, I noticed that radios were already laid out
+in the optimal way:
+
+![](/posts/fixing-turris-omnia-wifi-quality/radios.png)
+
+and that USB3 interference wasn't going to be the reason
+for my troubles.
+
+## Real problem
+
+So I took a good look at the wiring and found that while the the [larger
+radio](https://compex.com.sg/shop/wifi-module/802-11ac-wave-1/wle900vx/)
+(2.4 / 5 GHz dual-bander) was connected to all three antennas, the [smaller
+radio](https://compex.com.sg/shop/wifi-module/802-11n/wle200n2/) (2.4 GHz
+only) was connected to only 2 of the 3 antennas:
+
+![](/posts/fixing-turris-omnia-wifi-quality/overall.png)
+
+To make it possible for antennas 1 and 3 to carry the signal from both
+radios, a duplexer got inserted between the radios and the antenna:
+
+![](/posts/fixing-turris-omnia-wifi-quality/duplexer.png)
+
+On one side is the 2.4 antenna port and on the other side is the 5 GHz port.
+
+Looking at the wiring though, it became clear that **my 2.4 GHz radio was
+connected to the 5 GHz ports of the two duplexers and the 5 GHz radio was
+connected to the 2.4 GHz ports of the duplexers**. This makes sense
+considering that I had okay 5 GHz performance (with one of the three chains
+connected to the right filter) and abysimal 2.4 GHz performance (with none
+of the two chains connected to the right filter).
+
+## Solution
+
+**Swapping the antenna connectors around completely fixed the problem.**
+With the 2.4 GHz radio connected to the 2.4 side of the duplexer and the
+dual-bander connected to the 5 GHz side, I was able to get the performance I
+would expect from such a high-quality router.
+
+Interestingly enough, I found the solution to this problem the same weekend
+as I passed my advanced [amateur radio license
+exam](https://launchpad.net/canadian-ham-exam). I guess that was a good way
+to put the course material into practice!
+
+[[!tag nzoss]] [[!turris]]
diff --git a/posts/fixing-turris-omnia-wifi-quality/duplexer.jpg b/posts/fixing-turris-omnia-wifi-quality/duplexer.jpg
new file mode 100644
index 0000000..7a59d75
Binary files /dev/null and b/posts/fixing-turris-omnia-wifi-quality/duplexer.jpg differ
diff --git a/posts/fixing-turris-omnia-wifi-quality/fast.png b/posts/fixing-turris-omnia-wifi-quality/fast.png
new file mode 100644
index 0000000..ebe8d6e
Binary files /dev/null and b/posts/fixing-turris-omnia-wifi-quality/fast.png differ
diff --git a/posts/fixing-turris-omnia-wifi-quality/overall.jpg b/posts/fixing-turris-omnia-wifi-quality/overall.jpg
new file mode 100644
index 0000000..b36a840
Binary files /dev/null and b/posts/fixing-turris-omnia-wifi-quality/overall.jpg differ
diff --git a/posts/fixing-turris-omnia-wifi-quality/radios.jpg b/posts/fixing-turris-omnia-wifi-quality/radios.jpg
new file mode 100644
index 0000000..dd081f8
Binary files /dev/null and b/posts/fixing-turris-omnia-wifi-quality/radios.jpg differ

Comment moderation
diff --git a/posts/recovering-from-unbootable-ubuntu-encrypted-lvm-root-partition/comment_6_cc0e9e44b01885a989b41cbb417b0032._comment b/posts/recovering-from-unbootable-ubuntu-encrypted-lvm-root-partition/comment_6_cc0e9e44b01885a989b41cbb417b0032._comment
new file mode 100644
index 0000000..6a89be9
--- /dev/null
+++ b/posts/recovering-from-unbootable-ubuntu-encrypted-lvm-root-partition/comment_6_cc0e9e44b01885a989b41cbb417b0032._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ ip="82.6.2.26"
+ claimedauthor="Marcin"
+ url="mr-coffee.io"
+ subject="Saved my life"
+ date="2019-11-24T20:40:41Z"
+ content="""
+Very helpful, thanks a lot for that post! As a quick note, this also works for the Virtualbox related installation. Ony difference would be to mount the LiveCD in the Settings > Storage > Controller: IDE and start the VM. The other steps work as a charm!
+"""]]

Comment moderation
diff --git a/posts/recovering-from-unbootable-ubuntu-encrypted-lvm-root-partition/comment_5_0367ad2561d124b47e307502f1b85a96._comment b/posts/recovering-from-unbootable-ubuntu-encrypted-lvm-root-partition/comment_5_0367ad2561d124b47e307502f1b85a96._comment
new file mode 100644
index 0000000..70b0845
--- /dev/null
+++ b/posts/recovering-from-unbootable-ubuntu-encrypted-lvm-root-partition/comment_5_0367ad2561d124b47e307502f1b85a96._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ ip="2001:14ba:3f0:f600:7107:33f1:dce3:43f5"
+ claimedauthor="linux-girl"
+ subject="This really woks with minor change"
+ date="2019-11-22T08:09:19Z"
+ content="""
+First I recovered the /etc/fstab and /etc/crypttab from the backup with backup-tool because I had tried something and messed up these files.
+
+Then I followed these instructions but I left the command 'vgchange -ay' out. Reason for that was because after that I couldn't mount my partitions to anything. Without it mounting was done nicely and the rest of the steps could be done.
+
+It had the consequence that in the end I couldn't unmount and close the partition but that wasn't in this instruction and so I paid no attention to that.
+
+I encountered the problem when updating the initramfs (I was missing some firmware library and it gave some warnings). Solution to that was found here: https://askubuntu.com/questions/832524/possible-missing-frmware-lib-firmware-i915/832528 and the updating of initramfs were done without warnings.
+
+In the end I prayed a little and rebooted and everything was fine after these changes and now I can log in to my ubuntu again. 
+
+
+Thanks for clear instructions!
+"""]]

Move dunst to the first section since it's started by startup script
diff --git a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
index 279b9fc..9ebdaa7 100644
--- a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
+++ b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
@@ -10,6 +10,7 @@ After experimenting with [awesome](http://awesome.naquadah.org/) for 2 years and
 
 As soon as I log into my desktop, my [startup script](https://github.com/fmarier/user-scripts/blob/master/startup) starts a few programs, including:
 
+* [dunst package](https://packages.debian.org/stable/dunst): displays desktop notifications
 * [gnome-settings-daemon](https://packages.debian.org/stable/gnome-settings-daemon): makes GTK applications look nice by applying my preferred theme amongst other things
 * [gnome-keyring-daemon](https://packages.debian.org/stable/gnome-keyring): remembers ssh public keys for the duration of my session
 * [i3lock](https://packages.debian.org/stable/i3lock): locks the screen when I'm not around
@@ -22,15 +23,11 @@ Because of [a bug in gnome-settings-daemon](https://ask.fedoraproject.org/en/que
 
 # Notifications
 
-I use the [dunst package](https://packages.debian.org/stable/dunst) to receive desktop notifications:
-
-    apt install dunst
-
 You will probably also want to set the following in `/etc/xdg/dunst/dunstrc` to ensure that notifications use your default web browser:
 
     browser = /usr/bin/sensible-browser
 
-Here are the keyboard shortcuts you'll need to interact with the notifications that popup:
+Here are the keyboard shortcuts you'll need to interact with the notifications that pop up:
 
 - `Ctrl-Space` to close the current notification
 - `Ctrl-Shift-Space` to close all notifications

Switch from gnome-screensaver to i3lock
diff --git a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
index 103ae19..279b9fc 100644
--- a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
+++ b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
@@ -12,7 +12,7 @@ As soon as I log into my desktop, my [startup script](https://github.com/fmarier
 
 * [gnome-settings-daemon](https://packages.debian.org/stable/gnome-settings-daemon): makes GTK applications look nice by applying my preferred theme amongst other things
 * [gnome-keyring-daemon](https://packages.debian.org/stable/gnome-keyring): remembers ssh public keys for the duration of my session
-* [gnome-screensaver](https://packages.debian.org/stable/gnome-screensaver): locks the screen when I'm not around
+* [i3lock](https://packages.debian.org/stable/i3lock): locks the screen when I'm not around
 * [nm-applet](https://packages.debian.org/stable/network-manager-gnome): handles wifi and VPN connections
 * [syncthing](https://www.syncthing.net/): keeps my folders synchronized between machines
 
@@ -39,11 +39,9 @@ Here are the keyboard shortcuts you'll need to interact with the notifications t
 
 # Screensaver
 
-In addition, gnome-screensaver didn't automatically lock my screen, so I installed [xautolock](https://packages.debian.org/stable/xautolock) and added it to my startup script:
+To make i3lock automatically lock my screen, I installed [xautolock](https://packages.debian.org/stable/xautolock) and added it to my startup script:
 
-    xautolock -time 30 -locker "gnome-screensaver-command --lock" &
-
-to lock the screen using gnome-screensaver after 30 minutes of inactivity.
+    xautolock -time 30 -locker "i3lock -c 000000 -f" &
 
 I can also trigger it manually using the following shortcut defined in my `~/.i3/config`:
 

Fix broken escaping
diff --git a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
index 6980966..103ae19 100644
--- a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
+++ b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
@@ -34,7 +34,7 @@ Here are the keyboard shortcuts you'll need to interact with the notifications t
 
 - `Ctrl-Space` to close the current notification
 - `Ctrl-Shift-Space` to close all notifications
-- `Ctrl-\`` to show the last notification
+- `Ctrl-<backtick>` to show the last notification
 - `Ctrl-Shift-.` to show the context menu for the current notification
 
 # Screensaver

I do actually start dunst from my startup script
diff --git a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
index e3a00d7..6980966 100644
--- a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
+++ b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
@@ -22,8 +22,7 @@ Because of [a bug in gnome-settings-daemon](https://ask.fedoraproject.org/en/que
 
 # Notifications
 
-While my startup script doesn't run this tool directly, installing the
-[dunst package](https://packages.debian.org/stable/dunst) is required to receive desktop notifications:
+I use the [dunst package](https://packages.debian.org/stable/dunst) to receive desktop notifications:
 
     apt install dunst
 

Add tags to my SurveyMonkey post
diff --git a/posts/restricting-third-party-iframes-sandbox-referrer-feature-policy.mdwn b/posts/restricting-third-party-iframes-sandbox-referrer-feature-policy.mdwn
index a533e4d..bb08db9 100644
--- a/posts/restricting-third-party-iframes-sandbox-referrer-feature-policy.mdwn
+++ b/posts/restricting-third-party-iframes-sandbox-referrer-feature-policy.mdwn
@@ -195,3 +195,5 @@ benefits](https://csp-evaluator.withgoogle.com/).
 
 Embedded enforcement is thefore not a usable security control in this
 particular example until SurveyMonkey gets a stricter CSP policy.
+
+[[!tag web]] [[!tag security]] [[!tag csp]] [[!tag mozilla]]

Add SurveyMonkey blog post
diff --git a/posts/restricting-third-party-iframes-sandbox-referrer-feature-policy.mdwn b/posts/restricting-third-party-iframes-sandbox-referrer-feature-policy.mdwn
new file mode 100644
index 0000000..a533e4d
--- /dev/null
+++ b/posts/restricting-third-party-iframes-sandbox-referrer-feature-policy.mdwn
@@ -0,0 +1,197 @@
+[[!meta title="Restricting third-party iframe widgets using the sandbox attribute, referrer policy and feature policy"]]
+[[!meta date="2019-09-20T20:15:00.000-07:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+Adding third-party embedded widgets on a website is a common but potentially
+dangerous practice. Thankfully, the web platform offers a few controls that can help
+mitigate the risks. While this post uses the example of an embedded
+SurveyMonkey survey, the principles can be used for all kinds of other widgets.
+
+Note that this is by no means an endorsement of SurveyMonkey's proprietary
+service. If you are looking for a survey product, you should consider a free
+and open source alternative like [LimeSurvey](https://www.limesurvey.org/).
+
+# SurveyMonkey's snippet
+
+In order to embed a [survey on your
+website](https://www.surveymonkey.com/curiosity/how-to-embed-your-survey-on-a-website/),
+the SurveyMonkey interface will tell you to install the following [website
+collector](https://help.surveymonkey.com/articles/en_US/kb/Website-Collector) script:
+
+    <script>(function(t,e,s,n){var
+    o,a,c;t.SMCX=t.SMCX||[],e.getElementById(n)||(o=e.getElementsByTagName(s),a=o[o.length-1],c=e.createElement(s),c.type="text/javascript",c.async=!0,c.id=n,c.src=["https:"===location.protocol?"https://":"http://","widget.surveymonkey.com/collect/website/js/tRaiETqnLgj758hTBazgd9NxKf_2BhnTfDFrN34n_2BjT1Kk0sqrObugJL8ZXdb_2BaREa.js"].join(""),a.parentNode.insertBefore(c,a))})(window,document,"script","smcx-sdk");</script><a
+    style="font: 12px Helvetica, sans-serif; color: #999; text-decoration:
+    none;" href=https://www.surveymonkey.com> Create your own user feedback
+    survey </a>
+
+which can be rewritten in a more understandable form as:
+
+    (
+    function (s) {
+      var scripts, last_script, new_script;
+      window.SMCX = window.SMCX || [],
+      document.getElementById("smcx-sdk") ||
+        (
+          scripts = document.getElementsByTagName("script"),
+          last_script = scripts[scripts.length - 1],
+          new_script = document.createElement("script"),
+          new_script.type = "text/javascript",
+          new_script.async = true,
+          new_script.id = "smcx-sdk",
+          new_script.src =
+            [
+              "https:" === location.protocol ? "https://" : "http://",
+              "widget.surveymonkey.com/collect/website/js/tRaiETqnLgj758hTBazgd9NxKf_2BhnTfDFrN34n_2BjT1Kk0sqrObugJL8ZXdb_2BaREa.js"
+            ].join(""),
+          last_script.parentNode.insertBefore(new_script, last_script)
+        )
+      }
+    )();
+
+The fact that this adds a third-party script dependency to your website is
+problematic because it means that a security vulnerability in their
+infrastructure could lead to a complete compromise of your site, thanks to
+third-party scripts having full control over your website. Security issues
+aside though, this could also enable this third-party to violate your users'
+privacy expectations and extract any information displayed on your site for
+marketing purposes.
+
+However, if you embed the snippet on a test page and inspect it with the
+developer tools, you will find that it actually creates an
+[iframe](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe):
+
+    <iframe
+        width="500"
+        height="500"
+        frameborder="0"
+        allowtransparency="true"
+        src="https://www.surveymonkey.com/r/D3KDY6R?embedded=1"
+    ></iframe>
+
+and you can use that directly on your site without having to load their
+script.
+
+## Mixed content anti-pattern
+
+As an aside, the script snippet they propose makes use of a common front-end
+anti-pattern:
+
+    "https:"===location.protocol?"https://":"http://"
+
+This is presumably meant to avoid inserting an HTTP script element into an
+HTTPS page, since that would be considered [mixed
+content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content)
+and get blocked by browsers, however this is entirely unnecessary. One
+should only ever use the HTTPS version of such scripts anyways since an HTTP
+page [never prohibits embedding HTTPS
+content](https://www.w3.org/TR/mixed-content/#categorize-settings-object).
+
+In other words, the above code snippet can be simplified to:
+
+    "https://"
+
+# Restricting iframes
+
+Thanks to defenses which have been added to the web platform recently, there
+are a few things that can be done to constrain iframes.
+
+Firstly, you can choose to hide your full page URL from SurveyMonkey using
+the [referrer
+policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy):
+
+    referrerpolicy="strict-origin"
+
+This mean seem harmless, but page URLs sometimes include sensitive
+information in the URL path or query string, for example, search terms that
+a user might have typed. The `strict-origin` policy will limit the referrer
+to your site's hostname, port and protocol.
+
+Secondly, you can prevent the iframe from being able to access anything
+about its embedding page or to trigger popups and unwanted downloads using
+the [sandbox
+attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox):
+
+    sandbox="allow-scripts allow-forms"
+
+Ideally, the contents of this attribute would be empty so that all
+restrictions would be active, but SurveyMonkey is a JavaScript application
+and it of course needs to submit a form since that's the purpose of the widget.
+
+Finally, a new experimental capability is making its way into browsers:
+[feature policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Feature_Policy).
+In the context of untrusted iframes, it enables developers to explicitly
+disable [certain powerful
+features](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy#Directives):
+
+    allow="accelerometer 'none';
+           ambient-light-sensor 'none';
+           camera 'none';
+           display-capture 'none';
+           document-domain 'none';
+           fullscreen 'none';
+           geolocation 'none';
+           gyroscope 'none';
+           magnetometer 'none';
+           microphone 'none';
+           midi 'none';
+           payment 'none';
+           usb 'none';
+           vibrate 'none';
+           vr 'none';
+           webauthn 'none'"
+
+Putting it all together, we end up with the following HTML snippet:
+
+    <iframe
+        width="500"
+        height="500"
+        frameborder="0"
+        allowtransparency="true"
+        allow="accelerometer 'none'; ambient-light-sensor 'none';
+               camera 'none'; display-capture 'none';
+               document-domain 'none'; fullscreen 'none';
+               geolocation 'none'; gyroscope 'none'; magnetometer 'none';
+               microphone 'none'; midi 'none'; payment 'none'; usb 'none';
+               vibrate 'none'; vr 'none'; webauthn 'none'"
+        sandbox="allow-scripts allow-forms"
+        referrerpolicy="strict-origin"
+        src="https://www.surveymonkey.com/r/D3KDY6R?embedded=1"
+    ></iframe>
+
+# Content Security Policy
+
+Another advantage of using the iframe directly is that instead of loosening
+your site's [Content Security
+Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) by adding all
+of the following:
+
+* `script-src https://www.surveymonkey.com`
+* `img-src https://www.surveymonkey.com`
+* `frame-src  https://www.surveymonkey.com`
+
+you can limit the extra directives to just the frame controls:
+
+* `frame-src  https://www.surveymonkey.com`
+
+[CSP Embedded Enforcement](https://w3c.github.io/webappsec-cspee/) would be
+another nice mechanism to make use of, but looking at SurveyMonkey's CSP
+policy:
+
+    Content-Security-Policy:
+      default-src https: data: blob: 'unsafe-eval' 'unsafe-inline'
+          wss://*.hotjar.com 'self';
+      img-src https: http: data: blob: 'self';
+      script-src https: 'unsafe-eval' 'unsafe-inline' http://www.google-analytics.com http://ajax.googleapis.com
+          http://bat.bing.com http://static.hotjar.com http://www.googleadservices.com
+          'self';
+      style-src https: 'unsafe-inline' http://secure.surveymonkey.com 'self';
+      report-uri https://csp.surveymonkey.com/report?e=true&c=prod&a=responseweb
+
+it allows the injection of arbitrary Flash files, [inline
+scripts](https://developers.google.com/web/fundamentals/security/csp/#inline_code_is_considered_harmful),
+evals and any other scripts hosted on an HTTPS URL, which means that it
+[doesn't really provide any meaningful security
+benefits](https://csp-evaluator.withgoogle.com/).

(Diff truncated)
Comment moderation
diff --git a/posts/installing-debian-buster-on-gnubee2/comment_2_bc2dba3b221d2d92ae9c306d1be4fc0d._comment b/posts/installing-debian-buster-on-gnubee2/comment_2_bc2dba3b221d2d92ae9c306d1be4fc0d._comment
new file mode 100644
index 0000000..1ea2359
--- /dev/null
+++ b/posts/installing-debian-buster-on-gnubee2/comment_2_bc2dba3b221d2d92ae9c306d1be4fc0d._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ ip="165.225.114.98"
+ claimedauthor="Antoine"
+ subject="Same issue with SSH"
+ date="2019-09-09T08:49:57Z"
+ content="""
+Hi, 
+Just stumbled onto this post. I have the same issue with SSH, on a GnuBee PC1. I believe openssh is running (according to OpenMediaVault GUI), but it rejects all connections attempts. Please keep updating this post if you find a solution.
+"""]]
diff --git a/posts/installing-debian-buster-on-gnubee2/comment_3_5d038744e65cf79c39b9fd03b937c812._comment b/posts/installing-debian-buster-on-gnubee2/comment_3_5d038744e65cf79c39b9fd03b937c812._comment
new file mode 100644
index 0000000..7d29cdc
--- /dev/null
+++ b/posts/installing-debian-buster-on-gnubee2/comment_3_5d038744e65cf79c39b9fd03b937c812._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ ip="188.192.119.43"
+ claimedauthor="Hein Osenberg"
+ subject="Works for me"
+ date="2019-09-02T19:21:34Z"
+ content="""
+With Neil Browns new kernel (5.2.8 - see http://neil.brown.name/gnubee/), installed (see README) upgrading to Debian Buster worked perfectly for me. SSH access works out of the box without problems. 
+"""]]
diff --git a/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox/comment_3_2ce1f54d56c51d14432525478fb3224c._comment b/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox/comment_3_2ce1f54d56c51d14432525478fb3224c._comment
new file mode 100644
index 0000000..5d28a0d
--- /dev/null
+++ b/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox/comment_3_2ce1f54d56c51d14432525478fb3224c._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="francois@665656f0ba400877c9b12e8fbb086e45aa01f7c0"
+ nickname="francois"
+ subject="Re: programming Anytone 878"
+ date="2019-09-02T21:11:37Z"
+ content="""
+> In the instruction you say turn on the radio. How do you do that if it is locked and can be only unlocked by programing?
+
+The radio being factory-locked shouldn't prevent you from turning it on using the right knob. If you're talking about the keypad being locked, then yes that's one of the things that can be [unlocked using the CPS](https://www.youtube.com/watch?v=dzFqEM-yC7A).
+"""]]

Restore accidentally deleted comment
diff --git a/posts/installing-debian-buster-on-gnubee2/comment_1_2a3c537445b6d27e05446e43471ddc81._comment b/posts/installing-debian-buster-on-gnubee2/comment_1_2a3c537445b6d27e05446e43471ddc81._comment
new file mode 100644
index 0000000..83f1c74
--- /dev/null
+++ b/posts/installing-debian-buster-on-gnubee2/comment_1_2a3c537445b6d27e05446e43471ddc81._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ ip="188.192.119.43"
+ claimedauthor="Hein Osenberg"
+ subject="Works for me"
+ date="2019-09-02T19:21:34Z"
+ content="""
+With Neil Browns new kernel (5.2.8 - see <http://neil.brown.name/gnubee/>), installed (see README) upgrading to Debian Buster worked perfectly for me. SSH access works
+out of the box without problems.
+"""]]

Comment moderation
diff --git a/posts/poor-mans-raid1-between-ssd-and-hard-drive/comment_5_8e548908487f2d40ea9285800441daf1._comment b/posts/poor-mans-raid1-between-ssd-and-hard-drive/comment_5_8e548908487f2d40ea9285800441daf1._comment
new file mode 100644
index 0000000..6794a3b
--- /dev/null
+++ b/posts/poor-mans-raid1-between-ssd-and-hard-drive/comment_5_8e548908487f2d40ea9285800441daf1._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ ip="96.67.192.225"
+ claimedauthor="Alexis Wilke"
+ url="https://linux.m2osw.com/"
+ subject="Your title said RAID1..."
+ date="2019-09-01T23:03:01Z"
+ content="""
+I totally agree that a RAID1 would kill the speed of SSD. But then, your post title says RAID1... :-)
+
+Now, I wanted to mention that if you know the name of your device, you can check whether it's a rotational (HDD) or not (SSD). Here is an example of how you get the flag:
+
+alexis~$ cat /sys/block/sda/queue/rotational
+
+The file is either a 0 (SSD) or a 1 (HDD). What you need is the \"sda\" part of the path. In a shell script, it can be difficult to grab that info. Although a function such as \"df .\" give you the info, it's not that practical.
+
+Anyway, your solution is pretty much what I had in mind. Thank you.
+"""]]
diff --git a/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox/comment_1_d8c8da58ae4ccdd77c13f738b2606fbd._comment b/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox/comment_1_d8c8da58ae4ccdd77c13f738b2606fbd._comment
new file mode 100644
index 0000000..b950695
--- /dev/null
+++ b/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox/comment_1_d8c8da58ae4ccdd77c13f738b2606fbd._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ ip="2605:6000:6fc0:52:38c2:3e01:8b8a:e440"
+ claimedauthor="William Hennessy"
+ url="bhennessy2@satx.rr.com"
+ subject="programming Anytone 878"
+ date="2019-09-01T16:06:47Z"
+ content="""
+In the instruction you say turn on the radio.  How do you do that if it is locked and can be only unlocked by programing?
+"""]]
diff --git a/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox/comment_2_63881d9f9a28457c788c2f3a32b989af._comment b/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox/comment_2_63881d9f9a28457c788c2f3a32b989af._comment
new file mode 100644
index 0000000..79d6064
--- /dev/null
+++ b/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox/comment_2_63881d9f9a28457c788c2f3a32b989af._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ ip="2601:280:4100:8254:9a3b:8fff:fec1:f25a"
+ claimedauthor="Chris Keller, K0SWE"
+ subject="Finally, USB works!"
+ date="2019-08-09T11:37:29Z"
+ content="""
+Thanks for writing this down! I've tried a Virtualbox VM several times for programming radios but could never get USB devices to be visible inside the VM. Turns out, I was missing the `vboxusers` group. This should open up a lot of possibilities!
+"""]]

Automatically scale large images
diff --git a/local.css b/local.css
index 068fd89..3f1933d 100644
--- a/local.css
+++ b/local.css
@@ -1,4 +1,9 @@
 /* ikiwiki local style sheet */
+img {
+    max-width: 100%;
+    height: auto;
+}
+
 .blogform, .trail, .inlinefooter .pagelicense, .inlinefooter .tags, .inlinefooter .actions {
     display: none;
 }

Add my restricted passwordless guest account
diff --git a/posts/passwordless-restricted-guest-account-ubuntu.mdwn b/posts/passwordless-restricted-guest-account-ubuntu.mdwn
new file mode 100644
index 0000000..d1bcfe4
--- /dev/null
+++ b/posts/passwordless-restricted-guest-account-ubuntu.mdwn
@@ -0,0 +1,85 @@
+[[!meta title="Passwordless restricted guest account on Ubuntu"]]
+[[!meta date="2019-08-15T20:10:00.000-07:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+Here's how I created a restricted but *not ephemeral* guest account on an
+Ubuntu 18.04 desktop computer that can be used without a password.
+
+## Create a user that can login without a password
+
+First of all, I created a new user with a random password (using `pwgen -s 64`):
+
+    adduser guest
+
+Then following [these
+instructions](http://ubuntuhandbook.org/index.php/2019/02/enable-passwordless-login-ubuntu-18-04/),
+I created a new group and added the user to it:
+
+    addgroup nopasswdlogin
+    adduser guest nopasswdlogin
+
+In order to let that user login using
+[GDM](https://wiki.gnome.org/Projects/GDM) without a password, I added the
+following to the top of `/etc/pam.d/gdm-password`:
+
+    auth    sufficient      pam_succeed_if.so user ingroup nopasswdlogin
+
+Note that this user is unable to ssh into this machine since it's not part
+of the [`sshuser` group I have setup in my sshd
+configuration](https://feeding.cloud.geek.nz/posts/hardening-ssh-servers/#Whitelist_approach_to_giving_users_ssh_access).
+
+## Privacy settings
+
+In order to reduce the amount of digital traces left between guest sessions,
+I logged into the account using a GNOME session and then opened
+gnome-control-center. I set the following in the privacy section:
+
+![](/posts/passwordless-restricted-guest-account-ubuntu/privacy-settings.png)
+
+Then I replaced Firefox with [Brave](https://brave.com) in the sidebar,
+set it as the default browser in gnome-control-center:
+
+![](/posts/passwordless-restricted-guest-account-ubuntu/default-applications.png)
+
+and configured it to clear everything on exit:
+
+![](/posts/passwordless-restricted-guest-account-ubuntu/brave-clear-on-exit.png)
+
+## Create a password-less system keyring
+
+In order to suppress [prompts to unlock
+gnome-keyring](https://askubuntu.com/questions/867/how-can-i-stop-being-prompted-to-unlock-the-default-keyring-on-boot),
+I opened [seahorse](https://wiki.gnome.org/Apps/Seahorse) and deleted the
+default keyring.
+
+Then I started Brave, which prompted me to create a new keyring so that it
+can save the contents of its password manager securely. I set an **empty
+password** on that new keyring, since I'm not going to be using it.
+
+I also made sure to disable saving of passwords, payment methods and
+addresses in the browser too.
+
+![](/posts/passwordless-restricted-guest-account-ubuntu/brave-passwords.png)
+
+![](/posts/passwordless-restricted-guest-account-ubuntu/brave-payments.png)
+
+![](/posts/passwordless-restricted-guest-account-ubuntu/brave-addresses.png)
+
+## Restrict user account further
+
+Finally, taking an idea from this [similar
+solution](https://askubuntu.com/a/19696/8368), I prevented the user from
+making any system-wide changes by putting the following in
+`/etc/polkit-1/localauthority/50-local.d/10-guest-policy.pkla`:
+
+    [guest-policy]
+    Identity=unix-user:guest
+    Action=*
+    ResultAny=no
+    ResultInactive=no
+    ResultActive=no
+
+If you know of any other restrictions that could be added, please leave a
+comment!
+
+[[!tag ubuntu]] [[!tag debian]] [[!tag nzoss]] [[!tag brave]]
diff --git a/posts/passwordless-restricted-guest-account-ubuntu/brave-addresses.png b/posts/passwordless-restricted-guest-account-ubuntu/brave-addresses.png
new file mode 100644
index 0000000..6911611
Binary files /dev/null and b/posts/passwordless-restricted-guest-account-ubuntu/brave-addresses.png differ
diff --git a/posts/passwordless-restricted-guest-account-ubuntu/brave-clear-on-exit.png b/posts/passwordless-restricted-guest-account-ubuntu/brave-clear-on-exit.png
new file mode 100644
index 0000000..e60c47a
Binary files /dev/null and b/posts/passwordless-restricted-guest-account-ubuntu/brave-clear-on-exit.png differ
diff --git a/posts/passwordless-restricted-guest-account-ubuntu/brave-passwords.png b/posts/passwordless-restricted-guest-account-ubuntu/brave-passwords.png
new file mode 100644
index 0000000..e8795b3
Binary files /dev/null and b/posts/passwordless-restricted-guest-account-ubuntu/brave-passwords.png differ
diff --git a/posts/passwordless-restricted-guest-account-ubuntu/brave-payments.png b/posts/passwordless-restricted-guest-account-ubuntu/brave-payments.png
new file mode 100644
index 0000000..eb2cdab
Binary files /dev/null and b/posts/passwordless-restricted-guest-account-ubuntu/brave-payments.png differ
diff --git a/posts/passwordless-restricted-guest-account-ubuntu/default-applications.png b/posts/passwordless-restricted-guest-account-ubuntu/default-applications.png
new file mode 100644
index 0000000..72e5844
Binary files /dev/null and b/posts/passwordless-restricted-guest-account-ubuntu/default-applications.png differ
diff --git a/posts/passwordless-restricted-guest-account-ubuntu/privacy-settings.png b/posts/passwordless-restricted-guest-account-ubuntu/privacy-settings.png
new file mode 100644
index 0000000..a749079
Binary files /dev/null and b/posts/passwordless-restricted-guest-account-ubuntu/privacy-settings.png differ

Prune old stale files
diff --git a/posts/seeding-brave-browser-sccache.mdwn b/posts/seeding-brave-browser-sccache.mdwn
index d3398a5..423f702 100644
--- a/posts/seeding-brave-browser-sccache.mdwn
+++ b/posts/seeding-brave-browser-sccache.mdwn
@@ -45,6 +45,8 @@ and here are the contents of that script:
     git fetch --prune origin
     git pull
     npm install
+    rm -rf src/brave/*
+    gclient sync -D
     npm run init
     
     echo $(date)

Bump the sccache cache size to match ccache
diff --git a/posts/seeding-brave-browser-sccache.mdwn b/posts/seeding-brave-browser-sccache.mdwn
index 0936c99..d3398a5 100644
--- a/posts/seeding-brave-browser-sccache.mdwn
+++ b/posts/seeding-brave-browser-sccache.mdwn
@@ -72,7 +72,7 @@ It references a `~/.bashrc-brave` file which contains:
     #!/bin/sh
     export PATH="${PATH}:${HOME}/bin:${HOME}/devel/brave-browser/vendor/depot_tools:${HOME}/.cargo/bin"
     export SCCACHE_DIR="${HOME}/.cache/sccache"
-    export SCCACHE_CACHE_SIZE=100G
+    export SCCACHE_CACHE_SIZE=200G
     export NO_AUTH_BOTO_CONFIG="${HOME}/.boto"
 
 ## ccache instead of sccache

creating tag page tags/ccache
diff --git a/tags/ccache.mdwn b/tags/ccache.mdwn
new file mode 100644
index 0000000..bf2591a
--- /dev/null
+++ b/tags/ccache.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged ccache"]]
+
+[[!inline pages="tagged(ccache)" actions="no" archive="yes"
+feedshow=10]]

Switch to ccache
diff --git a/posts/seeding-brave-browser-sccache.mdwn b/posts/seeding-brave-browser-sccache.mdwn
index b4b8a8e..0936c99 100644
--- a/posts/seeding-brave-browser-sccache.mdwn
+++ b/posts/seeding-brave-browser-sccache.mdwn
@@ -75,4 +75,27 @@ It references a `~/.bashrc-brave` file which contains:
     export SCCACHE_CACHE_SIZE=100G
     export NO_AUTH_BOTO_CONFIG="${HOME}/.boto"
 
-[[!tag brave]] [[!tag sccache]]
+## ccache instead of sccache
+
+While I started using sccache for compiling Brave, I recently switched to
+[ccache](https://ccache.dev) as sccache turned out to be fairly
+[unreliable](https://github.com/brave/brave-browser/wiki/sccache-for-faster-builds#troubleshooting-the-install)
+at compiling Chromium.
+
+Switching to `ccache` is easy, simply install the package:
+
+    apt install ccache
+
+and then set the [environment
+variable](https://github.com/brave/brave-browser/wiki/sccache-for-faster-builds#setting-the-environment-variable)
+in `.npmrc`:
+
+    sccache = ccache
+
+Finally, you'll probably want to increase the maximum cache size:
+
+    ccache --max-size=200G
+
+in order to fit all of Chromium/Brave in the cache.
+
+[[!tag brave]] [[!tag sccache]] [[!tag ccache]]

Fix two more possible update/build errors
diff --git a/posts/seeding-brave-browser-sccache.mdwn b/posts/seeding-brave-browser-sccache.mdwn
index 4a11ece..b4b8a8e 100644
--- a/posts/seeding-brave-browser-sccache.mdwn
+++ b/posts/seeding-brave-browser-sccache.mdwn
@@ -38,9 +38,11 @@ and here are the contents of that script:
     rm -rf src/out node_modules src/brave/node_modules
     git clean -f -d
     git checkout HEAD package-lock.json
+    find -name "*.pyc" -delete
     
     echo $(date)
     echo "=> Update repo"
+    git fetch --prune origin
     git pull
     npm install
     npm run init

creating tag page tags/gnubee
diff --git a/tags/gnubee.mdwn b/tags/gnubee.mdwn
new file mode 100644
index 0000000..a60ebdf
--- /dev/null
+++ b/tags/gnubee.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged gnubee"]]
+
+[[!inline pages="tagged(gnubee)" actions="no" archive="yes"
+feedshow=10]]

Add GnuBee Debian installation guide
diff --git a/posts/installing-debian-buster-on-gnubee2.mdwn b/posts/installing-debian-buster-on-gnubee2.mdwn
new file mode 100644
index 0000000..3e80d85
--- /dev/null
+++ b/posts/installing-debian-buster-on-gnubee2.mdwn
@@ -0,0 +1,192 @@
+[[!meta title="Installing Debian buster on a GnuBee PC 2"]]
+[[!meta date="2019-07-14T15:30:00.000-07:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+Here is how I installed [Debian 10 /
+buster](https://www.debian.org/releases/buster/) on my [GnuBee Personal
+Cloud 2](http://gnubee.org/), a free hardware device designed as a network
+file server / [NAS](https://en.wikipedia.org/wiki/Network-attached_storage).
+
+## Flashing the LibreCMC firmware with Debian support
+
+Before we can install Debian, we need a firmware that includes all of the
+necessary tools.
+
+On another machine, do the following:
+
+1. Download the [latest `librecmc-ramips-mt7621-gb-pc1-squashfs-sysupgrade_*.bin`](https://github.com/gnubee-git/gnubee-git.github.io/tree/master/debian).
+2. Mount a **vfat**-formatted USB stick.
+3. Copy the file onto it and rename it to `gnubee.bin`.
+4. Unmount the USB stick
+
+Then plug a network cable between your laptop and the **black network port**
+and plug the USB stick into the GnuBee before rebooting the GnuBee via ssh:
+
+    ssh 192.68.10.0
+    reboot
+
+If you have a [USB serial
+cable](https://github.com/gnubee-git/GnuBee_Docs/blob/master/USB_to_UART/README.md),
+you can use it to monitor the flashing process:
+
+    screen /dev/ttyUSB0 57600
+
+otherwise keep an eye on the [LEDs and wait until they are fully done
+flashing](https://github.com/gnubee-git/GnuBee_Docs/wiki/Install-firmware#via-usb-stick).
+
+## Getting ssh access to LibreCMC
+
+Once the firmware has been updated, turn off the GnuBee manually using the
+power switch and turn it back on.
+
+Now enable SSH access via the built-in [LibreCMC](https://librecmc.org)
+firmware:
+
+1. Plug a network cable between your laptop and the **black network port**.
+2. Open web-based admin panel at <http://192.168.10.0>.
+3. Go to *System | Administration*.
+4. Set a root password.
+5. Disable ssh password auth and root password logins.
+6. Paste in your **RSA** ssh public key.
+7. Click *Save & Apply*.
+8. Go to *Network | Firewall*.
+9. Select "accept" for WAN Input.
+10. Click *Save & Apply*.
+
+Finaly, go to *Network | Interfaces* and note the ipv4 address of the WAN
+port since that will be needed in the next step.
+
+## Installing Debian
+
+The first step is to [install Debian
+jessie](https://github.com/gnubee-git/GnuBee_Docs/wiki/Debian) on the
+GnuBee.
+
+Connect the **blue network port** into your router/switch and ssh into the
+GnuBee using the IP address you noted earlier:
+
+    ssh root@192.168.1.xxx
+
+and the root password you set in the previous section.
+
+Then use `fdisk /dev/sda` to create the following partition layout on the
+first drive:
+
+    Device       Start       End   Sectors   Size Type
+    /dev/sda1     2048   8390655   8388608     4G Linux swap
+    /dev/sda2  8390656 234441614 226050959 107.8G Linux filesystem
+
+Note that I used an 120GB solid-state drive as the system drive in order to
+minimize noise levels.
+
+Then format the swap partition:
+
+    mkswap /dev/sda1
+
+and download the latest version of the jessie installer:
+
+    wget --no-check-certificate https://raw.githubusercontent.com/gnubee-git/GnuBee_Docs/master/GB-PCx/scripts/jessie_3.10.14/debian-jessie-install
+
+(Yes, the `--no-check-certificate` is really unfortunate. Please leave a
+comment if you find a way to work around it.)
+
+The stock installer fails to bring up the correct networking configuration
+on my network and so I have [modified the
+install script](https://github.com/gnubee-git/GnuBee_Docs/pull/102) by changing
+the `eth0.1` blurb to:
+
+    auto eth0.1
+    iface eth0.1 inet static
+        address 192.168.10.1
+        netmask 255.255.255.0
+
+Then you should be able to run the installer succesfully:
+
+    sh ./debian-jessie-install
+
+and reboot:
+
+    reboot
+
+# Restore ssh access in Debian jessie
+
+Once the GnuBee has finished booting, login using the [serial console](https://github.com/gnubee-git/GnuBee_Docs/blob/master/USB_to_UART/README.md):
+
+- username: `root`
+- password: `GnuBee`
+
+and change the root password using `passwd`.
+
+Look for the IPv4 address of `eth0.2` in the output of the `ip addr` command
+and then ssh into the GnuBee from your desktop computer:
+
+    ssh root@192.168.1.xxx  # type password set above
+    mkdir .ssh
+    vim .ssh/authorized_keys  # paste your ed25519 ssh pubkey
+
+## Finish the jessie installation
+
+With this in place, you should be able to ssh into the GnuBee using your
+public key:
+
+    ssh root@192.168.1.172
+
+and then finish the jessie installation:
+
+    wget --no-check-certificate https://raw.githubusercontent.com/gnubee-git/gnubee-git.github.io/master/debian/debian-modules-install
+    bash ./debian-modules-install
+    reboot
+
+After rebooting, I made a few tweaks to make the system more pleasant to
+use:
+
+    update-alternatives --config editor  # choose vim.basic
+    dpkg-reconfigure locales  # enable the locale that your desktop is using
+
+## Upgrade to stretch and then buster
+
+To upgrade to stretch, put this in `/etc/apt/sources.list`:
+
+    deb http://httpredir.debian.org/debian stretch main
+    deb http://httpredir.debian.org/debian stretch-updates main
+    deb http://security.debian.org/ stretch/updates main
+
+Then upgrade the packages:
+
+    apt update
+    apt full-upgrade
+    apt autoremove
+    reboot
+
+To upgrade to buster, put this in `/etc/apt/sources.list`:
+
+    deb http://httpredir.debian.org/debian buster main
+    deb http://httpredir.debian.org/debian buster-updates main
+    deb http://security.debian.org/debian-security buster/updates main
+
+and upgrade the packages:
+
+    apt update
+    apt full-upgrade
+    apt autoremove
+    reboot
+
+## Next steps
+
+At this point, my GnuBee is running the latest version of Debian stable,
+however there are two remaining issues to fix:
+
+1. [openssh-server doesn't
+   work](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=932089) and I am
+   forced to access the GnuBee via the serial interface.
+
+2. The firmware is running an outdated version of the Linux kernel though
+   this is [being worked
+   on](https://groups.google.com/d/topic/gnubee/YVM08lfWUUc/discussion) by
+   community members.
+
+I hope to resolve these issues soon, and will update this blog post once I
+do, but you are more than welcome to leave a comment if you know of a
+solution I may have overlooked.
+
+[[!tag debian]] [[!tag gnubee]] [[!tag nzoss]]

Enable apt sandboxing which is now available in buster
diff --git a/posts/usual-server-setup.mdwn b/posts/usual-server-setup.mdwn
index 07d944d..79ca04d 100644
--- a/posts/usual-server-setup.mdwn
+++ b/posts/usual-server-setup.mdwn
@@ -238,6 +238,10 @@ and the following to harden the TCP stack:
 
 before reloading these settings using `sysctl -p`.
 
+Sandboxing in apt can be enabled by putting the following in `/etc/apt/apt.conf.d/30-seccomp`:
+
+    APT::Sandbox::Seccomp "true";
+
 I also restrict the use of cron to the `root` user by putting the following in `/etc/cron.allow`:
 
     root

Add the replacement for mcelog
diff --git a/posts/usual-server-setup.mdwn b/posts/usual-server-setup.mdwn
index c8627d8..07d944d 100644
--- a/posts/usual-server-setup.mdwn
+++ b/posts/usual-server-setup.mdwn
@@ -9,7 +9,7 @@ how I customize recent releases of Debian on those servers.
 
 # Hardware tests
 
-    apt install memtest86+ smartmontools e2fsprogs
+    apt install memtest86+ smartmontools e2fsprogs rasdaemon
 
 Prior to spending any time configuring a new physical server, I like to
 ensure that the hardware is fine.

Include the contents of ~/.bashrc-brave
diff --git a/posts/seeding-brave-browser-sccache.mdwn b/posts/seeding-brave-browser-sccache.mdwn
index 77bb125..4a11ece 100644
--- a/posts/seeding-brave-browser-sccache.mdwn
+++ b/posts/seeding-brave-browser-sccache.mdwn
@@ -65,4 +65,12 @@ and here are the contents of that script:
     echo "=> Delete build output"
     rm -rf src/out
 
+It references a `~/.bashrc-brave` file which contains:
+
+    #!/bin/sh
+    export PATH="${PATH}:${HOME}/bin:${HOME}/devel/brave-browser/vendor/depot_tools:${HOME}/.cargo/bin"
+    export SCCACHE_DIR="${HOME}/.cache/sccache"
+    export SCCACHE_CACHE_SIZE=100G
+    export NO_AUTH_BOTO_CONFIG="${HOME}/.boto"
+
 [[!tag brave]] [[!tag sccache]]

Add SIP TLS/SRTP post
diff --git a/posts/sip-encryption-on-voip-ms.mdwn b/posts/sip-encryption-on-voip-ms.mdwn
new file mode 100644
index 0000000..2cb3209
--- /dev/null
+++ b/posts/sip-encryption-on-voip-ms.mdwn
@@ -0,0 +1,73 @@
+[[!meta title="SIP Encryption on VoIP.ms"]]
+[[!meta date="2019-07-06T16:00:00.000-07:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+My [VoIP provider](https://voip.ms) recently added [support for
+TLS/SRTP-based call
+encryption](https://wiki.voip.ms/article/Call_Encryption_-_TLS/SRTP). Here's
+what I did to enable this feature on my
+[Asterisk](https://www.asterisk.org/) server.
+
+First of all, I changed the registration line in `/etc/asterisk/sip.conf` to
+use the "tls" scheme:
+
+    [general]
+    register => tls://mydid:mypassword@servername.voip.ms
+
+then I enabled incoming TCP connections:
+
+    tcpenable=yes
+
+and TLS:
+
+    tlsenable=yes
+    tlscapath=/etc/ssl/certs/
+
+Finally, I changed my provider entry in the same file to:
+
+    [voipms]
+    type=friend
+    host=servername.voip.ms
+    secret=mypassword
+    username=mydid
+    context=from-voipms
+    allow=ulaw
+    allow=g729
+    insecure=port,invite
+    transport=tls
+    encryption=yes
+
+(Note the last two lines.)
+
+The dialplan didn't change and so I still have the following in
+`/etc/asterisk/extensions.conf`:
+
+    [pstn-voipms]
+    exten => _1NXXNXXXXXX,1,Set(CALLERID(all)=Francois Marier <5551234567>)
+    exten => _1NXXNXXXXXX,n,Dial(SIP/voipms/${EXTEN})
+    exten => _1NXXNXXXXXX,n,Hangup()
+    exten => _NXXNXXXXXX,1,Set(CALLERID(all)=Francois Marier <5551234567>)
+    exten => _NXXNXXXXXX,n,Dial(SIP/voipms/1${EXTEN})
+    exten => _NXXNXXXXXX,n,Hangup()
+    exten => _011X.,1,Set(CALLERID(all)=Francois Marier <5551234567>)
+    exten => _011X.,n,Authenticate(1234) ; require password for international calls
+    exten => _011X.,n,Dial(SIP/voipms/${EXTEN})
+    exten => _011X.,n,Hangup(16)
+
+## Server certificate
+
+The only thing I still need to fix is to make this error message go away in
+my logs:
+
+    asterisk[8691]: ERROR[8691]: tcptls.c:966 in __ssl_setup: TLS/SSL error loading cert file. <asterisk.pem>
+
+It appears to be related to the fact that I didn't set `tlscertfile` in
+`/etc/asterisk/sip.conf` and that it's using its default value of
+`asterisk.pem`, a non-existent file.
+
+Since my Asterisk server is only acting as a TLS *client*, and not a TLS
+*server*, there's probably no harm in not having a certificate. That said,
+it looks pretty easy to [use a Let's Encrypt cert with
+Asterisk](https://community.asterisk.org/t/has-anyone-used-letsencrypt-to-setup-ssl-for-asterisk/67145/6).
+
+[[!tag debian]] [[!tag asterisk]] [[!tag nzoss]] [[!tag letsencrypt]]

Add distro-info to get EOL info
https://askubuntu.com/a/1126933
diff --git a/posts/usual-server-setup.mdwn b/posts/usual-server-setup.mdwn
index 8a9cf7a..c8627d8 100644
--- a/posts/usual-server-setup.mdwn
+++ b/posts/usual-server-setup.mdwn
@@ -261,7 +261,7 @@ The above packages are all about catching mistakes (such as
 
 # Package updates
 
-    apt install apticron unattended-upgrades deborphan debfoster apt-listchanges reboot-notifier popularity-contest needrestart debian-security-support
+    apt install apticron unattended-upgrades deborphan debfoster apt-listchanges reboot-notifier popularity-contest needrestart debian-security-support distro-info
 
 These tools help me keep packages up to date and remove unnecessary or
 obsolete packages from servers. On Rackspace servers, a small [configuration

Use the Cloudflare NTP server
https://blog.cloudflare.com/secure-time/
diff --git a/posts/time-synchronization-with-ntp-and-systemd.mdwn b/posts/time-synchronization-with-ntp-and-systemd.mdwn
index 3f54067..f548d26 100644
--- a/posts/time-synchronization-with-ntp-and-systemd.mdwn
+++ b/posts/time-synchronization-with-ntp-and-systemd.mdwn
@@ -60,7 +60,7 @@ you and put it in `/etc/systemd/timesyncd.conf`. For example, mine reads
 like this:
 
     [Time]
-    NTP=ca.pool.ntp.org
+    NTP=time.cloudflare.com
 
 before restarting the daemon:
 

Add LXC post for OpenSUSE 15 on Ubuntu 18.04
diff --git a/posts/opensuse15-lxc-setup-on-ubuntu-bionic.mdwn b/posts/opensuse15-lxc-setup-on-ubuntu-bionic.mdwn
new file mode 100644
index 0000000..9e45f32
--- /dev/null
+++ b/posts/opensuse15-lxc-setup-on-ubuntu-bionic.mdwn
@@ -0,0 +1,101 @@
+[[!meta title="OpenSUSE 15 LXC setup on Ubuntu Bionic 18.04"]]
+[[!meta date="2019-06-14T20:15:00.000-07:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+Similarly to what I wrote for [Fedora](https://feeding.cloud.geek.nz/posts/fedora29-lxc-setup-on-ubuntu-bionic/),
+here is how I was able to create an [OpenSUSE](https://www.opensuse.org) 15 LXC
+container on an Ubuntu 18.04 (bionic) laptop.
+
+# Setting up LXC on Ubuntu
+
+First of all, install lxc:
+
+    apt install lxc
+    echo "veth" >> /etc/modules
+    modprobe veth
+
+turn on bridged networking by putting the following in
+`/etc/sysctl.d/local.conf`:
+
+    net.ipv4.ip_forward=1
+
+and applying it using:
+
+    sysctl -p /etc/sysctl.d/local.conf
+
+Then allow the right traffic in your firewall
+(`/etc/network/iptables.up.rules` in my case):
+
+    # LXC containers
+    -A FORWARD -d 10.0.3.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+    -A FORWARD -s 10.0.3.0/24 -j ACCEPT
+    -A INPUT -d 224.0.0.251 -s 10.0.3.1 -j ACCEPT
+    -A INPUT -d 239.255.255.250 -s 10.0.3.1 -j ACCEPT
+    -A INPUT -d 10.0.3.255 -s 10.0.3.1 -j ACCEPT
+    -A INPUT -d 10.0.3.1 -s 10.0.3.0/24 -j ACCEPT
+
+and apply these changes:
+
+    iptables-apply
+
+before restarting the lxc networking:
+
+    systemctl restart lxc-net.service
+
+# Creating the container
+
+Once that's in place, you can finally create the OpenSUSE 15 container:
+
+    lxc-create -n opensuse15 -t download -- -d opensuse -r 15 -a amd64
+
+To see a list of all distros available with the `download` template:
+
+    lxc-create -n foo --template=download -- --list
+
+# Logging in as root
+
+Start up the container and get a login console:
+
+    lxc-start -n opensuse15 -F
+
+In another terminal, set a password for the root user:
+
+    lxc-attach -n opensuse15 passwd
+
+You can now use this password to log into the console you started earlier.
+
+# Logging in as an unprivileged user via ssh
+
+As root, install a few packages:
+
+    zypper install vim openssh sudo man
+    systemctl start sshd
+    systemctl enable sshd
+
+and then create an unprivileged user:
+
+    useradd francois
+    passwd francois
+    cd /home
+    mkdir francois
+    chown francois:100 francois/
+
+and give that user [sudo access](https://en.opensuse.org/SDB:Administer_with_sudo):
+
+    visudo  # uncomment "wheel" line
+    groupadd wheel
+    usermod -aG wheel francois
+
+Now login as that user from the console and add an ssh public key:
+
+    mkdir .ssh
+    chmod 700 .ssh
+    echo "<your public key>" > .ssh/authorized_keys
+    chmod 644 .ssh/authorized_keys
+
+You can now login via ssh. The IP address to use can be seen in the output
+of:
+
+    lxc-ls --fancy
+
+[[!tag debian]] [[!tag lxc]] [[!tag nzoss]] [[!tag ubuntu]]

Comment moderation
diff --git a/posts/installing-vidyo-on-ubuntu-1804/comment_3_ea0a0f985040e8679fed6f98209126f1._comment b/posts/installing-vidyo-on-ubuntu-1804/comment_3_ea0a0f985040e8679fed6f98209126f1._comment
new file mode 100644
index 0000000..3482398
--- /dev/null
+++ b/posts/installing-vidyo-on-ubuntu-1804/comment_3_ea0a0f985040e8679fed6f98209126f1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ ip="2001:610:120:3000::192:161"
+ claimedauthor="Frans Schreuder"
+ subject="Topicons plus"
+ date="2019-06-14T06:33:04Z"
+ content="""
+The instruction works, but one important thing is missing. On Ubuntu with Gnome (Both 18.04 and 19.04) you will need the gnome extention TopIcons Plus installed in order to launch VidyoDesktop, otherwise the application will fail to start (at least for me).
+"""]]

Fix typo
diff --git a/posts/installing-vidyo-on-ubuntu-1804/comment_2_93c96cdc7713032646438fe0a172a56c._comment b/posts/installing-vidyo-on-ubuntu-1804/comment_2_93c96cdc7713032646438fe0a172a56c._comment
index c735c96..6d9f427 100644
--- a/posts/installing-vidyo-on-ubuntu-1804/comment_2_93c96cdc7713032646438fe0a172a56c._comment
+++ b/posts/installing-vidyo-on-ubuntu-1804/comment_2_93c96cdc7713032646438fe0a172a56c._comment
@@ -4,5 +4,5 @@
  subject="Re: comment 1"
  date="2018-11-08T06:32:12Z"
  content="""
-I'm not sure why you're saying that it's sloppy for a system-wide binary to be owned by root. That's both [the policy in Debian](https://www.debian.org/doc/debian-policy/ch-files.html#permissions-and-owners) and also it prevents an ordinary user from tampering a binary that could be used by other users.
+I'm not sure why you're saying that it's sloppy for a system-wide binary to be owned by root. That's both [the policy in Debian](https://www.debian.org/doc/debian-policy/ch-files.html#permissions-and-owners) and also it prevents an ordinary user from tampering with a binary that could be used by other users.
 """]]

Disable modelines in vim
https://nvd.nist.gov/vuln/detail/CVE-2019-12735
diff --git a/posts/usual-server-setup.mdwn b/posts/usual-server-setup.mdwn
index 9f5bad3..8a9cf7a 100644
--- a/posts/usual-server-setup.mdwn
+++ b/posts/usual-server-setup.mdwn
@@ -64,6 +64,7 @@ following to `/etc/vim/vimrc.local`:
     syntax on
     set background=dark
     set visualbell
+    set nomodeline
 
 # ssh
 

More thorough cleaning of old builds / checkouts
diff --git a/posts/seeding-brave-browser-sccache.mdwn b/posts/seeding-brave-browser-sccache.mdwn
index aef0e28..77bb125 100644
--- a/posts/seeding-brave-browser-sccache.mdwn
+++ b/posts/seeding-brave-browser-sccache.mdwn
@@ -34,16 +34,18 @@ and here are the contents of that script:
     echo
     
     echo $(date)
+    echo "=> Clean up repo and delete old build output"
+    rm -rf src/out node_modules src/brave/node_modules
+    git clean -f -d
+    git checkout HEAD package-lock.json
+    
+    echo $(date)
     echo "=> Update repo"
     git pull
     npm install
     npm run init
     
     echo $(date)
-    echo "=> Delete any old build output"
-    rm -rf src/out
-    
-    echo $(date)
     echo "=> Debug build"
     killall sccache || true
     ionice nice timeout 4h npm run build || ionice nice timeout 4h npm run build

Comment moderation
diff --git a/posts/setting-up-a-network-scanner-using-sane/comment_10_10aacafabba32f9596e18f4163fe9fd9._comment b/posts/setting-up-a-network-scanner-using-sane/comment_10_10aacafabba32f9596e18f4163fe9fd9._comment
new file mode 100644
index 0000000..49b0938
--- /dev/null
+++ b/posts/setting-up-a-network-scanner-using-sane/comment_10_10aacafabba32f9596e18f4163fe9fd9._comment
@@ -0,0 +1,141 @@
+[[!comment format=mdwn
+ ip="88.207.218.2"
+ claimedauthor="Anonymous Coward"
+ subject="Revised configuration necessary for saned under systemd"
+ date="2019-05-29T21:11:00Z"
+ content="""
+After encoutering numerous problems in setting up SANED network access with systemd on a Linux Mint 18.3 , here are some important points 
+
+1) make sure you do not have saned configured to run under inetd or xinetd as might be the case from an upgraded installation
+
+2) systemd needs a file for socket and an instance service file.  To avoid loss of customizations with package upgrades, put these in /etc/systemd/system not overwrite those in /lib/systemd/system
+
+    #*****************************************************************************#
+    #|
+    #|  file : /etc/systemd/system/saned.socket
+    #|
+    #*---------------------------------------------------------------------------*#
+
+    [Unit]
+    Description=SANED network daemon activation socket
+
+    [Socket]
+    Accept=yes
+    ListenStream=6566
+    MaxConnections=1
+
+    [Install]
+    WantedBy=sockets.target
+
+    #*****************************************************************************#
+
+The second item it needs is an instance service file NOT a service file.  This means that the file name contains an \"@\" as in saned@.service and the contents
+
+    #*****************************************************************************#
+    #|
+    #|  file : /etc/systemd/system/saned@.service
+    #|
+    #*---------------------------------------------------------------------------*#
+
+    [Unit]
+    Description=SANE network daemon instance %i
+    Documentation=man:saned(8)
+    After=local-fs.target network-online.target
+    Requires=saned.socket
+
+    [Service]
+    Environment=SANE_CONFIG_DIR=/etc/sane.d
+    ExecStart=/usr/sbin/saned
+    Group=saned
+    User=saned
+    StandardInput=null
+    StandardOutput=syslog
+    StandardError=syslog
+
+    [Install]
+    Also=saned.socket
+
+    #*****************************************************************************#
+
+
+If you want to do debugging you can add additional Environment lines
+
+    Environment=SANE_DEBUG_DLL=255
+    Environment=SANE_DEBUG_NET=255
+
+For completeness, to mirror the setup in /lib/systemd/system and to emphasize the point when looking in /etc/systemd/system that the file is not missing and that saned@.service is not misnamed, symbolically link  /dev/null to /etc/lib/systemd/system/saned.service
+
+     /etc/systemd/system/saned.service -> /dev/null
+
+This is unecessary because of the link present in /lib/systemd/system, but it makes it clear when looking at the /etc/systemd/system directory the configuration being used.
+
+Do a systemctl enable of saned.socket and it will create a symbolic link under the socket.target.wants directory
+
+/etc/services should have the entry
+
+     sane-port		 6566/tcp	sane saned
+    
+Ensure that /proc/sys/net/ipv6/bindv6only is set to 0 (and not set to 1 due to some hack from an old bindipv6only.conf file /etc/sysctl.conf.d) if you are wanting network connections on IPv4 to work.
+
+It may be necessary to ensure that the \"net\" featured is turned on in /etc/sane.d/dll.d configuration file for your scanner if it is some non-standard configuration.
+
+In your /etc/sane.d/saned.conf ensure your have a \"localhost\" entry -- 127.0.0.1 should also work but when saned starts up it says checking for localhost, so this is to be consistent.
+Then add the host names or network IP address ranges permitted to access the service.
+
+Adjust your firewall rules if necessary.
+
+You do not need to add the host IP address to the /etc/sane.d/net.conf file, this will result in you being offered both a local and a network connection to the scanner from the host, so keep it simple for the server host, but do add the server host IP address or name to the net.conf file on the client hosts which need to access the service.
+
+If you then do a systemctl start saned.socket followed by a systemctl status saned.socket you should see
+
+     saned.socket - SANED network daemon activation socket
+       Loaded: loaded (/etc/systemd/system/saned.socket; enabled; vendor preset: enabled)
+       Active: active (listening) since Wed 2019-05-29 20:12:40 BST; 30min ago
+       Listen: [::]:6566 (Stream)
+     Accepted: 21; Connected: 0
+
+Now where the \"magic\" comes in, is that when a connection is made on the socket, systemd fires up an **instance** of the saned service using the socket name as the instance name
+(which is why the standard input is set to \"null\" and NOT \"socket\" in the saned@.service file).
+
+So if when a remote connection is made you do
+
+    systemctl -all -l --no-pager | grep saned you should see
+
+      saned@21-192.168.21.12:6566-192.168.11.12:49314.service                                    loaded    active   running   SANE network daemon instance 3 (192.168.11.12:49314)
+      system-saned.slice                                                                        loaded    active   active    system-saned.slice
+      saned.socket                                                                              loaded    active   listening SANED network daemon activation socket
+
+where the instance number increases by one for each connection.
+
+If you want to advertise the service via Avahi, you could add a service file under /etc/avahi/servvices
+
+    <?xml version=\"1.0\" standalone='no'?>
+    <!DOCTYPE service-group SYSTEM \"avahi-service.dtd\">
+
+    <!-- #********************************************************************# -->
+    <!-- #|                                                                  |# -->
+    <!-- #|  file : /etc/avahi/services/saned.service                        |# -->
+    <!-- #|                                                                  |# -->
+    <!-- #|__________________________________________________________________|# -->
+
+    <service-group>
+
+	     <name replace-wildcards=\"yes\">%h.example.COM Network Scanning</name>
+
+        	<service>
+        		<domain-name>local</domain-name>
+        		<host-name>server_name.local</host-name>
+         		<port>6566</port>
+         		<type>_scanner._tcp</type>
+        	</service>
+
+      </service-group>
+
+     <!-- #********************************************************************# -->
+
+
+replacing example.COM and server_name as appropriate.  The value for \"type\" was taken from
+
+     http://www.dns-sd.org/ServiceTypes.html
+
+"""]]

Simplify sha256sum instructions
https://linuxmint.com/verify.php
diff --git a/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn b/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn
index b07b47d..9b983b5 100644
--- a/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn
+++ b/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn
@@ -36,10 +36,8 @@ signature](https://tutorials.ubuntu.com/tutorial/tutorial-how-to-verify-ubuntu):
 
 3. Verify the hash of the ISO file:
 
-        $ sha256sum ubuntu-18.04.2-server-amd64.iso 
-        a2cb36dc010d98ad9253ea5ad5a07fd6b409e3412c48f1860536970b073c98f5  ubuntu-18.04.2-server-amd64.iso
-        $ grep ubuntu-18.04.2-server-amd64.iso SHA256SUMS
-        a2cb36dc010d98ad9253ea5ad5a07fd6b409e3412c48f1860536970b073c98f5 *ubuntu-18.04.2-server-amd64.iso
+        $ sha256sum --ignore-missing -c SHA256SUMS
+        ubuntu-18.04.2-server-amd64.iso: OK
 
 Then copy it to a USB drive:
 

Add extra heading
diff --git a/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn b/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn
index a5acfd1..b07b47d 100644
--- a/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn
+++ b/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn
@@ -47,6 +47,8 @@ Then copy it to a USB drive:
 
 and boot with it.
 
+## Manual partitioning
+
 Inside the installer, use manual partitioning to:
 
 1. Configure the physical partitions.

Comment moderation
diff --git a/posts/installing-ubuntu-bionic-on-encrypted-raid1/comment_1_d178526dcf96e252ab0196c59c93d1b0._comment b/posts/installing-ubuntu-bionic-on-encrypted-raid1/comment_1_d178526dcf96e252ab0196c59c93d1b0._comment
new file mode 100644
index 0000000..4193372
--- /dev/null
+++ b/posts/installing-ubuntu-bionic-on-encrypted-raid1/comment_1_d178526dcf96e252ab0196c59c93d1b0._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ ip="82.141.154.4"
+ claimedauthor="random from planet debian"
+ subject="LVM"
+ date="2019-05-24T09:43:23Z"
+ content="""
+If you set up [MD-raid> LUKS > LVM > {pool/swap, pool/root etc}] stack then you get one PW prompt and suspend to disk still works...
+
+br: a random guy
+"""]]
diff --git a/posts/mercurial-commit-series-phabricator-using-arcanist/comment_2_4b6c0f885e5dea08a3d6d4cf4e2793a9._comment b/posts/mercurial-commit-series-phabricator-using-arcanist/comment_2_4b6c0f885e5dea08a3d6d4cf4e2793a9._comment
new file mode 100644
index 0000000..7c9bf9b
--- /dev/null
+++ b/posts/mercurial-commit-series-phabricator-using-arcanist/comment_2_4b6c0f885e5dea08a3d6d4cf4e2793a9._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ ip="83.56.36.123"
+ claimedauthor="leplatrem"
+ subject="How to manage updates after review?"
+ date="2019-05-08T10:00:16Z"
+ content="""
+After everything is submitted, I made some changes to my commits.
+
+When I run `arc diff` for a particular commit, the process is really confusing. For example, with `arc diff --update DXXX`, I get prompted with the whole list of revisions... 
+
+
+"""]]

Expand the dunst comments and turn them into a "notifications" section
diff --git a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
index 4dc4b8e..e3a00d7 100644
--- a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
+++ b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
@@ -20,11 +20,24 @@ Because of [a bug in gnome-settings-daemon](https://ask.fedoraproject.org/en/que
 
     dconf write /org/gnome/settings-daemon/plugins/cursor/active false
 
+# Notifications
+
 While my startup script doesn't run this tool directly, installing the
 [dunst package](https://packages.debian.org/stable/dunst) is required to receive desktop notifications:
 
     apt install dunst
 
+You will probably also want to set the following in `/etc/xdg/dunst/dunstrc` to ensure that notifications use your default web browser:
+
+    browser = /usr/bin/sensible-browser
+
+Here are the keyboard shortcuts you'll need to interact with the notifications that popup:
+
+- `Ctrl-Space` to close the current notification
+- `Ctrl-Shift-Space` to close all notifications
+- `Ctrl-\`` to show the last notification
+- `Ctrl-Shift-.` to show the context menu for the current notification
+
 # Screensaver
 
 In addition, gnome-screensaver didn't automatically lock my screen, so I installed [xautolock](https://packages.debian.org/stable/xautolock) and added it to my startup script:

Add re-try logic and compile tests too
diff --git a/posts/seeding-brave-browser-sccache.mdwn b/posts/seeding-brave-browser-sccache.mdwn
index ea742c1..aef0e28 100644
--- a/posts/seeding-brave-browser-sccache.mdwn
+++ b/posts/seeding-brave-browser-sccache.mdwn
@@ -45,12 +45,18 @@ and here are the contents of that script:
     
     echo $(date)
     echo "=> Debug build"
-    ionice nice timeout 4h npm run build
+    killall sccache || true
+    ionice nice timeout 4h npm run build || ionice nice timeout 4h npm run build
+    ionice nice ninja -C src/out/Debug brave_unit_tests
+    ionice nice ninja -C src/out/Debug brave_browser_tests
     echo
     
     echo $(date)
     echo "=>Release build"
-    ionice nice timeout 5h npm run build Release
+    killall sccache || true
+    ionice nice timeout 5h npm run build Release || ionice nice timeout 5h npm run build Release
+    ionice nice ninja -C src/out/Release brave_unit_tests
+    ionice nice ninja -C src/out/Release brave_browser_tests
     echo
     
     echo $(date)

Add my RAID1+LUKS post on Ubuntu
diff --git a/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn b/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn
new file mode 100644
index 0000000..a5acfd1
--- /dev/null
+++ b/posts/installing-ubuntu-bionic-on-encrypted-raid1.mdwn
@@ -0,0 +1,186 @@
+[[!meta title="Installing Ubuntu 18.04 using both full-disk encryption and RAID1"]]
+[[!meta date="2019-05-22T21:30:00.000-07:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+I recently setup a desktop computer with two SSDs using a software RAID1 and
+full-disk encryption (i.e. [LUKS](https://en.wikipedia.org/wiki/LUKS)).
+Since this is not a supported configuration in Ubuntu desktop, I had to use
+the server installation medium.
+
+This is my version of these [excellent
+instructions](https://askubuntu.com/questions/1066028/install-ubuntu-18-04-desktop-with-raid-1-and-lvm-on-machine-with-uefi-bios#1066041).
+
+## Server installer
+
+Start by downloading the [alternate server
+installer](http://cdimage.ubuntu.com/ubuntu/releases/bionic/release/) and
+[verifying its
+signature](https://tutorials.ubuntu.com/tutorial/tutorial-how-to-verify-ubuntu):
+
+1. Download the required files:
+
+        wget http://cdimage.ubuntu.com/ubuntu/releases/bionic/release/ubuntu-18.04.2-server-amd64.iso
+        wget http://cdimage.ubuntu.com/ubuntu/releases/bionic/release/SHA256SUMS
+        wget http://cdimage.ubuntu.com/ubuntu/releases/bionic/release/SHA256SUMS.gpg
+
+2. Verify the signature on the hash file:
+
+        $ gpg --keyid-format long --keyserver hkps://keyserver.ubuntu.com --recv-keys 0xD94AA3F0EFE21092
+        $ gpg --verify SHA256SUMS.gpg SHA256SUMS
+        gpg: Signature made Fri Feb 15 08:32:38 2019 PST
+        gpg:                using RSA key D94AA3F0EFE21092
+        gpg: Good signature from "Ubuntu CD Image Automatic Signing Key (2012) <cdimage@ubuntu.com>" [undefined]
+        gpg: WARNING: This key is not certified with a trusted signature!
+        gpg:          There is no indication that the signature belongs to the owner.
+        Primary key fingerprint: 8439 38DF 228D 22F7 B374  2BC0 D94A A3F0 EFE2 1092
+
+3. Verify the hash of the ISO file:
+
+        $ sha256sum ubuntu-18.04.2-server-amd64.iso 
+        a2cb36dc010d98ad9253ea5ad5a07fd6b409e3412c48f1860536970b073c98f5  ubuntu-18.04.2-server-amd64.iso
+        $ grep ubuntu-18.04.2-server-amd64.iso SHA256SUMS
+        a2cb36dc010d98ad9253ea5ad5a07fd6b409e3412c48f1860536970b073c98f5 *ubuntu-18.04.2-server-amd64.iso
+
+Then copy it to a USB drive:
+
+    dd if=ubuntu-18.04.2-server-amd64.iso of=/dev/sdX
+
+and boot with it.
+
+Inside the installer, use manual partitioning to:
+
+1. Configure the physical partitions.
+2. Configure the RAID array second.
+2. Configure the encrypted partitions last
+
+Here's the exact configuration I used:
+
+- `/dev/sda1` is 512 MB and used as the EFI parition
+- `/dev/sdb1` is 512 MB but **not used for anything**
+- `/dev/sda2` and `/dev/sdb2` are both 4 GB (RAID)
+- `/dev/sda3` and `/dev/sdb3` are both 512 MB (RAID)
+- `/dev/sda4` and `/dev/sdb4` use up the rest of the disk (RAID)
+
+I only set `/dev/sda2` as the EFI partition because I found that **adding a
+second EFI partition would break the installer**.
+
+I created the following RAID1 arrays:
+
+- `/dev/sda2` and `/dev/sdb2` for `/dev/md2`
+- `/dev/sda3` and `/dev/sdb3` for `/dev/md0`
+- `/dev/sda4` and `/dev/sdb4` for `/dev/md1`
+
+I used `/dev/md0` as my **unencrypted** `/boot` partition.
+
+Then I created the following LUKS partitions:
+
+- `md1_crypt` as the `/` partition using `/dev/md1`
+- `md2_crypt` as the *swap* partition (4 GB) with a **random
+  encryption key** using `/dev/md2`
+
+## Post-installation configuration
+
+Once your new system is up, sync the EFI partitions using DD:
+
+    dd if=/dev/sda1 of=/dev/sdb1
+
+and create a second EFI boot entry:
+
+    efibootmgr -c -d /dev/sdb -p 1 -L "ubuntu2" -l \EFI\ubuntu\shimx64.efi
+
+Ensure that the RAID drives are fully sync'ed by keeping an eye on
+`/prod/mdstat` and then reboot, selecting "ubuntu2" in the UEFI/BIOS menu.
+
+Once you have rebooted, remove the following package to speed up future boots:
+
+    apt purge btrfs-progs
+
+To switch to the desktop variant of Ubuntu, install these meta-packages:
+
+    apt install ubuntu-desktop gnome
+
+then use `debfoster` to remove unnecessary packages (in particular the ones
+that only come with the default Ubuntu server installation).
+
+## Fixing booting with degraded RAID arrays
+
+Since I have run into [RAID startup problems in the
+past](https://feeding.cloud.geek.nz/posts/the-perils-of-raid-and-full-disk-encryption-on-ubuntu/),
+I expected having to fix up a few things to make degraded RAID arrays
+boot correctly.
+
+I did not use [LVM](https://en.wikipedia.org/wiki/LVM2) since I
+didn't really feel the need to add yet another layer of abstraction of top
+of my setup, but I found that the `lvm2` package must still be installed:
+
+    apt install lvm2
+
+with `use_lvmetad = 0` in `/etc/lvm/lvm.conf`.
+
+Then in order to automatically bring up the RAID arrays with 1 out of 2
+drives, I added the following script in
+`/etc/initramfs-tools/scripts/local-top/cryptraid`:
+
+     #!/bin/sh
+     PREREQ="mdadm"
+     prereqs()
+     {
+          echo "$PREREQ"
+     }
+     case $1 in
+     prereqs)
+          prereqs
+          exit 0
+          ;;
+     esac
+     
+     mdadm --run /dev/md0
+     mdadm --run /dev/md1
+     mdadm --run /dev/md2
+
+before making that script executable:
+
+    chmod +x /etc/initramfs-tools/scripts/local-top/cryptraid
+
+and refreshing the initramfs:
+
+    update-initramfs -u -k all
+
+## Disable suspend-to-disk
+
+Since I use a [random encryption key for the swap
+partition](https://feeding.cloud.geek.nz/posts/encrypted-swap-partition-on/)
+(to avoid having a second password prompt at boot time), it means that
+suspend-to-disk is not going to work and so I disabled it by putting the
+following in `/etc/initramfs-tools/conf.d/resume`:
+
+    RESUME=none
+
+and by adding `noresume` to the `GRUB_CMDLINE_LINUX` variable in
+`/etc/default/grub` before applying these changes:
+
+    update-grub
+    update-initramfs -u -k all
+
+## Test your configuration
+
+With all of this in place, you should be able to do a final test of your
+setup:
+
+1. Shutdown the computer and unplug the second drive.
+2. Boot with only the first drive.
+3. Shutdown the computer and plug the second drive back in.
+4. Boot with both drives and re-add the second drive to the RAID array:
+
+        mdadm /dev/md0 -a /dev/sdb3
+        mdadm /dev/md1 -a /dev/sdb4
+        mdadm /dev/md2 -a /dev/sdb2
+
+5. Wait until the RAID is done re-syncing and shutdown the computer.
+6. Repeat steps 2-5 with the first drive unplugged instead of the second.
+7. Reboot with both drives plugged in.
+
+At this point, you have a working setup that will gracefully degrade to a
+one-drive RAID array should one of your drives fail.
+
+[[!tag debian]] [[!tag nzoss]] [[!tag ubuntu]] [[!tag raid]]

Fix list command
diff --git a/posts/fedora29-lxc-setup-on-ubuntu-bionic.mdwn b/posts/fedora29-lxc-setup-on-ubuntu-bionic.mdwn
index b7c4b22..7b87943 100644
--- a/posts/fedora29-lxc-setup-on-ubuntu-bionic.mdwn
+++ b/posts/fedora29-lxc-setup-on-ubuntu-bionic.mdwn
@@ -51,7 +51,7 @@ Once that's in place, you can finally create the Fedora 29 container:
 
 To see a list of all distros available with the `download` template:
 
-    lxc-create --template=download -- --list
+    lxc-create -n foo --template=download -- --list
 
 # Logging in as root
 

Add post about AnyTone programming in a Windows VM
diff --git a/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox.mdwn b/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox.mdwn
new file mode 100644
index 0000000..1d0463a
--- /dev/null
+++ b/posts/programming-anytone-d878uv-on-linux-using-windows10-and-virtualbox.mdwn
@@ -0,0 +1,78 @@
+[[!meta title="Programming an AnyTone AT-D878UV on Linux using Windows 10 and VirtualBox"]]
+[[!meta date="2019-04-16T22:15:00.000-07:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+I recently acquired an [AnyTone AT-D878UV DMR
+radio](https://www.bridgecomsystems.com/collections/amateur-handheld-radios/products/anytone-at-d878uv-dual-band-dmr-handheld-radio-w-gps-programming-cable)
+which is unfortunately not supported by
+[chirp](https://chirp.danplanet.com/projects/chirp/wiki/Home), my usual
+go-to free software package for programming amateur radios.
+
+Instead, I had to setup a Windows 10 virtual machine so that I could setup
+the radio using the manufacturer's computer programming software (CPS).
+
+# Install VirtualBox
+
+Install [VirtualBox](https://www.virtualbox.org):
+
+    apt install virtualbox virtualbox-guest-additions-iso
+
+and add your user account to the `vboxusers` group:
+
+    adduser francois vboxusers
+
+to make filesharing before the host and the guest work.
+
+Finally, **reboot** to ensure that group membership and kernel modules are
+all set.
+
+# Create a Windows 10 virtual machine
+
+Create a new Windows 10 virtual machine within VirtualBox. Then, [download Windows
+10](https://www.microsoft.com/en-in/software-download/windows10ISO) from
+Microsoft then start the virtual machine mounting the `.iso` file as an
+optical drive.
+
+Follow the instructions to install Windows 10, paying attention to the
+[various privacy options you will be
+offered](https://askleo.com/setting-up-windows-10-for-privacy/).
+
+Once Windows is installed, mount the host's
+`/usr/share/virtualbox/VBoxGuestAdditions.iso` as a virtual optical drive
+and install the VirtualBox guest additions.
+
+# Installing the CPS
+
+With Windows fully setup, it's time to download the latest version of the
+[computer programming
+software](https://www.bridgecomsystems.com/pages/anytone-at-d878uv-support-page).
+
+Unpack the downloaded file and then install it as Admin (right-click on the
+`.exe`).
+
+Do NOT install the GD driver update or the USB driver, they do not appear to
+be necessary.
+
+# Program the radio
+
+First, you'll want to download from the radio to get a starting configuration
+that you can change.
+
+To do this:
+
+1. Turn the radio on and wait until it has finished booting.
+2. Plug the USB programming cable onto the computer and the radio.
+3. From the CPS menu choose "Set COM port".
+4. From the CPS menu choose "Read from radio".
+
+**Save this original codeplug to a file as a backup** in case you need to
+easily reset back to the factory settings.
+
+To program the radio, follow this [handy third-party
+guide](https://www.bridgecomsystems.com/blogs/bridgecom-tx-rx-blog/anytone-868-878-programming-guide-v1-33)
+since it's much better than the official manual.
+
+You should be able to use the "Write to radio" menu option without any
+problems once you're done creating your codeplug.
+
+[[!tag ham]]

Mention how to get the list of available distros
diff --git a/posts/fedora29-lxc-setup-on-ubuntu-bionic.mdwn b/posts/fedora29-lxc-setup-on-ubuntu-bionic.mdwn
index 8bf166c..b7c4b22 100644
--- a/posts/fedora29-lxc-setup-on-ubuntu-bionic.mdwn
+++ b/posts/fedora29-lxc-setup-on-ubuntu-bionic.mdwn
@@ -49,6 +49,10 @@ Once that's in place, you can finally create the Fedora 29 container:
 
     lxc-create -n fedora29 -t download -- -d fedora -r 29 -a amd64
 
+To see a list of all distros available with the `download` template:
+
+    lxc-create --template=download -- --list
+
 # Logging in as root
 
 Start up the container and get a login console:

Improve quality of avatar
diff --git a/avatar.jpg b/avatar.jpg
index d2f346a..ab6c37b 100644
Binary files a/avatar.jpg and b/avatar.jpg differ

Update avatar
diff --git a/avatar.jpg b/avatar.jpg
index 5fb6671..d2f346a 100644
Binary files a/avatar.jpg and b/avatar.jpg differ

Improve formatting of user comment
diff --git a/posts/secure-ssh-agent-usage/comment_1_a169f55fa99dd3d9832d21102ebba053._comment b/posts/secure-ssh-agent-usage/comment_1_a169f55fa99dd3d9832d21102ebba053._comment
index f47d529..8822ece 100644
--- a/posts/secure-ssh-agent-usage/comment_1_a169f55fa99dd3d9832d21102ebba053._comment
+++ b/posts/secure-ssh-agent-usage/comment_1_a169f55fa99dd3d9832d21102ebba053._comment
@@ -5,7 +5,7 @@
  subject="comment 1"
  date="2019-04-13T15:41:02Z"
  content="""
-The -c option is a great recommendation, but I've been trying out https://github.com/StanfordSNR/guardian-agent and I like it even better; it gives you much more information about what is happening: which computer is asking for permission, which key they want to use, what server they're going to connect to, and what command they want to run using it. You can make a much more informed decision, and you can save those decisions so that you only have to decide for novel situations.
+The `-c` option is a great recommendation, but I've been trying out <https://github.com/StanfordSNR/guardian-agent> and I like it even better; it gives you much more information about what is happening: which computer is asking for permission, which key they want to use, what server they're going to connect to, and what command they want to run using it. You can make a much more informed decision, and you can save those decisions so that you only have to decide for novel situations.
 
-Also, the ProxyJump command is much nicer than ProxyCommand, but also newer. It's easier to use and harder to misuse.
+Also, the `ProxyJump` command is much nicer than ProxyCommand, but also newer. It's easier to use and harder to misuse.
 """]]

Add a few hardening steps and link to Mozilla guidelines
Disabling authorized_keys2 is from https://github.com/matrix-org/matrix.org/issues/371
while the rest are from Mozilla.
diff --git a/posts/hardening-ssh-servers.mdwn b/posts/hardening-ssh-servers.mdwn
index e39622d..7680ac3 100644
--- a/posts/hardening-ssh-servers.mdwn
+++ b/posts/hardening-ssh-servers.mdwn
@@ -2,6 +2,9 @@
 [[!meta date="2014-02-20T23:52:00.000+13:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
+These are the settings that I use on my servers. You may want to also review
+the [settings that are used at Mozilla](https://infosec.mozilla.org/guidelines/openssh).
+
 # Basic configuration
 
 There are a few basic things that most admins will already know (and that
@@ -20,6 +23,7 @@ This is what `/etc/ssh/sshd_config` should contain:
     AuthenticationMethods publickey
     PasswordAuthentication no
     PermitRootLogin no
+    AuthorizedKeysFile      .ssh/authorized_keys
 
 Once you've done that, make sure you have all of the required host keys by running:
 
@@ -33,6 +37,16 @@ You may also want to ensure you are using [strong ciphers and hash functions](ht
     Ciphers <insert Mozilla list>
     MACs <insert Mozilla list>
 
+and that you deactivate short Diffie-Hellman moduli:
+
+    awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.tmp
+    mv /etc/ssh/moduli.tmp /etc/ssh/moduli
+
+Finally, if you don't need `sftp` support, Mozilla recommends disabling it,
+which can be done by commenting out this line:
+
+    #Subsystem     sftp    /usr/lib/openssh/sftp-server
+
 # Whitelist approach to giving users ssh access
 
 To ensure that only a few users have ssh access to the server and that newly

Comment moderation
diff --git a/posts/secure-ssh-agent-usage/comment_1_a169f55fa99dd3d9832d21102ebba053._comment b/posts/secure-ssh-agent-usage/comment_1_a169f55fa99dd3d9832d21102ebba053._comment
new file mode 100644
index 0000000..f47d529
--- /dev/null
+++ b/posts/secure-ssh-agent-usage/comment_1_a169f55fa99dd3d9832d21102ebba053._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ ip="96.86.171.70"
+ claimedauthor="db48x"
+ url="http://db48x.net/"
+ subject="comment 1"
+ date="2019-04-13T15:41:02Z"
+ content="""
+The -c option is a great recommendation, but I've been trying out https://github.com/StanfordSNR/guardian-agent and I like it even better; it gives you much more information about what is happening: which computer is asking for permission, which key they want to use, what server they're going to connect to, and what command they want to run using it. You can make a much more informed decision, and you can save those decisions so that you only have to decide for novel situations.
+
+Also, the ProxyJump command is much nicer than ProxyCommand, but also newer. It's easier to use and harder to misuse.
+"""]]

Add ssh-agent post
diff --git a/posts/secure-ssh-agent-usage.mdwn b/posts/secure-ssh-agent-usage.mdwn
new file mode 100644
index 0000000..331c2ff
--- /dev/null
+++ b/posts/secure-ssh-agent-usage.mdwn
@@ -0,0 +1,63 @@
+[[!meta title="Secure ssh-agent usage"]]
+[[!meta date="2019-04-13T06:45:00.000-07:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+`ssh-agent` was in the news recently due to the [matrix.org
+compromise](https://github.com/matrix-org/matrix.org/issues/371). The main
+takeaway from that incident was that one should [avoid the `ForwardAgent`
+(or `-A`) functionality when `ProxyCommand` can
+do](https://heipei.io/2015/02/26/SSH-Agent-Forwarding-considered-harmful/)
+and consider multi-factor authentication on the server-side, for example
+using
+[libpam-google-authenticator](https://wiki.archlinux.org/index.php/Google_Authenticator)
+or [libpam-yubico](https://developers.yubico.com/yubico-pam/YubiKey_and_SSH_via_PAM.html).
+
+That said, there are also two options to `ssh-add` that can help reduce the
+risk of someone else with elevated privileges hijacking your agent to make
+use of your ssh credentials.
+
+## Prompt before each use of a key
+
+The first option is `-c` which will require you to confirm each use of your
+ssh key by pressing Enter when a graphical prompt shows up.
+
+Simply install an `ssh-askpass` frontend like
+[ssh-askpass-gnome](https://packages.debian.org/stable/ssh-askpass-gnome):
+
+    apt install ssh-askpass-gnome
+
+and then use this to when adding your key to the agent:
+
+    ssh-add -c ~/.ssh/key
+
+## Automatically removing keys after a timeout
+
+`ssh-add -D` will remove all identities (i.e. keys) from your ssh agent, but
+requires that you remember to run it manually once you're done.
+
+That's where the second option comes in. Specifying `-t` when adding a key
+will automatically remove that key from the agent after a while.
+
+For example, I have found that this setting works well at work:
+
+    ssh-add -t 10h ~/.ssh/key
+
+where I don't want to have to type my ssh password everytime I push a git
+branch.
+
+At home on the other hand, my use of ssh is more sporadic and so I don't
+mind a shorter timeout:
+
+    ssh-add -t 4h ~/.ssh/key
+
+## Making these options the default
+
+I couldn't find a configuration file to make these settings the default and
+so I ended up putting the following line in my `~/.bash_aliases`:
+
+    alias ssh-add='ssh-add -c -t 4h'
+
+so that I can continue to use `ssh-add` as normal and have not remember
+to include these extra options.
+
+[[!tag debian]] [[!tag nzoss]] [[!tag mozilla ]] [[!tag ssh]] [[!tag sysadmin]] [[!tag security]]

Format URLs properly and update a broken one
diff --git a/posts/hardening-ssh-servers/comment_3_34613b0bcc79caefa7dc6e515acdc43f._comment b/posts/hardening-ssh-servers/comment_3_34613b0bcc79caefa7dc6e515acdc43f._comment
index 6306f56..d004250 100644
--- a/posts/hardening-ssh-servers/comment_3_34613b0bcc79caefa7dc6e515acdc43f._comment
+++ b/posts/hardening-ssh-servers/comment_3_34613b0bcc79caefa7dc6e515acdc43f._comment
@@ -7,5 +7,5 @@
  content="""
 You can also use 2facthor auth with ( for example ) google authenticator:
 
-http://www.howtogeek.com/121650/how-to-secure-ssh-with-google-authenticators-two-factor-authentication/
+<http://www.howtogeek.com/121650/how-to-secure-ssh-with-google-authenticators-two-factor-authentication/>
 """]]
diff --git a/posts/hardening-ssh-servers/comment_5_cae71a2bede8405eb29f0b6d8d4bede4._comment b/posts/hardening-ssh-servers/comment_5_cae71a2bede8405eb29f0b6d8d4bede4._comment
index e22c3d0..ed98028 100644
--- a/posts/hardening-ssh-servers/comment_5_cae71a2bede8405eb29f0b6d8d4bede4._comment
+++ b/posts/hardening-ssh-servers/comment_5_cae71a2bede8405eb29f0b6d8d4bede4._comment
@@ -5,5 +5,5 @@
  subject="2FA & cipher restrictions"
  date="2014-09-13T22:04:59Z"
  content="""
-Nice tutorial. I wrote my own recently with a little more focus on Two-Factor Authentication and strong encryption (limiting weak ciphers/MACs) but found your tutorial really strong in the auditing department.  https://joscor.com/2014/09/hardening-openssh-server-ubuntu-14-04/ 
+Nice tutorial. I wrote my own recently with a little more focus on Two-Factor Authentication and strong encryption (limiting weak ciphers/MACs) but found your tutorial really strong in the auditing department.  <https://joscor.com/blog/hardening-openssh-server-ubuntu-14-04/>
 """]]

Fix typo
diff --git a/posts/hardening-ssh-servers.mdwn b/posts/hardening-ssh-servers.mdwn
index 1d5de08..e39622d 100644
--- a/posts/hardening-ssh-servers.mdwn
+++ b/posts/hardening-ssh-servers.mdwn
@@ -120,7 +120,7 @@ by enabling the `pam_tty_audit` module in `/etc/pam.d/sshd`:
 
 However this module is [not included in wheezy](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=699159) and has only recently been [re-added to Debian](http://packages.qa.debian.org/p/pam/news/20131021T001835Z.html).
 
-# Identitying stolen keys
+# Identifying stolen keys
 
 One thing I'd love to have is a way to identify a stolen public key. Given the IP
 restrictions described above, if a public key is stolen and used from a different IP,

Fix invalid dates
diff --git a/posts/checking-your-passwords-against-hibp.mdwn b/posts/checking-your-passwords-against-hibp.mdwn
index adfa2bb..cd6ac83 100644
--- a/posts/checking-your-passwords-against-hibp.mdwn
+++ b/posts/checking-your-passwords-against-hibp.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Checking Your Passwords Against the Have I Been Pwned List"]]
-[[!meta date="2017-10-16T22:10:00:00.000-07:00"]]
+[[!meta date="2017-10-16T22:10:00.000-07:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 Two months ago, Troy Hunt, the security professional behind
diff --git a/posts/mercurial-commit-series-phabricator-using-arcanist.mdwn b/posts/mercurial-commit-series-phabricator-using-arcanist.mdwn
index 746fe80..a1ddc64 100644
--- a/posts/mercurial-commit-series-phabricator-using-arcanist.mdwn
+++ b/posts/mercurial-commit-series-phabricator-using-arcanist.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Mercurial commit series in Phabricator using Arcanist"]]
-[[!meta date="2018-08-01T09:00:00:00.000-07:00"]]
+[[!meta date="2018-08-01T09:00:00.000-07:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 [Phabricator](https://www.phacility.com/phabricator/) supports multi-commit
diff --git a/posts/mysterious-400-bad-request-error-django-debug.mdwn b/posts/mysterious-400-bad-request-error-django-debug.mdwn
index 2c48fd7..cd86245 100644
--- a/posts/mysterious-400-bad-request-error-django-debug.mdwn
+++ b/posts/mysterious-400-bad-request-error-django-debug.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Mysterious 400 Bad Request in Django debug mode"]]
-[[!meta date="2017-06-10T17:20:00:00.000-07:00"]]
+[[!meta date="2017-06-10T17:20:00.000-07:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 While upgrading [Libravatar](https://www.libravatar.org) to a more recent
diff --git a/posts/pristine-tar-and-git-buildpackage-work-arounds.mdwn b/posts/pristine-tar-and-git-buildpackage-work-arounds.mdwn
index 1e801cd..cde2ef8 100644
--- a/posts/pristine-tar-and-git-buildpackage-work-arounds.mdwn
+++ b/posts/pristine-tar-and-git-buildpackage-work-arounds.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="pristine-tar and git-buildpackage Work-arounds"]]
-[[!meta date="2017-08-09T22:25:00:00.000-07:00"]]
+[[!meta date="2017-08-09T22:25:00.000-07:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 I recently ran into problems trying to package the
diff --git a/posts/proxy-acme-challenges-to-single-machine.mdwn b/posts/proxy-acme-challenges-to-single-machine.mdwn
index aa2ebb5..b258617 100644
--- a/posts/proxy-acme-challenges-to-single-machine.mdwn
+++ b/posts/proxy-acme-challenges-to-single-machine.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Proxy ACME challenges to a single machine"]]
-[[!meta date="2017-11-28T22:10:00:00.000-08:00"]]
+[[!meta date="2017-11-28T22:10:00.000-08:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 The [Libravatar mirrors](https://wiki.libravatar.org/run_a_mirror/) are
diff --git a/posts/recovering-from-botched-mercurial-bookmark-histedit.mdwn b/posts/recovering-from-botched-mercurial-bookmark-histedit.mdwn
index a80567d..7cecb5b 100644
--- a/posts/recovering-from-botched-mercurial-bookmark-histedit.mdwn
+++ b/posts/recovering-from-botched-mercurial-bookmark-histedit.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Recovering from a botched hg histedit on a mercurial bookmark"]]
-[[!meta date="2018-07-26T22:42:00:00.000-07:00"]]
+[[!meta date="2018-07-26T22:42:00.000-07:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 If you are in the middle of a failed
diff --git a/posts/test-mail-server-ubuntu-debian.mdwn b/posts/test-mail-server-ubuntu-debian.mdwn
index 6028b53..3fe9f26 100644
--- a/posts/test-mail-server-ubuntu-debian.mdwn
+++ b/posts/test-mail-server-ubuntu-debian.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Test mail server on Ubuntu and Debian"]]
-[[!meta date="2017-11-13T17:30:00:00.000+08:00"]]
+[[!meta date="2017-11-13T17:30:00.000+08:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 I wanted to setup a mail service on a staging server that would send all
diff --git a/posts/time-synchronization-with-ntp-and-systemd.mdwn b/posts/time-synchronization-with-ntp-and-systemd.mdwn
index 84d3841..3f54067 100644
--- a/posts/time-synchronization-with-ntp-and-systemd.mdwn
+++ b/posts/time-synchronization-with-ntp-and-systemd.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Time Synchronization with NTP and systemd"]]
-[[!meta date="2017-08-06T13:10:00:00.000-07:00"]]
+[[!meta date="2017-08-06T13:10:00.000-07:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 I recently ran into problems with generating
diff --git a/posts/tls_authentication_freenode_and_oftc.mdwn b/posts/tls_authentication_freenode_and_oftc.mdwn
index 31f7f1a..02e7506 100644
--- a/posts/tls_authentication_freenode_and_oftc.mdwn
+++ b/posts/tls_authentication_freenode_and_oftc.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="TLS Authentication on Freenode and OFTC"]]
-[[!meta date="2017-09-08T21:50:00:00.000-07:00"]]
+[[!meta date="2017-09-08T21:50:00.000-07:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 In order to easily authenticate with IRC networks such as
diff --git a/posts/toggling-between-pulseaudio-outputs-when-docking-a-laptop.mdwn b/posts/toggling-between-pulseaudio-outputs-when-docking-a-laptop.mdwn
index 696add0..e5434b5 100644
--- a/posts/toggling-between-pulseaudio-outputs-when-docking-a-laptop.mdwn
+++ b/posts/toggling-between-pulseaudio-outputs-when-docking-a-laptop.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Toggling Between Pulseaudio Outputs when Docking a Laptop"]]
-[[!meta date="2017-07-11T22:00:00:00.000-07:00"]]
+[[!meta date="2017-07-11T22:00:00.000-07:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 In addition to
diff --git a/posts/using-all-5ghz-wifi-frequencies-in-gargoyle-router.mdwn b/posts/using-all-5ghz-wifi-frequencies-in-gargoyle-router.mdwn
index d22ff84..c65cae1 100644
--- a/posts/using-all-5ghz-wifi-frequencies-in-gargoyle-router.mdwn
+++ b/posts/using-all-5ghz-wifi-frequencies-in-gargoyle-router.mdwn
@@ -1,5 +1,5 @@
 [[!meta title="Using all of the 5 GHz WiFi frequencies in a Gargoyle Router"]]
-[[!meta date="2017-12-10T18:00:00:00.000-08:00"]]
+[[!meta date="2017-12-10T18:00:00.000-08:00"]]
 [[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
 
 WiFi in the 2.4 GHz range is usually fairly congested in urban environments.

Add screenshot keybindings
https://faq.i3wm.org/question/202/what-do-you-guys-use-for-printscreen.1.html
https://unix.stackexchange.com/questions/497897/print-screen-key-in-i3
diff --git a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
index 5e52f51..4dc4b8e 100644
--- a/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
+++ b/posts/creating-a-modern-tiling-desktop-environment-using-i3.mdwn
@@ -65,7 +65,12 @@ While keyboard shortcuts can be configured in GNOME, they don't work within i3,
     # show battery stats
     bindsym XF86Battery exec gnome-power-statistics
 
-to make volume control, screen brightness and battery status buttons work as expected on my laptop.
+    # interactive screenshot by pressing printscreen
+    bindsym Print exec /usr/bin/gnome-screenshot -i
+    # crop-area screenshot by pressing Mod + printscreen
+    bindsym --release $mod+Print exec /usr/bin/gnome-screenshot -a
+
+to make volume control, screen brightness, battery status and print screen buttons work as expected on my laptop.
 
 These bindings require the following packages or scripts:
 

Revert "Comment moderation"
This reverts spam commit cd974a0dee9553c237b876c75ae21c96f206190c.
diff --git a/posts/test-mail-server-ubuntu-debian/comment_1_8d46bd0fae22e7b429d2e7a93b619a52._comment b/posts/test-mail-server-ubuntu-debian/comment_1_8d46bd0fae22e7b429d2e7a93b619a52._comment
deleted file mode 100644
index b597820..0000000
--- a/posts/test-mail-server-ubuntu-debian/comment_1_8d46bd0fae22e7b429d2e7a93b619a52._comment
+++ /dev/null
@@ -1,9 +0,0 @@
-[[!comment format=mdwn
- ip="46.185.122.180"
- claimedauthor="obazxopsum"
- url="http://theprettyguineapig.com/amoxicillin/"
- subject="Raynaud's generations rickettsial grief malignant re-intervention continuing. "
- date="2019-03-07T15:53:40Z"
- content="""
-http://theprettyguineapig.com/amoxicillin/ - Amoxicillin <a href=\"http://theprettyguineapig.com/amoxicillin/\">Amoxicillin No Prescription</a> http://theprettyguineapig.com/amoxicillin/
-"""]]

Comment moderation
diff --git a/posts/test-mail-server-ubuntu-debian/comment_1_8d46bd0fae22e7b429d2e7a93b619a52._comment b/posts/test-mail-server-ubuntu-debian/comment_1_8d46bd0fae22e7b429d2e7a93b619a52._comment
new file mode 100644
index 0000000..b597820
--- /dev/null
+++ b/posts/test-mail-server-ubuntu-debian/comment_1_8d46bd0fae22e7b429d2e7a93b619a52._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ ip="46.185.122.180"
+ claimedauthor="obazxopsum"
+ url="http://theprettyguineapig.com/amoxicillin/"
+ subject="Raynaud's generations rickettsial grief malignant re-intervention continuing. "
+ date="2019-03-07T15:53:40Z"
+ content="""
+http://theprettyguineapig.com/amoxicillin/ - Amoxicillin <a href=\"http://theprettyguineapig.com/amoxicillin/\">Amoxicillin No Prescription</a> http://theprettyguineapig.com/amoxicillin/
+"""]]

Link to another post on how to secure OpenVPN
diff --git a/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn b/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn
index 8013d6c..3f373f3 100644
--- a/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn
+++ b/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn
@@ -95,7 +95,7 @@ Then I took the official configuration template:
     cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
     gunzip /etc/openvpn/server.conf.gz
 
-and set the following in `/etc/openvpn/server.conf` (which includes recommendations from [BetterCrypto.org](https://bettercrypto.org/)):
+and set the following in `/etc/openvpn/server.conf` (which includes recommendations from [BetterCrypto.org](https://bettercrypto.org/) and [Gert van Dijk](https://blog.g3rt.nl/openvpn-security-tips.html)):
 
     dh dh2048.pem
     push "redirect-gateway def1 bypass-dhcp"

creating tag page tags/sccache
diff --git a/tags/sccache.mdwn b/tags/sccache.mdwn
new file mode 100644
index 0000000..f8d7fbd
--- /dev/null
+++ b/tags/sccache.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged sccache"]]
+
+[[!inline pages="tagged(sccache)" actions="no" archive="yes"
+feedshow=10]]

creating tag page tags/brave
diff --git a/tags/brave.mdwn b/tags/brave.mdwn
new file mode 100644
index 0000000..d3b44d6
--- /dev/null
+++ b/tags/brave.mdwn
@@ -0,0 +1,4 @@
+[[!meta title="pages tagged brave"]]
+
+[[!inline pages="tagged(brave)" actions="no" archive="yes"
+feedshow=10]]

Add sccache seeding post for brave-browser
diff --git a/posts/seeding-brave-browser-sccache.mdwn b/posts/seeding-brave-browser-sccache.mdwn
new file mode 100644
index 0000000..ea742c1
--- /dev/null
+++ b/posts/seeding-brave-browser-sccache.mdwn
@@ -0,0 +1,60 @@
+[[!meta title="Seeding sccache for Faster Brave Browser Builds"]]
+[[!meta date="2019-03-22T16:25:00.000-07:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+[Compiling the
+Brave Browser](https://github.com/brave/brave-browser/wiki#build-brave)
+(based on [Chromium](https://www.chromium.org/Home)) on Linux can take a
+really long time and so most developers use
+[sccache](https://github.com/brave/brave-browser/wiki/sccache-for-faster-builds)
+to cache objects files and speed up future re-compilations.
+
+Here's the cronjob I wrote to seed my local cache every work day to
+pre-compile the latest builds:
+
+    30 23 * * 0-4   francois  /usr/bin/chronic /home/francois/bin/seed-brave-browser-cache
+
+and here are the contents of that script:
+
+    #!/bin/bash
+    set -e
+    
+    # Set the path and sccache environment variables correctly
+    source ${HOME}/.bashrc-brave
+    export LANG=en_CA.UTF-8
+    
+    cd ${HOME}/devel/brave-browser-cache
+    
+    echo "Environment:"
+    echo "- HOME = ${HOME}"
+    echo "- PATH = ${PATH}"
+    echo "- PWD = ${PWD}"
+    echo "- SHELL = ${SHELL}"
+    echo "- BASH_ENV = ${BASH_ENV}"
+    echo
+    
+    echo $(date)
+    echo "=> Update repo"
+    git pull
+    npm install
+    npm run init
+    
+    echo $(date)
+    echo "=> Delete any old build output"
+    rm -rf src/out
+    
+    echo $(date)
+    echo "=> Debug build"
+    ionice nice timeout 4h npm run build
+    echo
+    
+    echo $(date)
+    echo "=>Release build"
+    ionice nice timeout 5h npm run build Release
+    echo
+    
+    echo $(date)
+    echo "=> Delete build output"
+    rm -rf src/out
+
+[[!tag brave]] [[!tag sccache]]

Turn on DNS rebinding protection
diff --git a/posts/setting-up-your-own-dnssec-aware.mdwn b/posts/setting-up-your-own-dnssec-aware.mdwn
index 8eb5a06..a33321c 100644
--- a/posts/setting-up-your-own-dnssec-aware.mdwn
+++ b/posts/setting-up-your-own-dnssec-aware.mdwn
@@ -20,6 +20,15 @@ In `/etc/unbound/unbound.conf.d/francois.conf`, I enabled the following security
         use-caps-for-id: no # makes lots of queries fail
         hide-identity: yes
         hide-version: yes
+        private-address: 10.0.0.0/8
+        private-address: 100.64.0.0/10
+        private-address: 127.0.0.0/8
+        private-address: 169.254.0.0/16
+        private-address: 172.16.0.0/12
+        private-address: 192.168.0.0/16
+        private-address: fc00::/7
+        private-address: fe80::/10
+        private-address: ::ffff:0:0/96
 
 and turned on prefetching to hopefully keep in cache the sites I visit regularly:
 

Add another Asterisk post
diff --git a/posts/connecting-voip-phone-directly-to-asterisk-server.mdwn b/posts/connecting-voip-phone-directly-to-asterisk-server.mdwn
new file mode 100644
index 0000000..61280da
--- /dev/null
+++ b/posts/connecting-voip-phone-directly-to-asterisk-server.mdwn
@@ -0,0 +1,62 @@
+[[!meta title="Connecting a VoIP phone directly to an Asterisk server"]]
+[[!meta date="2019-02-28T22:25:00.000-08:00"]]
+[[!meta license="[Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)"]]
+
+On my [Asterisk](https://www.asterisk.org/) server, I happen to have two
+on-board ethernet boards. Since I only used one of these, I decided to move
+my VoIP phone from the local network switch to being connected directly to
+the Asterisk server.
+
+The main advantage is that this phone, running proprietary software of
+unknown quality, is no longer available on my general home network. Most
+importantly though, it no longer has access to the Internet, without my
+having to firewall it manually.
+
+Here's how I configured everything.
+
+# Private network configuration
+
+On the server, I started by giving the second network interface a static IP
+address in `/etc/network/interfaces`:
+
+    auto eth1
+    iface eth1 inet static
+        address 192.168.2.2
+        netmask 255.255.255.0
+
+On the VoIP phone itself, I set the static IP address to `192.168.2.3` and
+the DNS server to `192.168.2.2`. I then updated the SIP registrar IP address
+to `192.168.2.2`.
+
+The DNS server actually refers to an [unbound
+daemon](https://feeding.cloud.geek.nz/posts/setting-up-your-own-dnssec-aware/)
+running on the Asterisk server. The only configuration change I had to make
+was to listen on the second interface and allow the VoIP phone in:
+
+    server:
+        interface: 127.0.0.1
+        interface: 192.168.2.2
+        access-control: 0.0.0.0/0 refuse
+        access-control: 127.0.0.1/32 allow
+        access-control: 192.168.2.3/32 allow
+
+Finally, I opened the right ports on the server's firewall in
+`/etc/network/iptables.up.rules`:
+
+    -A INPUT -s 192.168.2.3/32 -p udp --dport 5060 -j ACCEPT
+    -A INPUT -s 192.168.2.3/32 -p udp --dport 10000:20000 -j ACCEPT
+
+# Accessing the admin page
+
+Now that the VoIP phone is no longer available on the local network, it's
+not possible to access its admin page. That's a good thing from a security
+point of view, but it's somewhat inconvenient.
+
+Therefore I put the following in my `~/.ssh/config` to make the admin page
+available on `http://localhost:8081` after I connect to the Asterisk server
+via ssh:
+
+    Host asterisk
+        LocalForward 8081 192.168.2.3:80
+
+[[!tag debian]] [[!tag asterisk]] [[!tag nzoss]] [[!tag ubuntu]]

Make a note on how to prevent the CRL from expiring early
https://forums.openvpn.net/viewtopic.php?t=23166
diff --git a/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn b/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn
index fa0c8ec..8013d6c 100644
--- a/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn
+++ b/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu.mdwn
@@ -58,7 +58,15 @@ Create this symbolic link:
 
     ln -s openssl-1.0.0.cnf openssl.cnf
 
-and generate the keys:
+and set the following in `openssl.cnf`:
+
+    default_crl_days= 3650
+
+to avoid having the [CRL expire after one month](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=849909) and throw this error in the logs:
+
+    VERIFY ERROR: depth=0, error=CRL has expired:
+
+Finally, generate the keys:
 
     . ./vars
     ./clean-all

Add another DNSSEC test page
I found it here: https://github.com/bsclifton/home-router-config/commit/8241ba2e51291a3de3e703d277a1aba591cd2417#diff-a87b1e8c9fb22c6cce19716353a4a989R26
diff --git a/posts/setting-up-your-own-dnssec-aware.mdwn b/posts/setting-up-your-own-dnssec-aware.mdwn
index 727b27d..8eb5a06 100644
--- a/posts/setting-up-your-own-dnssec-aware.mdwn
+++ b/posts/setting-up-your-own-dnssec-aware.mdwn
@@ -94,6 +94,7 @@ Once everything is configured properly, the best way I found to test that this s
 
   * [http://www.dnssec.cz/](http://www.dnssec.cz/) should show a green key
   * [http://www.rhybar.cz/](http://www.rhybar.cz/) should not be reachable
+  * <https://dnssec.vs.uni-due.de/>
 
 and using dig: