words of wisdom from a systems engineer

Running Home Assistant in a Docker container with a Z-Wave USB stick

The Home Assistant project provides a great open source way to get started with home automtion that can be entirely self-contained within your home. It already has plenty of integrations with external services, but it can also monitor Z-Wave devices at your home or office.

Here are my devices:

Install the Z-Wave stick

Start by plugging the Z-Stick into your Linux server. Run lsusb and it should appear in the list:

# lsusb | grep Z-Stick
Bus 003 Device 006: ID 0658:0200 Sigma Designs, Inc. Aeotec Z-Stick Gen5 (ZW090) - UZB

The system journal should also tell you which TTY is assigned to the USB stick (run journalctl --boot and search for ACM):

kernel: usb 3-3.2: USB disconnect, device number 4
kernel: usb 3-1: new full-speed USB device number 6 using xhci_hcd
kernel: usb 3-1: New USB device found, idVendor=0658, idProduct=0200, bcdDevice= 0.00
kernel: usb 3-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
kernel: cdc_acm 3-1:1.0: ttyACM0: USB ACM device
kernel: usbcore: registered new interface driver cdc_acm
kernel: cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

In my case, my device is /dev/ttyACM0. If you have other serial devices attached to your system, your Z-Stick may show up as ttyACM1 or ttyACM2.

Using Z-Wave in the Docker container

If you use docker-compose, simply add a devices section to your existing YAML file:

version: '2'
      - "8123:8123/tcp"
    network_mode: "host"
      - /dev/ttyACM0
      - /etc/localtime:/etc/localtime:ro
      - /mnt/raid/hass/:/config:Z
    image: homeassistant/home-assistant
    restart: always

You can add the device to manual docker run commands by adding --device /dev/ttyACM0 to your existing command line.


For this step, always refer to the instructions that came with your Z-Wave device since some require different pairing steps. In my case, I installed the battery, pressed the button inside the sensor, and paired the device:

  • Go to the Home Assistant web interface
  • Click Configuration on the left
  • Click Z-Wave on the right
  • Click Add Node and follow the steps on screen

Understanding how the sensor works

Now that the sensor has been added, we need to understand how it works. One of the entities the sensor provides is an alarm_level. It has two possible values:

  • 0: the sensor is tilted vertically (garage door is closed)
  • 255: the sensor is tilted horizontally (garage door is open)

If the sensor changes from 0 to 255, then someone opened the garage door. Closing the door would result in the sensor changing from 255 to 0.

Adding automation

Let’s add automation to let us know when the door is open:

  • Click Configuration on the left
  • Click Automation on the right
  • Click the plus (+) at the bottom right
  • Set a good name (like “Garage door open”)
  • Under triggers, look for Vision ZG8101 Garage Door Detector Alarm Level and select it
  • Set From to 0
  • Set To to 255
  • Leave the For spot empty

Now that we can detect the garage door being open, we need a notification action. I love PushBullet and I have an action set up for PushBullet notifications already. Here’s how to use an action:

  • Select Call Service for Action Type in the Actions section
  • Select a service to call when the trigger occurs
  • Service data should contain the json that contains the notification message and title

Here’s an example of my service data:

  "message": "Someone opened the garage door at home.",
  "title": "Garage door opened"

Press the orange and white save icon at the bottom right and you are ready to go! You can tilt the sensor in your hand to test it or attach it to your garage door and test it there.

If you want to know when the garage door is closed, follow the same steps above, but use 255 for From and 0 for To.

Allow a port range with firewalld

Managing iptables gets a lot easier with firewalld. You can manage rules for the IPv4 and IPv6 stacks using the same commands and it provides fine-grained controls for various “zones” of network sources and destinations.

Quick example

Here’s an example of allowing an arbitrary port (for netdata) through the firewall with iptables and firewalld on Fedora:

## iptables
iptables -A INPUT -j ACCEPT -p tcp --dport 19999
ip6tables -A INPUT -j ACCEPT -p tcp --dport 19999
service iptables save
service ip6tables save

## firewalld
firewall-cmd --add-port=19999/tcp --permanent

In this example, firewall-cmd allows us to allow a TCP port through the firewall with a much simpler interface and the change is made permanent with the --permanent argument.

You can always test a change with firewalld without making it permanent:

firewall-cmd --add-port=19999/tcp
## Do your testing to make sure everything works.
firewall-cmd --runtime-to-permanent

The --runtime-to-permanent argument tells firewalld to write the currently active firewall configuration to disk.

Adding a port range

