Launch SSH improved keyboard navigation and natural sort

I've added some updates to Launch SSH and bumped the version to 0.1.2. The keyboard navigation has received a small update as the PAGE DOWN, PAGE UP, HOME and END keys are now functional. Also, when a history item is selected and RETURN is pressed, that session is now launched instead of whats in the input box.

Another small new feature is natural sorting in the history. For example if you were to have 20 webservers called web1, web2, all the way up to web20, it would previously sort like this: web1, web10, web11, .... From now on it will be sorted in a more natural way like this: web1, web2, ..., web9, web10, ..., web19, web20.

Finally, I've no longer created a deb installer for Ubuntu artful, but did created one for Ubuntu bionic, which is about to be released today! You can find the installers here:

Thursday, 26 April 2018, 01:03 Bert Hekman

Launch SSH 0.1 released

More than ten years after the final release for Geek Launcher, I've finally put some sort of a spiritual successor together called Launch SSH.

I mainly used Geek Launcher to launch SSH sessions, back in the day when I still used Windows XP a lot. It mostly just invoked PuTTy with the hostname of the machine I wanted to connect to. Quickly launching other types of applications was still useful back then, but has been totally unnecessary for the last few years since Windows 7 came with a useful start menu which could quickly filter through and launch applications.

MacOS has similar functionality with spotlight and Gnome, Cinnamon and KDE (and other desktop environments) on linux also have their own ways of launching applications in a similar fashion.

However, launching ssh sessions was still not as easy as it was using my Geek Launcher and Launch SSH is trying to fix that.

Launch SSH main window

The idea is that you install this package and add a global hotkey in the desktop environment to launch the application. After that you get a window with an input box and a list box which will fill up with hostnames you've connected to recently.

After you've connected to a few machines, the history should fill up. And that's where the efficiency should come from. Because you can navigate quickly through the list using the arrow keys and launch a session using the RETURN key and you can also quickly find the session you want using autocomplete (bound to the TAB key.) Removing items from the history is also easy and can be done using the DELETE key.

This should make starting new SSH session a breeze. Go try it out and tell me what you think. You can find it on my github or download it here:

Thursday, 5 April 2018, 00:52 Bert Hekman

Improve PulseAudio Arctis 5 support

After I got the chat and game output to work on my SteelSeries Arctis 5 on Ubuntu, I tried sending a patch to the PulseAudio maintainers to include it in the distribution by default.

PulseAudio maintainer Tanu Kaskinen pointed out to me that I had to use two separate (custom) output paths. Fixing this caused the outputs to be selected more easily in sound configuration dashboards. For example in the gnome sound configuration screen:

Gnome sound settings with Artcis 5 game output selected
The names steelseries-arctis-5-output-* aren't pretty, but to change that, pulseaudio would need to be recompiled.

I played around with the profile configuration and configured which elements belong to which output. The game output is linked to the PCM element and the chat output is linked to the Com Speaker element. After configuring this correctly I noticed that the chat output volume slider now goes a lot louder than before and they don't interfere with each other.

Some welcome improvements! I've immediately released an updated version of my distributed version:

Download the updated version for debian, ubuntu and linux mint:

Tuesday, 13 February 2018, 20:29 Bert Hekman

SteelSeries Arctis 5 on Ubuntu

A while ago, I bought a new gaming headset, the SteelSeries Arctis 5. One of the main reasons I got is, was the "ChatMix Dial", a physical knob which can mix two audio outputs. Turning it to the left gives you more game sound, turning it to the right gives you more voice chat sound.

Steelseries Acrtis 5 with ChatMix dial

This works fine on Windows. It recogizes the two audio outputs and you can mix between them. On Ubuntu however, it doesn't. The only output it enables is the voice chat output and the microphone work. The game output stays hidden.

A simple solution

I took some time trying to figure out how to fix this and found out that ALSA recognizes the game output, but pulseaudio does not.

Yesterday I found an article about the Arctis 7 headset on Ubuntu by Johan Heikkilä and decided to try out the solutions he'd come up with. His first solution was using this command:

pacmd load-module module-alsa-sink device=hw:1,1

I've had to change the device address to hw:2,1 for mine to work and this added an extra audio device in my sound settings screen that enabled the game audio output.

The main problem with this approach is that once you reboot or unplug and plug in the device, it no longer comes up and you need to enter the command again for it to show up again.

A better (more sophisticated) solution

The second solution Johan added involved adding a pulseaudio profile file, a udev rule and some configuration to go with it. After putting all these files in place, I needed to change the product id in the udev rule from 1260 to 1250 so it matches the Arctis 5 and enables the profile:

ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1250", ENV{PULSE_PROFILE_SET}="steelseries-arctis-usb-audio.conf"

This did something! The game output was now enabled and the sound overall was a bit louder. However, the voice chat output and microphone input now were no longer working.

After that I figured out that the profile expects a mono output for the voice chat, but the Arctis 5 seems to have stereo. After changing that, everything worked.

The result

I've cleaned up the configuration and pushed it to a repository on github, along with a deb file for easy installation on Debian, Ubuntu, Linux Mint, etc.

The repository can be found here:

Download the deb:

After installing, and reconnecting the headset, it should enable the game output by default. In apps like Discord, the voice chat output should also be available to be selected as output:

Discord Arctis 5 settings

Saturday, 6 January 2018, 16:24 Bert Hekman

Local Symfony development with Docker Compose

