Move LXC container to new VM

Create snapshot on your current VM

lxc snapshot container_name snapshot_name

Validate created snapshot by checking the snapshots list displayed with:

lxc info container_name 

In case you have not named your snapshot, look for the most recent creation date. It might have a default name like snap1.

Create an image from the snapshot

lxc publish container_name/snapshot_name --alias="image_alias" description="image_description"

Verify your created image by checking the image list displayed with:

lxc image info image_alias

Export the created image to an archive in your current path

lxc image export image_alias image_archive_name

Send the file to your new VM

Make sure, that you can establish an SSH connection to your new VM from your old VM, e.g. by a VPN or Wireguard connection. Use scp to copy the image like so:

scp ./image_archive_name.tar.gz usera@host:/home/user

Import image and launch new container on your new VM

Make sure lxc and lxd are installed on your new VM and then import the image like so:

lxc image import image_archive_name.tar.gz --alias image_alias_on_new_vm

Make sure the imported image appears in the list on your new VM.

lxc image list

Then launch a new container from the image with:

lxc launch image_alias_on_new_vm container_name
Posted by Joshua Simon in Container, LXC

How to filter for DNS “A” responses in Wireshark

In Wireshark, you can filter for DNS packets with an A (IPv4 record) response type using the

dns.resp.type == 1

filter. 1 is the binary code for the A response.

In particular, this will filter out NXDOMAIN responses that might clutter your view.

Example:

Posted by Uli Köhler in Networking

How to remote packet capture DNS requests / responses on MikroTik RouterOS

In order to packet capture just DNS packets using Tools -> Packet Sniffer, use the following settings:

  • IP protocol: Select udp (17 (udp))
  • Port: Enter 53 (53 (dns))

Note that this does not capture DNS-over-HTTPS traffic, but at the time of writing this article, this type of traffic is rare.

Example:

Posted by Uli Köhler in MikroTik, Networking

How to install avidemux3 on Ubuntu 22.04

You can install Avidemux 3 (QT) from the xtradebs PPA:

sudo apt -y install software-properties-common apt-transport-https -y
sudo add-apt-repository -y ppa:xtradeb/apps
sudo apt -y install avidemux-qt

After that, run

avidemux3_qt5

to run Avidemux 3.

Posted by Uli Köhler in Audio/Video, Linux

How to re-encode all videos in a directory as H.265 & opus using ffmpeg

In our previous post How to re-encode videos as H.265 & opus using ffmpeg for archival we listed ffmpeg commands to re-encode video files to H.265 for archival purposes.

In many cases, you want to re-encode all files in a directory. The following example command (for Linux shell such as bash) re-encodes every .avi file in the current directory, assuming that all files are non-interlaced (this affects the ffmpeg flags – see our previous post for more details).

for i in *.avi ; do ffmpeg -i "$i" -c:v libx265 -crf 26 -c:a libopus -b:a 56k "${i}.mkv" ; done

From mymovie.avi, this script will produce mymovie.avi.mkv, saving approximately 70% of the filesize (that, of course, depends heavily on the video itself).

You can easily adapt this command to your liking – for example, by encoding .mp4 files instead of .avi or usign a different CRF or audio bitrate. However, in my opinion, these are sane defaults for most video where the focus is to find a compromise between good video quality and file sie.

Posted by Uli Köhler in Audio/Video

How to properly document electronics connectors – an easy guideline

When you’re using some connector in your electronics project, you should always document the pinout – if you forget to do, you will absolutely 100% find yourself reverse-engineering your own pinout (Ask how I know). That’s a process that can easily take a few hours whereas you could have documented the pintout

Here’s a simple strategy that allows you to document the pinout.

1. Take a photo using your phone

It doesn’t have to look nice, we’re not creating an artwork here. The only requirements are that you can see the connector in its context and that you can see it :

  • For a connector on a PCB, ensure that you can see a few features around the connector from the board, and you can easily see notches or other features of the connector
  • For a connector on a cable, ensure that you can see the cable clip or any other cable

