Mlterm Configuration

mlterm is a lightweight and fast terminal. You can have your own configuration and customize it as you like.

I like mlterm because it can:

  1. Display texts in non-English locales and supports input methods.
  2. Has less dependencies. Unlike Konsole or Gnome-terminal, you don't need to install the extra packages when you're not using those desktop environments.
  3. lsix to view pictures inside the terminal.


There are two ways to configure mlterm.

First, use the GUI configuration.
mlterm GUI configuration

What you need to do is to use Control + Right Click on the mlterm window to open the GUI configuration. You can make the change, apply it, and view the change. Remember to save it so that you don't lose the changes when you open mlterm later. I found it doesn't save some settings. I have to modify the configuration files.

The second way to configure mlterm is to modify the files. The configurations are in the folder $HOME/.mlterm. There are a few files.The ones I'll make changes are in main, key, and aafont. The main configuration file contains settings for mlterm in general. The key configuration file contains the key bindings. The aafont configuration file contains the font settings when you use anti-alias fonts.

Use Multiple Languages

My locale is UTF-8 and mlterm can detect it automatically. So I don't touch encoding related settings. I do change the settings for fonts and input method.

  1. Set use_aafont to true in the main configuration. Its default values is true if you run it on a desktop environment. It's false in mlterm-fb. So this is optional if you only use mlterm on a desktop environment. I explicitly set it to true in case I run mlterm-fb.
  2. Choose the font for the corresponding encodings. you can choose fonts for different encodings. Since my locale is UTF-8, I set it for the UNICODE one. In the aafont configuration file. you need to put something like this:
    UNICODE = Noto Sans Mono CJK SC 20
  3. Enable anti alias. You need to choose the font type that supports this feature. This is the setting use_anti_alias in main configuration file.
  4. Choose the input method. This is the setting input_method in the main configuration file. For example
    input_method = fcitx

Copy And Paste

It's better to understand selection on X11 before configure copy and paste. Anything you want to transfer from application to application is stored in selection. There are PRIMARY and CLIPBOARD as the destination of the selection. Anything you select or highlight will go to PRIMARY automatically. It's easy do it. You just need to use the mouse to select the text and that will go to PRIMARY. Once you select different texts, the new texts will overwrite the old ones in PRIMARY. To paste from PRIMARY, you can click the middle button or use SHIFT + INSERT. Mlterm supports it out of box. CLIPBOARD maybe is what most of us are familiar with. You copy by using Control + C and paste by Control + V. It's different from PRIMARY in that a new selection doesn't overwrite the contents in CLIPBOARD. You have to repeat the copy to clipboard action to update CLIPBOARD. I am familar with CLIPBOARD's way of copy and paste, so I configure mlterm to use it.


There is a setting to copy the selection to both PRIMARY and CLIBOARD. It's the setting use_clipboard=true in the main configuration file. Its default value is true so the setting is optional. But if you would like to separate them, as I do, you need to set use_clipboard=false to copy the selection to only PRIMARY. Then create a key binding to copy it to CLIPBOARD


exesel runs a command on the selected text. copy_to_clip is a script I create. Remember to put it in the folder that can be found from PATH.
Here is what the script copy_to_clip does:

echo $@ | xsel -i --clipboard

mlterm passes the selected text to the command copy_to_clip. What that does is to echo it to the ouput and pipe it to xsel. xsel takes the input from the pipe (-i) and copies it to CLIPBOARD (--clipboard).

Paste from CLIPBOARD

To paste from the clipboard, I configure the key bindings. The key bindings are defined in the key configuration file. The format is key=feature. The mlterm man page lists what keys can be used and what features are supported. To paste from CLIPBOARD, I use the feature proto:paste clipboard. I bind it to both right click and CTRL +SHIFT +V. The binding are

Control+Shift+v="proto:paste clipboard"
Button3="proto:paste clipboard"

There is another feature INSERT_CLIPBOARD that allows you to paste from the clipboard. But you can only assign one key binding to it. But you can have multiple bindings to the proto features. That is why I use it and bind to both Control+Shift+v and Button3.

Use lsix

