EMQX 5.x HTTP password authentication server using NodeJS

Note: If you also want to implement ACL authorization via HTTP, see our extension to this example: EMQX 5.x HTTP ACL server using NodeJS

This server implements a minimal HTTP authentication server. In this minimal example, it will always allow authentication – you need to implement your own logic to verify passwords. Note: This server is written for EMQX versionx5.0 and will not work for EMQX 4.x without modification. See the official documentation on EMQX 5.x HTTP auth for more information.

#!/usr/bin/env node
const router = require('koa-router')();
const koaBody = require('koa-body');
const Koa = require('koa');
const app = new Koa();

app.use(koaBody());

router.post('/emqx/auth', async ctx => {
    const body = ctx.request.body;
    const username = body.username;
    const password = body.password;
    // TODO: This example always returns "allow"
    // You need to implement your authentication logic
    ctx.body = {
        result: "allow",
        is_superuser: false
    };
});

app.use(router.routes());

if (!module.parent) app.listen(19261);

This script is based on our previous post Minimal Koa.JS example with Router & Body parser, hence you can install the dependencies using

npm i --save koa koa-router koa-body

The request body config which you can set in the EMQX dashboard is

{
  "client_id": "${clientid}",
  "password": "${password}",
  "username": "${username}"
}

 

Posted by Uli Köhler in EMQX, MQTT, NodeJS

How to install mosquitto_sub on Ubuntu 22.04

You can install the mosquitto client (mosquitto_sub) by running

sudo apt -y install mosquitto-clients

 

Posted by Uli Köhler in Linux, MQTT

How to git clone only a specific file or directory

Git does not directly support cloning only a specific file or directory from a repository. However, you can use --depth 1 to clone only one specific revision (as opposed to the entire history) and use --no-checkout followed by git sparse-checkout set to checkout not the entire file tree but only a specific file.

In the following example, we’ll checkout only the EMQX config files (in apps/emqx/etc) from the entire emqx repository:

git clone --depth 1 --branch v5.0.8 --no-checkout https://github.com/emqx/emqx.git
cd emqx
git sparse-checkout set apps/emqx/etc
git checkout v5.0.8

After this command, the emqx folder will only contain .git and apps/emqx/etc.

Note that you can call git sparse-checkout set multiple times in order to checkout multiple distinct paths.

This example was adapted from this StackOverflow post.

Posted by Uli Köhler in git, Version management

How to query all camera parameters using v4l2-ctl

You can query all parameters using v4l2-ctl‘s --all parameter, for example:

v4l2-ctl --device /dev/video0 --all

 

Posted by Uli Köhler in Audio/Video

PySerial minimal example: Copy data received from serial port to stdout

This example does not send data to the serial port but only copies data received from the serial port to stdout. Newlines received from the serial port are preserved.

#!/usr/bin/env python3
import serial
ser = serial.Serial("/dev/ttyUSB0", baudrate=115200)

try:
    while True:
        response = ser.read()
        if response:
            print(response.decode("iso-8859-1"), end="")
finally:
    ser.close()

By using iso-8859-1   decoding, we ensure that even binary bytes are decoded in some way and do not cause an exception.

Posted by Uli Köhler in 3D printing, Embedded, Python

How to leave netmaker network

Once you have used netclient join to join a netmaker network, you can use

netclient leave --network mynetwork

to permanently leave the network named mynetwork (until you re-join of course).

 

Posted by Uli Köhler in Networking, VPN

How to load & start EMQX plugin using emqx_ctl

You can easily load (& start) an EMQX plugin such as emqx_auth_mnesia

./bin/emqx_ctl plugins load emqx_auth_mnesia

If you are using docker-compose and your container is named emqx, you can use

docker-compose exec emqx ./bin/emqx_ctl plugins load emqx_auth_mnesia

After running this command, the plugin will show up as Running in the dashboard:

Posted by Uli Köhler in EMQX, MQTT

How to change EMQX admin password

Changing the password is as simple as

./bin/emqx_ctl admins passwd admin "[new password]"

If you are using docker-compose and your container is named emqx, you can use

docker-compose exec ./bin/emqx_ctl admins passwd admin "[new password]"
Posted by Uli Köhler in EMQX, MQTT

What is the EMQX default username & password

The default credentials for EMQX are:

  • Username: admin
  • Password:public

It should go without saying that you must change the password!

Posted by Uli Köhler in EMQX, MQTT

