Photon OS on WSL2 - dcasota/photonos-scripts GitHub Wiki

To make run various Nvidia tutorials directly on a user laptop, the idea came up to use Photon OS on WSL2. The initiative has been specified at https://github.com/vmware/photon/issues/1532.

Environment

  1. Summary The following Photon OS recipe to accomplish the installation and configuration in WSL2 has been tested on

  2. Ensure WSL2 is installed and configured.

    # Uninstall any previous installation if necessary
    # Open a Powershell Terminal (Administrator) 
    wsl --unregister <distribution-name> # for each distro
    wsl --uninstall
    dism /online /disable-feature /featurename:VirtualMachinePlatform /norestart
    dism /Online /disable-Feature /FeatureName:Microsoft-Windows-Subsystem-Linux /norestart
    dism /online /disable-feature /featurename:microsoft-hyper-v-all /norestart
    dism /Online /disable-feature /featurename:HypervisorPlatform /norestart
    dism /Online /disable-feature /featurename:Containers /norestart
    bcdedit /set hypervisorlaunchtype off
    # uninstall docker desktop
    wusa /uninstall /kb:5039212 # https://github.com/microsoft/WSL/issues/11675#issuecomment-2172538707
    
    # Install
    # see https://learn.microsoft.com/en-us/windows/wsl/install-manual#step-1---enable-the-windows-subsystem-for-linux
    dism /Online /Enable-Feature /All /FeatureName:Microsoft-Hyper-V /norestart # not necessary accordingly to prerequisites but helps for vswitch
    dism /Online /Enable-Feature /All /FeatureName:Microsoft-Windows-Subsystem-Linux /norestart
    dism /Online /Enable-feature /All /featurename:VirtualMachinePlatform /norestart
    dism /Online /Enable-feature /All /featurename:HypervisorPlatform /norestart
    dism /Online /Enable-feature /featurename:Containers /norestart
    bcdedit /set hypervisorlaunchtype auto
    # reboot
    

    Optional: run wsl --update, install latest WSL2 release from https://github.com/microsoft/WSL/releases and WSL2 GUI (wslg) from https://github.com/microsoft/wslg/releases.

  3. Ensure Docker Desktop is installed to make use of it importing Photon OS docker in WSL2 e.g. x86_64 version.

    invoke-webrequest https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe -outfile "$env:userprofile\downloads\Docker Desktop Installer.exe"
    $oprocess = start-process "$env:userprofile\downloads\Docker Desktop Installer.exe" -passthru
    

    Close the Powershell window.

