What’s up with mod_security and User-Agent? (406 Not Acceptable)

May 1, 2018

So… what’s the deal with mod_security and User-Agent? I tried to browse to HandheldRadio.net using Lynx, and was greeted with this 406 error:

                            Not Acceptable

   An appropriate representation of the requested resource / could not be
   found on this server.

   Additionally, a 406 Not Acceptable error was encountered while trying
   to use an ErrorDocument to handle the request.

A few searches and I discovered this was due to Apache mod_security.

I don’t get it. Why would you exclude based on User-Agent? That’s something that can be changed at will by any program that decides to be nefarious. This seems like security theatre rather than real security.

Even in the best case, this kind of “security” just turns into a red queen’s race to the bottom where everything will now lie about what it is because someone screwed up a config file somewhere.

And so I’ve started lying (in my .bashrc):

alias lynx='lynx -useragent="Mozilla/5.0 (X11; Ubuntu Lynx; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0"'

Damn, that’s stupid.


Setting a user and group for Samba drives

April 14, 2018

The last time I tried to set a user and password on my Samba drive, I ran into a strange problem: even though my credentials were correct, I was still using the user and group I was logged in as, rather than the one I’d stored with the Samba config.

Luckily, these days there’s an easy way around it in /etc/fstab:

//mysvr/music /music cifs uid=1000,gid=1000,credentials=/etc/samba/credentials/mysvr


Simply adding the uid= and gid= lines fixed up the problem for me.

What the hell, Gnome? Canonical?

January 1, 2018

Today when I started working on my desktop, I saw a crash in gom-media-tracker. What? Why is there a media tracker on my desktop?

I learned this is part of Gnome (what? Why is there a media tracker in Gnome?) and it’s included in Ubuntu 16.04 LTS (why is Canonical including tracking software in Ubuntu?)

Screw that. I removed it.

$ sudo apt remove gnome-online-miners
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages will be REMOVED:
  gnome-documents gnome-online-miners gnome-photos ubuntu-gnome-desktop
0 upgraded, 0 newly installed, 4 to remove and 0 not upgraded.
After this operation, 6,472 kB disk space will be freed.
Do you want to continue? [Y/n] y
dpkg: warning: files list file for package 'fonts-gfs-complutum' missing; assuming package has no files currently installed
(Reading database ... 493027 files and directories currently installed.)
Removing ubuntu-gnome-desktop (0.58.3) ...
Removing gnome-documents (3.18.3-0ubuntu0.16.04.1) ...
Removing gnome-photos (3.18.2-1) ...
Removing gnome-online-miners (3.14.3-1ubuntu2) ...
Processing triggers for libglib2.0-0:amd64 (2.48.2-0ubuntu1) ...
Processing triggers for man-db (2.7.5-1) ...
Processing triggers for hicolor-icon-theme (0.15-0ubuntu1) ...
Processing triggers for gnome-menus (3.13.3-6ubuntu3.1) ...
Processing triggers for desktop-file-utils (0.22-1ubuntu5.1) ...
Processing triggers for bamfdaemon (0.5.3~bzr0+16.04.20160824-0ubuntu1) ...
Rebuilding /usr/share/applications/bamf-2.index...
Processing triggers for mime-support (3.59ubuntu1) ...

Now that I’ve done that, I don’t appear to have lost anything I use. (Why is an optional packages forcing other packages out?)

I don’t want random tracking software on my machine.

wiki.gnome.org/Projects/Tracker, you suck. Gnome, you suck. Canonical, you suck.

Updating to the latest TeX on Ubuntu 16.04

November 20, 2017

I had problems running the TeXLive package manager tlmgr on my Ubuntu 16.04 LTS install. Apparently the package manager changed formats in 2016, so the version that is included with Ubuntu is out of date (and presumably so is TeX/LaTeX).

Luckily, there’s a repo with the latest TeX as described here:

In short, if you have TeX already installed, do this:

sudo add-apt-repository ppa:jonathonf/texlive
sudo apt update; sudo apt upgrade