You can cut out the relevant section from the photo, but be sure to leave plenty of space around it (especially for PCB connectors) so you can

Example: PCB:

Example: Cable connector

2. Document the pins

Now load your picture into a drawing software. I mostly use draw.io which you can use from the Browser, but Inkscape also works totally fine. You can also use pixel image editing software like GIMP or Paint, but I recommend to instead use vector drawing software because it’s much easier to later modify some information when you use a vector graphics software. You can just use word, but DrawIO is typically just less cumbersome.

Place texts to annotate the function of pins and draw lines from the text to the actual pin. Use a signal color like red to make your annotations clearly visible. 

Keep in mind that this is absolutely not about making it look good. As long as it’s clear which pin belongs to which annotation, always prefer quick to nice. Trying to make it look nice will not only cost you time but also distract you from the core task of making it unambiguous.

Also document special features like the clip of a connector, or a notch (indicating pin 1) in a different color.

 

Example: PCB:

Example: Cable connector

3. For cable connectors: Document the colors that are connected to the respective pins

You can skip this step if you want to document a connector on a PCB.

For cables, you want to make sure that when manufacturing e.g. a replacement cable that the correct color of wire is soldered/crimped/etc to the connector.

I suggest you do this using a different color like green.

Example:

4. Write down what exactly you’re documenting

Typically above the photo, include metadata what it is you’re documenting. I suggest to always include that in the diagram (as opposed to just pasting the diagram into some Word document and writing it down there) because it makes it less likely that the diagram will get detached from its metadata. However, you can still write into any document where the diagram is included, there’s no reason why you have to avoid having the same information twice (sometimes it helps to spot mistakes after changes).

Always write down:

  • The name of the project, e.g. ESP32 fridge controller
  • The name of the connector within the project, e.g. debug connector
  • The type of the connector, e.g. Type of connector: RJ10 (4P4C). If applicable, also include information about where you bought the connector, manufacturer part number
  • Any information giving context to the annotations such as UART is from ESP32 perspective
  • The revision number of the project, eg. R1.0. If you don’t have a revision system, just call it R1.0, the next one R2.0 etc
  • The date when you created (or modified) the drawing, e.g. 2022-10-06. I recommend to use ISO8601 format (YYYY-MM-DDexclusively to avoid month/day confusions.

Generally, more information is better. What you think is obvious now will be totally unclear tomorrow (or to someone else)

Example:

 

5. Save the result where you’ll find it when you need it most

I always recommend to save the connector documentation both as immutable file format (i.e. a format not intended for editing) such as PDFPNGJPG and using the original format from the drawing software (.xml or .drawio) for DrawIO,

If you are managing your project in git, upload both files to the git repository. If you are using a project management software such as redmine, upload your documentation there as well. You can absolutely upload it to multiple places, that’s why we used a date and a revision number above – the most important aspect is that it’s easy to find.

6. Further reading

You might also want to take a look at the following posts:

  • This post is new so I don’t have any related posts so far 🙂
Posted by Uli Köhler in Documentation, Electronics

How to capture/sniff ICMPv6 traffic on MikroTik RouterOS

Problem:

On RouterOS up to at least v7.4.1 you can’t select ICMPv6 as IP protocol in the Tools -> Packet Sniffer

If you select icmp, you will not sniff any ICMPv6 traffic.

Solution:

The solution is to enter the ICMPv6 IP protocol ID58 – into the IP protocol field manually:

After that, ensure that you apply the settings. You can start sniffing ICMPv6 traffic immediately.

Posted by Uli Köhler in MikroTik, Networking

How to configure nginx for static Angular UIs

In order to make Angular UIs work with nginx, you have to load index.html for any URL where you would otherwise return 404 in order to allow routing to work:

location / {
  try_files $uri $uri$args $uri$args/ /index.html;
}

Full example for default site with API:

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;

        index index.html;

        server_name MyServer;

        location / {
          try_files $uri $uri$args $uri$args/ /index.html;
        }

        location /api {
                proxy_pass http://localhost:8080;
        }
}

 

