How to configure OctoPrint/OctoPi with Ethernet using a static IP

In order to configure OctoPrint/OctoPi to use the Raspberry Pi Ethernet interface with a static IP, first open the rootfs partition on the SD card. After that, open etc/network/interfaces in your preferred text editor (you might need to open it as root, e.g. sudo nano etc/network/interfaces – ensure that you don’t edit your local computer’s /etc/network/interfaces but the one on the SD card).

Now copy the following text to the end of etc/network/interfaces:

auto eth0
allow-hotplug eth0
iface eth0 inet static

You might need to adjust the IP addresses so they match your router.

Save the file and insert the SD card into your Raspberry Pi. You should be able to ping in – in our example, ping

Tested with OctoPrint 0.16.0

Original source: OctoPrint forum

Posted by Uli Köhler in Embedded, Linux

How to fix ‘elasticsearch exited with code 78’


You want to run ElasticSearch using docker, but the container immediately stops again using this error message

elasticsearch exited with code 78


elasticsearch2 exited with code 78


If you look through the entire log message, you’ll find lines like

elasticsearch     | [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

Therefore we need to increase the vm.max_map_count limit:

sudo sysctl -w vm.max_map_count=524288

Now we need to edit /etc/sysctl.conf so the setting will also be in effect after a reboot.

Look for any vm.max_map_count line in /etc/sysctl.conf. If you find one, set its value to 524288. If there is no such line present, add the line


to the end of /etc/sysctl.conf

Original source: GitHub


Posted by Uli Köhler in Container, Databases, Docker, Linux

MongoDB: How to run db.adminCommand() in NodeJS


You want to run a db.adminCommand() in NodeJS using the node-mongodb-native client, e.g. you want to run the NodeJS equivalent of

db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: 100151432});


Use conn.executeDbAdminCommand() where db is a MongoDB database object.

db.executeDbAdminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: 100151432});

Full example:

// To install, use npm i --save mongodb
const MongoClient = require('mongodb').MongoClient;