After that you’ll run into the following bug:
You’ll need to do the following to get around it:

sudo apt -f remove texlive-base texlive-fonts-recommended texlive-latex-extra texlive-latex-recommended texlive-pictures texlive-pstricks texlive-base-bin prosper texlive-fonts-recommended-doc texlive-fonts-extra-doc texlive-latex-base texlive-generic-recommended texlive-latex-base-doc texlive-latex-extra-doc texlive-latex-recommended-doc texlive-pictures-doc texlive-pstricks-doc tipa

sudo apt install texlive-base texlive-fonts-recommended texlive-latex-extra texlive-latex-recommended texlive-pictures texlive-pstricks texlive-base-bin prosper texlive-fonts-recommended-doc texlive-fonts-extra-doc texlive-latex-base texlive-generic-recommended texlive-latex-base-doc texlive-latex-extra-doc texlive-latex-recommended-doc texlive-pictures-doc texlive-pstricks-doc tipa

After that, you should be running the latest TexLive.

Upgrading Mythbuntu from Trusty to Xenial

June 25, 2017

Yesterday I took the plunge and upgraded my Mythbuntu install from Trusty to Xenial. Except for a few heart-stopping moments, it went smoothly.

Things I wish I’d known about the upgrade

  • There’s a bug with upgrading MySQL when you have the Mythbuntu tweaks installed. As a result, the upgrade fails to install MySQL properly – and then everything looks broken. Ouch. You can find out more about the defect here. The symptom is the message “[ERROR] unknown variable ‘table_cache=128’ ” which scrolls off the screen when you do an upgrade (or dpkg –configure -a). The fix is to change
table_cache = 128


table_open_cache = 128

in /etc/mysql/conf.d/mythtv-tweaks.cnf.

  • During the upgrade, I got prompted for which user to use for the database. (With the recommendation to use “root” if you don’t thoroughly understand the permissions models.) But of course “root” didn’t work. What did work was the default, debian-sys-maint.
  • After install, lirc didn’t work. I uninstalled lirc using Mythbuntu Control Center and rebooted; that appeared to fix things and now my Streamzap remote is being detected as a keyboard device with the appropriate mappings. (I get a warning about a plugin using MCC, but hey, it seems to work.)
  • Next, I got warnings using apt. Probably due to the upgrade failure, I had a file called 50unattended-upgrades.ucf-old left over in /etc/apt/apt.conf.d. Nuking that fixed things.
  • It looks as if mythfrontend and mythbackend are using different users now. I’m not sure why, but some day I’ll need to go through and fix permissions / unify those two users.
  • I had to go into mythtv-setup and assign directories for music and music art. (Since I didn’t have an art directory, I created one under my music directory. That seems to work.)
  • Probably as a result of the botched upgrade, mythweb was broken. I installed php7.0-mysql, then removed/installed mythweb and it was working again.
  • Finally, I tried to look into mythconverg. In this release the admin user is debian-sys-maint, and the password for that user is stored in /etc/mysql/debian.cnf.

US coin values by weight

February 6, 2017

One thing that it’s often wise to have for emergencies is a handful of change. If you’re stuck somewhere where there’s nothing to eat but vending machine goodness, it might mean the difference between having a meal or not.

But if you bring change, what sort of change should you bring? Going strictly by weight, the $1 coin is the best value for weight right now. But there’s one drawback to that: some vending machines don’t take $1 coins. So what should you carry if you want to get maximum snacks?

The US Mint has a list of US coin weights as part of their specifications. That tells you what you need to know. Here’s a table based on the weight of mint condition coins (coins lose mass as they get used):

Coin Value ($) Coin Weight (g) Weight (g) for $1
0.01 2.5 250.0
0.05 5.0 100.0
0.10 2.268 22.68
0.25 5.670 22.68
1.00 11.34 11.34

That reveals some interesting facts.

  • Nickles weigh exactly 5 g each
  • Two pennies weigh the same as one nickle
  • $10 in nickels or $4 in pennies weigh 1 kg
  • Quarters and dimes have the same value by weight
  • Dollar coins are twice as valuable as quarters and dimes by weight

