Generating Secure Passphrases on the Command Line

The following snippet should work on every system that has coreutils.

$ shuf /usr/share/dict/words --repeat --random-source /dev/random -n 5

You can swap /usr/share/dict/words with any good word list, like EFF’s or Arnold Reinhold’s Diceware list.

You can also add it to your ~/.bash_aliases for ease of use:

alias passphrase="shuf ~/dotfiles/misc/diceware8k.txt --repeat --random-source /dev/random -n"

Then you can easily use it in bash:

$ passphrase 5
notch
kane
to
drag
cater

Migrating from WP-Syntax to PrismJS

WP-Syntax was a great syntax-highlighting plugin for WordPress. However, development had ceased, and it had not been updated for a very long time. While it is not broken per se, it didn’t work with Jetpack’s markdown support, so I stopped using it on the site and started using a different plugin. With the introduction of the Gutenberg editor, I started looking again for a plugin that would allow me to easily highlight fenced code blocks (this feature worked in the old editor with SyntaxHighlighter Evolved but isn’t supported in Gutenberg). Realizing that I don’t want three syntax-highlighting plugins enabled simultaneously, and not wanting to have an abandoned plugin enabled, I decided to migrate all the posts from WP-Syntax to a new solution.

The new solution I chose was PrismJS. I decided to use it directly (without a plugin), as it highlights by default all the <pre><code class="language-..."> constructs (which is what markdown produces as well), and I didn’t want (yet again) to use plugin-specific shortcodes like before, which would require migration when the plugin eventually stops working.

WP-Syntax used the <pre lang="...">code goes here</pre> construct. Furthermore, it took care of HTML-escaping everything inside the <pre> tag. So the migration solution would be to rewrite the <pre> tags to <pre><code> constructs, HTML-escape the code inside the pre tag, and finally remove any leading newlines. I wrote it to work on dumped SQL tables, as that seemed easiest. The flow is

$ mysqldump --add-drop-table -u USER -p blog wp_comments > wp_posts.sql
$ python3 < wp_posts.sql > wp_posts_updated.sql
$ mysql --user=USER --password blog < /tmp/wp_posts_updated.sql
#!/usr/bin/python3

import re
import html
import sys

def convert(fin, fout):
    for line in fin:
        # Each post is in a single line
        # <pre><code> doesn't ignore the first newline like <pre>
        replaced = re.sub(r'<pre lang="(.*?)">(?:r)?(?:n)?(.*?)</pre>', replace_and_escape, line)
        print(replaced)
        if line != replaced:
            print(line, replaced, sep="n============>n", file=sys.stderr)


def replace_and_escape(matchobj):
    language = matchobj.group(1)
    # We don't escape quotes because it's unnecessary and it would mess up the
    # SQL escaping
    content = html.escape(matchobj.group(2), quote=False)
    return r'<pre><code class="language-{}">{}</code></pre>'.format(language, content)


if __name__=='__main__':
    convert(sys.stdin, sys.stdout)

Disable YubiKey’s OTP

By default, when you touch a YubiKey it types an OTP code. These codes look like:

cccjgjgkhcbbirdrfdnlnghhfgrtnnlgedjlftrbdeut

Theoretically they are used for Yubico’s proprietary authentication, but in reality they are mostly annoying. This is especially true for the YubiKey Nano, which is impossible to remove without touching it and triggering the OTP.

YubiKey 5 Nano

Disabling the OTP is possible using the YubiKey Manager, and does not affect any other functionality of the YubiKey.

$ sudo apt install yubikey-manager
$ ykman config usb --disable otp
Disable OTP.
Configure USB interface? [y/N]: y

Note for YubiKey 4: the above command will not work and will fail with the following error:

Error: Configuring applications is not supported on this YubiKey. Use the `mode` command to configure USB interfaces.

Instead, use the following command:

$ ykman mode FIDO+CCID
Set mode of YubiKey to FIDO+CCID? [y/N]: y
Mode set! You must remove and re-insert your YubiKey for this change to take effect.

virt-manager: Error Starting Domain

Virtual Machine Manager (virt-manager) doesn’t automatically start your virtual networks. This leads to the following error when starting a virtual machine:

Error starting domain: Requested operation is not valid: network 'default' is not active

To solve this error, in Virtual Machine Manager go to Edit->Connection Details->Virtual Networks, select the required network (‘default’ in our case), and press the Start Network button (it has a play-button icon). You can avoid having to go through this process by ticking the Autostart checkbox, which will make the network start automatically at boot.

Resizing Huge Panoramas for Google Photos

Google Photos imposes a 100 megapixel limit on uploaded photos. This may sound like a lot, as even the very high-end Sony Alpha a7R III has “only” a 48MP sensor, but in reality, when you shoot panoramas and stitch them yourself, you can quickly get there and hit the 100MP limit. When you try to upload your huge panorama to Google Photos, you will get a

A photo or video was skipped

error.

To solve it, you need to resize your image and make it smaller. This can be done automatically using ImageMagick’s convert:

$ convert -resize "100000000@>" panorama-in.jpg panorama-out.jpg

This will resize panorama-in.jpg to at most 100MP, and save it as panorama-out.jpg. The > makes sure we will only downsize larger photos.

By default, under Debian, ImageMagick comes with a very strict `policy.xml` controlling the resources it can use. Practically, this means that unless you change those limits, you’ll encounter resource limit errors such as:

