Really stop autoplay in Firefox / Librefox

I am not sure who thought, that autoplay on music and videos is a good idea in a browser. Using my tablet on travel, it is just a joy to click on a link and some video starts entertaining everyone else but me. Firefox offers some toggles in the regular settings to deactivate autoplay, however I found, that it does not stop videos from playing in certain situations.

So what is the solution

Open a page with about:config and set the following settings:

Setting Value
media.autoplay.allow-extension-background-pages false
media.autoplay.block-event.enabled true
media.autoplay.blocking_policy 2
media.autoplay.default 5

This works for me in Firefox / Librefox and Firefox Mobile (nightly)

Full article view...

Add google traffic overlay to OSMAnd

OSMAnd is great with detailed maps, however when traveling I often miss traffic information. Luckily you can add an online overlay, that will show the google traffic data.

I used guides like these here or here, however all I could find would add the traffic information PLUS a whole google map, street names or anything else. I wanted to just have the traffic information.

So what is the solution

  1. First of all to use online overlays, you need to activate the plugin “Online maps” in OSMAnd

  2. After activating the plugin you can add in “Configure map” -> “Map source…” a new map:

New map settings

The URL string: https://mt1.google.com/vt/lyrs=h,traffic&x={1}&y={2}&z={0}&apistyle=s.t%3A0|s.e%3Al|p.v%3Aoff

The important part to remove labels and maps in here is the URL with the following config:

  • lyrs=h,traffic - selects the street layer with traffic information. If you use s or m in the beginning you will get the satellite or maps view with the traffic information
  • x, y and z - are the coordinates and zoom level filled by OSMAnd
  • apistyle=s.t%3A0|s.e%3Al|p.v%3Aoff - selects all feature styles (s.t), labels (s.e) and turns them off (p.v). Otherwise you will have street and location names in the overlay.

Especially the apistyle part was hard to find. Finally I found an explanation on stackoverflow for the different possible settings.

Saving this map, then you can configure your map and activate an overlay map. If you need to change the traffic map settings you find them in the local maps for editing. Be advised that this is an online function and requires a working internet connection and is also not included in route finding.

Full article view...

What I learnt using docker as a beginner

Running my own server setup with docker, I ran into some issues over time. To not forget what I did and maybe to help others here is what I found.

It is a gathering of simple things I now try to include in all my docker setups, as they make life with docker easier. For some this might be obvious things. If you have additional thoughts, I am happy to hear of them.

Do not mix your hosts file system with your docker mounts

It might be a tempting idea to store config files of your container within your regular /etc or logs to /var/log. However you easily get lost to know which file is used by whom. Log files may get merged with others and so on. Hence have your own directory in which you store your docker stuff. It also makes backups, git use etc. easier.

Use git - a lot

You should use git to version everything you do on docker. Starting with your dockerfiles, to configuration files for services. Especially building a new container needs a lot of testing. Things might go forth and back, hence a history and versioning is utterly helpful.

Keep ENTRYPOINT and CMD separate

Use the entrypoint for something that needs to be done before each start of the service, like correcting permissions, update small things, etc. Keep the command separated from this (hence do not put the service start command in the entrypoint) so you can override it easily.

Use dumb-init in your own Dockerfiles

It is a small package you can easily install and easily add to your image. It simply puts a tiny init system into the container to properly start and stop your service. You can read more on the dumb-init github page. A lot of images out there ignore this. It is not per se harmful, but a lot of services get killed instead of properly shut down.

Prosody container example:

ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["bash", "-c", "/usr/local/sbin/entrypoint.sh && exec prosodyctl start"]

Learn about IPv6, iptables and internal docker networks

Docker takes over iptables when running a container, be sure to understand what is happening. Especially take a look on internal networks, as they can easily secure database container and other backend services.

For IPv6 better still use NAT. I didn’t like that in the beginning as well, however you run into so many troubles (like dynamic prefixes, limited IPv6 configuration options, etc.), that it is just way easier to use NAT again. Sadly docker does not support NAT on IPv6, for that use https://github.com/robbertkl/docker-ipv6nat. It is a simple binary to run in the background, that fills the gap.

Make sure your container runs with the correct user:group

Especially when using bind-mounts, make sure your use proper UID:GID combinations. I have created the users on my host machine that will be used inside the container and pass the UID:GID into the container. This ensures, that files stored on the host will not by accident be accessible by other processes due to UID overlap.

Again a prosody example on debian for your Dockerfile

ARG uid=1001
ARG gid=1002

# Add user and group before install, for correct file permission
RUN addgroup --gid $gid prosody \
    && adduser --system --disabled-login --disabled-password --home /var/lib/prosody --uid $uid --gid $gid prosody

Use docker logging

It is tempting to just mount a folder and store logfiles. However when using images, e.g. from hub.docker it can be quite difficult to correctly map this and often leads into some sort of chaos.

I actually like the webserver approach to just link the logfiles to /dev/stdout and /dev/stderr

RUN ln -sf /dev/stdout /var/log/nginx/access.log
RUN ln -sf /dev/stderr /var/log/nginx/error.log

With that you can use the regular docker logs command and use configuration options to divert it to whatever log facility you are using.