async function configureMongoDB() {
    // Connect to MongoDB
    const conn = await MongoClient.connect('mongodb://localhost:27017/', { useNewUrlParser: true });
    const db = await conn.db('mydb');
    // Configure MongoDB settings
    await db.executeDbAdminCommand({
        setParameter: 1,
        internalQueryExecMaxBlockingSortBytes: 100151432
    // Cleanup
    return conn.close();

// Run configureMongoDB()
configureMongoDB().then(() => {}).catch(console.error)


Posted by Uli Köhler in Databases, NodeJS

How to find absolute path on webserver using PHP

The following script shows you the absolute path on the webserver which often can’t be found using FTP alone.

<?php /* path.php */
list($scriptPath) = get_included_files();
echo $scriptPath;

Upload this script to your webspace using FTP and then access it using the browser. It will show you a path like

Posted by Uli Köhler in PHP

How to install docker and docker-compose on Ubuntu in 30 seconds

Use our script:

wget -qO- | sudo bash /dev/stdin

After that, logout and login (or close your SSH session and re-connect) (else, you will only be able to run the docker client as root – see Solving Docker permission denied while trying to connect to the Docker daemon socket)

Or do it manually:

Copy and paste these command blocks into your Linux shell. You need to copy & paste one block at a time – you can paste the next block once the previous block is finished!

# Install prerequisites
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# Add docker's package signing key
curl -fsSL | sudo apt-key add -
# Add repository
sudo add-apt-repository -y "deb [arch=$(dpkg --print-architecture)] $(lsb_release -cs) stable"
# Install latest stable docker stable version
sudo apt-get update
sudo apt-get -y install docker-ce
# Install docker-compose
sudo curl -L "$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod a+x /usr/local/bin/docker-compose
# Enable & start docker
sudo systemctl enable docker
sudo systemctl start docker

Note that this will install Docker as deb package whereas docker-compose will be downloaded to /usr/local/bin.

In case you intend to use docker under your normal user account (i.e. without sudo), you might want to add that user to the docker group (we recommend you do this):

sudo usermod -a -G docker $USER

This settings requires that you logout and log back in (or completely terminate your SSH session and open a new SSH session) in order to take effect.

In case that does not work and you still get permission denied error messages try rebooting your computer.

In order to check if your user is currently a member of the docker groups, run


Example output:

uli adm tty lp uucp dialout cdrom sudo dip plugdev lpadmin sambashare vboxusers lxd docker

These are the groups your user currently belongs to (as said before, changes only take effect after logging out and logging back in or terminating and re-opening your SSH session). If docker is listed in the output of groups (tip: it’s typically near the end in case you have just added it!), you should be able to access the docker socket. See the Background information section of Solving Docker permission denied while trying to connect to the Docker daemon socket for more details on docker sockets and their permissions.

Posted by Uli Köhler in Container, Docker, Linux

How to read NodeJS child-process.exec stdout/stderr using async/await Promises

You want to run a command like file my.pdf using NodeJS child-process.exec and get its stdout after it’s finished.


TL;DR: (await exec('file my.pdf')).stdout

We’re using child-process-promise here in order to simplify our implementation. Install it using npm i --save child-process-promise !

const { exec } = require('child-process-promise');

async function run () {
    const ret = await exec(`file my.pdf`);
    return ret.stdout;


You can also use .stderr instead of .stdout to get the stderr output as a string

Posted by Uli Köhler in Javascript, NodeJS

How to fix MicroPython I2C no data


You’ve configured MicroPython’s I2C similar to this (in my case on the ESP8266 but this applies to many MCUs):

i2c = machine.I2C(-1, machine.Pin(5), machine.Pin(4))

but you can’t find any devices on the bus:

>>> i2c.scan()


Likely you forgot to configure the pins as pullups. I2C needs pullups to work, and many MCUs (like the ESP8266) provide support for integrated (weak) pull-ups.

p4 = machine.Pin(4, mode=machine.Pin.OUT, pull=machine.Pin.PULL_UP)
p5 = machine.Pin(5, mode=machine.Pin.OUT, pull=machine.Pin.PULL_UP)
i2c = machine.I2C(-1, p5, p4)

i2c.scan() # [47]

You can also verify this by checking with a multimeter or an oscilloscope: When no communication is going on on the I2C bus, the voltage should be equivalent to the supply voltage of your MCU (usually 3.3V or 5V – 0V indicates a missing pullup or some other error).

Posted by Uli Köhler in Electronics, MicroPython, Python

How to fix MicroPython ‘ValueError: invalid I2C peripheral’

If you see the error message

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid I2C peripheral

you are likely running code like this:

import machine

i2c = machine.I2C(machine.Pin(5), machine.Pin(4))


The MicroPython API has changed (source: forum). You need to use this syntax instead:

import machine

i2c = machine.I2C(-1, machine.Pin(5), machine.Pin(4))

-1 is the I2C ID that selects a specific peripheral. -1 selects a software I2C implementation which can work on most pins. See the MicroPython I2C class documentation for more details.

Posted by Uli Köhler in Electronics, MicroPython, Python

How to fix NodeJS MongoDB ‘Cannot read property ‘high_’ of null’

When encountering an error message like

TypeError: Cannot read property 'high_' of null
    at Long.equals (/home/uli/dev/NMUN/node_modules/bson/lib/bson/long.js:236:31)
    at nextFunction (/home/uli/dev/NMUN/node_modules/mongodb-core/lib/cursor.js:473:16)
    at (/home/uli/dev/NMUN/node_modules/mongodb-core/lib/cursor.js:763:3)
    at Cursor._next (/home/uli/dev/NMUN/node_modules/mongodb/lib/cursor.js:211:36)
    at nextObject (/home/uli/dev/NMUN/node_modules/mongodb/lib/operations/cursor_ops.js:192:10)
    at hasNext (/home/uli/dev/NMUN/node_modules/mongodb/lib/operations/cursor_ops.js:135:3)

you likely have code like this:

const cursor = db.getCollection('mycollection').find({})
while (cursor.hasNext()) {
    const doc =;
    // ... handle doc ...

The solution is quite simple: Since find(), cursor.hasNext() and all return Promises, you can’t use their results directly.

This example shows you how to do it properly using async/await:

const cursor = await db.getCollection('mycollection').find({})
while (await cursor.hasNext()) {
    const doc = await;
    // ... handle doc ...

In order to do this remember that the function containing this code will need to be an async function. See the Mozilla documentation or google for Javascript async tutorial in order to learn about the details!

Posted by Uli Köhler in Databases, Javascript

How to install MongoDB CE on Ubuntu in 1 minute

Quick install using

wget -qO- | bash

Run these shell commands on your Ubuntu computer to install the current MongoDB community edition and automatically start it (both instantly and on bootup)

sudo apt-key adv --keyserver hkp:// --recv 4B7C549A058F8B6B
echo "deb [ arch=amd64 ] bionic/mongodb-org/4.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.2.list
sudo apt-get update
sudo apt-get install -y mongodb-org
sudo systemctl enable mongod
sudo systemctl start mongod

Source: Official MongoDB documentation

Posted by Uli Köhler in Databases, Linux

Fixing Promise ‘TypeError: myfunc(…).then(…).reject is not a function’

When encountering this error message in Javascript related to Promises:

TypeError: myfunc(...).then(...).reject is not a function

The solution is quite simple: When you want to catch the error from the promise, you need to use catch instead of reject like this:



Posted by Uli Köhler in Javascript

How to install NodeJS 10.x on Ubuntu in 1 minute

Note: Also see How to install NodeJS 12.x on Ubuntu in 1 minute

Run these shell commands on your Ubuntu computer to install NodeJS 10.x:

curl -sL | sudo -E bash -
sudo apt-get install -y nodejs

Instead of setup_10.x you can also choose other versions like setup_8.x. However, using this method, you can’t install multiple versions of NodeJS in parallel.

Source: Official nodesource documentation

Posted by Uli Köhler in Linux, NodeJS

How to run X server using xserver-xorg-video-dummy driver on Ubuntu

When you need to have a dummy display on a headless server (i.e. without any physical monitor attached), first install the dummy driver package:

sudo apt install xserver-xorg-video-dummy

After that, save this config file as dummy-1920x1080.conf

Section "Monitor"
  Identifier "Monitor0"
  HorizSync 28.0-80.0
  VertRefresh 48.0-75.0
  # 1920x1080 @ 60.00 Hz (GTF) hsync: 67.08 kHz; pclk: 172.80 MHz
  Modeline "1920x1080_60.00" 172.80 1920 2040 2248 2576 1080 1081 1084 1118 -HSync +Vsync

Section "Device"
  Identifier "Card0"
  Driver "dummy"
  VideoRam 256000

Section "Screen"
  DefaultDepth 24
  Identifier "Screen0"
  Device "Card0"
  Monitor "Monitor0"
  SubSection "Display"
    Depth 24
    Modes "1920x1080_60.00"

Now you can start

sudo X -config dummy-1920x1080.conf

The output will look like this:

X.Org X Server 1.19.6
Release Date: 2017-12-20
X Protocol Version 11, Revision 0
Build Operating System: Linux 4.4.0-138-generic x86_64 Ubuntu
Current Operating System: Linux ubuntu-s-1vcpu-2gb-fra1-01 4.15.0-45-generic #48-Ubuntu SMP Tue Jan 29 16:28:13 UTC 2019 x86_64
Kernel command line: BOOT_IMAGE=/boot/vmlinuz-4.15.0-45-generic root=LABEL=cloudimg-rootfs ro console=tty1 console=ttyS0
Build Date: 25 October 2018  04:11:27PM
xorg-server 2:1.19.6-1ubuntu4.2 (For technical support please see 
Current version of pixman: 0.34.0
        Before reporting problems, check
        to make sure that you have the latest version.
Markers: (--) probed, (**) from config file, (==) default setting,
        (++) from command line, (!!) notice, (II) informational,
        (WW) warning, (EE) error, (NI) not implemented, (??) unknown.
(==) Log file: "/var/log/Xorg.0.log", Time: Sat Feb 23 17:48:07 2019
(++) Using config file: "dummy-1920x1080.conf"
(==) Using system config directory "/usr/share/X11/xorg.conf.d"

You need to keep this process running as long as you need the display.

Identifying the display number

If no other X server is running, this will, by default, use display number 0. Look for this line to identify the display in use:

(==) Log file: "/var/log/Xorg.0.log", Time: Sat Feb 23 17:48:07 2019

In said line, Xorg.0.log tells you that display 0 is in use, whereas Xorg.1.log tells you that display 1 is in use.

Starting your software

Now you can start your software that needs a graphical interface as follows (we use firefox, and display number 0, as an example):

DISPLAY=:0 firefox

Don’t forget the colon in DISPLAY=:0!

Starting on a specific display number

If you want to start the X server on a specific display number, e.g. 7, because some other dummy server is running concurrently, use this command to start the X server:

sudo X :7 -config dummy-1920x1080.conf

Of course you’ll need to use DISPLAY=:7 firefox in order to start firefox using this config!

In case there is already an X server running on that display, you’ll see an error message like this:

Fatal server error:
(EE) Server is already active for display 7
        If this server is no longer running, remove /tmp/.X7-lock
        and start again.
Please consult the The X.Org Foundation support 
 for help. 

Look for Server is already active for display 7 to be sure you’re seeing the same error message!

Posted by Uli Köhler in Linux

How to download a file or directory from a LXC container

To download files, use

lxc file pull <container name>/<path>/<filename> <target directory>

To download directories, use

lxc file pull --recursive <container name>/<path>/<filename> <target directory>


Download /root/myfile.txt from mycontainer to the current directory (.):

lxc file pull mycontainer/root/myfile.txt .

Download /root/mydirectory from mycontainer to the current directory (.):

lxc file pull -r mycontainer/root/mydirectory .


Posted by Uli Köhler in Container, Linux, LXC, Virtualization

How to recover WordPress admin access if you only have FTP access

There are well-documented solutions to recover the wordpress admin access if you have MySQL, phpMyAdmin or shell access.

This solution shows you how to create a new admin user if you don’t know the admin username or password and you don’t have any form of MySQL or shell access (only FTP access is required).

Step 1: Identify your currently active theme

This can be done by looking at the source code of your homepage (go to your domain, then Ctrl+U to show the source) and then Ctrl+F-search for wp-content/themes. It will show hits like This means the currently active theme is twentyfifteen.

Step 2: Create a new admin user using functions.php

Now open your FTP software (I recommend FileZilla) and find your wp-content folder. Inside wp-content, go to themes and then open the folder of your currently active theme.

If the currently active theme is not listed in your wp-content/themes folder, you might have the wrong wp-content folder. Check if there are any other folders around.

When you have found your theme folder, edit functions.php and, just after the first <?php, add this block of code:

function wpb_admin_account(){
    $user = 'newadmin';
    $pass = 'saiquae9shahZus6eeri3feNae8gie';
    $email = '[email protected]';
    if ( !username_exists( $user )  && !email_exists( $email ) ) {
        $user_id = wp_create_user( $user, $pass, $email );
        $user = new WP_User( $user_id );
        $user->set_role( 'administrator' );

Be sure to replace the username, password and email! I recommend to use a new random password and a non-generic username! The username you enter here must.

Save the file and upload it to the server.

After that, goto your homepage and reload once (this will create the new user).

Then, try to login using your newly created user (go to e.g. to do so!). If it doesn’t work, check if you edited the functions.php for the correct theme and try to use a different username!

Step 3: Delete the code we just created

If you just leave in the code, this will create a potential security risk. So I recommend deleting it right away!

Also, be sure to delete any admin users you don’t need afterwards.


Posted by Uli Köhler in PHP, Wordpress

Get all suffixes for a string in Python (Suffix list)


Given a string, e.g. foobar, you want to get the list of all suffixes of said string, e.g. ["r", "ar", "bar", "obar", "oobar", "foobar"]


Use this snippet:

def all_suffixes(s):
    return [s[-i:] for i in range(1, len(s) + 1)]

s = "foobar"
print(all_suffixes(s)) # ['r', 'ar', 'bar', 'obar', 'oobar', 'foobar']


Posted by Uli Köhler in Algorithms, Python

How to use Z0 (characteristic impedance of vacuum) constant in SciPy/NumPy

If you want to use the Z0 constant (characteristic impedance of free space) in Python, use this snippet:

import scipy.constants
Z0 = scipy.constants.physical_constants['characteristic impedance of vacuum'][0]

print(Z0) # 376.73031346177066

In contrast to other constants, Z0 is not available directly like scipy.constants.pi but you need to use the scipy.constants.physical_constants dict in order to access it.

Posted by Uli Köhler in Mathematics, Python