diff --git a/flake.lock b/flake.lock index 1954acd..4352e6d 100644 --- a/flake.lock +++ b/flake.lock @@ -21,6 +21,20 @@ "type": "github" } }, + "flake-compat": { + "locked": { + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "revCount": 69, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.1.0/01948eb7-9cba-704f-bbf3-3fa956735b52/source.tar.gz?rev=ff81ac966bb2cae68946d5ed5fc4994f96d0ffec&revCount=69" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -39,6 +53,24 @@ "type": "github" } }, + "flake-utils_2": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -81,6 +113,21 @@ "type": "github" } }, + "nix-filter": { + "locked": { + "lastModified": 1757882181, + "narHash": "sha256-+cCxYIh2UNalTz364p+QYmWHs0P+6wDhiWR4jDIKQIU=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "59c44d1909c72441144b93cf0f054be7fe764de5", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, "nix4vscode": { "inputs": { "nixpkgs": [ @@ -124,7 +171,8 @@ "home-manager": "home-manager", "niri-float-sticky": "niri-float-sticky", "nix4vscode": "nix4vscode", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "winapps": "winapps" } }, "systems": { @@ -158,6 +206,21 @@ "type": "github" } }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "utils": { "locked": { "lastModified": 1652776076, @@ -172,6 +235,29 @@ "repo": "flake-utils", "type": "github" } + }, + "winapps": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils_2", + "nix-filter": "nix-filter", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1783436030, + "narHash": "sha256-mx3ag4EJdosy90FEwMwtQftrSCCyP+TYyJ2tephvRgU=", + "owner": "winapps-org", + "repo": "winapps", + "rev": "5cbf7381f9a12af630e5a289d6dab5f7adc70e5d", + "type": "github" + }, + "original": { + "owner": "winapps-org", + "repo": "winapps", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index ee0e37f..fdf601d 100644 --- a/flake.nix +++ b/flake.nix @@ -29,6 +29,11 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + winapps = { + url = "github:winapps-org/winapps"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + # Homelab inputs inputs.copyparty = { diff --git a/hosts/desktop/default.nix b/hosts/desktop/default.nix index 04c1512..ff81848 100644 --- a/hosts/desktop/default.nix +++ b/hosts/desktop/default.nix @@ -12,6 +12,7 @@ ++ builtins.map (i: ../../modules/${i}) ([ "codium" "niri-de" + "winapps" "customisation.nix" "docker.nix" "editing.nix" diff --git a/hosts/laptop/default.nix b/hosts/laptop/default.nix index ca3c200..277eb9e 100644 --- a/hosts/laptop/default.nix +++ b/hosts/laptop/default.nix @@ -13,6 +13,7 @@ "codium" "kde" "niri-de" + "winapps" "battery-notify.nix" "docker.nix" "editing.nix" diff --git a/modules/flint.nix b/modules/flint.nix index a45353f..1445829 100644 --- a/modules/flint.nix +++ b/modules/flint.nix @@ -5,5 +5,7 @@ # Internship firefox teams-for-linux + + kdePackages.krdc ]; } diff --git a/modules/winapps/default.nix b/modules/winapps/default.nix new file mode 100644 index 0000000..76f5c51 --- /dev/null +++ b/modules/winapps/default.nix @@ -0,0 +1,19 @@ +{ flakes, pkgs, ... }: + +{ + environment.systemPackages = with pkgs; [ + flakes.inputs.winapps.packages."${system}".winapps + flakes.inputs.winapps.packages."${system}".winapps-launcher # optional + ]; + + home-manager.users."fantomitechno" = + { + config, + dotfileFolder, + ... + }: + { + xdg.configFile."winapps/winapps.conf".source = + config.lib.file.mkOutOfStoreSymlink "${dotfileFolder}/modules/winapps/winapps.conf"; + }; +} diff --git a/modules/winapps/winapps.conf b/modules/winapps/winapps.conf new file mode 100644 index 0000000..41e27a6 --- /dev/null +++ b/modules/winapps/winapps.conf @@ -0,0 +1,176 @@ +################################## +# WINAPPS CONFIGURATION FILE # +################################## + +# INSTRUCTIONS +# - Leading and trailing whitespace are ignored. +# - Empty lines are ignored. +# - Lines starting with '#' are ignored. +# - All characters following a '#' are ignored. + +# [WINDOWS USERNAME] +RDP_USER="Simon" + +# [WINDOWS PASSWORD] +# NOTES: +# - If using FreeRDP v3.9.0 or greater, you *have* to set a password +# - RDP_ASKPASS is provided as a more secure option to RDP_PASS: +# - Calls an external command and uses its stdout as the password +# - The password is not passed on the command line to freerdp, keeping it out of logs +# - If specified, takes precedence over RDP_PASS +# - Examples to use this: +# - RDP_ASKPASS="~/some-custom-command" +# - RDP_ASKPASS="bash -c 'cat ~/.some-secret-file'" +# - RDP_ASKPASS="bash -c 'kwallet-query --folder winapps --read-password rdp kdewallet'" +# +RDP_PASS="MyWindowsPassword" +RDP_ASKPASS="" + +# [WINDOWS DOMAIN] +# DEFAULT VALUE: '' (BLANK) +RDP_DOMAIN="" + +# [WINDOWS IPV4 ADDRESS] +# NOTES: +# - If using 'libvirt', 'RDP_IP' will be determined by WinApps at runtime if left unspecified. +# DEFAULT VALUE: +# - 'docker': '127.0.0.1' +# - 'podman': '127.0.0.1' +# - 'libvirt': '' (BLANK) +RDP_IP="127.0.0.1" + +# [RDP PORT] +# NOTES: +# - For Docker and Podman, this is the host port mapped to Windows port 3389. +# - If you changed the host-side RDP port in compose.yaml, set this to match. +# DEFAULT VALUE: '3389' +RDP_PORT="3389" + +# [VM NAME] +# NOTES: +# - Only applicable when using 'libvirt' +# - The libvirt VM name must match so that WinApps can determine VM IP, start the VM, etc. +# DEFAULT VALUE: 'RDPWindows' +VM_NAME="RDPWindows" + +# [WINAPPS BACKEND] +# DEFAULT VALUE: 'docker' +# VALID VALUES: +# - 'docker' +# - 'podman' +# - 'libvirt' +# - 'manual' +WAFLAVOR="docker" + +# [DISPLAY SCALING FACTOR] +# NOTES: +# - If an unsupported value is specified, a warning will be displayed. +# - If an unsupported value is specified, WinApps will use the closest supported value. +# DEFAULT VALUE: '100' +# VALID VALUES: +# - '100' +# - '140' +# - '180' +RDP_SCALE="100" + +# [MOUNTING REMOVABLE PATHS FOR FILES] +# NOTES: +# - By default, `udisks` (which you most likely have installed) uses /run/media for mounting removable devices. +# This improves compatibility with most desktop environments (DEs). +# ATTENTION: The Filesystem Hierarchy Standard (FHS) recommends /media instead. Verify your system's configuration. +# - To manually mount devices, you may optionally use /mnt. +# REFERENCE: https://wiki.archlinux.org/title/Udisks#Mount_to_/media +REMOVABLE_MEDIA="/run/media" + +# [ADDITIONAL FREERDP FLAGS & ARGUMENTS] +# NOTES: +# - You can try adding /network:lan to these flags in order to increase performance, however, some users have faced issues with this. +# If this does not work or if it does not work without the flag, you can try adding /nsc and /gfx. +# DEFAULT VALUE: '/cert:tofu /sound /microphone +home-drive' +# VALID VALUES: See https://github.com/awakecoding/FreeRDP-Manuals/blob/master/User/FreeRDP-User-Manual.markdown +RDP_FLAGS="/cert:tofu /sound /microphone +home-drive" + +# [NON FULL WINDOWS RDP FLAGS] +# NOTES: +# - Use these flags to pass specific flags to the freerdp command when you are starting a non-full RDP session (any other command than winapps windows) +# DEFAULT_VALUES: '' +# VALID_VALUES: See https://github.com/awakecoding/FreeRDP-Manuals/blob/master/User/FreeRDP-User-Manual.markdown +RDP_FLAGS_NON_WINDOWS="" + +# [FULL WINDOWS RDP FLAGS] +# NOTES: +# - Use these flags to pass specific flags to the freerdp command when you are starting a full RDP session (winapps windows) +# DEFAULT_VALUES: '' +# VALID_VALUES: See https://github.com/awakecoding/FreeRDP-Manuals/blob/master/User/FreeRDP-User-Manual.markdown +RDP_FLAGS_WINDOWS="" + +# [DEBUG WINAPPS] +# NOTES: +# - Creates and appends to ~/.local/share/winapps/winapps.log when running WinApps. +# DEFAULT VALUE: 'true' +# VALID VALUES: +# - 'true' +# - 'false' +DEBUG="true" + +# [AUTOMATICALLY PAUSE WINDOWS] +# NOTES: +# - This is currently INCOMPATIBLE with 'manual'. +# DEFAULT VALUE: 'off' +# VALID VALUES: +# - 'on' +# - 'off' +AUTOPAUSE="off" + +# [AUTOMATICALLY PAUSE WINDOWS TIMEOUT] +# NOTES: +# - This setting determines the duration of inactivity to tolerate before Windows is automatically paused. +# - This setting is ignored if 'AUTOPAUSE' is set to 'off'. +# - The value must be specified in seconds (to the nearest 10 seconds e.g., '30', '40', '50', etc.). +# - For RemoteApp RDP sessions, there is a mandatory 20-second delay, so the minimum value that can be specified here is '20'. +# - Source: https://techcommunity.microsoft.com/t5/security-compliance-and-identity/terminal-services-remoteapp-8482-session-termination-logic/ba-p/246566 +# DEFAULT VALUE: '300' +# VALID VALUES: >=20 +AUTOPAUSE_TIME="300" + +# [FREERDP COMMAND] +# NOTES: +# - WinApps will attempt to automatically detect the correct command to use for your system. +# DEFAULT VALUE: '' (BLANK) +# VALID VALUES: The command required to run FreeRDPv3 on your system (e.g., 'xfreerdp', 'xfreerdp3', etc.). +FREERDP_COMMAND="" + +# [TIMEOUTS] +# NOTES: +# - These settings control various timeout durations within the WinApps setup. +# - Increasing the timeouts is only necessary if the corresponding errors occur. +# - Ensure you have followed all the Troubleshooting Tips in the error message first. + +# PORT CHECK +# - The maximum time (in seconds) to wait when checking if the RDP port on Windows is open. +# - Corresponding error: "NETWORK CONFIGURATION ERROR" (exit status 13). +# DEFAULT VALUE: '5' +PORT_TIMEOUT="5" + +# RDP CONNECTION TEST +# - The maximum time (in seconds) to wait when testing the initial RDP connection to Windows. +# - Corresponding error: "REMOTE DESKTOP PROTOCOL FAILURE" (exit status 14). +# DEFAULT VALUE: '30' +RDP_TIMEOUT="30" + +# APPLICATION SCAN +# - The maximum time (in seconds) to wait for the script that scans for installed applications on Windows to complete. +# - Corresponding error: "APPLICATION QUERY FAILURE" (exit status 15). +# DEFAULT VALUE: '60' +APP_SCAN_TIMEOUT="60" + +# WINDOWS BOOT +# - The maximum time (in seconds) to wait for the Windows VM to boot if it is not running, before attempting to launch an application. +# DEFAULT VALUE: '120' +BOOT_TIMEOUT="120" + +# FREERDP RAIL HIDEF +# - This option controls the value of the `hidef` option passed to the /app parameter of the FreeRDP command. +# - Setting this option to 'off' may resolve window misalignment issues related to maximized windows. +# DEFAULT VALUE: 'on' +HIDEF="on" diff --git a/modules/winapps/windows.yaml b/modules/winapps/windows.yaml new file mode 100644 index 0000000..c9f0ffe --- /dev/null +++ b/modules/winapps/windows.yaml @@ -0,0 +1,49 @@ +# For documentation, FAQ, additional configuration options and technical help, visit: https://github.com/dockur/windows + +name: "winapps" # Docker Compose Project Name. +volumes: + # Create Volume 'data'. + # Located @ '/var/lib/docker/volumes/winapps_data/_data' (Docker). + # Located @ '/var/lib/containers/storage/volumes/winapps_data/_data' or '~/.local/share/containers/storage/volumes/winapps_data/_data' (Podman). + data: +services: + windows: + image: ghcr.io/dockur/windows:latest + container_name: WinApps # Created Docker VM Name. + environment: + # Version of Windows to configure. For valid options, visit: + # https://github.com/dockur/windows?tab=readme-ov-file#how-do-i-select-the-windows-version + # https://github.com/dockur/windows?tab=readme-ov-file#how-do-i-install-a-custom-image + VERSION: "11" + RAM_SIZE: "4G" # RAM allocated to the Windows VM. + CPU_CORES: "4" # CPU cores allocated to the Windows VM. + DISK_SIZE: "64G" # Size of the primary hard disk. + # DISK2_SIZE: "32G" # Uncomment to add an additional hard disk to the Windows VM. Ensure it is mounted as a volume below. + USERNAME: "Simon" # Edit here to set a custom Windows username. The default is 'MyWindowsUser'. + PASSWORD: "MyWindowsPassword" # Edit here to set a password for the Windows user. The default is 'MyWindowsPassword'. + HOME: "${HOME}" # Set path to Linux user home folder. + ports: + - 8006:8006 # Map '8006' on Linux host to '8006' on Windows VM --> For VNC Web Interface @ http://127.0.0.1:8006. + - 3389:3389/tcp # Map '3389' on Linux host to '3389' on Windows VM --> For Remote Desktop Protocol (RDP). + - 3389:3389/udp # Map '3389' on Linux host to '3389' on Windows VM --> For Remote Desktop Protocol (RDP). + cap_add: + - NET_ADMIN # Add network permission + stop_grace_period: 120s # Wait 120 seconds before sending SIGTERM when attempting to shut down the Windows VM. + restart: on-failure # Restart the Windows VM if the exit code indicates an error. + volumes: + - data:/storage # Mount volume 'data' to use as Windows 'C:' drive. + - ${HOME}:/shared # Mount Linux user home directory @ '\\host.lan\Data'. + #- /path/to/second/hard/disk:/storage2 # Uncomment to create a virtual second hard disk and mount it within the Windows VM. Ensure 'DISK2_SIZE' is specified above. + - ./oem:/oem # Enables automatic post-install execution of 'oem/install.bat', applying Windows registry modifications contained within 'oem/RDPApps.reg'. + #- /path/to/windows/install/media.iso:/custom.iso # Uncomment to use a custom Windows ISO. If specified, 'VERSION' (e.g. 'tiny11') will be ignored. + devices: + - /dev/kvm # Enable KVM. + - /dev/net/tun # Enable tuntap + # Uncomment to mount a disk directly within the Windows VM. + # WARNING: /dev/sdX paths may change after reboot. Use persistent identifiers! + # NOTE: 'disk1' will be mounted as the main drive. THIS DISK WILL BE FORMATTED BY DOCKER. + # All following disks (disk2, ...) WILL NOT BE FORMATTED. + # - /dev/disk/by-id/:/disk1 + # - /dev/disk/by-id/:/disk2 + # group_add: # uncomment this line and the next one for using rootless podman containers + # - keep-groups # to make /dev/kvm work with podman. needs "crun" installed, "runc" will not work! Add your user to the 'kvm' group or another that can access /dev/kvm. \ No newline at end of file