Natural Scrolling for Ubuntu 16.04 LTS

The touchpad can be automatically set up via Settings > Touchpad > Natural Scrolling.

However, plugging in a USB mouse is more difficult.

Enable system-wide inverse/reverse/natural scrolling on Ubuntu

In case it disappears:

1. Get your mouse device id by running the following in a terminal, you have to choose the right one:

xinput list

Take that number you got (just the number after “id=”) and replace “{device id}” with that number in the following command:

xinput list-props {device id} | grep "Scrolling Distance"

In my case:

xinput list-props 6 | grep "Scrolling Distance"

This will output something like below, remember that “Scrolling Distance” is case-sensitive. If nothing is outputted, you’ve chosen a wrong device id, go back to step 1 and choose another one:

Evdev Scrolling Distance (270): 1, 1, 1

So 270 is your property number, 1, 1, 1 is your scrolling distance, remember this to use later.

It is case sensitive unless you use -i in the grep command. Write down the numbers you find in the output from that command (in my case it was the number 1, shown three times and separated by commas). You will use the negative values of the numbers you get in your output. Also, make sure to write down the property number (it will be in parentheses in the output; in my case, it was (270) in Ubuntu and (273) in Fedora).

Note: If you get no output containing the property “Scrolling Distance” this method will not work for you and you will need to stop here and skip to an alternate way.

2. Create a natural scrolling config file by running the following command in your open terminal:

sudo touch /usr/share/X11/xorg.conf.d/20-natural-scrolling.conf

3. Now, config the natural scrolling profile by running the following command (you can use your favorite text editor instead of nano but I use nano):

sudo nano /usr/share/X11/xorg.conf.d/20-natural-scrolling.conf

In the file you have opened in your preferred text editor, paste the following (but be sure to change the numbers to the same comma-separated numbers you got from step 3; in my case, the number was 1 so in order to make the scroll inverse, I will change 1 to -1):

Section "InputClass"
        Identifier "Natural Scrolling"
        MatchIsPointer "on"
        MatchDevicePath "/dev/input/event*"
        Option "VertScrollDelta" "-1"
        Option "HorizScrollDelta" "-1"
        Option "DialDelta" "-1"

Save the file (Ctrl+O) and exit (Ctrl+X) the text editor. No need for a reboot. Just issue the following command (substituting the property number and the negatives of the numbers you got in the third step, and the device id you got from the second step):

xinput set-prop {device id} {property number} -1 -1 -1

In my case:

xinput set-prop 6 270 -1 -1 -1

Python: raise KeyError(key) from None


#!/usr/bin/env python3
import os
testing = os.environ['testing']

will generate:

Traceback (most recent call last):
  File "./", line 3, in <module>
    testing = os.environ['testing']
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/", line 669, in __getitem__
    raise KeyError(key) from None
KeyError: 'testing'

if the environment variable does not exist.


Instead use:

testing = os.environ.get('testing', 'False')

which lets you set a default.


aws_autoscaling_group – diffs didn’t match during apply. This is a bug with Terraform

happens when you have code like this:

resource "aws_autoscaling_group" "my_asg" {
  name                 = "my_asg"
  launch_configuration = "${}"
  min_size             = 1
  max_size             = 1
  availability_zones = "${var.availability_zones}"

  vpc_zone_identifier = ["${}"]

Seems you can’t mix availability_zones and vpc_zone_identifier.

CIDR to IPv4 converter

Handy converter:

E.g. for the CIDR to IP Range using a CIDR Range of

means 64 IP addresses – the first being 0 and the last 33.


You can calculate this simply by adding up how many you need to get to 32 – i.e. 6.

Then 2^6 = 64.

So, the first would be and the last would be


Terraform: Error creating launch configuration: AlreadyExists: Launch Configuration by this name already exists

If you’re creating an ASG using an AWS Launch Configuration, you cannot use a name for the Launch Configuration.

The solution? Simply omit name from your launch configuration.

Launch Configurations cannot be updated after creation with the Amazon Web Service API.


Install multiple versions of Python


Ignore the top link on Google which takes you a process of using pyenv. It’s not until you’ve spent several hours painstakingly following the instructions that you find out it’s for some shell I’ve never used called Fish.

Just do:

  1. brew install python2
  2. brew install python3
  3. then to use Python 2, use python2 and for Python 3, use python3


i.e. DON’T DO:

  1. use pyenv
  2. make sure brew is up to date: brew update && brew upgrade pyenv
  3. pyenv install 3.7.2
  4. pyenv install 2.7.14
  5. Set the global version with pyenv global 3.7.2
  6. Set local versions (e.g. for legacy projects) with pyenv local 2.7.14



  • latest version of Python:
  • Blog post on pyenv:



ERROR: The Python zlib extension was not compiled. Missing the zlib?

brew install readline xz

did not work for me.

This worked though:

CFLAGS="-I$(xcrun --show-sdk-path)/usr/include" pyenv install -v 2.7.14







Let’s say you want to find out the version of some software. It’s a fucking mess. The options tend to be:

<software name> -v

<software name> --version

<software name> -V

<software name> version

<software name> -version


Unfortunately they all vary. E.g.

Python understands --version and -V.

Whereas Ansible only takes --version.

ssh only understands -V whereas PHP understands -v and --version.

Finally, Java stands by itself with the odd -version.

And I still haven’t figured out how you get ls to tell you its version on the Mac:


Here’s what uses what: 


  • PHP


  • Ansible
  • awk
  • PHP
  • Python 2.7 and 3.x
  • Terraform
  • zsh


  • Python 2.7 and 3.x
  • ssh


  • kubectl
  • Terraform


  • Java


Kubernetes Up & Running: Chapter 7



kubectl run alpaca-prod --replicas=3 --port=8080 --labels="ver=1,app=alpaca,env=prod"
kubectl expose deployment alpaca-prod
kubectl run bandicoot-prod --replicas=2 --port=8080 --labels="ver=2,app=bandicoot,env=prod"
kubectl expose deployment bandicoot-prod
kubectl get services -o wide


In another terminal:

ALPACA_POD=$(kubectl get pods -l app=alpaca -o jsonpath='{.items[0]}')
echo $ALPACA_POD alpaca-prod-7f94b54866-dwwxg
kubectl port-forward $ALPACA_POD 48858:8080

Forwarding from -> 8080
Forwarding from [::1]:48858 -> 8080


Now access the cluster with:



  • use http not https
  • If you get localhost refused to connect. then check original pod. E.g.
    • kubectl logs alpaca-prod-7f94b54866-dwwxg
2019/01/09 11:44:22 Starting kuard version: v0.7.2-1
2019/01/09 11:44:22 **********************************************************************
2019/01/09 11:44:22 * WARNING: This server may expose sensitive
2019/01/09 11:44:22 * and secret information. Be careful.
2019/01/09 11:44:22 **********************************************************************
2019/01/09 11:44:22 Config:
  "address": ":8080",
  "debug": false,
  "debug-sitedata-dir": "./sitedata",
  "keygen": {
    "enable": false,
    "exit-code": 0,
    "exit-on-complete": false,
    "memq-queue": "",
    "memq-server": "",
    "num-to-gen": 0,
    "time-to-run": 0
  "liveness": {
    "fail-next": 0
  "readiness": {
    "fail-next": 0
  "tls-address": ":8443",
  "tls-dir": "/tls"
2019/01/09 11:44:22 Could not find certificates to serve TLS
2019/01/09 11:44:22 Serving on HTTP on :8080

which seems to indicate it’s successfully serving on 8080 locally.

So, the issue is with the code on Page 67. i.e. it should be:

kubectl port-forward $ALPACA_POD 8080:8080


DNS Resolver: http://localhost:8080/-/dns

with alpaca-prod


alpaca-prod.default.svc.cluster.local.	5	IN	A

i.e. name of service: alpaca-prod

namespace: default

resource type: svc

base domain: cluster.local

Note: you could use:

  • alpaca-prod.default
  • alpaca-prod.default.svc.cluster.local.


Adding in a readinessProbe:

      - image:
        imagePullPolicy: IfNotPresent
        name: alpaca-prod
                path: /ready
                port: 8080
            periodSeconds: 2
            initialDelaySeconds: 0
            failureThreshold: 3
            successThreshold: 1

and restart port-forward (as the pods are recreated).

There should now be a Readiness Probe tab where you can make that pod fail / succeed /ready checks.

The pod with that IP address is destroyed after 3 fails and recreated after it succeeds.

k get endpoints alpaca-prod --watch


Now, after halting the port-forward and watch, we’ll look at NodePorts:

kubectl edit service alpaca-prod

and change

type: ClusterIP


type: NodePort

It immediately changes when you save. i.e.

kubectl describe service alpaca-prod

shows `Type: NodePort`

Note: if you misspell the Service type you’ll immediately be bounced back into the Editor with a couple of lines at the top indicating the problem. E.g.

# services "alpaca-prod" was not valid:
# * spec.type: Unsupported value: "Nodey": supported values: "ClusterIP", "ExternalName", "LoadBalancer", "NodePort"

See also Kubernetes: kubectl