Prettify your fish shell

Windows Terminal running Ubuntu in WSL2 with Fish

I am using the fish shell these days. Fish stands for Friendly Interactive Shell. I like how programming the shell works and it has some very nice features like syntax and command highlighting you will not find in regular shells.

Note: important note if you are considering to use fish, fish is not a POSIX compliant shell. As such, for shell scripts that will need to work on any system you will still need to know how to script in sh/bash/ksh/etc. I do not consider fish to be a replacement for bash and it should not be the default shell on any system. It’s great as your interactive shell when working the console though.

With that out of the way, using a different or alternate shell can be fun but you probably also want it to look good. Or you want it to look the same or similar to your previous shell because that is what you are used to. As did I. I had a pretty nice prompt setup in bash, so I really wanted my fish shell to look and feel similar. This was the result:

fish prompt for root and regular user

To get this prompt, I created the following under ~/.config/fish/functions.

# This theme is based on Bira theme from oh-my-fish (
# This theme also based on the default bash prompt of Kali Linux. (
# Created, modified and where possible bluntly stolen by throttlemeister.
# Bira theme from oh-my-fish listed abouve, based on:
# Theme based on Bira theme from oh-my-zsh:
# Some code stolen from oh-my-fish clearance theme:

function __user_host
  set fqdn (hostname -f)
  set -l content 
  if [ (id -u) = "0" ];
    echo -n (set_color --bold yellow)\((set_color --bold red)$USER(set_color --bold yellow)πŸ’€(set_color --bold red)$fqdn(set_color --bold yellow)\) (set color normal)
    echo -n (set_color --bold blue)\((set_color --bold white)$USER(set_color --bold blue)웃(set_color --bold white)$fqdn(set_color --bold blue)\) (set color normal)

function __current_path
  if [ (id -u) = "0" ];
    echo -n (set_color --bold yellow) [(set_color --bold white)(prompt_pwd)(set_color --bold yellow)] (set_color normal)
    echo -n (set_color --bold blue) [(set_color --bold white)(prompt_pwd)(set_color --bold blue)] (set_color normal) 

function _git_branch_name
  echo (command git symbolic-ref HEAD 2> /dev/null | sed -e 's|^refs/heads/||')

function _git_is_dirty
  echo (command git status -s --ignore-submodules=dirty 2> /dev/null)

function __git_status
  if [ (_git_branch_name) ]
    set -l git_branch (_git_branch_name)

    if [ (_git_is_dirty) ]
      set git_info '<'$git_branch"*"'>'
      set git_info '<'$git_branch'>'

    echo -n (set_color yellow) $git_info (set_color normal) 

function fish_prompt
  if [ (id -u) = "0" ];
    echo -n (set_color --bold yellow)"╭─"(set_color normal)
    echo -n (set_color --bold blue)"╭─"(set_color normal)
  echo -e ''
  if [ (id -u) = "0" ];
    echo (set_color --bold yellow)"╰─""# "(set_color normal)
    echo (set_color --bold blue)"╰─""\$ "(set_color normal)

function fish_right_prompt
  set -l st $status

  if [ $st != 0 ];
    echo (set_color red) ↡ $st  (set_color normal)
  set_color -o 666
  date '+ %T'
  set_color normal

Note: the latest version of this script can always be found on my GitHub here.

This prompt was, as the top comments indicate, not all my own and heavily borrowed and modified other prompt and resources. This exercise greatly helped me to understand the fishshell scripting language. This helped me to create some more scripts and functions to make my life in fish easier and simpler.

Mind you, sometimes bash is a lot simpler. For the same prompt, including checks for color support etc, the full bash equivalent for this in my .bashrc is this:

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
        # We have color support; assume it's compliant with Ecma-48
        # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
        # a case would tend to support setf rather than setaf.)

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '

host=`hostname -f`