Since I mentioned lsix on mlterm, I would like to add to that there is an issue with it. The pictures are not displayed at the right place on mlterm. The good news is that lsix knows about that and has a fix for that. However, it only applies the fix when it detects that the terminal is mlterm. It checks the terminal type. But mlterm reports it's xterm. To fix that, I put termtype=mlterm in the main configuration file. You can also pass it in the argument (--term=mlterm) when you starts mlterm. That tells mlterm to report itself as mlterm and lsix can apply the fix. With this change, lsix will display the pictures at the right place.
Display images using lsix

Use DisplayLink in Gentoo

I've been using Gentoo on my desktop for over five years. The computer connects to a 1080p monitor. Recently I use a DisplayLink 6xxx dock station to connect to a 4k monitor.

Current Configurations

I don't have any plans to replace the computrt. The only option is to make it work with my current configurations.

  1. The graphic card can only support 1080p.
  2. I have two monitors. One is 1080p, the other 4k.
  3. I have a Dell Universal Dock - D6000. It's using DisplayLink and can support 4K monitors.
  4. I'm using i3wm. There aren't any display managers. Instead, I start x11 when I login on console. Only i3wm is used.

Given the existing configurations, I decide to connect to the 1080p monitor from the graphic card, and connect to the 4k monitor as a second monitor via the dock.

Install the Driver

I follow Gentoo DisplayLink wiki to set up the kernel. The wiki however looks outdated in general.

The only official driver for Linux is for Ubuntu. This article suggests to adapt the script to port the driver to other distributions. It's easier said than done. There is an overlay zyrenth that has ebuilds for displaylink-driver and evdi packages. The ebuilds are solid. But there are some issues with evdi and displaylink manager themselves.

  1. evdi version 17.0 fails to compile with kernel 5.10. It's fixed in later versions.
  2. evdi version 19.0 is not compatible to Display Manager 5.3.1, which is the version from the displaylink-driver ebuild.

The only viable option is the evdi version 17.2. It's not provided in the overlay zyrenth. But build on top of others' work, I'm able to create my own ebuild. I follow the wiki custom ebuild repository to create a local repository. How to create a 17.2 ebuild? Just copy the 17.0 from overlay zyrenth and rename it 17.2. Then I have the ebuild for evdi version 17.2 and install it.

Configure HiDPI

The 4k monitor's maximium resolution is 3840 × 2160. Everything seems quite small on it. It's unpleasant to use. We need to conifure it for HiDPI. According to HiDPI document, I make this changes.

  1. Pass --dpi 196 when using xrandr.
  2. Set the xft.dpi: 196 in .Xresource and merge it with xrdb.
  3. Set the scaling factor for Gnome environment.
    gsettings set org.gnome.desktop.interface scaling-factor 2
    gsettings set org.gnome.desktop.interface text-scaling-factor 2
  4. Set the scaling factor for Qt.
      export QT_FONT_DPI=196
      export QT_SCALE_FACTOR=2
  5. Set the scaling factor for GTK based applications.
    export GDK_DPI_SCALE=2

I don't use Gnome or KDE and haven't verified how the settings for Gnome and Qt work. It seems xft.dpi setting makes the status bar in my i3wm larger and nicerr. But it doesn't make Firefox or Thunderbird or other GTK based appliations more legible. I have to use GDK_DPI_SCALE.

Probably it's because of my own configuration, I spend quite a while setting the HiDPI. I haven't tried other desktop environments. While I'm searching online, I feel like some desktop environment has the configuration from the GUI. That may make it easier for those desktop environments.

Connect to the Second Monitor

The second monitor is connected via the dock. The monitor capability in the dock isn't hotplug-able. So it's important to connect it to the computer when the system boots. After that, we can disconnect and re-connect the dock and we still can use the second monitor.

There are some extra work to connect to the second monitor. It's needed only one time when x11 starts.

  1. The displaylink-driver installs a dlm systemd service. The service has to be started after x11 starts. Since I start x11 from the console, I have to run systemctl start dlm once i3wm starts.
  2. I have to run xrandr --dpi 196 --output DVI-I-1-1 --mode 3840x2160 --rate 60 --right-of VGA-0 once after i3wm starts.

After running that, the second monitor is ready. I can disconnect and re-connect the dock at any time.

There are some research involved. It's not too difficult to find them. But overall, there are documents I can borrow to set up the DisplayLink for Gentoo.

Learning from Installing Smart Switches

I installed a few smart switches and automated my house lighting recently. It's a long journey and I've learned a lot along the way. As a software engineer, I'm surprised there are a few in common in software engineering and replacing switches. Probably those are common in tackling a problem.