convert-im6.q16: width or height exceeds limit `panorama-in.jpg' @ error/cache.c/OpenPixelCache/3802.

To solve it, you will need to edit /etc/ImageMagick-6/policy.xml and increase the limits for memory, width, height, and area. For example:

  <policy domain="resource" name="memory" value="8GiB"/>
  <policy domain="resource" name="width" value="128KB"/>
  <policy domain="resource" name="height" value="128KB"/>
  <policy domain="resource" name="area" value="8GB"/>

OpenVPN server fails to start on Debian Stretch

After a recent upgrade to Debian Stretch, my OpenVPN server stopped working. Checking the relevant log file, /var/log/openvpn.log, I found the following not-very-helpful error message.

Fri Nov 23 16:46:37 2018 OpenVPN 2.4.0 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Jul 18 2017
Fri Nov 23 16:46:37 2018 library versions: OpenSSL 1.0.2l  25 May 2017, LZO 2.08
Fri Nov 23 16:46:37 2018 daemon() failed or unsupported: Resource temporarily unavailable (errno=11)
Fri Nov 23 16:46:37 2018 Exiting due to fatal error

Fortunately, someone had already reported this error to Debian and found out that the error is caused by the

LimitNPROC=10

in /lib/systemd/system/openvpn@.service. The LimitNPROC directive in systemd is used to limit the number of forks a service is allowed to make. Removing this limit might not be the best idea, so I would suggest that instead of commenting it out, you find the minimal value that allows OpenVPN to start and work. After some testing, I found that the minimal value that worked for me is

LimitNPROC=27

After editing /lib/systemd/system/openvpn@.service, you need to reload the systemd service files and restart the OpenVPN server process.

$ sudo systemctl daemon-reload
$ sudo systemctl restart openvpn@server

Getting Radeon RX 550 to work under Debian Stretch

There are three things that need to be updated in Debian Stretch in order to get the Radeon RX 550 running properly (or at all): kernel, Mesa, and proprietary binary firmware (bummer, I know).

First, make sure you have stretch-backports in your apt sources with all the relevant components.

$ deb http://ftp.debian.org/debian stretch-backports main contrib non-free

Now, the kernel that currently comes with Stretch (4.9.0-8) is missing some important configurations: CONFIG_DRM_AMDGPU_SI and CONFIG_DRM_AMDGPU_CIK. So you will need to install the latest one from the backports, which does have the correct configuration.

$ sudo apt install -t stretch-backports linux-image-amd64

Next is getting the proper firmware.

$ sudo apt install -t stretch-backports firmware-linux-nonfree

This will also update the firmware-amd-graphics, which provides the binary blobs that are needed by the amdgpu driver to work properly. The old version does not support the new Polaris 12 architecture used by the RX 550, while the version from the backports (20180825) does support Polaris 12.

Now comes the part of upgrading Mesa. There are a bunch of binary packages that are derived from the Mesa source package, and we need to upgrade each one of them to version 18 (or later, but 18 is what is provided by the backports). The following two commands will upgrade any Mesa-related package already installed and then re-mark them as automatically installed (just to keep things tidy as they were).

sudo apt install -t stretch-backports $(grep-status -S mesa -a -FStatus "install ok installed" -s Package -n | sort -u)
sudo apt-mark auto $(grep-status -S mesa -a -FStatus "install ok installed" -s Package -n | sort -u)

(credit for the last two lines). Now you can restart your computer, and the RX 550 should work. You can test it using

$ DRI_PRIME=1 glxinfo | grep OpenGL
OpenGL vendor string: X.Org
OpenGL renderer string: Radeon 500 Series (POLARIS12, DRM 3.26.0, 4.18.0-0.bpo.1-amd64, LLVM 6.0.0)
OpenGL core profile version string: 4.5 (Core Profile) Mesa 18.1.6

The DRI_PRIME=1 is necessary; otherwise, glxinfo would use the integrated card.

This is not necessary, but if lspci does not properly display the RX 550, you will need to update the PCI IDs that are used to translate IDs to actual human-readable names.

$ sudo update-pciids

Final word: if you are using TLP for power management, it may not play nice with the RX 550. With TLP enabled, I get pretty horrible performance out of it (regardless of whether it’s on AC or battery).

Sharing a folder on a Windows guest under virt-manager

Sharing data between guest and host systems is necessary in many scenarios. If the guest is a Linux system, you can simply add a shared folder that will be automatically mounted. However, this does not work if the guest is Windows. Sometimes, you can simply work around it by using Samba shares, but in some scenarios the network configuration makes it difficult. For example, when using usermode networking, the host machine can’t easily communicate with the guest via the network.

However, there is another way to share folders in virt-manager that actually works for a Windows guest – SPICE. The first step is to configure the sharing in virt-manager. In the VM details view, click on “Add Hardware” and select a “Channel” device. Set the new device name to org.spice-space.webdav.0 and leave the other fields as-is.

Now start the guest machine and install spice-webdav on it. After installing spice-webdav, make sure the “Spice webdav proxy” service is actually running (via services.msc).

Now, running C:Program FilesSPICE webdavdmap-drive.bat will map the shared folder, which is by default ~/Public. If you encounter the following error:

System error 67 has occurred.

the network name cannot be found

It means that the Spice webdav proxy service is not running.

If you want to change the shared folder, you will have to use virt-viewer instead of virt-manager and configure it under File->Preferences.