if [ "$color_prompt" = yes ]; then
    if [ "$EUID" -eq 0 ]; then # Change prompt colors for root user
    PS1=$prompt_color'β”Œβ”€β”€${debian_chroot:+($debian_chroot)──}('$info_color'\u'$p_col'${prompt_symbol}'$info_color'$host'$prompt_color')-[\[\033[0;1m\]\w'$prompt_color']\n'$prompt_color'└─\$\[\033[0m\] '
    # BackTrack red prompt

    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '

Where basically only the last bit is what makes the prompt. And even that can be concatenated into a single line if you insert the colors directly instead of setting variables.

As short as possible: application containers, system containers, virtualization

Sometimes, there is a bit of confusion as to what the difference is between application containers (Docker, Podman, K8S, OpenShift), system containers (LXC/LXD) and virtualization (KVM, Vmware, Hyper-V, Xen) and when you should use them. I will try to explain the differences as short as possible.

Application containers
Application containers are created with the most minimal environment to run a specific application. This includes the OS and all dependencies for that application. Every tool or program normally present in the OS that is not needed to run the application is typically left out so that the container image is a small as possible and performs as fast as possible.

Examples of application containers are Docker, Podman, Kubernetes and OpenShift.

System containers
System containers are typically as the minimal environment needed to run a specific operating system. All the basic tools are present, including the package manager so you can set up the system as you want with all the tools you need. A system container is like a virtual machine, but without the hardware virtualization layer. A system container uses and identifies the host hardware and runs the same kernel as the host. This means it is much lighter on resources than full blown virtualization, but also that in certain cases it can be incompatible with certain software.

Examples of system containers are LXC, LXD

Virtualization is software that emulates the hardware so that more than one virtual machines can be installed on the same physical hardware at the same time. As the full hardware layer needs to be simulated, it has the most overhead of these options but it also is the most compatible with all software.

There are two types of virtualization:

Type 1 hypervisors: virtualization is done by the kernel, providing low-level access to the physical hardware for the virtualization software for increased performance.
Examples of Type 1 hypervisors: KVM, Vmware ESXi, Hyper-V Server

Type 2 hypervisors: virtualization is done by an application installed on an operating system. Access to hardware must be done through the OS and no direct access is possible. IT provides convenience over performance, as it can run on any sytem.
Examples of Type 2 hypervisors: Vmware Workstation, VirtualBox, Hyper-V manager

Did you know… (or, RHEL on LXC/LXD)

  • There are no RedHat Enterprise Linux (RHEL) LXC/LXD container images publicly available?
  • There are LXC/LXD container images available for CentOS and Fedora?
  • You can convert a CentOS install to RHEL using the Convert2RHEL tool?
  • This also works for a LXC/LXD container?
  • You will need to do this if you want to run RHEL on Proxmox in a LXC container?
  • You can create a tarbal of a running system to import into a vanilla LXC/LXD installation?
  • You will need to create a metafile.tar.gz with a few lines of information about the tarbal to do this?
  • You can also use an export from a Docker container to get the system?
  • And that you can also use an export from a WSL distribution for this?
  • This means you can set up a WSL environment on your Windows box (see other posts here) just the way you want with all the tools you need, and you can export it to run it independently in a LXC/LXD container as a server?

Tested distributions under WSL2

The following distributions I have installed/created, tested and used under WSL2 and Windows 10.

  1. Alpine Linux – extremely tiny; created from Docker image
  2. AlmaLinux – migrated from CentOS using AlmaLinux migration tool
  3. Arch Linux – created from virtual machine install
  4. CentOS 7 – created from rootfs image, then upgraded to latest version
  5. CentOS 8 – Upgraded from CentOS7
  6. CentOS Stream – upgraded from from CentOS8 install
  7. Deepin Linux – created from virtual machine install
  8. Debian 10 (“Buster”) – Microsoft Store
  9. Debian Testing (“Bullseye”) – upgraded from official Debian 10 release
  10. Devuan – migrated from Debian as installed from the Microsoft Store
  11. Fedora – created from virtual machine installation
  12. Gentoo – compiled from source using Stage3 tarball/rootfs iamge
  13. Kali Linux – Microsoft Store
  14. Oracle Linux – migrated from CentOS instance using CentOS migration tool from Oracle
  15. RedHat Enterprise Linux – created from virtual machine installation
  16. Rocky Linux – migrated from CentOS using RockyLinux migration tool
  17. Ubuntu – Microsoft Store
  18. Slackware – created from Docker image