I've been using a combination of Vagrant, Virtualbox and Ansible for a while now when developing my Symfony (and other PHP) applications and it has worked out just fine. Ever since I heard about Docker a few years ago, it seemed like a good idea, but a bit of a pain to set up and manage. But when my colleague Jordy showed me Docker Compose last week, which seemed a lot simpler and faster than my current flow, I was eager to try that out.

Docker vs Vagrant

At work our projects are quite complex and require a lot of different services like RabbitMQ, Couchbase and Elasticsearch, but my personal project are much more traditional, requiring only a webserver, PHP and MySQL. Fact of the matter is that I could reuse the same Vagrant/Ansible configuration for all my projects, and it would work just fine.

However, there are a few problems with that. Every vagrant box I spawn needs a whole operating system to run, a disk image containing said OS and the CPU and RAM resources to run it. When I use Docker, I can use the same image per service (eg. MySQL or nginx) and they would only use that diskspace once. It also doesn't need a whole operating system to run, since it runs isolated on my already running Linux kernel.

Aside from that, starting up a few Docker containers is much quicker than booting a whole virtual machine with a lot of services (and some stuff I don't really need.)

My Docker Compose setup

In the root of my project I added a docker-compose.yml file which contains something like this. (I stripped it down a bit and made it more generic...)

# docker-compose.yml
version: '3'

        image: mysql:5.7
            - 3306:3306
            - myproject_mysql:/var/lib/mysql
            MYSQL_ROOT_PASSWORD: rootpassword
            MYSQL_DATABASE: myproject
            MYSQL_USER: myproject
            MYSQL_PASSWORD: myproject

        image: nginx:1.12-alpine
            - 8080:80
            - ./docker/nginx/vhost.conf:/etc/nginx/conf.d/default.conf:ro
            - ./:/code
            - php

        build: docker/php
            - ./:/code

        driver: local

I defined a volume called myproject_mysql and mounted it in the mysql service on /var/lib/mysql. This is the path where MySQL stores all its data. By mounting the volume, we persist the data outside of the Docker container. This makes sure the data is saved when the container is shut down and started up again.

The mysql and nginx services are quite straight forward and use images directly from the Docker Hub with some custom configuration. You can tell because it uses the image: directive.

I also mounted the ./docker/nginx/vhost.conf file into the nginx container. I used the nginx vhost file provided in the Symfony documentation and changed server_name to _ and root to /code/web.

The php service is different, because it needs to be built. The build: directive tells Docker Compose where it can find the Dockerfile containing the steps to build the container. In this case it is in docker/php/Dockerfile, relative to the docker-compose.yml file.

It might contain the following:

# docker/php/Dockerfile

FROM php:7-fpm

RUN apt-get update && apt-get install -y \
    git \
    zlib1g-dev \
    libicu-dev \
    libxml2-dev \
    libaio1 \
    vim \

RUN docker-php-ext-install \
    pdo \
    pdo_mysql \
    opcache \
    intl \

RUN docker-php-ext-enable \
    pdo \
    pdo_mysql \
    intl \

RUN usermod -u 1000 www-data


The FROM directive tells on which Docker image it should be based. These images are also the ones you can find in the Docker Hub. The RUN directives run a command inside the container. As you probably can tell, the RUN commands I defined install and enable some PHP extensions.

The RUN usermod -u 1000 www-data is a bit a hack, by the way. Symfony writes cache and logs to the var directory and to prevent permission problems, we'll just give the www-data user in the container the same uid as the user I'm using on my PC. You should note that if your uid is not 1000, this will not work for you and you'll need to change it accordingly.

WORKDIR finally set the default working directory.

Running the containers

Once the docker-compose.yml, the docker/php/Dockerfile and docker/nginx/vhost.conf files are in place, we can start up the containers.

You can use the following command to start all containers in foreground mode:

docker-compose up

In foreground mode, the logs for all containers will be shown as if you were using tail -f. If you press CTRL-C, the containers will shut down. What I prefer to do is run the containers in detached mode:

docker-composer up -d

This will start the containers and return to your shell after that. If you want to see the latest logs, you can run:

docker-compose logs

Or you could follow (tail -f) the logs by adding -f.

Shut everything down using:

docker-compose down

By adding -v, you'll also delete the volumes you've defined.

Accessing the webserver, php or mysql

Now you've got your containers running, you might want to access the webserver to check if your project still runs correctly. Since we've added some port mappings in the docker-compose.yml file, you'll easily be able to.

On the nginx we've mapped port 8080 to 80. This means you can access http://localhost:8080 and it maps to port 80 inside the nginx container.

We did the same on the mysql container, mapping localhost:3306 or mysql://localhost to port 3306 inside the container. That will allow you to access your mysql server using something like DBeaver or MySQL Workbench.

You may also run your Symfony console commands from inside the php container. You can do this using this command:

docker-compose exec --user www-data php bin/console <arguments>

The --user www-data argument ensures you don't get the permission issues I described earlier.


This is all a whole lot faster than what I was used to when running Vagrant boxes. I also found it quite easy to set up. Switching between versions of services has also been made much easier since we no longer depend on a base operating system anymore.

The only problem I was stuck on quite a while was the permissions problem, but settings the uid of the www-data user to my local hosts user id and using --user www-data when running php commands from inside the php box seems to be a nice and simple solution.

Thursday, 4 May 2017, 23:21 Bert Hekman