Hugo Conversion

I finally bit the bullet and decided to get rid of wordpress, after 16 years. There’s no benefit for my personal blog to be running a dynamic platform, I don’t have any users, or dynamic content, and comments which might be the main attraction are not something I really use.

I still need to figure out how to replace the dynamic contact form, though.

To achieve this, I initially tried to follow the Hugo tutorial, but it really only described a very incomplete set of basics. I had more luck with this other tutorial, and the theme they recommend actually has some interesting sample posts that describe how to create a hugo theme.

I also looked at this to figure out some intricacies of markdown image rendering.

I’ll continue migrating content to the new site, and running both in parallel until ready to switch.

TIL - Python f-string expression value

There’s a python module called icecream which provides a nice ic() function to print an expression and its value, but in a discussion about it I learned that a quick equivalent can be achieved by using Python f-strings (available since Python 3.6) and appending “=” to the variable name:

>>> print(f"{d['key'][1]=}")
d['key'][1]='one'

new minidlna server broke my network

Categories: Uncategorized

We added a new device which can expose a connected USB drive via DLNA, internally it uses minidlna which uses SSDP for service discovery. For some strange reason that rendered my *existing* minidlna (hosted on a raspberry pi) invisible. When researching the problem, it looks like neighbor discovery (which didn’t happen before as there were no other devices) uses a multicast 239.0.0.0/8 address which my rpi was blocking due to reasons (only allows traffic via the local network and a vpn gateway). My theory is that the new minidlna device took over as “primary” and then couldn’t find other peers and so the old server wasn’t visible anymore. The solution was to allow the specific multicast address used by SSDP.

#!/bin/bash
iptables -F
#Tunnel interface
iptables -A INPUT -i tun+ -j ACCEPT
iptables -A OUTPUT -o tun+ -j ACCEPT
#Localhost and local networks
iptables -A INPUT -s 127.0.0.0/16 -j ACCEPT
iptables -A OUTPUT -d 127.0.0.0/16 -j ACCEPT
iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.0/16 -j ACCEPT
#multicast for minidlna/SSSP
iptables -I OUTPUT -d 239.255.255.250 -j ACCEPT
iptables -I INPUT -d 239.255.255.250 -j ACCEPT
#Allow VPN establishment, this is the port in the config's #remote
iptables -A OUTPUT -p udp --dport 1198 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p udp --sport 1198 -m state --state ESTABLISHED,RELATED -j ACCEPT
#Drop everything else
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP

convert color pdf to monochrome

Categories: Uncategorized
gs \
 -sOutputFile=output.pdf \
 -sDEVICE=pdfwrite \
 -sColorConversionStrategy=Gray \
 -dProcessColorModel=/DeviceGray \
 -dCompatibilityLevel=1.4 \
 -dNOPAUSE \
 -dBATCH \
 input.pdf

Jump Bike invasion in Montreal and why Uber sucks

Categories: Uncategorized

As Uber’s Jump electric bike offering arrives in Montreal, a very common sight starts appearing: Orange Jump bikes parked everywhere: in parks, on sidewalks, tied to private property or public structures, sometimes blocking the way for pedestrians.

Lalala
Bad parking spot, blocks the sidewalk, out-of-area

Uber’s permit stipulates that bikes have to be parked in designated spots only; a “designated spot” is a bike rack, not any random pole or fence. Of course, users park where convenient, and of course, Uber always washes their hands from any responsibility by claiming “it’s the user’s responsibility to park bikes in the appropriate spot”. Yet, for all their billions of dollars and technology, they are unwilling to enforce in any way compliance with the permit the city has granted.

I say “unwilling” because it’s entirely feasible to use technology to ensure compliance. I gave this some thought and came up with at least 3 solutions in 5 minutes. The solutions use technologies that are well within Uber’s reach and areas of expertise. They could locate and identify the allowed parking spots and areas and disallow releasing a bike unless it’s properly parked, which can be done either by analyzing Google Street View imagery (using AI, with which Uber is quite adept), sending a human to actually note locations of valid parking structures, or using AI to identify common and likely parking spots, based on density and frequency of bikes parked nearby.

Interestingly, a much smaller company (Lime, the electric scooters) has also just arrived in Montreal, with similar restrictions as to where scooters can be parked. They came up with yet another solution: upon finishing a ride, one must take a picture of the scooter, showing it is correctly parked in a designated area, and upload it.