As you can see, if you can find your favorite distribution in the Microsoft Store, great, if not or if its only available as a paid distribution, just bake your own. It’s not that difficult and really there is no reason why you should not have the Linux distribution of your choice available under WSL2.

A couple little Windows things

I recently had a discussion on a forum on the usefulness of virtual desktops and the implementation on Windows 10. Now everyone can have their opinions on virtual desktops and I do as well, but in that discussion some things came up that are apparently not so well known.

  1. Some people find it cumbersome to switch between virtual desktops to the point it becomes unusable for them. They need to go to Task View (WIN+TAB), then use the mouse to click the desktop they want.

    What people do not realize, is there is of course a keyboard shortcut for this too. Just hit CTRL+WIN+β†’ or CTRL+WIN+← to switch/scroll through all the virtual desktops you have created.

    Bonus tip: when in Task View, you can drag and drop any open window into any existing virtual desktop, or even on a new one to organize your windows.
  2. Some people find it a great feature that Windows launches programs in each virtual desktop in their own process. Others find that annoying. Few people seem to know, you can choose the behavior you want with the correct settings:

    Go to: Settings -> System -> Multitasking

    Then, under Virtual desktops, you will see the first line that says: “On the taskbar, show windows that are open on” with a drop down. This dropdown has two options. The first is “All desktops” and the second is “Only the desktop I’m using”.

    “All desktops” will have programs share process, so if you click an open program in the taskbar, it will switch to the desktop it is running on and make the window active. The other option will start a new instance of that program on the desktop you are on if it is not running there.
  3. Some people do not like the new timeline feature in the task view screen (WIN+TAB). This can be turned off if you want.

    Go to: Settings -> Privacy -> Activity history

    On that page, uncheck both items. Scroll down and toggle all accounts for which activities are shown, and done. No more timeline when doing WIN+TAB

New site

After building and setting up my new computer and subsequent move away from the Apple Mac ecosystem, I was left with an issue that the site I had built was setup using a Mac-only tool and could not be migrated to Windows. After mucking around with different tools on Windows and hacking things together, I have now decided to go platform independent and recreate my website using the ever popular WordPress CMS.

Setting it up on the Synology was a breeze and after finding a suitable theme for my needs I have now started to get things up and running again, adding the content, etc. So far, it looks pretty ok and this may indeed be the way to go.

Any Linux distribution on Windows 10 with WSL2

Introduction – WSL 2 on Windows 10 introduced the ability to run a native linux kernel on your computer while using Windows 10 as your main operating system. Instead of emulating a Linux kernel, like WSL 1 does, WSL 2 uses a lightweight hypervisor to run linux in parallel with Windows.
To be able to run WSL 2 on Windows 10, installation of Windows 10 feature update 2004 is required.

An explanation on how to enable WSL2 support can be found on the page detailing how to create a Gentoo instance on WSL2.

Any Linux distribution on Windows? – Yes, you can run any distribution of Linux on WSL quickly and easily, provided that:    
   1) a Docker image for that distribution is available.
   2) you install your distribution as normal in a virtual machine first

For the Docker method

docker pull <image name for your Linux distro>
docker create --name <distro> <image name for your distro>
docker export -o <distro>.tar <distro>

wsl --import "<distro>" "<location for your wsl distro>" "PATH/TO/<distro>.tar" --version 2

How does it work – The first line, the docker pull, downloads the docker image to your computer. This can be any image, as long as it is Linux based, but since you are trying to get a specific Linux distribution for use in WSL, the assumption is it is an image for a Linux distro.