(Re-)Setup

  1. Open a new Powershell Terminal (Administrator) and start Docker Desktop. Configure it initially if necessary.

    start-process "$env:ProgramFiles\Docker\Docker\Docker Desktop.exe"
    

    Good to know:

    • Issue in Docker Desktop releases 4.29 + 4.30:
      If docker does not start, open services .msc and stop WSL Service. In Docker Desktop remove WSL 2 integration, and restart Docker Desktop.
  2. Prepare Photon OS docker container

    docker pull photon:latest # docker pull photon release from https://hub.docker.com/_/photon/
    docker run -it -d photon:latest # run container in background
    
    # get docker container id
    $jsonstring = docker container list --format '{\"Image\":"\"{{.Image}}\",\"ID\":\"{{.ID}}\"}' 2>$NULL
    
    # does not work anymore. convertfrom-json has an issue
    # $ID = ($jsonstring | convertfrom-json | where-object -Property image -eq "photon:latest" | select ID).ID
    $ID=($jsonstring.substring(($jsonstring.indexof("ID\"))+7)).replace('\"}',"")
    
    docker export -o "$env:userprofile\photon.tar" $ID # docker export
    docker container stop $ID # docker container stop and prune
    docker container prune --force # docker container stop and prune
    
  3. Import Photon OS docker container and configure as WSL2 distro.

    Importing or starting a WSL2 distribution under Windows 11, actually starts two distributions:

    • the user Linux distribution
    • a corresponding system distribution system distro for each "main" distribution. This distribution is actually Microsoft CBL-Mariner.

    Using the docker container method, the user Linux distribution can be configured. I haven't found out how to exchange the system distro.

    This scenario explicitly uses the default WSL networking setting NAT. The new networkingMode=mirrored isn't used because it caused more complexity for debugging and didn't solve a minor NAT issue (see workaround 2).

    $distroname="Ph5"
    $targetdirectory="$env:userprofile\$distroname"
    mkdir $targetdirectory
    
    # configure .wslconfig . If needed, change debugConsole=true
    echo "[wsl2]">"$env:userprofile\.wslconfig"
    echo "# Enable nested virtualization">>"$env:userprofile\.wslconfig"
    echo "nestedVirtualization=true">>"$env:userprofile\.wslconfig"
    echo "# networking mode">>"$env:userprofile\.wslconfig"
    echo "networkingMode=NAT">>"$env:userprofile\.wslconfig"
    echo "# Turn on default connection to bind WSL 2 localhost to Windows localhost">>"$env:userprofile\.wslconfig"
    echo "localhostforwarding=true">>"$env:userprofile\.wslconfig"
    echo "# turn off idle timeout">>"$env:userprofile\.wslconfig"
    echo "vmIdleTimeout = -1">>"$env:userprofile\.wslconfig"
    echo "# needed to start properly [email protected]">>"$env:userprofile\.wslconfig"
    echo "guiApplications = true">>"$env:userprofile\.wslconfig"
    echo "# debug console" >>"$env:userprofile\.wslconfig"
    echo "debugConsole=false">>"$env:userprofile\.wslconfig"
    # backup the global .wslconfig
    cp "$env:userprofile\.wslconfig" "$targetdirectory\.wslconfig.bkup"
    
    wsl --set-default-version 2 # set wsl version
    wsl --import $distroname $targetdirectory "$env:userprofile\photon.tar" # wsl import to a target directory
    # wsl --set-default $distroname # set wsl default
    
    # start and login as root
    wsl -d $distroname -u root -e /bin/bash # Keep calm as it starts with "ERROR: UtilTranslatePathList". time settings will fix this.
    
  4. With the first boot, configure the following steps.

    # this is a preparation to run Photon OS on WSL2 with a user. In addition, the user is used for docker rootless.
    # Change here.
    ROOTLESS_USER="dcaso"  
    
    # WORKAROUND 1
    # This snippet solves the issue "ERROR: UtilTranslatePathList".
    # ntpd does not work yet in WSL2 because systemd isn't the booted init system but ntpdate can be triggered at this time.
    tdnf install -y ntp tzdata
    ZONEINFO="Europe/Zurich"
    set $ZONEINFO timezone
    ln -sf /usr/share/zoneinfo/$ZONEINFO /etc/localtime
    ntpdate -u pool.ntp.org
    hwclock --systohc --localtime
    
    # install dbus as prerequisite to use systemd on boot
    tdnf install -y sudo dbus-user-session systemd-udev
    
    # install docker, also docker-rootless
    tdnf install -y runc containerd shadow fuse slirp4netns libslirp docker docker-rootless usbutils pciutils
    # disable docker for first boot to not conflict with system services
    systemctl disable docker
    
    # WORKAROUND 2
    # It's not clear why the wsl'ified Photon OS does not get a NAT dhcp ip with the next boot.
    # As workaround, the actual NAT dhcp ip address is saved and stored as static ip.
    # This seems to work as long as you don't reconfigure the vswitch settings for WSL.
    IPADDRESS=`ifconfig -S | grep eth0 | awk '{print $2}'`
    NAMESERVER=`cat /etc/resolv.conf | grep nameserver | awk '{print $2}'`
    echo "[Match]"> /etc/systemd/network/10-static-en.network
    echo "Name=eth0">> /etc/systemd/network/10-static-en.network
    echo "[Network]">> /etc/systemd/network/10-static-en.network
    echo "Address=$IPADDRESS">> /etc/systemd/network/10-static-en.network
    echo "Gateway=$NAMESERVER">> /etc/systemd/network/10-static-en.network
    echo "DNS=$NAMESERVER">> /etc/systemd/network/10-static-en.network
    chmod 644 /etc/systemd/network/10-static-en.network
    
    # WORKAROUND 3
    # see https://forums.developer.nvidia.com/t/wsl2-libcuda-so-and-libcuda-so-1-should-be-symlink/236301
    cd /usr/lib/wsl/lib
    rm libcuda.so libcuda.so.1
    ln -s libcuda.so.1.1 libcuda.so.1
    ln -s libcuda.so.1 libcuda.so
    /sbin/ldconfig
    
    # remove root password expiration
    chage -m 0 root
    
    # create and configure ROOTLESS_USER
    # systemd-managed see https://rootlesscontaine.rs/getting-started/common/subuid/
    uid="524288"
    useradd $ROOTLESS_USER --uid $uid -m -g users -G sudo,wheel
    echo "$ROOTLESS_USER:$uid:65536" >> /etc/subuid
    echo "$ROOTLESS_USER:$uid:65536" >> /etc/subgid
    echo "kernel.unprivileged_userns_clone = 1" >> /etc/sysctl.d/50-rootless.conf
    chmod 644 /etc/subuid /etc/subgid /etc/sysctl.d/50-rootless.conf
    
    # WORKAROUND
    mkdir -p /run/user/0 # seems a wsl2 bug
    mkdir -p /run/user/$uid # seems a wsl2 bug
    
    chage -m 0 $ROOTLESS_USER
    # add ROOTLESS_USE to visudo
    echo "$ROOTLESS_USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
    
    # /etc/wsl.conf contains the configuration to run Photon OS on WSL2 and to boot as systemd. 
    # In addition, to boot systemd it seems to be necessary to preserve the dhcp address as static ip with no new resolv.conf.
    echo "[user]"> /etc/wsl.conf
    echo "default = $ROOTLESS_USER">> /etc/wsl.conf
    echo "">> /etc/wsl.conf
    echo "[boot]">> /etc/wsl.conf
    echo "systemd=true">> /etc/wsl.conf
    echo "">> /etc/wsl.conf
    echo "[network]">> /etc/wsl.conf
    echo "generateResolvConf = false">> /etc/wsl.conf
    
    # see https://github.com/microsoft/wslg/wiki/WSLg-Configuration-Options-for-Debugging
    
    #  see https://github.com/microsoft/wslg/issues/43#issuecomment-826039096
    echo "#  This file is part of the debianisation of systemd."> /etc/tmpfiles.d/wslg.conf
    echo "#">> /etc/tmpfiles.d/wslg.conf
    echo "#  systemd is free software; you can redistribute it and/or modify it">> /etc/tmpfiles.d/wslg.conf
    echo "#  under the terms of the GNU General Public License as published by">> /etc/tmpfiles.d/wslg.conf
    echo "#  the Free Software Foundation; either version 2 of the License, or">> /etc/tmpfiles.d/wslg.conf
    echo "#  (at your option) any later version.">> /etc/tmpfiles.d/wslg.conf
    echo "">> /etc/tmpfiles.d/wslg.conf
    echo "# See tmpfiles.d(5) for details">> /etc/tmpfiles.d/wslg.conf
    echo "">> /etc/tmpfiles.d/wslg.conf
    echo "# Type Path           Mode UID  GID  Age Argument">> /etc/tmpfiles.d/wslg.conf
    echo "L+     /tmp/.X11-unix -    -    -    -   /mnt/wslg/.X11-unix">> /etc/tmpfiles.d/wslg.conf
    
    touch /mnt/wslg/.X11-unix
    chmod 777 /mnt/wslg/.X11-unix
    
    # change password of $ROOTLESS_USER
    passwd $ROOTLESS_USER
    
    exit
    
  5. Shutdown Photon OS on WSL2.

    wsl -d $distroname --shutdown
    

    Boot, and login as <ROOTLESS_USER>.

    # Change here
    $ROOTLESS_USER="dcaso"
    wsl -d $distroname -u $ROOTLESS_USER -e /bin/bash
    

    You can use this wsl'ified Photon OS now more or less like a typical installation.

  6. Option 1: Configure Photon OS system to make use of docker and ssh.

    sudo cat <<EOFInstall | sudo tee $HOME/install.sh
     
    # enable ntpd
    systemctl enable ntpd.service
    systemctl restart ntpd
    
    # install and configure openssh
    tdnf remove -y openssh openssh-server openssh-clients
    rm -r -f /etc/ssh
    sleep 5
    tdnf install -y openssh
    sleep 5
    sed -i "s/#PermitRootLogin no/PermitRootLogin yes/" /etc/ssh/sshd_config
    sed -i "s/#PermitRootLogin yes/PermitRootLogin yes/" /etc/ssh/sshd_config
    sed -i "s/PermitRootLogin no/PermitRootLogin yes/" /etc/ssh/sshd_config
    sed -i "s/#PasswordAuthentication no/PasswordAuthentication yes/" /etc/ssh/sshd_config
    sed -i "s/#PasswordAuthentication yes/PasswordAuthentication yes/" /etc/ssh/sshd_config
    sed -i "s/PasswordAuthentication no/PasswordAuthentication yes/" /etc/ssh/sshd_config
    sed -i "s/#LoginGraceTime/LoginGraceTime/" /etc/ssh/sshd_config
    sed -i "s/#Port /Port /" /etc/ssh/sshd_config
    sed -i "s/#ListenAddress 0.0.0.0/ListenAddress 0.0.0.0/" /etc/ssh/sshd_config
    systemctl restart sshd
    
    # docker neeeds iptables just installed. Configure docker.
    tdnf install -y iptables
    systemctl enable containerd.service
    systemctl restart containerd
    systemctl enable docker.socket
    systemctl enable docker
    systemctl restart docker
    # check docker
    docker run -it hello-world
    EOFInstall
    

    Run the install script.

    sudo chmod a+x $HOME/install.sh
    sudo /bin/bash $HOME/install.sh
    sudo rm $HOME/install.sh
    
  7. Option 2: Recompile kernel to make use of usb connectivity. By default, usb is not enabled. To enable the use of usb video and usb audio, the kernel configuration file .config has to be modified.

    Here a configuration which enables usb video and audio. A bunch of vendor usb devices are marked as enabled.

    (Do not use anymore: old configuration )

    The configuration file will be downloaded and used for the kernel recompilation.

    sudo cat <<EOFKernelCompile | sudo tee $HOME/kernelcompile.sh
    # change here
    ROOTLESS_USER="dcaso"
    distroname="Ph5"
    
    # prerequisites
    sudo tdnf makecache
    sudo tdnf install -y git ncurses-devel dwarves openssl-devel bc build-essential unzip elfutils-devel rsync
    cd /usr/local/src
    
    # sound utils
    sudo tdnf install -y sysdig linux-drivers-sound linux-drivers-gpu alsa-utils alsa-lib linux-devel linux-firmware tree
    
    # see https://github.com/microsoft/WSL2-Linux-Kernel/releases
    tag="6.6.36.6"
    # For dockerized Photon OS 5.0 with Kernel 6.1
    # tag="6.1.21.2"
    tagname=linux-msft-wsl-\${tag}
    sudo git clone --depth 1 -b \${tagname} https://github.com/microsoft/WSL2-Linux-Kernel.git \${tag}-microsoft-standard
    sudo ln -s \${tag}-microsoft-standard \${tag}-microsoft-standard-WSL2+
    cd \${tag}-microsoft-standard-WSL2+
    
    # For dockerized Photon OS 5.0 with Kernel 5.15 e.g. "5.15.137.3", "5.15.146.1", "5.15.150.1", "5.15.153.1"
    # tag="5.15.137.3" 
    # tagname=linux-msft-wsl-${tag}
    # sudo git clone --depth 1 -b ${tagname} https://github.com/microsoft/WSL2-Linux-Kernel.git ${tag}-microsoft-standard
    # sudo ln -s ${tag}-microsoft-standard ${tag}-microsoft-standard-WSL2+
    # cd ${tag}-microsoft-standard-WSL2+
    
    # prepare
    export TERM=linux
    sudo make clean
    
    # Option1: use the kernel template Microsoft/config-wsl
    # sudo cp Microsoft/config-wsl .config
    # The Microsoft template must be modified to allow a bunch of vendor devices.
    # Unfinished / do not use the bash script : https://github.com/user-attachments/files/15820415/run.txt
    
    
    # Option2: use actual Photon OS kernel as template
    # sudo cp /proc/config.gz config.gz
    # sudo gunzip config.gz
    # sudo cp config .config
    
    # Option3: use the custom kernel template config-photon.txt
    sudo curl -J -L -O https://github.com/user-attachments/files/15889740/config-photon.txt
    sudo mv config-photon.txt .config
    
    # prepare
    sudo chmod 777 .config
    sudo make prepare modules_prepare
    
    # reconfigure kernel by `sudo make menuconfig` if necessary
    # sudo make menuconfig
    
    # compile
    sudo make -j\$(nproc --all) KCONFIG_CONFIG=.config modules
    sudo make -j\$(nproc --all) KCONFIG_CONFIG=.config modules_install
    sudo make -j\$(nproc --all) KCONFIG_CONFIG=.config
    
    cp /usr/local/src/\${tag}-microsoft-standard/arch/x86_64/boot/bzImage /mnt/c/Users/\$ROOTLESS_USER/\$distroname/vmlinux
    # cp /usr/local/src/${tag}-microsoft-standard/vmlinux /mnt/c/Users/$ROOTLESS_USER/$distroname/vmlinux
    EOFKernelCompile
    

    Run the kernel compile script.

    sudo chmod a+x $HOME/kernelcompile.sh
    sudo /bin/bash $HOME/kernelcompile.sh
    sudo rm $HOME/kernelcompile.sh
    
    exit
    

    Shutdown wsl and make use of the new kernel in .wslconfig.

    wsl -d $distroname --shutdown
    # wait a few seconds
    # add vmlinux location to [wsl2] section in .wslconfig
    echo "kernel=C:\\Users\\$env:username\\$distroname\\vmlinux" >>"$env:userprofile\.wslconfig"
    

    Boot and login.

    wsl -d $distroname -u $ROOTLESS_USER -e /bin/bash
    

    Check the date of the kernel.

    uname -a
    Linux yourcomputer 5.15.137.3-microsoft-standard-WSL2+ #2 SMP Mon Jan 15 20:56:55 CET 2024 x86_64 GNU/Linux
    
    exit
    

    If using Docker Desktop, in Docker Desktop > Settings > Resources > WSL integration > Enable integration with additional distros: Ph5 > Apply & restart, if needed.

    Install and configure usbip to redirect and use usb devices in wsl2.

    # (re-)installation of usbipd
    winget install usbipd --force
    # (re-)installation seems to be necessary for the usbip client tool
    winget install --interactive --exact dorssel.usbipd-win --force
    
    # close Powershell Terminal (Administrator)
    

    In the following example, the laptop has a built-in video camera which is detected as usb camera .
    In addition, an attached Isy 14-1-usb-c adapter has an audio jack which is detected as usb audio device.

    Reopen Powershell Terminal (Administrator).

    #change here
    $ROOTLESS_USER="dcaso"
    $distroname="Ph5"
    
    # find busid
    PS C:\Users\dcaso> usbipd list
    Connected:
    BUSID  VID:PID    DEVICE                                                        STATE
    2-4    04f2:b7c1  Integrated Camera, Integrated IR Camera, APP Mode             Attached
    2-10   8087:0033  Intel(R) Wireless Bluetooth(R)                                Not shared
    3-1    1b3f:2008  USB Audio Device, USB-Eingabegerät                            Attached
    3-2    05e3:0751  USB-Massenspeichergerät                                       Not shared
    4-3    046d:c316  USB-Eingabegerät                                              Not shared
    4-4    046d:c046  USB-Eingabegerät                                              Not shared
    5-1    0bda:8153  Realtek USB GbE Family Controller                             Not shared
    
    Persisted:
    GUID                                  DEVICE
    23f3a5e2-bceb-4014-8b3c-4ac4034a646e  VMware USB Device
    
    # bind the usb camera device by busid (already done)
    usbipd bind -b 2-4
    
    # bind the usb audio device by busid (already done)
    usbipd bind -b 3-1
    
    # start wsl and exit to background
    wsl -d $distroname -u $ROOTLESS_USER -e /bin/bash -c "echo 'wsl running in background..';exit"
    
    # attach usb devices
    usbipd attach --wsl -b 2-4  
    usbipd attach --wsl -b 3-1  
    
    # enter wsl again
    wsl -d $distroname -u $ROOTLESS_USER -e /bin/bash
    
    # install utils
    sudo tdnf install -y usbutils
    
    dcaso [ /mnt/c/Users/dcaso ]# lsusb
    Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 001 Device 003: ID 1b3f:2008 Generalplus Technology Inc. USB Audio Device
    Bus 001 Device 002: ID 04f2:b7c1 Chicony Electronics Co., Ltd Integrated Camera
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    
      
    # snd directory must be present
    ls /dev/snd  
    by-id    controlC0  controlC2  controlC4  pcmC0D0c  pcmC1D0c  pcmC1D1c  pcmC3D0p  pcmC4D0p  timer  
    by-path  controlC1  controlC3  midiC2D0   pcmC0D0p  pcmC1D0p  pcmC1D1p  pcmC4D0c  seq  
    
    # check the output for aplay  
    sudo aplay -l | grep card
    card 0: Dummy [Dummy], device 0: Dummy PCM [Dummy PCM]
    card 1: Loopback [Loopback], device 0: Loopback PCM [Loopback PCM]
    card 1: Loopback [Loopback], device 1: Loopback PCM [Loopback PCM]
    card 3: pcsp [pcsp], device 0: pcspeaker [pcsp]
    card 4: Device [USB Audio Device], device 0: USB Audio [USB Audio]
    
    # configure usb audio device (card 4) as default audio device
    sudo cat <<EOFSound | sudo tee /etc/asound.conf
    defaults.pcm.card 4
    defaults.ctl.card 4
    EOFSound
    
    # check sound
    sudo aplay /usr/share/sounds/alsa/Front_Center.wav
    speaker-test -t sine -f 1000 -l 1
    
    # video0 must be present
    ls /dev/video0
    
    # Option: Install video 4 linux
    cd $HOME
    sudo tdnf install -y git meson build-essential which clang doxygen cmake libgssglue json-c systemd-devel libjpeg-turbo libjpeg-turbo-devel libgudev alsa-lib alsa-lib-devel alsa-utils json-c-devel libgssglue-devel libXcursor-devel libXi-devel libXinerama-devel libXrandr-devel ninja-build
    sudo tdnf install -y gstreamer gstreamer-devel gstreamer-plugins-base gstreamer-plugins-base-devel libtiff libtiff-devel lttng-tools lttng-ust lttng-ust-devel libglvnd-devel libglvnd-opengl mesa
    cd $HOME
    git clone https://github.com/gjasny/v4l-utils.git
    cd v4l-utils
    
    sudo meson setup build/ # sudo meson build/ --reconfigure
    sudo ninja -C build/
    sudo ninja -C build/ install
    cd ./build/utils/v4l2-ctl
    sudo ./v4l2-ctl --all
    # You should get a similar [sample output](https://github.com/dcasota/photonos-scripts/files/13948048/v4l2-ctl.output.txt).
    

Additional information

Prepare make use of vCenter Converter

Converting a WSL2 installation with VMware vCenter Converter does not work.
The following steps were found to be necessary to reach a point where VMware vCenter Converter would be ready to readout the disk.

On Photon OS, install additional packages for vCenter Converter Worker.
```
# install and configure openssh. See steps above.
# install additional prerequisites
sudo tdnf install -y grub2-efi grub2-efi-image dmidecode dracut
```

In Powershell Terminal (Administrator) configure the Hyperv firewall.
```
New-NetFirewallHyperVRule -Name SSH -DisplayName "SSH" -Direction Inbound -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Protocol TCP -LocalPorts 22
New-NetFirewallHyperVRule -Name https -DisplayName "https" -Direction Inbound -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Protocol TCP - 
LocalPorts 443
New-NetFirewallHyperVRule -Name Port9089 -DisplayName "Port9089" -Direction Inbound -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Protocol TCP -LocalPorts 9089
```   

Hardening

DOES NOT WORK YET AS EXPECTED. DO NOT USE.
Hardening using Photon OS iptables and Hyperv firewall.

port proxy settings.  

```
netsh interface portproxy reset
# In Photon OS run ifconfig -S and determine the ipaddress
$connectaddress="172.19.160.222"
netsh interface portproxy set v4tov4 listenport=22 listenaddress=0.0.0.0 connectport=22 connectaddress=$connectaddress
netsh interface portproxy add v4tov4 listenport=443 listenaddress=0.0.0.0 connectport=443 connectaddress=$connectaddress
netsh interface portproxy add v4tov4 listenport=9089 listenaddress=0.0.0.0 connectport=9089 connectaddress=$connectaddress
```

Firewall Hyperv settings.

```
get-netfirewallhypervrule | where-object {$_.VMCreatorId -eq "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}"} | remove-netfirewallhypervrule
Set-NetFirewallHyperVVMSetting -Name "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -DefaultInboundAction Allow
Set-NetFirewallHyperVVMSetting -Name "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -DefaultOutboundAction Allow
Set-NetFirewallHyperVVMSetting -Name "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -LoopbackEnabled True
Set-NetFirewallHyperVVMSetting -Name "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -AllowHostPolicyMerge True
Set-NetFirewallHyperVVMSetting -Name "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Enabled True 
New-NetFirewallHyperVRule -Name SSH -DisplayName "SSH" -Direction Inbound -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Protocol TCP -LocalPorts 22
New-NetFirewallHyperVRule -Name https -DisplayName "https" -Direction Inbound -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Protocol TCP -LocalPorts 443
New-NetFirewallHyperVRule -Name Port9089 -DisplayName "vCenter Converter Port 9089" -Direction Inbound -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Protocol TCP -LocalPorts 9089
```   

On Photon OS install and configure iptables.
```
sudo cat <<EOFInstall2 | sudo tee $HOME/install2.sh

# Configure iptables
tdnf install -y iptables
systemctl enable iptables
systemctl restart iptables

# delete all of the rules in the INPUT,FORWARD and OUTPUT chain
iptables -F INPUT
iptables -F FORWARD
iptables -F OUTPUT

# set default in the INPUT,FORWARD and OUTPUT chain
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

# ntp
iptables -A INPUT -i eth0 -p udp --dport 123 -j ACCEPT
# dns
iptables -A INPUT -i eth0 -p udp --dport 53 -j ACCEPT
# dhcp
iptables -A INPUT -i eth0 -p udp --dport 67 -j ACCEPT

# ping
iptables -A INPUT -i eth0 -p icmp -j ACCEPT
# ssh and https
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 443 -j ACCEPT
# VMware vCenter Converter source Windows machine
iptables -A INPUT -i eth0 -p udp --dport 137 -j ACCEPT
iptables -A INPUT -i eth0 -p udp --dport 138 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 139 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 9089 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 445 -j ACCEPT
# VMware vCenter Converter connectivity
iptables -A INPUT -i eth0 -p tcp --dport 902 -j ACCEPT

iptables-save >/etc/systemd/scripts/ip4save
ip6tables-save >/etc/systemd/scripts/ip6save
EOFInstall2
```

Run the install script.
```
sudo chmod a+x $HOME/install2.sh
sudo /bin/bash $HOME/install2.sh
```

Known issues

ISSUE: simply starting wsl does not login.

Didn't find the cause. Use wsl -u $ROOTLESS_USER -e /bin/bash as workaround.

ISSUE: docker-rootless fails.

The setup above should be ready to allow docker-rootless, however it fails. See steps below.

  • Login as ROOTLESS_USER.

    $distroname="Ph5"
    $ROOTLESS_USER="dcaso"
    wsl -d $distroname -u $ROOTLESS_USER -e /bin/bash
    
  • Finish rootless setup.

    /usr/bin/dockerd-rootless-setuptool.sh install --skip-iptables # retry if it doesn't work the first time. docker daemon must be up and running.
    
    ROOTLESS_USER=localuser # same user as above.
    echo "export PATH=/usr/bin:\$PATH" >> $HOME/.bashrc
    echo export DOCKER_HOST=unix:///run/user/$ROOTLESS_USER/docker.sock >> $HOME/.bashrc
    
    sudo docker run -it hello-world
    

ISSUE: How to avoid check connection?

The debug log shows that on each boot there is a sort of connection test. I do not understand how to configure -> https://learn.microsoft.com/en-us/windows-server/networking/ncsi/ncsi-frequently-asked-questions#does-linux-have-its-own-ncsi

CheckConnection: resolving the name www.msftconnecttest.com [AF_INET]
CheckConnection: connecting to 80.67.82.217
CheckConnection: resolving the name www.msftconnecttest.com [AF_INET6]
Exception: CheckConnection: getaddrinfo() failed: -2
CheckConnection: arming select for 5 seconds
CheckConnection: v4 succeeded
CheckConnection: returning v4 (1) v6 (2)
LxGnsMessageConnectTestRequest (destination: www.msftconnecttest.com) returning: 0x20001
GNS: Processing Next Message Successful (0x20001)
Returning LxGnsMessageResult [131073 - ]

ISSUE: Sound in WSL2 does not work.

This has to be distinguished in

    1. Pulseaudio support -> does not work yet
    1. laptop built-in audio hardware support -> does not work yet
    1. usb-c attached audio devices -> works (see above)

Pulseaudio support

Pulse audio support seems to be an issue in the actual Photon OS setup and configuration.

In /mnt/wslg there are logs. stderr.log

[11:31:52.825] <3>WSLGd: LogException:75: Exception: No such file or directory @../FontMonitor.cpp:280 (Start)

[11:31:52.825] <5>WSLGd: Stop:330: FontMonitor: monitoring stopped.
dbus[16]: Unknown username "pulse" in message bus configuration file
glamor: 'wl_drm' not supported
Missing Wayland requirements for glamor GBM backend
Failed to initialize glamor, falling back to sw
The XKEYBOARD keymap compiler (xkbcomp) reports:
> Warning:          Unsupported maximum keycode 569, clipping.
>                   X11 cannot support keycodes above 255.
Errors from xkbcomp are not fatal to the X server

pulseaudio.log

(   0.000|   0.000) W: [pulseaudio] authkey.c: Failed to open cookie file '/home/wslg/.config/pulse/cookie': No such file or directory
(   0.000|   0.000) W: [pulseaudio] authkey.c: Failed to load authentication key '/home/wslg/.config/pulse/cookie': No such file or directory
(   0.000|   0.000) W: [pulseaudio] authkey.c: Failed to open cookie file '/home/wslg/.pulse-cookie': No such file or directory
(   0.000|   0.000) W: [pulseaudio] authkey.c: Failed to load authentication key '/home/wslg/.pulse-cookie': No such file or directory
(   0.005|   0.005) E: [pulseaudio] module-console-kit.c: GetSessionsForUnixUser() call failed: org.freedesktop.DBus.Error.ServiceUnknown: The name    org.freedesktop.ConsoleKit was not provided by any .service files
(   0.005|   0.000) E: [pulseaudio] module.c: Failed to load module "module-console-kit" (argument: ""): initialization failed.
(   0.007|   0.001) W: [pulseaudio] cli-command.c: stat('/etc/pulse/default.pa.d'): No such file or directory
(   0.513|   0.506) E: [rdp-sink] module-rdp-sink.c: RDP Sink - Trying to connect to /mnt/wslg/PulseAudioRDPSink
(   0.513|   0.000) E: [rdp-sink] module-rdp-sink.c: Connected failed
(   5.514|   4.999) E: [rdp-sink] module-rdp-sink.c: RDP Sink - Trying to connect to /mnt/wslg/PulseAudioRDPSink
(   5.514|   0.000) E: [rdp-sink] module-rdp-sink.c: RDP Sink - Connected to fd 1

and two additional logs weston.log, wlog.log.

Research notes.

sudo tdnf install -y git meson build-essential which clang doxygen cmake libgssglue json-c systemd-devel libjpeg-turbo libjpeg-turbo-devel libgudev alsa-lib alsa-lib-devel alsa-utils json-c-devel libgssglue-devel libXcursor-devel libXi-devel libXinerama-devel libXrandr-devel ninja-build
 sudo tdnf install -y gstreamer gstreamer-devel gstreamer-plugins-base gstreamer-plugins-base-devel libtiff libtiff-devel lttng-tools lttng-ust lttng-ust-devel libglvnd-devel libglvnd-opengl mesa
sudo tdnf install -y dbus dbus-devel dbus-glib dbus-glib-devel dbus-broker libcap-devel valgrind autogen
sudo git clone https://github.com/microsoft/PulseAudio-mirror
cd PulseAudio-mirror

sudo git clone https://github.com/libsndfile/libsndfile
cd libsndfile
sudo autoreconf -vif
sudo ./configure --enable-werror
sudo make
sudo make install
cd ..

sudo meson build # FAILS
sudo meson compile -C build
sudo build/src/daemon/pulseaudio -n -F build/src/daemon/default.pa -p $(pwd)/build/src/modules/
autoreconv -vif
# libflac, libogg,
# configure: WARNING: *** libvorbis and libopus)
# "MPEG support selected but external Lame library cannot be found.

# 3rd attempt
sudo git clone https://github.com/xiph/ogg
cd ogg
sudo ./autogen.sh
sudo ./configure
sudo make
sudo make install
cd ..

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

sudo ldconfig

sudo git clone https://github.com/xiph/vorbis
cd vorbis
sudo ./autogen.sh
sudo ./configure
sudo make
sudo make install
cd ..

sudo ldconfig

sudo git clone https://github.com/xiph/flac
cd flac
sudo ./autogen.sh
sudo ./configure
sudo make
sudo make install

sudo ldconfig

sudo git clone https://github.com/xiph/opus
cd opus
sudo ./autogen.sh
sudo ./configure
sudo make
sudo make install

sudo ldconfig

cd $HOME
curl -J -L -O https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-amd64-static.tar.xz
sudo tar -xvf ffmpeg-git-amd64-static.tar.xz
export PATH=$HOME/ffmpeg-git-20240504-amd64-static:$PATH


sudo tdnf install -y autoconf-archive
sudo git clone https://github.com/chirlu/sox.git
cd sox
sudo autoreconf -i
sudo ./configure --enable-pulseaudio

sudo git clone https://gitlab.freedesktop.org/pipewire/pipewire.git
cd pipewire
sudo tdnf install -y dbus dbus-glib dbus-glib-devel
sudo ./autogen.sh
sudo make
sudo make install

sudo tdnf remove alsa-lib
sudo rpm -ivh https://ftp.lysator.liu.se/pub/opensuse/distribution/leap/15.5/repo/oss/x86_64/libasound2-1.2.8-150500.1.1.x86_64.rpm

# another attempt
sudo tdnf install -y autogen
sudo git clone -b master https://github.com/libsndfile/libsndfile/
cd src
sudo curl -J -L -O https://raw.githubusercontent.com/libsndfile/libsndfile/master-evpobr/src/test_endswap.c
cd ..
cd tests
sudo git clone -b master-evpobr https://github.com/libsndfile/libsndfile/
sudo cp ./libsndfile/tests/*.c .
sudo rm -r -f libsndfile/
cd ..
sudo make install


sudo tdnf install -y wayland wayland-devel wayland-protocols wayland-protocols-devel
sudo tdnf install -y libxkbcommon libxkbcommon-devel libxkbcommon-x11 libxkbcommon-x11-devel
sudo groupadd audio
sudo useradd pulse -m -g users -G sudo,wheel
echo "pulse ALL=(ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoers
sudo usermod -a -G audio pulse

cd $HOME
git clone https://github.com/libsdl-org/SDL
cd SDL
sudo cmake -S . -B build
sudo cmake --build build
sudo cmake --install build


wsl -d Ph5 --system -u root
cp -vr /home/wslg/ /mnt/c/Users/dcaso
exit
wsl -d Ph5 -u dcaso -e /bin/bash
sudo cp -vr /mnt/c/Users/dcaso/wslg /home
sudo chmod 777 /home/wslg/.config/pulse/cookie
sudo mkdir -p /etc/pulse/default.pa.d


sudo tdnf install -y gstreamer gstreamer-devel gstreamer-plugins-base gstreamer-plugins-base-devel gst-plugins-bad gst-plugins-bad-devel
sudo tdnf install -y libdrm libdrm-devel mesa mesa-libgbm mesa-libgbm-devel mesa-vulkan-drivers vulkan-headers vulkan-loader-devel vulkan-tools 
sudo tdnf install -y python3-lxml python3-sphinx libapparmor-devel readline-devel
sudo tdnf install -y dbus-glib dbus-glib-devel glib-devel glibc-devel glibc-i18n glibc-tools glibmm-devel json-glib-devel linux-drivers-intel-i40e linux-drivers-intel-ice

laptop built-in audio hardware support

The laptop built-in audio hardware isn't detected automatically.

A speaker-test speaker-test -t sine -f 1000 -l 1 fails with ALSA lib confmisc.c:855:(parse_card) cannot find card '0'.

Output alsa-info.sh.

ALSA Information Script v 0.5.3
--------------------------------

This script visits the following commands/files to collect diagnostic
information about your ALSA installation and sound related hardware.

  dmesg
  lspci
  aplay
  amixer
  alsactl
  rpm, dpkg
  /proc/asound/
  /sys/class/sound/
  ~/.asoundrc (etc.)

See '/usr/sbin/alsa-info.sh --help' for command line options.

/usr/sbin/alsa-info.sh: line 478: /proc/asound/modules: No such file or directory
cat: /tmp/alsa-info.Cy535VqKIW/sdwstatus.tmp: No such file or directory
cat: /tmp/alsa-info.Cy535VqKIW/alsamodules.tmp: No such file or directory
cat: /proc/asound/modules: No such file or directory

Your ALSA information is in /tmp/alsa-info.txt.2SNknRW67y

sudo alsamixer opens the user interface, but the laptop built-in audio device is not recognized. Same for sudo amixer.

image

ISSUE: systemd status fails output

see https://github.com/microsoft/WSL/issues/8879

dcaso [ /mnt/c/Users/dcaso ]$ sudo systemctl status --no-pager
● ltdca
    State: running
    Units: 306 loaded (incl. loaded aliases)
     Jobs: 0 queued
   Failed: 0 units
    Since: Wed 2024-06-19 20:32:34 CEST; 3min 57s ago
  systemd: v253.19-4.ph5
  Tainted: cgroupsv1
   CGroup: /
Failed to dump process list for 'ltdca', ignoring: Input/output error

ISSUE: dmesg and journalctl show a few error messages in Photon OS 5.x with WSL-kernel 6.1.21. How to avoid these?

dxgk (dxgkio_query_adapter_info: Ioctl failed: -22)
potentially unexpected fatal signal 11
systemd-coredump (Failed to connect to coredump service: No such file or directory)
ERROR: WaitForBootProcess:3335: /sbin/init failed to start within 10000 (udev-worker)[106]: controlC4: Process '/usr/sbin/alsactl restore 4' failed with exit code 99 usr/lib/udev/rules.d/60-block-scheduler.rules (Failed to write ATTR), etc/udev/rules.d/60-ioschedulers.rules (Failed to write ATTR)
/proc/sys/fs/binfmt_misc/WSLInterop-late (Permission denied)
modprobe: FATAL: Module aufs not found in directory /lib/modules/6.1.21.2-microsoft-standard-WSL2+ Kernel reports TIME_ERROR: 0x41 (Clock Unsynchronized)

(old) dmesg.txt (old) journal.txt

How to use Photon OS kernel?

How to use Photon OS kernel instead of cbl mariner as default ? (and not only the dockerized Photon OS distro.) The cbl-mariner system distribution can be explored started using

  • wsl --system which starts in context of the internal wslg user.
    wslg [ /mnt/c/Users/dcaso ]$ cat /etc/os-release
    NAME="Common Base Linux Mariner"
    VERSION="2.0.20231130"
    ID=mariner
    VERSION_ID="2.0"
    PRETTY_NAME="CBL-Mariner/Linux"
    ANSI_COLOR="1;34"
    HOME_URL="https://aka.ms/cbl-mariner"
    BUG_REPORT_URL="https://aka.ms/cbl-mariner"
    SUPPORT_URL="https://aka.ms/cbl-mariner"
    
  • wsl --system -u root /bin/bash which starts in context of the internal root user. cbl-mariner allows to make use of tdnf.
    tdnf update -y tdnf
    tdnf install -y rpm-build
    tdnf distro-sync -y
    
    The changes above aren't persistent, but allows to quickly test a newer release.
    root [ /mnt/c/Users/dcaso ]# cat /etc/os-release
    NAME="Common Base Linux Mariner"
    VERSION="2.0.20240223"
    ID=mariner
    VERSION_ID="2.0"
    PRETTY_NAME="CBL-Mariner/Linux"
    ANSI_COLOR="1;34"
    HOME_URL="https://aka.ms/cbl-mariner"
    BUG_REPORT_URL="https://aka.ms/cbl-mariner"
    SUPPORT_URL="https://aka.ms/cbl-mariner"
    

Various

Enable Docker Desktop WSL2 integration with Photon OS

In Docker Desktop > Settings > Resources > WSL integration > Enable integration with additional distros: Ph5 > Apply & restart

Cleanup Photon OS on WSL2

Run the following powershell commands.

wsl -d $distroname --shutdown
wsl --unregister $distroname
rm "$targetdirectory\.wslconfig"
rm "$targetdirectory\vmlinux"
rm "$targetdirectory\photon.tar"
# rm "$targetdirectory/.ssh/known_hosts"

Weblinks

How to recompile the Linux Kernel: - https://github.com/PINTO0309/wsl2_linux_kernel_usbcam_enable_conf/tree/main

Notes

For smartcard support, you need at least release 5.15.150.1, see https://github.com/microsoft/WSL/issues/10581