From ff2b258ae39460369f95cdf7670077bb9a3e501e Mon Sep 17 00:00:00 2001 From: Rohan Barar Date: Fri, 19 Jul 2024 13:13:02 +1000 Subject: [PATCH] Added official support for Podman. --- README.md | 15 +++++------ bin/winapps | 17 ++++++++++--- docs/docker.md | 3 +++ installer.sh | 68 +++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 80 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 2818b9c..e93da75 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # WinApps *The WinApps project, forked from Fmstrat's [original repository](https://github.com/Fmstrat/winapps).* -Run Windows applications (including [Microsoft 365](https://www.microsoft365.com/) and [Adobe Creative Cloud](https://www.adobe.com/creativecloud.html)) on GNU+Linux with `KDE` or `GNOME`, integrated seamlessly as if they were native to the OS. +Run Windows applications (including [Microsoft 365](https://www.microsoft365.com/) and [Adobe Creative Cloud](https://www.adobe.com/creativecloud.html)) on GNU+Linux with `KDE`, `GNOME` or `XFCE`, integrated seamlessly as if they were native to the OS. WinApps Demonstration Animation. @@ -75,10 +75,10 @@ Contributing to the list of supported applications is encouraged through submiss ## Installation ### Step 1: Configure a Windows VM -The optimal choice for running a Windows VM as a subsystem for WinApps is `Docker`. `Docker` facilitates automated installation processes while leveraging a `KVM/QEMU` backend. Despite continuing to provide documentation for configuring a Windows VM using `libvirt` and `virt-manager`, this method is now considered deprecated. +The optimal choice for running a Windows VM as a subsystem for WinApps is `Docker`. `Docker` facilitates automated installation processes while leveraging a `KVM/QEMU` backend. Despite continuing to provide documentation for configuring a Windows VM using `virt-manager`, this method is now considered deprecated. The following guides are available: -- [Creating a Windows VM with `Docker`](docs/docker.md) +- [Creating a Windows VM with `Docker` or `Podman`](docs/docker.md) - [Creating a Windows VM with `virt-manager`](docs/KVM.md) (Deprecated) If you already have a Windows VM or server you wish to use with WinApps, you will need to merge `install/RDPApps.reg` into the Windows Registry. @@ -107,7 +107,8 @@ If you already have a Windows VM or server you wish to use with WinApps, you wil sudo emerge --ask=n sys-libs/dialog net-misc/freerdp:3 ``` -Please note that WinApps requires `FreeRDP` version 3 or later. If not available for your distribution through your package manager, you can install the [Flatpak](https://flathub.org/apps/com.freerdp.FreeRDP). +> [!NOTE] +> WinApps requires `FreeRDP` version 3 or later. If not available for your distribution through your package manager, you can install the [Flatpak](https://flathub.org/apps/com.freerdp.FreeRDP). ```bash flatpak install flathub com.freerdp.FreeRDP @@ -121,8 +122,8 @@ RDP_USER="MyWindowsUser" RDP_PASS="MyWindowsPassword" #RDP_DOMAIN="MYDOMAIN" #RDP_IP="192.168.123.111" -#WAFLAVOR="docker" -#RDP_SCALE=100 +#WAFLAVOR="docker" # Acceptable values are 'docker', 'podman' and 'libvirt'. +#RDP_SCALE=100 # Acceptable values are 100, 140, and 180. #RDP_FLAGS="" #MULTIMON="true" #DEBUG="true" @@ -133,7 +134,7 @@ RDP_PASS="MyWindowsPassword" > `RDP_USER` and `RDP_PASS` must correspond to a complete Windows user account and password, such as those created during Windows setup or for a domain user. User/PIN combinations are not valid for RDP access. > [!NOTE] -> If you wish to use the older (deprecated) `virt-manager` method, uncomment and change `WAFLAVOR="docker"` to `WAFLAVOR="libvirt"`. +> If you wish to use an alternative WinApps backend (other than `Docker`), uncomment and change `WAFLAVOR="docker"` to `WAFLAVOR="podman"` or `WAFLAVOR="libvirt"`. #### Configuration Options Explained - When using a pre-existing non-KVM RDP server, you must use `RDP_IP` to specify the location of the Windows server. diff --git a/bin/winapps b/bin/winapps index 5433ad4..6c52ca1 100755 --- a/bin/winapps +++ b/bin/winapps @@ -94,7 +94,7 @@ function waThrowExit() { "$EC_INVALID_FLAVOR") dprint "ERROR: INVALID FLAVOR. EXITING." echo -e "${ERROR_TEXT}ERROR: INVALID FLAVOR.${CLEAR_TEXT}" - echo "Please ensure either 'docker' or 'libvirt' are specified as the flavor in the WinApps configuration file." + echo "Please ensure 'docker', 'podman' or 'libvirt' are specified as the flavor in the WinApps configuration file." ;; esac @@ -255,12 +255,16 @@ function waCheckContainerRunning() { # Declare variables. local CONTAINER_STATE="" - # Determine container state. + # Determine container state (docker). if command -v docker &>/dev/null; then CONTAINER_STATE=$(docker ps --filter name="WinApps" --format '{{.Status}}') - else + fi + + # Determine container state (podman). + if [ -z "$CONTAINER_STATE" ]; then CONTAINER_STATE=$(podman ps --filter name="WinApps" --format '{{.Status}}') fi + CONTAINER_STATE=${CONTAINER_STATE,,} # Convert the string to lowercase. CONTAINER_STATE=${CONTAINER_STATE%% *} # Extract the first word. @@ -395,7 +399,12 @@ waLastRun waLoadConfig waGetFreeRDPCommand -if [ "$WAFLAVOR" = "docker" ]; then +# If using podman backend, modify the FreeRDP command to enter a new namespace. +if [ "$WAFLAVOR" = "podman" ]; then + FREERDP_COMMAND="podman unshare --rootless-netns ${FREERDP_COMMAND}" +fi + +if [ "$WAFLAVOR" = "docker" ] || [ "$WAFLAVOR" = "podman" ]; then RDP_IP="$DOCKER_IP" waCheckContainerRunning elif [ "$WAFLAVOR" = "libvirt" ]; then diff --git a/docs/docker.md b/docs/docker.md index 4b56eef..1b752fd 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -59,6 +59,9 @@ docker compose kill # Force shut down the Windows VM ### Setup `Podman` Container Please follow the [`docker` instructions](#setup-docker-container). +> [!NOTE] +> Ensure `WAFLAVOR` is set to `"podman"` in `~/.config/winapps/winapps.conf`. + ### Installing Windows After navigating into the cloned WinApps repository, you can initiate the Windows installation using `podman-compose`. ```bash diff --git a/installer.sh b/installer.sh index 33d1b9a..9816134 100755 --- a/installer.sh +++ b/installer.sh @@ -30,6 +30,7 @@ readonly EC_NO_IP="12" # Windows does not have an IP address. readonly EC_BAD_PORT="13" # Windows is unreachable via RDP_PORT. readonly EC_RDP_FAIL="14" # FreeRDP failed to establish a connection with Windows. readonly EC_APPQUERY_FAIL="15" # Failed to query Windows for installed applications. +readonly EC_INVALID_FLAVOR="16" # Backend specified is not 'libvirt', 'docker' or 'podman'. # PATHS # 'BIN' @@ -586,7 +587,7 @@ function waCheckDependencies() { return "$EC_MISSING_DEPS" fi elif [ "$WAFLAVOR" = "docker" ]; then - if ! command -v docker &>/dev/null && ! command -v podman-compose &>/dev/null; then + if ! command -v docker &>/dev/null; then # Complete the previous line. echo -e "${FAIL_TEXT}Failed!${CLEAR_TEXT}\n" @@ -594,11 +595,29 @@ function waCheckDependencies() { echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}MISSING DEPENDENCIES.${CLEAR_TEXT}" # Display the error details. - echo -e "${INFO_TEXT}Please install 'Docker Engine' OR 'podman' and 'podman-compose' to proceed.${CLEAR_TEXT}" + echo -e "${INFO_TEXT}Please install 'Docker Engine' to proceed.${CLEAR_TEXT}" # Display the suggested action(s). echo "--------------------------------------------------------------------------------" echo "Please visit https://docs.docker.com/engine/install/ for more information." + echo "--------------------------------------------------------------------------------" + + # Terminate the script. + return "$EC_MISSING_DEPS" + fi + elif [ "$WAFLAVOR" = "podman" ]; then + if ! command -v podman-compose &>/dev/null || ! command -v podman &>/dev/null; then + # Complete the previous line. + echo -e "${FAIL_TEXT}Failed!${CLEAR_TEXT}\n" + + # Display the error type. + echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}MISSING DEPENDENCIES.${CLEAR_TEXT}" + + # Display the error details. + echo -e "${INFO_TEXT}Please install 'podman' and 'podman-compose' to proceed.${CLEAR_TEXT}" + + # Display the suggested action(s). + echo "--------------------------------------------------------------------------------" echo "Please visit https://podman.io/docs/installation for more information." echo "Please visit https://github.com/containers/podman-compose for more information." echo "--------------------------------------------------------------------------------" @@ -729,12 +748,16 @@ function waCheckContainerRunning() { # Declare variables. local CONTAINER_STATE="" - # Determine container state. + # Determine container state (docker). if command -v docker &>/dev/null; then CONTAINER_STATE=$(docker ps --filter name="WinApps" --format '{{.Status}}') - else + fi + + # Determine container state (podman). + if [ -z "$CONTAINER_STATE" ]; then CONTAINER_STATE=$(podman ps --filter name="WinApps" --format '{{.Status}}') fi + CONTAINER_STATE=${CONTAINER_STATE,,} # Convert the string to lowercase. CONTAINER_STATE=${CONTAINER_STATE%% *} # Extract the first word. @@ -881,7 +904,7 @@ function waCheckRDPAccess() { # Check if FreeRDP process is not complete. if ps -p "$FREERDP_PROC" &>/dev/null; then # SIGKILL FreeRDP. - kill -9 "$FREERDP_PROC" + kill -9 "$FREERDP_PROC" &>/dev/null fi # Check if test file does not exist. @@ -1010,7 +1033,7 @@ function waFindInstalled() { # Check if the FreeRDP process is not complete. if ps -p "$FREERDP_PROC" &>/dev/null; then # SIGKILL FreeRDP. - kill -9 "$FREERDP_PROC" + kill -9 "$FREERDP_PROC" &>/dev/null fi # Check if test file does not exist. @@ -1299,7 +1322,9 @@ function waConfigureDetectedApps() { if [[ $APP_INSTALL == "Select which applications to set up" ]]; then inqChkBx "Which other applications would you like to set up?" APPS SELECTED_APPS elif [[ $APP_INSTALL == "Set up all detected applications" ]]; then - readarray -t SELECTED_APPS <<<"${APPS[@]}" + for APP in "${APPS[@]}"; do + SELECTED_APPS+=("$APP") + done fi for SELECTED_APP in "${SELECTED_APPS[@]}"; do @@ -1382,20 +1407,39 @@ function waInstall() { FREERDP_COMMAND="${FREERDP_COMMAND} ${RDP_FLAGS}" fi - if [ "$WAFLAVOR" = "docker" ]; then - # Set RDP_IP to localhost. + # If using 'docker' or 'podman', set RDP_IP to localhost. + if [ "$WAFLAVOR" = "docker" ] || [ "$WAFLAVOR" = "podman" ]; then RDP_IP="$DOCKER_IP" + fi + # If using podman backend, modify the FreeRDP command to enter a new namespace. + if [ "$WAFLAVOR" = "podman" ]; then + FREERDP_COMMAND="podman unshare --rootless-netns ${FREERDP_COMMAND}" + fi + + if [ "$WAFLAVOR" = "docker" ] || [ "$WAFLAVOR" = "podman" ]; then # Check if Windows is powered on. waCheckContainerRunning elif [ "$WAFLAVOR" = "libvirt" ]; then - # Check the group membership of the current user. - waCheckGroupMembership + # Verify the current user's group membership. + waCheckGroupMembership # Check membership # Check if the Windows VM is powered on. waCheckVMRunning else - waThrowExit "$EC_INVALID_FLAVOR" + # Display the error type. + echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}INVALID WINAPPS BACKEND.${CLEAR_TEXT}" + + # Display the error details. + echo -e "${INFO_TEXT}An invalid WinApps backend '${WAFLAVOR}' was specified.${CLEAR_TEXT}" + + # Display the suggested action(s). + echo "--------------------------------------------------------------------------------" + echo -e "Please ensure 'WAFLAVOR' is set to 'docker', 'podman' or 'libvirt' in ${COMMAND_TEXT}${CONFIG_PATH}${CLEAR_TEXT}." + echo "--------------------------------------------------------------------------------" + + # Terminate the script. + return "$EC_INVALID_FLAVOR" fi # Check if the RDP port on Windows is open.