Another one yay
Another one yay

That very simple solution is easy and cheap to implement, and it keeps users honest while ensuring everyone complies with the conditions set by the city. Honesty, however, is something that escapes Uber; it’s been shown time and time again that they will do the bare minimum necessary, and sometimes not even that if they perceive that the level of enforcement will allow them to get away with just shifting blame to users.

In my opinion, the city should mandate that Uber implement measures to curb badly-parked bicycles, seize badly-parked bikes and impose hefty fines on each one that is found, and ultimately (because these measures will NOT make Uber relent), just rescind their permit. A predatory, disrespectful company like Uber should NOT be allowed to operate in our city.

Using virsh to add a volume (disk) to an existing vm

Categories: English Geeky

I have a second hard disk mounted under /thepool, and I want to make “virtual disks” in there and be able to mount them on any of my virsh-defined virtual machines.

The root filesystem of the VM resides on a different storage pool (uvtool) on a fast SSD, but for bulk storage I don’t want to fill out the SSD with crap.

# Create the storage pool, under "/thepool" where the big disk is mounted
virsh pool-define-as disk-pool dir - - - - "/thepool/libvirt-pool/"
virsh pool-build disk-pool
virsh pool-autostart disk-pool
virsh pool-start disk-pool
# CHeck it's there
virsh pool-list
# Create a volume inside the pool, qcow2 format
virsh vol-create-as disk-pool juju-zfs-pool.qcow2 64G --format qcow2
# Attach it to the VM
virsh attach-disk juju /thepool/libvirt-pool/juju-zfs-pool.qcow2  vdc --persistent  --subdriver=qcow2
# Now inside the vm, /dev/vdc exists and can be formatted/partitioned and mounted as normal

Converting only one stream in a mkv file.

Categories: English Geeky

These mkv files have h.265 hevc video which my media player can’t read, so I’d like to convert only the video stream to h.264, while leaving all other streams (2 audio tracks in aac, 2 subtitle tracks) intact.

ffmpeg -i some-x265-video.mkv -map 0 -c:v libx264 -c:a copy /tmp/x264-version.mkv

Cross-timezone date calculations using the “date”command

Categories: English Geeky

Working remotely for a timezone-distributed company poses an interesting challenge: that of having to figure out dates and times for people in different timezones. This involves not only the relatively trivial “what time is it now in A_FARAWAY_PLACE”, but “what time, in FARAWAY_PLACE_X, will it be in FARAWAY_PLACE_Z” and other fun things.

There are a handful of websites that have handy tools to do these conversions for you; but a problem I’ve found is that the web is going to the crapper, and these sites often have confusing UIs concocted by some javascript-crazed, CSS-infected webmonkey; and often they are completely swamped and rendered unusable by a rising tide of ads and other aggressive content (oh and some won’t let you do anything until you agree to them storing information in cookies in your browser – which they then bafflingly don’t use to store the PREFERENCE you have selected , so like a forgetful vampire, they ask you every single time if you want to accept their silly cookies).

I’ve known how to use the date command to show the date on a different place/timezone, which is already a huge timesaver:

$ TZ="Taiwan/Taipei" date
Fri Apr 12 19:25:31 Taiwan 2019

but – today I was trying to answer “what time in TZ=”America/Chicago” is 1 PM, on Tuesday, in “UK/London“. This is interesting because it’s conversion between two timezones which are not the one I’m in, of a date/time in the future. So I was checking date’s man page for “how to convert a specific point in time”, when I realized date can do this for you! Right in the man page there’s this example:

Show the local time for 9AM next Friday on the west coast of the US

$ date --date='TZ="America/Los_Angeles" 09:00 next Fri'

so then I combined that with the earlier one to come up with:

$ TZ="America/Chicago" date --date='TZ="UK/London" 1:00 PM next Tue'
Tue Apr 16 08:00:00 CDT 2019

This combines:

  • TZ argument to calculate dates for a specific timezone, not the current one
  • --date parameter to “display time described by STRING, not ‘now’”
  • Descriptive time specifications (1:00 PM next Tuesday – this is a pseudo-human-readable format which is not entirely intuitive – info date has the specifics)
  • TZ support inside the descriptive specification

And a list of known timezones can be obtained with timedatectl list-timezones.