So if you’re on a road trip and plan to dine at the automat, grab your dollar coins first, then your dimes and quarters. Skip the nickles (unless you think that you’ll have to weigh something – it might be handy to have a few 5g weights around). And there’s a reason that only zinc producers like pennies.

Dockerizing TicketsCAD

January 4, 2017

Over the recent holiday, I decided to teach myself about Docker by using it to build a running TicketsCAD system. It turned out to be pretty slick. Here’s what I did.

TicketsCAD is a PHP application that requires an SQL backend. It does computer dispatching for public safety answering points (PSAPs). Yes, I have weird hobbies.

When I first started, I grabbed the official Docker PHP image, then tried to customize it by installing a MariaDB server. But that turned out to be a bad idea. (It’s certainly possible, but not the right thing to do.) After a little while, I did a search for “Docker philosophy”, which brought me to this page:
which set me straight. The right way to do what I wanted to do was to have two separate (but linked) Docker container instances – one with the web server and PHP (customized the way I wanted) and the other with the SQL database. So here’s what I came up with.

Grab TicketsCAD

I grabbed the files from the TicketsCAD download area: tickets_3.12A_082516.

Next I created a directory for everything. In that, I put a directory for the ticketscad server (I cleverly called it ticketscad) and another directory for the ticketscad SQL server (even more cleverly called ticketscadmariadb). Then I created var-www-html in ticketscad, and untarred the TicketsCAD files into it.

Dockerfile for TicketsCAD

Here’s the first Docker file (named Dockerfile in the ticketscad directory).

FROM php:7.0-apache
# Set the timezone
RUN echo Canada/Eastern > /etc/timezone && dpkg-reconfigure -f \
        noninteractive tzdata
# get PHP GD libraries
RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libmcrypt-dev \
        libpng12-dev \
    && docker-php-ext-install -j$(nproc) iconv mcrypt \
    && docker-php-ext-configure gd \
       --with-freetype-dir=/usr/include/ \
       --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) gd

# Install Mariadb client
RUN apt-get install mariadb-client -y
RUN docker-php-ext-install mysqli pdo pdo_mysql

# Fix permissions for ticketscad
RUN chown -R www-data.www-data /var/www/html
RUN chmod -R u+w /var/www/html

From top to bottom, here’s the explanation.

  • I used the official PHP Docker build with Apache from hub.docker.com. There were some issues with TicketsCAD and PHP 7.1, so I went down to PHP 7.0. (Docker made this very easy to do.)
  • I set the timezone. This is a bit of Docker weirdness – there’s no standard way in Linux to set timezones, so you need to know how to do it in the distribution you’re using. This is how to do it in the PHP distribution. More details about timezones are at www.ivankrizsan.se/2015/10/31/time-in-docker-containers
  • I installed the PHP GD libraries. This is stolen from the PHP Core Extensions section of PHP on hubs.docker.com, and it installs a few other things I probably don’t need (mcrypt, etc.) I just copied and pasted.
  • I installed the MariaDB client and PHP SQL extensions.
  • TicketsCAD wants to write to /var/www/html and its subdirectories, so I made them rw. (I’m not sure how that makes me feel about security – I’d kind of prefer it not to do that and to store configuration somewhere not visible to the world. But that’s how it works.)

Now that I had that running, I needed a SQL backend. Luckily, there’s an official MariaDB Docker build as well. The Dockerfile for this is so simple that I almost don’t need it, but hey, I had a directory created already, so here it is:

Dockerfile for MariaDB

FROM mariadb:10.1
RUN echo Canada/Eastern > /etc/timezone && dpkg-reconfigure -f \
      noninteractive tzdata
RUN chown -R mysql.mysql /var/lib/mysql

Pretty self-explanatory. I don’t know for sure that I need that chown, but it doesn’t hurt.


I built a docker-compose.yml in my parent directory. This is a way to start both instances at the same time.