Understand the Goal and Resources

In my daily job and other programming, I mostly focus on completing a product or getting a service online. They're not trivial or simple by nature. We analyze and divide that into minimum viable product, and continue to create tasks and solve the small tasks one by one. Like what we do in the software engineering, I think of what my goal is in this lighting automation project: automate the lights in my house. But it is not every light. I just need to automate lights in the dining room, kitchen, living room, garage, and the doors. This goal is clear and well scoped. It's also clear that I need to replace the existing switches with smart switches, connect the new smart switches to the hub, and configure the rules in the hub to automate the lights.

With the goal, it's also important to understand the resources and priorities. I have a full time job and I like to spend time with my family. That means I cannot devote myself to the project all the time. The good thing is there is no hard deadline. I can think of the small task and work on that one by one. For example, I can just replace one or two switches at a time. With the goal in mind, I need to be flexible and consistent.

Learn And Explore

I feel like there are much to learn in software engineering: language, design, architecture, and process, to name a few. It doesn't mean everybody has to learn all of them now. What I mean is the situations and requirements may change. We need to adapt to that and learn new technology on the way. For example, software engineers who are interested in Mac development won't ignore Apple M1 when it's released. Learning is a nonstop journey. Exploring is how to get to new and unfamiliar areas. It looks simple to replace the switches. But in the end, I need to spend some time in learning some basic wire code, understanding the differences between a regular switch and a smart switch, and understanding how that particular smart switch works in 3-way and 4-way wire. It only becomes possible after I read and explore the way to install the smart switches properly.

Don't Rush

There is always some form of design, development, testing, and release cycle. It's said that if we have a flaw at one stage and carry that down the cycle, it'll cost more to correct it. The later it's fixed, the more expensive it becomes. It's a waste of time and counterproductive if we have to re-work. It also applies when we replace the switches. If we don't get the wires connected right before putting it back, eventually we have to open the plate and correct that. Otherwise, we'll not be able to use the switches. It's important to get things right instead of done quickly. It's critical not to rush to finish it given that it's related to electricity. If we don't do our diligence in the safety, we can get shocked.

Work with the Existing System

It looks great and cool to work on something brand new. That means we have more choices to use new technology. In reality, we most likely add new features to the existing system. It doesn't sound that exciting. But we still need to weigh in how bad the existing system is, whether a from scratch new system can solve those issues, how many resources we need and we get, and whether there are other higher priorities. Replacing the switches is also working with the existing system. It's just too much work to replace the entire wiring in the house. There seems to be some wiring there I don't understand, for example, a white wire is connected to a black wire directly. It's also beyond my ability to try to make it follow the code.

It's fascinating to me that we can borrow the method and approach from one discipline to another. That reminds me that learning is a on-going journey and it can be applied to multiple areas.

Tips on docker-compose

Docker is a technology to create containers. What if we have multiple contains and need them to work together? Docker compose comes to rescue. The configuration is a yaml file and it's easy to follow. I'm going to write down some tips when I learned to use it.

Keep the Docker Container Running

The docker container is supposed to run only one process. The container stops when the process exits. So if we have a process that runs in the forground, it'll most likely exit because there is no console or input. For this kind of container, usually we run the command docker run -ti <image name> to keep the container running. In docker-compose world, you need to put this in the configuration for the service.

tty: true
stdin_open: true

Expose the Network Ports

In running docker, we can use docker -P to expose all the ports specified in the Dockerfile. We can also use docker -p [] to expose the specified ports in the command line. However, docker -P doesn't guarantee to map those ports from the container to the same ports on the host. The mapping is random. We can explicitly set those mapping using docker -p []. docker-compose by default will create a bridge for the specified containers. Depending on how we write it, we can expose the port only to that bridge network or also in the host.

- "8080"

This will only expose the ports to the linked services.

- "8080:80"

This also expose the ports on the host. It maps the port 8080 on host to the port 80 on the container.

Connect to the Linked Service in a Container

We specify the service in the configuration. docker-compose will bring up one or multiple container running the same thing for the service. Even if you don't specify the networks, docker-compose still creates a default one for you. You can find all the network by docker network ls. The name of the default network for your docker-compose containers is derived from the directory of the docker-compose.yml file. For example, docker-compose.yml is in the directory 'example'. The default network for those containers is 'example_default'. This may change but this is the behavior right now.

