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 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.

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 -j ACCEPT
iptables -A OUTPUT -d -j ACCEPT
iptables -A INPUT -s -j ACCEPT
iptables -A OUTPUT -d -j ACCEPT
#multicast for minidlna/SSSP
iptables -I OUTPUT -d -j ACCEPT
iptables -I INPUT -d -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 \
 -dBATCH \

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.

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.

Web pages are 60-70% ads nowadays

Categories: Uncategorized

Here’s a screenshot of a typical web page, highlighting the actual content and how much of the page are actually ads and unrelated stuff. (Click on the scaled image to see a larger version but I warn you it’s quite long).

Holy canoli

KVM bridged to the LAN with DHCP

Categories: English Geeky Uncategorized

The goal here is to instantiate VMs with a br0 interface grabbing an IP from the LAN DHCP, so in turn the VM can instantiate LXD containers whose IP is also exposed to the LAN. That way everything is visible on the same network segment and this makes some experimentation easier.

Host configuration

Some info taken from this URL.

The metal host is running Ubuntu 18.04, which uses netplan. Here’s the netplan.yaml file:

            addresses: []
            dhcp4: no
            dhcp6: no
            optional: true
            dhcp4: true
            dhcp6: no
                - enp7s0
                stp: false
                forward-delay: 0
    version: 2

With this, on boot the system grabs an address from the network’s DHCP service (from my home router) and puts it on the br0 interface (which bridges enp7s0, a Gigabit Ethernet port).

The system also has avahi-daemon installed so I can ssh the-server.local easily.

VM configuration

Next, the VM which I created using uvt-kvm:

# Get a Xenial cloud image
uvt-simplestreams-libvirt --verbose sync release=xenial arch=amd64
# Create/launch a VM
PARAMS='--memory 8192 --disk 32 --cpu 4'
uvt-kvm create the-vm  $PARAMS --bridge br0 --packages avahi-daemon,bridge-utils,haveged --run-script-once

The script takes care of setting up the network 🙂 This can more cleanly be done with cloud-init but I’m lazy and wanted something fast.

The script deletes the cloudconfig-created .cfg file, tells cloud-init to NOT reconfigure the network, and drops the config file I actually need in place.


echo "Acquire::http::Proxy \"\"; " >/etc/apt/apt.conf.d/80proxy

# Drop the cloudinit-configured interface
ifdown ens3

# Reconfigure the network...
cat <<EOF >/etc/network/interfaces.d/1-bridge.cfg
auto lo br0

iface lo inet loopback

iface ens3 inet manual

iface br0 inet dhcp
    bridge_ports ens3
    bridge_stp off       # disable Spanning Tree Protocol
    bridge_waitport 0    # no delay before a port becomes available
    bridge_fd 0          # no forwarding delay

echo "network: {config: disabled}" > /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
rm /etc/network/interfaces.d/50-cloud-init.cfg

# Then bring up the new nice bridge
ifup br0

apt-get remove -y snapd && apt-get -y autoremove

The network config in /etc/network/interfaces.d/1-bridge.cfg should look like:

auto lo br0

iface lo inet loopback

iface ens3 inet manual

iface br0 inet dhcp
    bridge_ports ens3
    bridge_stp off       # disable Spanning Tree Protocol
    bridge_waitport 0    # no delay before a port becomes available
    bridge_fd 0          # no forwarding delay

LXD configuration

Finally,  install lxd. When asked to configure the lxd bridge, respond “no”, and on the next question you’ll be asked whether to supply an existing bridge. Respond “yes” and specify “br0”.

Now, when an lxd container is instantiated, it’ll by default appear on the same network (the home network!) as the VM and the main host, getting its DHCP from the home router.

When things break

Suddenly the bridge interface stopped working. I checked this to help diagnose it. But that wasn’t it. Turns out, I’d installed Docker on the main host and Docker messes with the firewall configuration by setting iptables -P FORWARD DROP. I just set it back to ACCEPT to get it working.

Buying a house in Montreal – Getting a realtor

Categories: House buying Uncategorized