version: '2'
    build: ./ticketscadmariadb
    image: ticketscadmariadb:1.0
     - ./ticketscadmariadb/var-lib-mysql:/var/lib/mysql
     - "3306:3306"
     - MYSQL_DATABASE=ticketscaddb
     - MYSQL_USER=ticketscaduser
     - MYSQL_PASSWORD=ticketscadpassword
    build: ./ticketscad
    image: ticketscad:1.0
     - ./ticketscad/var-www-html:/var/www/html
     - "8080:80"
     - ticketscadmariadb

There’s a lot in there. I’ll break it down.

  • I’m using version 2 of the docker-compose.yml file format. Gotta say so.
  • First I specified the way to build ticketscadmariadb. I pointed to the subdirectory that holds the Dockerfile and gave it an image name.
  • I exposed the directory on my local machine that will hold the MariaDB database. (It’s /var/lib/mysql on the Docker instance; I called it var-lib-mysql in the ticketscadmariadb directory on my local machine.) Why did I do this? So the SQL database would persist across Docker rebuilds. Needless to say, I created an empty var-lib-mysql under ticketscadmariadb on my local system.
  • I exposed the MariaDB SQL port (3306) and mapped it to 3306 on my local machine. If you have SQL running on your local machine already, you’ll need a different local port.
  • I specified a bunch of environment variables for MariaDB. The MariaDB Docker image is smart enough to know that if it sees those variables, it creates a database with the specified name / user / password / root user. Thanks, MariaDB Docker image! (You’ll probably want different passwords than I used.)
  • Now it’s time for the TicketsCAD image (PHP/Apache server). I pointed to the ticketscad subdirectory (which holds the Dockerfile) and gave it an image name.
  • I mapped the /var/www/html directory on my Docker image to ./ticketscad/var-www-html on my local machine. Why not just COPY? Because TicketsCAD writes to /var/www/html and /var/www/html/incs, and I want that to persist across builds.
  • I exposed port 80 on the Docker image as port 8080 on my local machine.
  • Finally, I told Docker that I want to be able to have the ticketscad image talk to the ticketscadmariadb image using the links: command. (If I didn’t do this, the two images wouldn’t be able to communicate.)

Building and running

So now everything’s set up. At this point, I can go to the parent directory and type:

docker-compose up

That reads docker-compose.yml by default, downloads the files that are needed and creates my images. And voilà, a working TicketsCAD install is ready to go.

Well, almost ready to go. Because Docker assigns IP addresses for each build, I had to interrogate the running images in order to figure out what they were. First I used docker ps to find out that the container ID of the ticketscadmariadb instance was 2e13d01384ac, then I used docker inspect to discover its IP address. I needed to know the IP address for the TicketsCAD configuration screen.

docker ps
docker inspect 2e13d01384ac | grep IPAddress

For me it was

Because I have the TicketsCAD port 80 exposed on my local machine as 8080, I can now go to localhost:8080 to run TicketsCAD.

What next?

This is enough to get TicketsCAD up and running in a “play” environment. In a real environment, you’d want to harden things. In particular, remove the install.php script and save the Docker image after installation, and make sure that random yahoos on the Internet can’t write to /var/www/html. Give the machines real hostnames. Set up real certificates and put them on the network. Run something to prevent DDOS attacks. All them devops things.

Hey TicketsCAD guys!

You’ve got some cool software. If possible, it would be nice for TicketsCAD to have a check box to delete install.php for you after running it – then it would be more compatible with Docker.

A few more more useful things

1. If you want to look into a running Docker instance, this is nice to know:

docker exec -it containerID bash

It brings you to a root shell running bash on the instance.

2. I ran into problems after I removed some images with docker -rmi. stackoverflow.com/questions/37454548/docker-compose-no-such-image solved my problem (in short: docker-compose down).

3. Sometimes you’ll need to rebuild.

docker-compose up --build

is a handy way to do that.

My directory structure

      (all the TicketsCAD files go here)