How do you connect to other containers brought up by docker-compose? There are two ways:

  1. Use the service name. For example, in docker-compose.yml, you specify the service like
    image: 'centos:latest'
    image: 'ubuntu:latest'

    In the container that runs Centos, you can use bar to connect to the other container that runs Ubuntu.

  2. Use the ip address.
    When you find the network for your containers, you can use docker network inspect <network name> to inspect the details of the network. From there, you can find the ip address of the containers. For example:

        "Name": "example_default",
        "Containers": {
            "4a87be92f610b839c77f0fa87c7bdd13797ca4eac3c2061a4d8e66a1c5e9c867": {
                "Name": "example_foo_1",
                "EndpointID": "0752c01405904b702459560fcc1bc90ef0e24d3e769e8bc46d5edcf06944dba1",
                "MacAddress": "02:42:ac:15:00:03",
                "IPv4Address": "",
                "IPv6Address": ""
            "6244c44cab85df31d684abb5e0b2ce12ecfbef902e13c638d1ab50981b876142": {
                "Name": "example_bar_1",
                "EndpointID": "5b0edb758b080010f8c3fca92e5cb583724c9fefcc23c5148c8c3375517d0093",
                "MacAddress": "02:42:ac:15:00:02",
                "IPv4Address": "",
                "IPv6Address": ""

By far, those are the things I think it's useful when using docker-compose. I spent some time on searching online. I hope this can help you to try out the way to manage containers.

What Do We Need to Know about DNS

Not every programmer needs to know DNS. We tend to take it for granted. It's there. It's working. As we are moving to the cloud and Devops, it's inevitable that we need to deal with network configuration. It's important to understand some basics of DNS.

This is the place to add a custom domain to a web in Azure. It provides A record and CNAME record. What record type should I use?

Add a custom domain for Azure app service
Add a custom domain for Azure app service

What's DNS

If you still have some memory about basic network. IP address is what we use to locate a service on the Internet. But how many IP addresses do you remember? We rarely use the IP address directly. Those are hard-to-remember long numbers. Instead, we remember domain names. What is a domain name? When you type in the browser address bar like, that is the domain name. But we use the IP address. How do we find the IP address by the domain name? That comes the DNS (domain name systems). It resolves the domain name to the IP address.

DNS Hierarchy

You don't need to worry about setting up DNS for your network at home. When the modem connects, it will set up the DNS. Usually it is the ISP DNS. Does it know all the domains? No. It inquires other kinds of DNS servers. These DNS servers together resolve the domain name to the IP address.

DNS servers
dns server

At the top, it is the root server. The root server doesn't know what the domain name map to. But it knows what top level domain server (TLD) is. The top level domain is something like .com, .net etc. For example, goes to the. com top level domain server. TLD server goes to authoritative servers to find the IP address.

The ISP server can cache the result. So it doesn't waste time to go to root servers and other servers.

DNS Records

DNS records are stored in the DNS servers. The record contains information about how to resolve the DNS inquiry. For example, if there is a record like [], and when you inquire, it returns the IP address.

There are three types I want to cover here. CNAME (Canonical Name record). It sets up a domain name to its canonical name. In another word, it creates an alias to the canonical name. For example, for this record [], when you inquire, it'll return the canonical name The CNAME record doesn't contain the IP address.

The second type of record is A or AAA. It maps from the the domain name to the IP address. Record A maps to the IPv4 address and AAA maps to the IPv6 address.

The third type of record is TXT. It allows to add any human readable text to the domain. You can also add machine readable contents too. What is the content? It's up to you. Consider this is a note to the domain.

How to Get the IP Address

When the browser needs to get the IP address for the domain in the address bar, it'll send the inquiry to the DNS server configured for the network. The DNS server will ask for that following the DNS hierachy. If the domain in the address bar is an alias, it'll get a CNAME record. It then restart the process again with the canonical name. This time it'll receive the A record or AAA record which contains the IP address.

By now, hopefully you have a clearer answer to what to choose when you try to add a new custom donmain to the web in Azure. The DNS is the infrastracture of the Internet. We all should know what the underlying works when developing in the cloud era. Cloud computing has already taken care of a lot of stuffs. We still need to know the basics to be better working in the cloud.