I use mosh with most of my servers since it allows me to reconnect to an existing session from anywhere in the world and it makes higher latency connections less painful. Mosh requires a range of UDP ports (60000 to 61000) to be opened.

We can do that easily in firewalld:

firewall-cmd --add-port=60000-61000/udp --permanent

We can also see the rule it added to the firewall:

# iptables-save | grep 61000
-A IN_public_allow -p udp -m udp --dport 60000:61000 -m conntrack --ctstate NEW,UNTRACKED -j ACCEPT
# ip6tables-save | grep 61000
-A IN_public_allow -p udp -m udp --dport 60000:61000 -m conntrack --ctstate NEW,UNTRACKED -j ACCEPT

If you haven’t used firewalld yet, give it a try! There’s a lot more documentation on common use cases in the Fedora firewalld documentation.

Disable autoplay for videos in Firefox 65

Firefox has some great features, but one of my favorites is the ability to disable autoplay for videos. We’ve all had one of those moments: your speakers are turned up and you browse to a website with an annoying advertisement that plays immediately.

GIF: I just want it to stop.

This feature stopped working for me somewhere in the Firefox 65 beta releases. Also, the usual setting in the preference page (under Privacy & Security) seems to be missing.

Luckily we can edit Firefox’s configuration directly to get this feature working again. Open up a new browser tab, go to about:config, and adjust these settings:

  • Set media.autoplay.default to 1 to disable video autoplay for all sites

  • Set media.autoplay.allow-muted to false to disable video autoplay even for muted videos

Those changes take effect for any new pages that you open after making the change.

Getting started with ham radio repeaters

Amateur radio is a fun way to mess around with technology, meet new people, and communicate off the grid. Talking directly to another radio on a single frequency (also called simplex) is the easiest way to get started. However, it can be difficult to communicate over longer distances without amplifiers, proper wiring, and antennas. This is where a radio repeater can help.

What’s in scope

This post is focused on fairly local communication on VHF/UHF bands. The most common frequencies for local communication in these bands are:

  • 2 meters (~144-148MHz)*
  • 70 centimeters (~420-450MHz)*

* NOTE: Always consult the band plan for your area to see which part of the frequency band you could and should use.

Of course, you can do some amazing things with weak signal VHF (which can be used to commuinicate over great distances), but we’re not talking about that here. The HAMSter Amateur Radio Group is a great place to get started with that.

We’re also not talking about radio bands longer than 2 meters (which includes high frequency (HF) bands). Some of those bands require advanced FCC licensing that takes additional studying and practice.

Keeping it simple(x)

Simplex radio involves communication where radios are tuned to a single frequency and only one radio can transmit at a time. This is like a simple walkie-talkie. If one person is transmitting, everyone else listens. If someone else tries to transmit at the same time, then the waves will be garbled and nobody will be able to hear either person. This is often called “doubling up”.

This method works well when radios are in range of each other without a bunch of objects in between. However, it’s difficult to talk via simplex over great distances or around big obstables, such as mountains or hills.


Repeaters are a little more complex to use, but they provide some great benefits. A repeater usually consists of one or two radios, one or two antennas, duplexers, and some other basic equipment. They receive a signel on one frequency and broadcast that same signal on another frequency. They often are mounted high on towers and this gives them a much better reach than antennas on your car or home.

I enjoy using a repeater here in San Antonio called KE5HBB. The repeater has this configuration:

  • Downlink: 145.370
  • Uplink: 144.770
  • Offset: -0.6 MHz
  • Uplink Tone: 114.8
  • Downlink Tone: 114.8

Let’s make sense of this data:

  • Downlink: This is the frequency that the repeater uses to transmit. In other words, when people talk on this repeater, this is the frequency you use to hear them.

  • Uplink: The receiver listens on this frequency. If you want to talk to people who are listening to this repeater, you need to transmit on this frequency.

  • Offset: This tells you how to calculate the uplink frequency if it is not shown. This repeater has a negative 0.6 offset, so we can calculate the uplink frequency if it was not provided:

    145.370 - 0.600 = 144.770
  • Uplink/Downlink Tones: Your radio must transmit this tone to open the squelch on the repeater (more on this in a moment). The repeater will use the same tone to transmit, so we can configure our radio to listen for that tone and only open our squelch when it is detected.

Opening the squelch

Transmitting radio waves uses a lot of power and it creates a lot of heat. There are parts of a radio that will wear out much more quickly if a radio is transmitting constantly. This is why receivers have a squelch. This means that a radio must transmit something strong enough on the frequency (or use a tone) to let the repeater know that it needs to repeat something.