The second line, the docker create, creates the docker container. It doesn’t start it, it just creates it so you don’t have to worry about containers all of a sudden taking up resources/

The third line, the docker export, dumps the container into a tar archive. This is the file we need for WSL and contains the entire Linux distribution. At this point, you can throw away your docker container if you want as we do not need it anymore.

Lastly, we are importing the tar archive we created from the docker container into WSL. We can now boot our newly created Linux distro of our choice in WSL and use it, modify it and work it like we want to.

NOTE: This process works in reverse as well! If you want to create and use a docker image from any WSL2 instance you have created you can simply export the WSL distro to a tar archive and import that into Docker and fire it up!

For the virtual machine method
After you have installed the virtual machine, log into the virtual machine and issue the following commands.

Note: this also works for physical Linux machine or dual boot system where you want to copy the Linux system to WSL!

$ sudo su -
# cd /
# tar -cpzf backup.tar.gz --exclude=/backup.tar.gz --exclude=/proc --exclude=/tmp --exclude=/mnt --exclude=/dev --exclude=/sys /

This will create a tar archive of the entire system. This can get quite big, especially if you are doing this from a previously installed system and not a clean, base install so make sure you have enough space to save it.

When the tar file has been created, copy it to your Windows machine somehow and issue the following command:

wsl --import "<Your_Distro_Name>" "<Location_to_store_your_Distro>" "PATH/TO/<archive.tar>" --version 2

This will create the WSL instance by side-loading it and you can start it by issueing wsl.exe -d <Your_Distro_Name> or by opening Windows Terminal; it should already be listed in the dropdown menu as one of the options.

Gentoo on Windows with WSL2

IntroductionΒ – WSL 2 on Windows 10 introduced the ability to run a native linux kernel on your computer while using Windows 10 as your main operating system. Instead of emulating a linux kernel, like WSL 1 does, WSL 2 uses a hypervisor to run linux in parallel with Windows.
To be able to run WSL 2 on Windows 10, installation of Windows 10 feature update 2004 or newer is required.

Enabling WSL2 support – Open an administrator PowerShell by pressing Windows + X, then A or select PowerShell (Run as Administrator) from the start menu. Execute the following commands to enable the hypervisor to start on system boot.

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