After visiting the mortgage broker and getting an idea of how much we can afford (oh I just found this link with some very sensible advice on how much you can afford), I wanted to go looking for a realtor to help me wade through the house-buying process. When I mentioned I didn’t yet have one, the mortgage broker offered to refer me to an agency. Sure enough, a few days later I got a call from a realtor who asked about my basic needs and signed me up for Centris, the Quebec equivalent of MLS.

The realtor enters your search criteria, such as price range, number of bedrooms/bathrooms, type of construction, desired neighborhoods and some other features. Then the system will e-mail you when new listings are published. Supposedly you’ll have access to “pre-listings”, but in practice I’ve been able to see the same listings that are published in

However, the Realtor-managed site does show a lot of additional information, like more detail on the rooms, better data on building/lot areas, and very importantly, information about closing dates, which may even influence the interest rate you’ll get for the loan.

Additionally, I sent my realtor a list we wrote with the requirements we had for a property. We indicated general building requirements, possible locations, and other wishlist items such as “no creepy basements”, closeness to parks, river and amenities, distance to public transport and so on. She thought this was quite useful to fine-tune the criteria, although since the process is mechanized, there are some criteria the system is not able to verify (e.g. no concept of creepiness on basements).

Keep in mind that the data captured in Centris may be inaccurate, and that could affect the results of filtering. Example: initially we specified we wanted to have a driveway (though not necessarily a garage) and there were very few listings. After we removed the driveway criteria, a lot more popped up, and a lot of them did have driveways! The issue here is that the listing brokers didn’t capture that information. So try to make your criteria as broad as possible, and do part of the filtering yourself, when going through the listings.

Another example: we wanted two bathrooms (even if one of them is a half-bathroom with no shower), but if you ask the system for 2 bathrooms, sometimes it doesn’t consider halfs in the criteria. So even though it’s super important for us, we decided to leave this criteria out and are focusing on visually checking for a second bathroom and/or possibility of building one.

Once listings start landing in my inbox, we compiled a list of houses we wanted to visit and told the realtor about them.

Weechat trigger sounds based on specific keywords

Categories: Uncategorized

Weechat used to require some weird perl scripts to trigger on specific conditions, but since version 1.1 (from 2014) a trigger plugin can do all that without needing an external script.

This will create a trigger that runs a command when a specific word (or words) is mentioned in any channel you’re on:

/trigger addreplace warningword signal *,irc_in2_PRIVMSG "${message_without_tags} =~ (danger will robinson|stop the line|help me)" "" "/exec -bg /usr/bin/paplay /usr/share/sounds/ubuntu/notifications/Positive.ogg

Vegan picadillo

Categories: Uncategorized

Vegan picadillo, served with fried white basmati rice

Picadillo is a traditional Mexican recipe, usually made with minced meat.  Seitan, however, makes a great substitute for minced meat, and since most of picadillo’s flavor comes from the sauce and reduction process, the flavor stays mostly similar.


  • Half a kg of Seitan (here’s the best recipe we’ve found – can be made well in advance as it keeps nicely in the fridge).
  • One large potato, diced
  • Two large carrots, diced
  • One cup cooked green peas
  • Two cups of vegetable broth
  • Two or three tomatoes (about 500g worth)
  • Two garlic cloves, finely chopped
  • One quarter onion, finely chopped
  • 1 teaspoon olive oil

Serves 6-8.

How to make:

Mince the seitan: Chop it into small dice, then run in small batches through a food processor on high, until you get a size similar to cooked, minced meat.

Prepare the sauce: Put the tomatoes, garlic and broth in the blender, blend for 1 minute or until smooth.

Do the thing: On a large (5L or more) pot, fry the onion with the olive oil until transparent. Once fried, dump the seitan, potato and carrot dice in the pot, dump the sauce and stir (it should initially look like a stew – if it’s drier, make some more sauce and add it to the pot). Set the heat to medium-high, bring the mixture to a boil and let simmer until the liquid is consumed and the carrots and potatoes are soft. BEWARE, there’ll come a point where you will need to start stirring to avoid burning the bottom part of the stew. This will happen even if the top seems to have enough liquid, so keep an eye on it. It should take 20-25 minutes to evaporate the sauce to the desired consistency.

When done, stir in the already-cooked green peas (so they remain firm, if you cook them in the stew they’ll go mushy).

Serve with white or red rice, or with corn tortillas.