You may come across repeaters with no tones listed (sometimes shown as PL). This means that you can just transmit on the uplin frequency and the repeater will repeat your signal. These repeaters are easy to use, but they can create problems.

Imagine if you’re traveling through an area and you’re using a frequency to talk to a friend in another car. As you’re driving, you move in range of a repeater that is listening on that frequeny. Suddenly your conversation is now being broadcasted through the repeater and everyone listening to that repeater must listen to you. This isn’t what you expected and it could be annoying to other listeners.

Also, in crowded urban areas, there’s always a chance that signals might end up on the repeater’s listening frequency unintentionally. That would cause the repeater to start transmitting and it would increase wear.

Two repeaters might be relatively close (or just out of range) and the tone helps each repeater identify its own valid radio traffic.

Tuning the tones

Most repeaters have a tone squelch. That means you can blast them with 100 watts of radio waves and they won’t repeat a thing until you transmit an inaudible tone at the beginning of your transmission.

As an example, in the case of KE5HBB, this tone is 114.8. You must configure a CTCSS tone on your radio so that the tone is transmitted as soon as you begin transmitting. That signals the repeater that it’s time to repeat. These signals aren’t audible to humans.

If you know you’re tuned to the right frequency to transmit (the uplink frequency), but the repeater won’t repeat your traffic, then you are most likely missing a tone. There’s also a chance that you programmed the uplink and downlink tones into your radio in reverse, so check that, too.

Repeater transmit tone

Some receivers will transmit a tone when they broadcast back to you, but some won’t. If you can transmit but you can’t hear anyone else when they talk, double check your radio’s settings for a tone squelch on the receiving side. Your radio can also listen for these tones and only open its squelch when it hears them.

I usually disable receiver squelch for tones on my radio since the repeater operator could disable that feature at any time and I wouldn’t be able to hear any transmissions since my radio would be waiting for the tone.

Testing a repeater

First off, please don’t test a repeater unless you have a proper amateur radio license in your jurisdiction. In the United States, that’s the FCC. Don’t skip this step.

Once you get your repeater’s frequencies programmed into your radio properly and you’ve double checked the settings for sending tones, you can try “breaking the squelch.”

Press the transmit button on your radio briefly for about half second and release. You should hear something when you do this. For some repeaters, you may hear a KERRRCHUNK noise. That’s the sound of the repeater squelch closing the transmission now that you’re done with your transmission. On other repeaters, you may hear some audible tones or beeps as soon as you release the transmit button.

Once you have it working properly, stop breakng the squelch and introduce yourself! For example, when I’m in my car, I might say: “W5WUT mobile and monitoring.” That lets people on the repeater know that I’m there and that I’m moving (so I might not be on for a very long time).

Good luck on the radio waves! 73’s from W5WUT.

Use a secret as an environment variable in OpenShift deployments

OpenShift deployments allow you to take a container image and run it within a cluster. You can easily add extra items to the deployment, such as environment variables or volumes.

The best practice for sensitive environment variables is to place them into a secret object rather than directly in the deployment configuration itself. Although this keeps the secret data out of the deployment, the environment variable is still exposed to the running application inside the container.

Creating a secret

Let’s start with a snippet of a deploymentConfig that has a sensitive environment variable in plain text:

    - env:
        - name: MYAPP_SECRET_TOKEN
          value: vPWps5E7KO8KPlljaD3eXED3f6jmLsV5mQ
    image: "fedora:29"
    name: my_app

The first step is to create a secret object that contains our sensitive environment variable:

apiVersion: v1
kind: Secret
  name: secret-token-for-my-app
  SECRET_TOKEN: vPWps5E7KO8KPlljaD3eXED3f6jmLsV5mQ

Save this file as secret-token.yml and deploy it to OpenShift:

oc apply -f secret-token.yml

Query OpenShift to ensure the secret is ready to use:

$ oc get secret/secret-token-for-my-app
NAME                            TYPE      DATA      AGE
secret-token-for-my-app         Opaque    1         1h

Using the secret

We can adjust the deployment configuration to use this new secret:

    - env:
      - name: MYAPP_SECRET_TOKEN
            key: SECRET_TOKEN
            name: secret-token-for-my-app
    image: "fedora:29"
    name: my_app

This configuration tells OpenShift to look inside the secret object called secret-token-for-my-app for a key matching SECRET_TOKEN. The value will be passed into the MYAPP_SECRET_TOKEN environment variable and it will be available to the application running in the container.

Security note: If someone has access to change the deployment configuration object, they could get access to the value of the secret without having direct access to the secret object itself. It would be trivial to change the startup command in the container to print all of the environment variables in the container (using the env command) and view them in the container logs.