Download the latest stage 3 build from the gentoo website ( Select the profile which suits your needs. In my case I decided to use the most up-to-date, non-hardened, no-multilib, amd64 stage3 build.

Quick-Link to index: current-stage3-amd64-nomultilib

non-hardened: This is only a development system, so no hardening is needed.
no-multilib: Who needs x86 support anyway when compiling from source?
amd64: Because an up-to-date Windows 10 should be running on an up-to-date amd64 plaform.
Convert the tar.xz archive into an uncompressed tar archive by opening it with 7-Zip and selecting the extract option from the menu. Or use a Linux distro on WSL already installed. Do not extract the linux filesystem packed in the tar archive.

Open an administrator command promt / PowerShell by pressing Windows + X, then A or select PowerShell (Run as Administrator) from the start menu. Run the following command to import the userspace image into your WSL configuration. Be sure that you provide full paths and didn’t forget the –version argument. The destination path can be adjusted to your liking and is preferably on an SSD with at least 25 GB of free space. The import command will create a single virtual disk image (ext4.vhdx) in the destination folder.

wsl.exe --import "Gentoo" "D:\path\to\your\installation\directory" "C:\path\to\your\folder\stage3-amd64-nomultilib-20191113T214501Z.tar" --version 2

If you forgot the –version switch, the result of the command above is an extracted linux filesystem in the specified Windows folder. Remove the distribution with wsl –unregister and restart the import operation.

WSL setup in Gentoo – As with every new piece of software, the configuration needs some changes on the WSL / Gentoo side to run smoothly. Run the following commands on the Gentoo instance to fix problems with a non-functional nameserver configuration and file system attributes on Windows drives.

set -e -x

# Delete auto-generated files
rm /etc/resolv.conf || true
rm /etc/wsl.conf || true

# Enable changing /etc/resolv.conf
# Enable extended attributes on Windows drives
cat <<EOF > /etc/wsl.conf
generateResolvConf = false

enabled = true
options = "metadata"
mountFsTab = false

# Use google nameservers for DNS resolution
cat <<EOF > /etc/resolv.conf

Create a .wslconfig configuration file for WSL in the Windows user directory. This is necessary to set a maximum size limit of the RAM which WSL may consume. Sometimes the linux kernel uses a portion of the free memory as cache and therefore will start to “eat away” all RAM of the host system. This can be mitigated by setting the memory configuration option. Replace YOURUSERNAME with your Windows username in the script below.

set -e -x

cat <<EOF > /mnt/c/Users/YOURUSERNAME/.wslconf

Now close all instances of Gentoo / WSL and stop the virtual machine by opening the Command Prompt (Windows-Key + X, then A) and issuing the command wsl –shutdown.

Gentoo setup in WSL – Run all following commands in the Gentoo instance.

For gentoo to work correctly under the hypervisor some feature flags have to be disabled. Open the file /etc/portage/make.conf and adjust the following settings. Below is an example configuration used for my system.

– Add FEATURES=”-ipc-sandbox -pid-sandbox -mount-sandbox -network-sandbox” to disbable the non-functional sandboxing features
– Adjust COMMON_FLAGS to match your PC architecture.
– Adjust USE to your needs
– Ajdust MAKEOPTS to the number of CPU cores (+1) to make the compilation faster
– The other options are all optional

# No GUI (-X -gtk), only english error messages (-nls)
USE="-X -gtk -nls"

# Enable python 3.7 and set 3.6 as default
PYTHON_TARGETS="python3_6 python3_7"

# Define targets for QEMU
QEMU_SOFTMMU_TARGETS="aarch64 arm i386 riscv32 riscv64 x86_64"
QEMU_USER_TARGETS="aarch64 arm i386 riscv32 riscv64 x86_64"

# No hardware videocard support

# Disable non-functional sandboxing features
FEATURES="-ipc-sandbox -pid-sandbox -mount-sandbox -network-sandbox"

# Always ask when managing packages, always consider deep dependencies (slow) EMERGE_DEFAULT_OPTS="--ask --complete-graph"

# Enable optimizations for the used CPU
COMMON_FLAGS="-march=haswell -O2 -pipe"

# NOTE: This stage was built with the bindist Use flag enabled

# This sets the language of build output to English.
# Please keep this setting intact when reporting bugs.

Final installation steps – To finish the Gentoo installation a new snapshot of the ebuild repository should be downloaded. A recompilation of the compiler ensures that GCC is on the most recent stable version. After updating GCC a recompilation of all programs / libraries ensures that the set optimizations take effect.

set -e -x

# Download a snapshot of all official ebuilds

# Upgrade the compiler and the required libtool library
emerge --oneshot --deep sys-devel/gcc
emerge --oneshot --usepkg=n sys-devel/libtool

# Update all packages with the newly built compiler
# This will take a long time, ~1-5 hours
emerge --oneshot --emptytree --deep @world
emerge --oneshot --deep @preserved-rebuild
emerge --ask --depclean

Enabling overlays for portage – Eselect provides an easy integration of overlays into portage. The main portage respository should already be configured properly, so only a simple installation of eselect is necessary. For more information see the official wiki. Run the command shown below to install the repository module for eselect.


# Install portage overlays
emerge --ask app-eselect/eselect-repository 

The configuration for the plugin is located in the /etc/eselect/repository.conf file. The default path of the repository index is specified by the REPOS_CONF option which points to /etc/portage/repos.conf by default. Make sure that this directory exists or create it with the following command.

mkdir -p /etc/portage/repos.conf

A file named gentoo.conf should be located in this directory (/etc/portage/repos.conf) which holds the configuration for the main gentoo repository. Below is an example default configuration file which was created on my system.

main-repo = gentoo

location = /var/db/repos/gentoo
sync-type = rsync
sync-uri = rsync://
auto-sync = yes
sync-rsync-verify-jobs = 1
sync-rsync-verify-metamanifest = yes
sync-rsync-verify-max-age = 24
sync-openpgp-key-path = /usr/share/openpgp-keys/gentoo-release.asc
sync-openpgp-keyserver = hkps://
sync-openpgp-key-refresh-retry-count = 40
sync-openpgp-key-refresh-retry-overall-timeout = 1200
sync-openpgp-key-refresh-retry-delay-exp-base = 2
sync-openpgp-key-refresh-retry-delay-max = 60
sync-openpgp-key-refresh-retry-delay-mult = 4
sync-webrsync-verify-signature = yes

The synchronization of emerge can now be done via the command below. This might take some time, depending on the internet speed and if the repository was synchronized before.

emerge –sync

Using Git for portage sync – An alternative method to sync the portage repository is to use git. For this the git package has to be installed on the system as shown below.


# Install the git version control system
emerge --ask dev-vcs/git

Edit the sync-type and sync-uri in the portage configuration file under /etc/portage/repos.conf/gentoo.conf as shown below.

main-repo = gentoo

location = /var/db/repos/gentoo
#sync-type = rsync
#sync-uri = rsync://
sync-type = git
sync-uri =
auto-sync = yes
sync-rsync-verify-jobs = 1
sync-rsync-verify-metamanifest = yes
sync-rsync-verify-max-age = 24
sync-openpgp-key-path = /usr/share/openpgp-keys/gentoo-release.asc
sync-openpgp-keyserver = hkps://
sync-openpgp-key-refresh-retry-count = 40
sync-openpgp-key-refresh-retry-overall-timeout = 1200
sync-openpgp-key-refresh-retry-delay-exp-base = 2
sync-openpgp-key-refresh-retry-delay-max = 60
sync-openpgp-key-refresh-retry-delay-mult = 4
sync-webrsync-verify-signature = yes

Portage will now complain when synchronizing with git for the first time that the repository folder is not empty and that the folder can not be used to clone the git repository into it. This can be fixed by deleting the old rsync-managed repository which is located under /var/db/repos/gentoo when using the default configuration. Use the command below to do this.


# Remove old and generate new repository
rm -r /var/db/repos/gentoo
emerge --sync

# Sync twice to test synchronization speed
emerge --sync

Final bits and bobs and clean-up – Now that we have Gentoo installed and working in WSL2, we should do some cleaning up and do some things to make our lives easier.

First, it would a good idea right now to create and export of our installed Gentoo WSL distribution.

wsl.exe --export Gentoo gentoo.tar

Store this file somewhere safe. You can use this later to import the Gentoo again if needed, or use it on another computer without having to go through all the steps above.

Now would also be a good time to add a user to Gentoo that you would normally use, instead of using root. If you are installing Gentoo and have come this far, I probably don’t need to explain how to create a user on Linux. So I am not going to.

After you have created the user, note the user ID. Normally, this would be 1000.

To set the default user for Gentoo to use, we cannot use the normal procedure as used for distributions installed from the Windows store. Instead, we need to open the registry editor and navigate to:


You will see a list of folders with seemingly random names. One of these is for Gentoo, probably the bottom one. Find the one for Gentoo, and edit the key named “DefaultUid” and set the value to (decimal) 1000 or the number from your user ID if it is something else.

WARNING: if you do this before you have created your username on Gentoo, the distribution will be unusable, however you can fix it by changing the “DefaultUid” back to zero. Changes are in effect immediately; no need to reboot after changing this value.

PRO TIP: If you want to be able to change parameters using the .exe of the distribution as you can when you are using for instance Ubuntu or Debian from the store, grab the .exe from one of these store distro’s and put it in the directory where you installed Gentoo. Then rename the file to the name of the distribution as you have added it to WSL. You can now start your distribution using that .exe and for instance set the default user the normal way.