Posted by Uli Köhler in nginx

Best practice Angular 14 production build command

This is the command I use to make production builds of Angular 14 webapps:
ng build ---aot --build-optimizer --common-chunk --vendor-chunk --named-chunks

While it will consume quite some CPU and RAM during the build, it will produce a highly efficient compiled output.

Posted by Uli Köhler in Angular, Javascript

Angular HttpClient plaintext (text/plain) minimal example

In order for Angular’s HttpClient to process plaintext responses and not result in an error, you need to set responseType: 'text' in the options(which is the second parameter to .get(). Otherwise, Angular will try to parse the plaintext response, even if the response MIME type is set to text/plain.

getPlaintext(command: string): Observable<string> {
  return this.http.get(`/api/text`, { responseType: 'text' });
}

Full service example

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class PlaintextService {

  constructor(private http: HttpClient) { }
  
  getPlaintext(command: string): Observable<string> {
    return this.http.get(`/api/text`, { responseType: 'text' });
  }
}

 

Posted by Uli Köhler in Angular, Typescript

bottle Python HTTP custom response code minimal example

In bottle you can generate a custom HTTP response code by first importing HTTPResponse:

from bottle import HTTPResponse

and then, in your @route function, raiseHTTPResponse, for example

raise HTTPResponse("This is a HTTP 401 test URL", status=401)

Full example

#!/usr/bin/env python3
from bottle import HTTPResponse, route, run

@route('/test401')
def hello():
    raise HTTPResponse("This is a HTTP 401 test URL", status=401)

run(host='localhost', port=8080, debug=True)

Run this, script, then open http://localhost/test401 which will result in a HTTP 401 (unauthorized) response code with

This is a HTTP 401 test URL

as response body.

 

Posted by Uli Köhler in Python

bottle Python HTTP query parameters minimal example

In order to obtain the value of a query parameter named myparam in bottle, first import request:

from bottle import request

and then use

request.params["myparam"]

Full example:

#!/usr/bin/env python3
from bottle import route, run, request

@route('/test')
def hello():
    query_param = request.params["myparam"]
    return f"myparam is {query_param}"

run(host='localhost', port=8080, debug=True)

Run this script and open http://localhost:8080/test?myparam=xyz in your browser – you will see

myparam is xyz

 

Posted by Uli Köhler in Python

Angular HttpClient GET query parameter minimal example

sendCommand(command: string): Observable<any> {
  return this.http.get<any>(`/api/command`, {
    params: {"command": command}
  });
}

Running

sendCommand("test")

will send a HTTP GET request to /api/command?command=test.

Full service example

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class CommandService {

  constructor(private http: HttpClient) { }

  sendSerialCommand(command: string): Observable<any> {
    return this.http.get<any>(`/api/command`, {
      params: {"command": command}
    });
  }

}

 

Posted by Uli Köhler in Angular, Typescript

How to fix error NG8002: Can’t bind to ‘ngModel’ since it isn’t a known property of ‘input’.

Problem:

When trying to load your Angular app in ng serve you see an error message like

error NG8002: Can't bind to 'ngModel' since it isn't a known property of 'input'.

2     <input type="text" pInputText [(ngModel)]="text"/>
                                    ~~~~~~~~~~~~~~~~~~~~~

Solution:

You have not loaded FormsModule in your app.module.ts.

Import it using

import {FormsModule} from '@angular/forms';

and load it by appending

FormsModule,

to imports: [...] in app.module.ts , for example:

imports: [
  BrowserModule,
  AppRoutingModule,
  HttpClientModule,
  InputTextModule,
  FormsModule,
],
Posted by Uli Köhler in Angular, Javascript

How I fixed Visual Studio Code Remote SSH “Waiting for server log…” SSH

Problem:

When you try to connect Visual Studio Code to a computer (such as a Raspberry Pi) using SSH, you see log messages like

[16:23:13.444] > Waiting for server log...
[16:23:13.480] > Waiting for server log...
[16:23:13.520] > Waiting for server log...
[16:23:13.560] > Waiting for server log...
[16:23:13.598] > Waiting for server log...
[16:23:13.638] > Waiting for server log...

and VS code restarts the connection process repeatedly without connecting

Solution:

In my case, the ~/.vscode-server on the device where you’re connecting to was corrupted.

Therefore, the solution was to manually login using ssh to the device as the same user you’re using for VS code remote SSH and then running

rm -rf ~/.vscode-server

After that, just reconnect using VS code – it will automatically re-install the server.

Posted by Uli Köhler in Linux

How to test MikroTik UserManager (RADIUS) using radtest

On Ubuntu or other Linux distribution, you can easily install radtest using

sudo apt -y install freeradius-utils

After that, you need to create a Router representing your test PC on the MikroTik device so that RADIUS requests will be accepted.

Now you can run radtest like this:

radtest -t mschap [Username of the user to authenticate] [Password of the user to authenticate] [MikroTik IP] 1812 [Router shared secret]

Note the Router shared secret is the password that you used when setting up the Router instance for radtest in User manager -> Routers before and not the router’s admin password etc.

1812 is the default (and recommended) port for RADIUS.

Posted by Uli Köhler in MikroTik, Networking

How I fixed my old Sony Laptop backlight under Ubuntu 22.04

Until recently, my old Sony laptop was running Ubuntu 20.04 with the nvidia-340 proprietary graphics drivers. After upgrading to Ubuntu 22.04, the nvidia proprietary graphics driver didn’t work, so I uninstalled it – the noveau graphics driver worked fine, except that the backlight buttons didn’t work (the corresponding popup was shown but the backlight was stuck at full brightness).

In /sys/class/backlight there were both the nv_backlight and the sony directory. Writing to nv_backlight using

sudo echo 20 > /sys/class/backlight/nv_backlight/brightness

worked perfectly.

In order to permanently fix the issue and make the backlight buttons work again, I had to modify the kernel command line used at boot. By adding acpi_backlight=video in /etc/default/grub by appending it to the GRUB_CMDLINE_LINUX_DEFAULT= line.

Now said line looks like this:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash acpi_sleep=nonvs acpi_backlight=video"

After that, I ran sudo update-grub and rebooted the computer. After the reboot, the backlight worked fine.

Posted by Uli Köhler in Linux

How to fix MikroTik RouterOS User Manager error: Database disk not yet usable

Problem:

When trying to add for example a router to MikroTik’s User Manager, you see the following error popup:

Solution:

Initialize the database by using the following command in the terminal:

/user-manager/database save name=""

After that, the database is initialized and you will be able to use it.

Posted by Uli Köhler in MikroTik, Networking

EMQX 5.x HTTP ACL server using NodeJS

In our previous post EMQX 5.x HTTP password authentication server minimal example using NodeJS we provided a complete example of how to implement EMQX HTTP authentication.

This post provides an extension to our previous HTTP auth by adding a Koa router (i.e. a HTTP endpoint / URL) to provide ACL authentication, i.e. allow or deny topic level access with custom logic.

router.post('/emqx/acl', async ctx => {
    const body = ctx.request.body;
    console.log(body)
    // TODO: This example always returns true
    // You need to implement your authentication logic
    ctx.body = {
        result: "allow",
    };
});

Add that code before app.use(router.routes()); in the script from EMQX 5.x HTTP password authentication server minimal example using NodeJS.

My recommended Authorization configuration body which you can set in the EMQX dashboard is

{
  "action": "${action}",
  "client_id": "${clientid}",
  "ip": "${peerhost}",
  "topic": "${topic}",
  "username": "${username}"
}

 

Posted by Uli Köhler in EMQX, MQTT, NodeJS
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 &amp; Cookies Policy