Make sure your container are in the right timezone

A lot of images nowadays use the TZ=<timezone> as an environment variable in the container to control the timezone. You should set this always and use it in your own Dockerfiles

RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime

Nothing is more confusing than log files with non matching timestamps.

If you need to build from source use multi-stage builds

Instead of bloating your production image with build-tools and sources, use multi-stage builds.

With that you can create a build image, run it and use the build results in a regular image:

Shortened example for coturn

### 1. stage: create build image
FROM debian:stable-slim AS coturn-build

# Install build dependencies
[...]

# Clone Coturn
WORKDIR /usr/local/src
RUN git clone https://github.com/coturn/coturn.git

# Build Coturn
WORKDIR /usr/local/src/coturn
RUN ./configure
RUN make


### 2. stage: create production image
FROM debian:stable-slim AS coturn
[...]

# Copy out of build environment
COPY --from=coturn-build /usr/local/src/coturn/bin/ /usr/local/bin/
COPY --from=coturn-build /usr/local/src/coturn/man/ /usr/local/man/
COPY --from=coturn-build /usr/local/src/coturn/sqlite/turndb /usr/local/var/lib/coturn/turndb
COPY --from=coturn-build /usr/local/src/coturn/turndb /usr/local/turndb

# Install missing software
[...]

Make sure your services start in order

A lot of errors come up when services that depend on each other just start in random order. Sometimes you are lucky and it works, sometimes you get an error. Within docker-compose you can use the depends_on directive. If you have for some reason separate setups, you can use the following bit within your entrypoint:

/bin/bash -c " \
  while ! nc -z mariadb 3306; \
  do \
    echo 'Waiting for MariaDB'; \
    sleep 5; \
  done; \
  echo 'Connected!';"
Full article view...

Parsing config files in bash using awk

Ever so often I get to some sort of complex bash script and find, that a configuration or ini file would make sense, to control the script and make it more flexible. However bash does not bring nice libraries to parse config files, e.g. like python.

In essence two things are needed to write a config file parser:

  1. good trim of the config option, as you can have
    • <option>=<value>
    • <option> = <value>
    • <option> =<value>
    • and so on…
  2. structured way to move the config to usable variables within bash.

So what is the solution

First lets take a look on how to analyze a config file line. It is normally setup like: <option><delimiter><value>

To parse this, we need to separate the option and value by the delimiter. For this awk is perfect to use as it can seperate a line with a field separator in parts and store each in a variable.

Additionally we can eliminate spaces around the delimiter to make the config parser more robust. However we need to do that left and right of the delimiter, to only trim the leading and trailing spaces of each side. Just eliminating spaces in the whole string would delete spaces in configurations as well. Using the delimiter = this would look like the following for the left side (for right side change $1 to $2).

awk -F'[=]' '{gsub("^\\s+|\\s+$", "", $1); print $1}' <<< $line

So what does this do?

  • -F[=] sets the delimiter to =
  • gsub("^\\s+|\\s+$", "", $1); starting starting from the first letter (^) replace 1 or more spaces at beginning and end (\\s+|\\s+$) with an empty string (""). $1 use the left part of the delimiter for the gsub command
  • print $1 as awk automatically splits with the delimiter, print the first part (left side of the config line)
  • <<< $line is the feeded line of our config. Within bash you can easily loop through a file line by line with the read command.

Now that we have the basics, we can write a parser function with it.

An example within a script:

#!/bin/bash

declare -A settings_map

function read_config () {
    while IFS= read -r line; do
        case "$line" in
            ""|\#*)
                # do nothing on comments and empty lines
                ;;
            *)
                # parse config name and value in array
                settings_map[$(awk -F'[=]' '{gsub("^\\s+|\\s+$", "", $1); print $1}' <<< $line)]=$(awk -F'[=]' '{gsub("^\\s+|\\s+$", "", $2);print $2}' <<< $line)
                ;;
        esac
    done < $1
    echo ${settings_map[*]}
}

# call fuction with the config file to parse
read_config parser-test.conf

# show that it is working and picking "option" from the array
echo ${settings_map[option]}

This would read a config file like this (or with some spaces around the =):

# parser-test.conf
# Use option=value
#
type=value_type
option = value_option

test =value_test
spaces    = value space

It reads line by line, remove leading and trailing spaces on the left and right site of the config line, then store it into the settings_map array. The array can be used within the rest of the bash script.

Important: This function uses a globally declared array. Handing back an array from a function is not trivial. You could create and return a string, then initialize an array afterwards. However I feel that to be a bit cumberstone and not adding to the functionality.

Full article view...

Deactivate bluetooth on startup

For some reason my laptop thinks bluetooth is the technology to go and activates it on startup of Linux Mint/Ubuntu.

Searching the internet you will find a lot of answers for this problem, that quite brutally kill the bluetooth service or block devices. All not very elegant.

So what is the solution

Most laptops use tlp for power management. If you don’t you should check it out. With that it is quite easy. Uncomment and edit in /etc/tlp.conf:

DEVICES_TO_DISABLE_ON_STARTUP="bluetooth"

You can also edit tlp to remember the last state when powering down. But for me deactivating bluetooth was all enough.

Full article view...