What is the EMQX default password for the ‘admin’ account?

The default password for the EMQX admin account is publicChange it as soon as possible 🙂

Posted by Uli Köhler in EMQX, MQTT

How to run emqx_ctl for docker-compose-based EMQX setups

You can simply run emqx_ctl using the following command:

docker-compose exec emqx ./bin/emqx_ctl [command]

where emqx is the name of the container to run emqx_ctl in.

Example:

docker-compose exec emqx ./bin/emqx_ctl status

 

Posted by Uli Köhler in EMQX, MQTT

How to fix docker emqx_ctl Node ’[email protected]’ not responding to pings.

Problem:

When trying to run emqx_ctl in a dockerized emqx setup using a command like

docker-compose exec emqx ./bin/emqx status

you see an error message like

Node '[email protected]' not responding to pings.
/opt/emqx/bin/emqx: line 41: die: command not found

Solution:

The problem here is that emqx_ctl is trying to connect to the IP address for node1.emqx.mydomain.com but that IP address does not point to the IP address for the docker container (maybe it’s the public IP address for your server?)

The solution here is to create a network alias within docker/docker-compose so that the Docker DNS system resolves node1.emqx.mydomain.com to the internal IP address of the container.

For example, in docker-compose, you can create your network using

networks:
  emqx:
    driver: bridge

and then configure the alias for the container using

services:
  emqx:
    image: emqx:4.4.4
    environment:
      - "EMQX_NAME=emqx"
      - "EMQX_HOST=node1.emqx.mydomain.com"
      - "EMQX_LOADED_PLUGINS=emqx_recon,emqx_retainer,emqx_management,emqx_dashboard"
    ports:
      - 18083:18083
      - 1883:1883
    volumes:
      - ./emqx_data:/opt/emqx/data
      - ./emqx_log:/opt/emqx/log
    networks:
      emqx:
        aliases:
          - "node1.emqx.mydomain.com"

 

 

Posted by Uli Köhler in Container, Docker, EMQX, MQTT

How to use custom port for ZeroTier instead of 9993 on Linux

You can create /var/lib/zerotier-one/local.conf – by default it doesn’t exist, if it does, just add these settings:

{
  "settings": {
    "primaryPort": 9994
  }
}

 

Posted by Uli Köhler in Linux, Networking, ZeroTier

How I fixed zerotier-one: fatal error: cannot bind to local control interface port 9993

Problem:

On my server, which was running zerotier already using docker, I wanted to install zerotier on a system level.

but whenever I ran zerotier-cli I saw the following error message:

zerotier-one: fatal error: cannot bind to local control interface port 9993

and when I tried to start the daemon using zerotier-one -d this error message was displayed:

zerotier-cli: missing port and zerotier-one.port not found in /var/lib/zerotier-one

Solution:

In my case, this was due to the standard port 9993 already being used by the dockerized zerotier. Therefore I needed to configure a custom port by creating /var/lib/zerotier-one/local.conf:

{
  "settings": {
    "primaryPort": 9994
  }
}

You can choose any port you like.

Posted by Uli Köhler in Networking, ZeroTier

How to install gcsfuse on Ubuntu 22.04 (jammy)

If you try to install gcsfuse on Ubuntu 22.04, you will face two issues. First, the signature can’t be verified due to the new method of managing APT keys. Secondly, the gcsfuse repo does not have packages for Ubuntu 22.04 even 5 months after its release:

Err:10 http://packages.cloud.google.com/apt gcsfuse-jammy Release                                                                                                                  
  404  Not Found [IP: 64.233.161.101 80]

You can work around both issues by force-installing the bionic packages which appear to work fine for me.

export GCSFUSE_REPO=gcsfuse-bionic
echo "deb [signed-by=/usr/share/keyrings/gcsfuse.gpg] http://packages.cloud.google.com/apt $GCSFUSE_REPO main" | sudo tee /etc/apt/sources.list.d/gcsfuse.list
wget -qO- https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor --yes --output /usr/share/keyrings/gcsfuse.gpg

 

Posted by Uli Köhler in Linux

How to fix apt error: NO_PUBKEY FEEA9169307EA071 NO_PUBKEY 8B57C5C2836F4BEB

Problem:

When running apt update, you see the following error message:

Err:12 http://packages.cloud.google.com/apt gcsfuse-bionic InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY FEEA9169307EA071 NO_PUBKEY 8B57C5C2836F4BEB

Solution:

This error occurs due to the VirtualBox repo using the outdated (as of April 2022) apt-key method of importing keys.

You can import the key by just installing the gcsfuse repo again. The following commands are based on the official installation guide.

export GCSFUSE_REPO=gcsfuse-`lsb_release -c -s`
echo "deb [signed-by=/usr/share/keyrings/gcsfuse.gpg] http://packages.cloud.google.com/apt $GCSFUSE_REPO main" | sudo tee /etc/apt/sources.list.d/gcsfuse.list
wget -qO- https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor --yes --output /usr/share/keyrings/gcsfuse.gpg

and then running

apt update

again. Note that at the time of writing this post, gcsfuse is not available for Ubuntu 22.04 in the official repository.

You can work around this by installing the bionic packages instead of jammy. For more details, see our post

Posted by Uli Köhler in Linux

Coyping a folder and renaming file extensions in Python

This script copies myfolder to myfolder2 recursively and renames all .txt files to .xml

#!/usr/bin/env python3
import os
import os.path
import re
import shutil

srcfolder = "myfolder"
dstfolder = "myfolder2"

for subdir, dirs, files in os.walk(srcfolder):
    for file in files:
        # Rename .txt to .xml
        if file.endswith(".txt"):
            dstfile_name = re.sub(r"\.txt$", ".xml", file) # Regex to replace .txt only at the end of the string
        else:
            dstfile_name = file
        # Compute destination path
        srcpath = os.path.join(subdir, file)
        dstpath_relative_to_outdir = os.path.relpath(os.path.join(subdir, dstfile_name), start=srcfolder)
        dstpath = os.path.join(dstfolder, dstpath_relative_to_outdir)
        # Create directory if not exists
        os.makedirs(os.path.dirname(dstpath), exist_ok=True)
        # Copy file (copy2 preserves metadata)
        shutil.copy2(srcpath, dstpath)

 

Posted by Uli Köhler in Python

How to zip folder recursively using Python (zipfile)

This script will zip the folder myfolder recursively to myzip. Note that empty directories will not be copied over to the ZIP.

#!/usr/bin/env python3
import zipfile
import os

# This folder 
folder = "myfolder"

with zipfile.ZipFile(f"{folder}.zip", "w") as outzip:
    for subdir, dirs, files in os.walk(folder):
        for file in files:
            # Read file
            srcpath = os.path.join(subdir, file)
            dstpath_in_zip = os.path.relpath(srcpath, start=folder)
            with open(srcpath, 'rb') as infile:
                # Write to zip
                outzip.writestr(dstpath_in_zip, infile.read())

 

Posted by Uli Köhler in Python

How to generate random hex string using OpenSSL

The following command will generate a 32-bytes long random hex string

openssl rand -hex 16

Example:

$ openssl rand -hex 16
122166dd9e2d617246da9af9d7d3cd6f

The command lists 16, not 32 because OpenSSL will generate 16 random binary bytes and then convert these 16 bytes into 32 hex characters.

Posted by Uli Köhler in Linux

How I create my wildcard certificates using certbot

When I’m not using traefik to automagically manage my Let’s Encrypt certificates, this is my preferred way to create Let’s Encrypt wildcard certificates. I use the certbot cloudflare plugin in order to perform the DNS-01 challenge which is required in order to obtain the certificate.

First, I create the script in /etc/letsencrypt/wildcard-mydomain.sh

#!/bin/sh
sudo certbot certonly -d mydomain.de,*.mydomain.de --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare-mydomain.ini --preferred-challenges dns-01

and, if not already present, I also create the credentials file /etc/letsencrypt/cloudflare-mydomain.ini (replace the credentials by your cloudflare email and API key):

dns_cloudflare_email = "[email protected]"
dns_cloudflare_api_key = "f4a800573c41858be35aaead4e73d741"

After that, you only have to run the script once:

bash /etc/letsencrypt/wildcard-mydomain.sh

If the process succeeds, your certificate will be in /etc/letsencrypt/live/mydomain.de. However you need to ensure to regularly run certbot renew in order to renew the certificates which are only valid for 3 months.

In our previous post How to automatically renew Let’s Encrypt certbot certs on Ubuntu we provide a simple solution to install a system service to automatically renew the certificates daily. It’s extremely easy to install using just a single command to install the systemd service.

Posted by Uli Köhler in Networking
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Cookie settingsACCEPTPrivacy & Cookies Policy