Remove deadalus-win and deadalus-ubuntu profiles

Rimuove completamente i due host non più in uso dal playbook:
- inventory: gruppi ubuntu_workstation, workstation_dev_ubuntu,
  workstation_host_windows e relative entry host
- host_vars deadalus-ubuntu/deadalus-win e group_vars windows
- play workstation_dev_ubuntu e workstation_host_windows in site.yml
- ruolo profile_workstation_host_windows e bootstrap PowerShell
- var PSRP nel vault.yml.example, pacchetti python pypsrp/pyspnego WSL
- collection ansible.windows/community.windows
- riferimenti nella documentazione (README/AGENTS/CLAUDE)

Workstation Linux nativa: resta solo deadalus-fedora.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Fabio Scotto di Santolo
2026-06-21 16:30:30 +02:00
parent 0fb8f23ae2
commit a135edaa3f
14 changed files with 33 additions and 1145 deletions

View File

@@ -1,6 +1,4 @@
---
collections:
- name: ansible.posix
- name: ansible.windows
- name: community.general
- name: community.windows

View File

@@ -19,9 +19,7 @@ workstation_removed_snap_packages: []
workstation_snap_packages:
- name: glab
classic: true
workstation_dev_wsl_python_packages:
- pypsrp
- pyspnego
workstation_dev_wsl_python_packages: []
workstation_wsl_systemd_enabled: true
workstation_dev_wsl_dotfiles:
- src: .gnupg/gpg-agent.conf

View File

@@ -1,71 +0,0 @@
---
ansible_connection: psrp
ansible_psrp_auth: negotiate
ansible_psrp_cert_validation: ignore
ansible_psrp_protocol: https
ansible_port: 5986
ansible_shell_type: powershell
windows_enable_dark_theme: true
windows_hide_taskbar_search: true
windows_hide_taskbar_widgets: true
windows_terminal_default_profile_name: Ubuntu
windows_taskbar_layout_directory: 'C:\ProgramData\Infra\Windows'
windows_taskbar_layout_path: '{{ windows_taskbar_layout_directory }}\taskbar-layout.xml'
windows_taskbar_reapply_every_logon: false
windows_taskbar_pins:
- type: desktop_application_id
id: Chrome
- type: desktop_application_id
id: Microsoft.Windows.Explorer
- type: app_user_model_id
id: Microsoft.OutlookForWindows_8wekyb3d8bbwe!Microsoft.OutlookforWindows
- type: app_user_model_id
id: MSTeams_8wekyb3d8bbwe!MSTeams
- type: app_user_model_id
id: 5319275A.WhatsAppDesktop_cv1g1gvanyjgm!App
- type: desktop_application_id
id: Telegram.TelegramDesktop
- type: desktop_application_id
id: Microsoft.VisualStudioCode
- type: desktop_application_link_path
path: '%APPDATA%\Microsoft\Windows\Start Menu\Programs\JetBrains Toolbox\IntelliJ IDEA Ultimate.lnk'
- type: desktop_application_id
id: com.squirrel.Postman.Postman
- type: app_user_model_id
id: Microsoft.WindowsTerminal_8wekyb3d8bbwe!App
- type: desktop_application_link_path
path: '%APPDATA%\Microsoft\Windows\Start Menu\Programs\DBeaver Community\DBeaver.lnk'
windows_winget_packages:
- id: 7zip.7zip
name: 7-Zip
- id: Adobe.Acrobat.Reader.64-bit
name: Adobe Acrobat Reader
- id: DBeaver.DBeaver.Community
name: DBeaver Community
- id: Google.Chrome
name: Google Chrome
- id: JetBrains.IntelliJIDEA.Ultimate
name: IntelliJ IDEA Ultimate
- id: Logitech.OptionsPlus
name: Logitech Options+
- id: Microsoft.VisualStudioCode
name: Visual Studio Code
- id: Microsoft.WindowsTerminal
name: Windows Terminal
- id: Postman.Postman
name: Postman
- id: Telegram.TelegramDesktop
name: Telegram Desktop
- id: 9NKSQGP7F2NH
name: WhatsApp
source: msstore
windows_vscode_extensions:
- ms-vscode-remote.remote-containers
- ms-vscode-remote.remote-ssh
- ms-vscode-remote.remote-wsl
windows_wsl_distribution_name: Ubuntu

View File

@@ -1,319 +0,0 @@
---
hostname: deadalus-ubuntu
host_packages: []
host_enabled_services: []
workstation_host_vscode_extensions:
- ms-vscode-remote.remote-containers
- ms-vscode-remote.remote-ssh
- ms-azuretools.vscode-docker
- redhat.vscode-yaml
- redhat.ansible
workstation_gnome_managed_settings:
- schema: org.gnome.shell
key: favorite-apps
value: "['google-chrome.desktop', 'org.gnome.Nautilus.desktop', 'spotify_spotify.desktop', 'thunderbird_thunderbird.desktop', 'telegram-desktop_telegram-desktop.desktop', 'code_code.desktop', 'intellij-idea-ultimate_intellij-idea-ultimate.desktop', 'dbeaver-ce_dbeaver-ce.desktop', 'postman_postman.desktop', 'org.gnome.Ptyxis.desktop']"
- schema: org.gnome.shell
key: app-picker-layout
value: "[{'Utilities': <{'position': <0>}>, 'System': <{'position': <1>}>, 'a3b499f3-e2cc-40ac-9145-7db9c827dff2': <{'position': <2>}>, 'org.gnome.Calculator.desktop': <{'position': <3>}>, 'com.mattjakeman.ExtensionManager.desktop': <{'position': <4>}>, 'org.gnome.clocks.desktop': <{'position': <5>}>, 'htop.desktop': <{'position': <6>}>, 'org.gnome.Characters.desktop': <{'position': <7>}>, 'gnome-language-selector.desktop': <{'position': <8>}>, 'org.gnome.Meld.desktop': <{'position': <9>}>, 'net.nokyan.Resources.desktop': <{'position': <10>}>, 'org.gnome.TextEditor.desktop': <{'position': <11>}>, 'org.gnome.tweaks.desktop': <{'position': <12>}>, 'vim.desktop': <{'position': <13>}>, 'snap-store_snap-store.desktop': <{'position': <14>}>, 'org.gnome.Yelp.desktop': <{'position': <15>}>}]"
- schema: org.gnome.desktop.app-folders
key: folder-children
value: "['System', 'Utilities', 'YaST', 'Pardus', 'a3b499f3-e2cc-40ac-9145-7db9c827dff2']"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/System/
key: name
value: "'X-GNOME-Shell-System.directory'"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/System/
key: translate
value: "true"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/System/
key: categories
value: "@as []"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/System/
key: apps
value: "['nm-connection-editor.desktop', 'org.gnome.baobab.desktop', 'org.gnome.DiskUtility.desktop', 'im-config.desktop', 'org.gnome.Logs.desktop', 'org.gnome.Sysprof.desktop', 'gufw.desktop', 'firmware-updater_firmware-updater.desktop', 'org.gnome.Settings.desktop', 'update-manager.desktop', 'desktop-security-center_desktop-security-center.desktop']"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/Utilities/
key: name
value: "'X-GNOME-Shell-Utilities.directory'"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/Utilities/
key: translate
value: "true"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/Utilities/
key: categories
value: "@as []"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/Utilities/
key: apps
value: "['org.gnome.Papers.desktop', 'org.gnome.font-viewer.desktop', 'org.gnome.Loupe.desktop', 'org.gnome.seahorse.Application.desktop']"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/YaST/
key: name
value: "'suse-yast.directory'"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/YaST/
key: translate
value: "true"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/YaST/
key: categories
value: "['X-SuSE-YaST']"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/YaST/
key: apps
value: "@as []"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/Pardus/
key: name
value: "'X-Pardus-Apps.directory'"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/Pardus/
key: translate
value: "true"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/Pardus/
key: categories
value: "['X-Pardus-Apps']"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/Pardus/
key: apps
value: "@as []"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/a3b499f3-e2cc-40ac-9145-7db9c827dff2/
key: name
value: "'Office'"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/a3b499f3-e2cc-40ac-9145-7db9c827dff2/
key: translate
value: "false"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/a3b499f3-e2cc-40ac-9145-7db9c827dff2/
key: categories
value: "@as []"
- schema: org.gnome.desktop.app-folders.folder
path: /org/gnome/desktop/app-folders/folders/a3b499f3-e2cc-40ac-9145-7db9c827dff2/
key: apps
value: "['libreoffice-calc.desktop', 'libreoffice-base.desktop', 'libreoffice-draw.desktop', 'libreoffice-impress.desktop', 'libreoffice-math.desktop', 'libreoffice-writer.desktop', 'xournalpp_xournalpp.desktop', 'libreoffice-startcenter.desktop', 'pdfarranger_pdfarranger.desktop']"
- schema: org.gnome.desktop.input-sources
key: sources
value: "[('xkb', 'us')]"
- schema: org.gnome.desktop.interface
key: accent-color
value: "'orange'"
- schema: org.gnome.desktop.interface
key: clock-format
value: "'24h'"
- schema: org.gnome.desktop.interface
key: clock-show-date
value: "true"
- schema: org.gnome.desktop.interface
key: color-scheme
value: "'prefer-dark'"
- schema: org.gnome.desktop.interface
key: cursor-theme
value: "'Adwaita'"
- schema: org.gnome.desktop.interface
key: document-font-name
value: "'Adwaita Sans 12'"
- schema: org.gnome.desktop.interface
key: font-name
value: "'Adwaita Sans 11'"
- schema: org.gnome.desktop.interface
key: gtk-theme
value: "'Yaru-dark'"
- schema: org.gnome.desktop.interface
key: icon-theme
value: "'Yaru-dark'"
- schema: org.gnome.desktop.interface
key: monospace-font-name
value: "'Ubuntu Sans Mono 11'"
- schema: org.gnome.desktop.interface
key: show-battery-percentage
value: "false"
- schema: org.gnome.desktop.interface
key: text-scaling-factor
value: "1.0"
- schema: org.gnome.desktop.privacy
key: report-technical-problems
value: "false"
- schema: org.gnome.desktop.wm.preferences
key: button-layout
value: "'appmenu:close'"
- schema: org.gnome.desktop.wm.preferences
key: focus-mode
value: "'click'"
- schema: org.gnome.desktop.wm.preferences
key: focus-new-windows
value: "'smart'"
- schema: org.gnome.desktop.wm.preferences
key: num-workspaces
value: "4"
- schema: org.gnome.nautilus.preferences
key: click-policy
value: "'double'"
- schema: org.gnome.nautilus.preferences
key: date-time-format
value: "'simple'"
- schema: org.gnome.nautilus.preferences
key: default-folder-viewer
value: "'icon-view'"
- schema: org.gnome.nautilus.preferences
key: default-sort-order
value: "'name'"
- schema: org.gnome.nautilus.preferences
key: recursive-search
value: "'local-only'"
- schema: org.gnome.nautilus.preferences
key: show-create-link
value: "true"
- schema: org.gnome.nautilus.preferences
key: show-delete-permanently
value: "true"
- schema: org.gnome.nautilus.preferences
key: show-directory-item-counts
value: "'local-only'"
- schema: org.gnome.nautilus.preferences
key: show-hidden-files
value: "false"
- schema: org.gnome.nautilus.preferences
key: show-image-thumbnails
value: "'local-only'"
- schema: org.gnome.nautilus.preferences
key: thumbnail-limit
value: "uint64 50"
- schema: org.gnome.nautilus.icon-view
key: captions
value: "['none', 'none', 'none']"
- schema: org.gnome.nautilus.icon-view
key: default-zoom-level
value: "'medium'"
- schema: org.gtk.gtk4.Settings.FileChooser
key: clock-format
value: "'24h'"
- schema: org.gtk.gtk4.Settings.FileChooser
key: date-format
value: "'regular'"
- schema: org.gtk.gtk4.Settings.FileChooser
key: location-mode
value: "'path-bar'"
- schema: org.gtk.gtk4.Settings.FileChooser
key: show-hidden
value: "false"
- schema: org.gtk.gtk4.Settings.FileChooser
key: show-size-column
value: "true"
- schema: org.gtk.gtk4.Settings.FileChooser
key: show-type-column
value: "true"
- schema: org.gtk.gtk4.Settings.FileChooser
key: sort-column
value: "'name'"
- schema: org.gtk.gtk4.Settings.FileChooser
key: sort-directories-first
value: "true"
- schema: org.gtk.gtk4.Settings.FileChooser
key: sort-order
value: "'ascending'"
- schema: org.gtk.gtk4.Settings.FileChooser
key: startup-mode
value: "'recent'"
- schema: org.gtk.gtk4.Settings.FileChooser
key: type-format
value: "'category'"
- schema: org.gtk.gtk4.Settings.FileChooser
key: view-type
value: "'list'"
- schema: org.gnome.settings-daemon.plugins.color
key: night-light-schedule-automatic
value: "false"
- schema: org.gnome.settings-daemon.plugins.power
key: sleep-inactive-ac-timeout
value: "3600"
- schema: org.gnome.settings-daemon.plugins.power
key: sleep-inactive-ac-type
value: "'nothing'"
- schema: org.gnome.system.location
key: enabled
value: "false"
- schema: org.gnome.TextEditor
key: auto-indent
value: "true"
- schema: org.gnome.TextEditor
key: auto-save-delay
value: "uint32 3"
- schema: org.gnome.TextEditor
key: custom-font
value: "'Monospace 11'"
- schema: org.gnome.TextEditor
key: discover-settings
value: "true"
- schema: org.gnome.TextEditor
key: draw-spaces
value: "@as []"
- schema: org.gnome.TextEditor
key: enable-snippets
value: "false"
- schema: org.gnome.TextEditor
key: highlight-current-line
value: "false"
- schema: org.gnome.TextEditor
key: highlight-matching-brackets
value: "true"
- schema: org.gnome.TextEditor
key: indent-style
value: "'tab'"
- schema: org.gnome.TextEditor
key: indent-width
value: "-1"
- schema: org.gnome.TextEditor
key: keybindings
value: "'default'"
- schema: org.gnome.TextEditor
key: line-height
value: "1.2"
- schema: org.gnome.TextEditor
key: recolor-window
value: "true"
- schema: org.gnome.TextEditor
key: restore-session
value: "true"
- schema: org.gnome.TextEditor
key: right-margin-position
value: "uint32 80"
- schema: org.gnome.TextEditor
key: show-grid
value: "false"
- schema: org.gnome.TextEditor
key: show-line-numbers
value: "false"
- schema: org.gnome.TextEditor
key: show-map
value: "false"
- schema: org.gnome.TextEditor
key: show-right-margin
value: "false"
- schema: org.gnome.TextEditor
key: spellcheck
value: "true"
- schema: org.gnome.TextEditor
key: style-scheme
value: "'Adwaita'"
- schema: org.gnome.TextEditor
key: style-variant
value: "'follow'"
- schema: org.gnome.TextEditor
key: tab-width
value: "uint32 8"
- schema: org.gnome.TextEditor
key: use-system-font
value: "true"
- schema: org.gnome.TextEditor
key: wrap-text
value: "true"

View File

@@ -1,2 +0,0 @@
---
hostname: deadalus-win

View File

@@ -17,7 +17,6 @@ all:
ubuntu:
children:
ubuntu_workstation:
workstation_dev_wsl:
ubuntu_server:
@@ -33,11 +32,9 @@ all:
workstation_host:
children:
workstation_host_linux:
workstation_host_windows:
workstation_dev:
children:
workstation_dev_ubuntu:
workstation_dev_fedora:
workstation_dev_wsl:
@@ -45,11 +42,6 @@ all:
children:
ubuntu_server:
ubuntu_workstation:
hosts:
deadalus-ubuntu:
ansible_connection: local
fedora_workstation:
hosts:
deadalus-fedora:
@@ -57,25 +49,14 @@ all:
workstation_host_linux:
hosts:
deadalus-ubuntu:
ansible_connection: local
deadalus-fedora:
ansible_connection: local
workstation_dev_ubuntu:
hosts:
deadalus-ubuntu:
ansible_connection: local
workstation_dev_fedora:
hosts:
deadalus-fedora:
ansible_connection: local
workstation_host_windows:
hosts:
deadalus-win:
workstation_dev_wsl:
hosts:
deadalus-wsl:

View File

@@ -1,411 +0,0 @@
---
- name: Enable required Windows features for WSL
tags: [packages, services, wsl]
ansible.windows.win_optional_feature:
name:
- Microsoft-Windows-Subsystem-Linux
- VirtualMachinePlatform
state: present
include_parent: true
- name: Gather Windows host version details
tags: [packages]
ansible.windows.win_powershell:
script: |
$os = Get-ComputerInfo
$buildNumber = [int]$os.OsBuildNumber
$Ansible.Result = @{
product_name = $os.WindowsProductName
build_number = $buildNumber
is_windows_11 = $buildNumber -ge 22000
}
$Ansible.Changed = $false
register: windows_host_version_state
- name: Fail when Windows host is not Windows 11
tags: [packages]
ansible.builtin.fail:
msg: >-
workstation_host_windows is supported only on Windows 11. Detected {{ windows_host_version_state.result.product_name }}
build {{ windows_host_version_state.result.build_number }}.
when: not (windows_host_version_state.result.is_windows_11 | default(false))
- name: Enable dark mode for Windows apps
tags: [packages]
ansible.windows.win_regedit:
path: HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize
name: AppsUseLightTheme
data: 0
type: dword
register: windows_apps_dark_mode_state
when: windows_enable_dark_theme | default(false)
- name: Enable dark mode for Windows system surfaces
tags: [packages]
ansible.windows.win_regedit:
path: HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize
name: SystemUsesLightTheme
data: 0
type: dword
register: windows_system_dark_mode_state
when: windows_enable_dark_theme | default(false)
- name: Hide Windows taskbar search box
tags: [packages]
ansible.windows.win_regedit:
path: HKCU:\Software\Microsoft\Windows\CurrentVersion\Search
name: SearchboxTaskbarMode
data: 0
type: dword
register: windows_taskbar_search_state
when: windows_hide_taskbar_search | default(false)
- name: Hide Windows 11 taskbar widgets
tags: [packages]
ansible.windows.win_regedit:
path: HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
name: TaskbarDa
data: 0
type: dword
register: windows_11_widgets_state
when: windows_hide_taskbar_widgets | default(false)
- name: Disable Windows 11 widgets via policy
tags: [packages]
ansible.windows.win_regedit:
path: HKLM:\SOFTWARE\Policies\Microsoft\Dsh
name: AllowNewsAndInterests
data: 0
type: dword
register: windows_11_widgets_policy_state
when: windows_hide_taskbar_widgets | default(false)
- name: Note when Windows shell settings may require sign out
tags: [packages]
ansible.builtin.debug:
msg: >-
Windows shell appearance settings changed. Sign out and back in, or restart explorer.exe,
if taskbar or theme updates do not appear immediately. Windows 11 widget policy changes can require
signing out before the widget button disappears from the taskbar.
changed_when: false
when: >-
(windows_apps_dark_mode_state is changed)
or (windows_system_dark_mode_state is changed)
or (windows_taskbar_search_state is changed)
or (windows_11_widgets_state is changed)
or (windows_11_widgets_policy_state is changed)
- name: Ensure winget is executable on Windows host through PSRP
tags: [packages]
when: windows_package_backend == 'winget_psrp'
ansible.windows.win_powershell:
script: |
$winget = Get-Command winget.exe -ErrorAction SilentlyContinue
if ($null -eq $winget) {
throw 'winget.exe is not available on the Windows host. Install App Installer or rerun the bootstrap script.'
}
& $winget.Source --info *> $null
if ($LASTEXITCODE -ne 0) {
throw 'winget.exe is not executable through the current PSRP session. Set windows_package_backend to winget_wsl_local on WSL-managed hosts.'
}
$Ansible.Changed = $false
- name: Ensure winget is executable through local Windows PowerShell from WSL
tags: [packages]
when: windows_package_backend == 'winget_wsl_local'
block:
- name: Ensure winget_wsl_local backend is running inside WSL
ansible.builtin.assert:
that:
- lookup('ansible.builtin.env', 'WSL_DISTRO_NAME') | length > 0
fail_msg: >-
winget_wsl_local requires running the playbook from inside the
target machine's WSL environment.
- name: Get local Windows host name through WSL interop
ansible.builtin.shell: |
powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command '$env:COMPUTERNAME'
args:
executable: /bin/bash
delegate_to: localhost
register: local_windows_host_name_state
changed_when: false
- name: Get local Windows host IP addresses through WSL interop
ansible.builtin.shell: |
powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command '
Get-NetIPAddress -AddressFamily IPv4, IPv6 -ErrorAction SilentlyContinue |
Where-Object {
$_.IPAddress -notin @("127.0.0.1", "::1") -and
$_.IPAddress -notlike "169.254.*" -and
$_.IPAddress -notlike "fe80:*"
} |
Select-Object -ExpandProperty IPAddress
'
args:
executable: /bin/bash
delegate_to: localhost
register: local_windows_host_ip_state
changed_when: false
- name: Ensure winget_wsl_local backend targets the local Windows host
ansible.builtin.assert:
that:
- >-
(ansible_host | lower) in ['localhost', '127.0.0.1', '::1']
or (local_windows_host_name_state.stdout | trim | upper)
== ((ansible_host | regex_replace('\\..*$', '')) | upper)
or (ansible_host | lower)
in (local_windows_host_ip_state.stdout_lines | map('trim') | map('lower') | list)
fail_msg: >-
winget_wsl_local can only target the local Windows host reached
through WSL interop. Local Windows host '{{ local_windows_host_name_state.stdout | trim }}'
with addresses {{ local_windows_host_ip_state.stdout_lines | map('trim') | list }}
does not match ansible_host '{{ ansible_host }}'.
- name: Ensure winget is executable through local Windows PowerShell
ansible.builtin.shell: |
powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command '
$ErrorActionPreference = "Stop"
$winget = Get-Command winget.exe -ErrorAction SilentlyContinue
if ($null -eq $winget) {
throw "winget.exe is not available on the local Windows host. Install App Installer or rerun the bootstrap script."
}
& $winget.Source --info *> $null
if ($LASTEXITCODE -ne 0) {
throw "winget.exe is not executable through local Windows PowerShell interop."
}
'
args:
executable: /bin/bash
delegate_to: localhost
changed_when: false
- name: Ensure WSL 2 is the default backend
tags: [packages, services, wsl]
ansible.windows.win_powershell:
script: |
$status = & wsl --status 2>$null
if ($LASTEXITCODE -eq 0 -and $status -match 'Default Version:\s*2') {
$Ansible.Changed = $false
return
}
& wsl --set-default-version 2
if ($LASTEXITCODE -ne 0) {
throw 'Failed to set WSL default version to 2.'
}
$Ansible.Changed = $true
- name: Install Windows workstation applications with winget through PSRP
tags: [packages]
when: windows_package_backend == 'winget_psrp'
ansible.windows.win_powershell:
script: |
$packageId = '{{ item.id }}'
$packageName = '{{ item.name | default(item.id) }}'
$packageSource = '{{ item.source | default('') }}'
$listArgs = @(
'list'
'--id', $packageId
'--exact'
'--accept-source-agreements'
'--disable-interactivity'
)
$installArgs = @(
'install'
'--id', $packageId
'--exact'
'--silent'
'--accept-package-agreements'
'--accept-source-agreements'
'--disable-interactivity'
)
if (-not [string]::IsNullOrWhiteSpace($packageSource)) {
$listArgs += @('--source', $packageSource)
$installArgs += @('--source', $packageSource)
}
$installed = & winget @listArgs 2>$null
if ($LASTEXITCODE -eq 0 -and $installed -match [regex]::Escape($packageId)) {
$Ansible.Changed = $false
return
}
& winget @installArgs
if ($LASTEXITCODE -ne 0) {
throw "Failed to install $packageName with winget"
}
$Ansible.Changed = $true
loop: "{{ windows_winget_packages | default([]) }}"
loop_control:
label: "{{ item.id }}"
- name: Install Windows workstation applications with winget through WSL local backend
tags: [packages]
when: windows_package_backend == 'winget_wsl_local'
ansible.builtin.shell: |
powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command '
$ErrorActionPreference = "Stop"
$packageId = "{{ item.id }}"
$packageName = "{{ item.name | default(item.id) }}"
$packageSource = "{{ item.source | default('') }}"
$winget = Get-Command winget.exe -ErrorAction Stop
$listArgs = @(
"list"
"--id", $packageId
"--exact"
"--accept-source-agreements"
"--disable-interactivity"
)
$installArgs = @(
"install"
"--id", $packageId
"--exact"
"--silent"
"--accept-package-agreements"
"--accept-source-agreements"
"--disable-interactivity"
)
if (-not [string]::IsNullOrWhiteSpace($packageSource)) {
$listArgs += @("--source", $packageSource)
$installArgs += @("--source", $packageSource)
}
$installed = & $winget.Source @listArgs 2>$null
if ($LASTEXITCODE -eq 0 -and $installed -match [regex]::Escape($packageId)) {
[Console]::Out.WriteLine("changed=false")
exit 0
}
& $winget.Source @installArgs
if ($LASTEXITCODE -ne 0) {
throw "Failed to install $packageName with winget"
}
[Console]::Out.WriteLine("changed=true")
'
args:
executable: /bin/bash
delegate_to: localhost
register: windows_wsl_local_winget_install_state
changed_when: "'changed=true' in windows_wsl_local_winget_install_state.stdout"
loop: "{{ windows_winget_packages | default([]) }}"
loop_control:
label: "{{ item.id }}"
- name: Configure Windows taskbar pin layout
tags: [packages]
when: (windows_taskbar_pins | default([])) | length > 0
block:
- name: Ensure Windows taskbar layout directory exists
ansible.windows.win_file:
path: "{{ windows_taskbar_layout_directory }}"
state: directory
- name: Render Windows taskbar layout policy file
ansible.windows.win_template:
src: taskbar-layout.xml.j2
dest: "{{ windows_taskbar_layout_path }}"
register: windows_taskbar_layout_file_state
- name: Enable Windows taskbar layout policy
ansible.windows.win_regedit:
path: HKCU:\Software\Policies\Microsoft\Windows\Explorer
name: LockedStartLayout
data: 1
type: dword
register: windows_taskbar_layout_policy_state
- name: Set Windows taskbar layout policy file path
ansible.windows.win_regedit:
path: HKCU:\Software\Policies\Microsoft\Windows\Explorer
name: StartLayoutFile
data: "{{ windows_taskbar_layout_path }}"
type: expandstring
register: windows_taskbar_layout_policy_path_state
- name: Set Windows taskbar layout policy refresh behavior
ansible.windows.win_regedit:
path: HKCU:\Software\Policies\Microsoft\Windows\Explorer
name: ReapplyStartLayoutEveryLogon
data: "{{ (windows_taskbar_reapply_every_logon | default(false)) | ternary(1, 0) }}"
type: dword
register: windows_taskbar_layout_policy_reapply_state
- name: Note when Windows taskbar pin layout may require sign out
ansible.builtin.debug:
msg: >-
Windows taskbar pin policy changed. Sign out and back in if the updated pin order does not appear immediately.
changed_when: false
when: >-
(windows_taskbar_layout_file_state is changed)
or (windows_taskbar_layout_policy_state is changed)
or (windows_taskbar_layout_policy_path_state is changed)
or (windows_taskbar_layout_policy_reapply_state is changed)
- name: Install VS Code WSL extensions on Windows host
tags: [packages, vscode]
ansible.windows.win_powershell:
script: |
$extensionId = '{{ item }}'
$code = Get-Command code.cmd -ErrorAction SilentlyContinue
if ($null -eq $code) {
throw 'code.cmd is not available. Ensure Visual Studio Code is installed before managing extensions.'
}
$installedExtensions = & $code.Source --list-extensions
if ($installedExtensions -contains $extensionId) {
$Ansible.Changed = $false
return
}
& $code.Source --install-extension $extensionId --force
if ($LASTEXITCODE -ne 0) {
throw "Failed to install VS Code extension $extensionId"
}
$Ansible.Changed = $true
loop: "{{ windows_vscode_extensions | default([]) }}"
loop_control:
label: "{{ item }}"
- name: Set Windows Terminal default profile to Ubuntu
tags: [packages, wsl]
ansible.windows.win_powershell:
script: |
$terminalSettingsPath = Join-Path $env:LOCALAPPDATA 'Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json'
if (-not (Test-Path $terminalSettingsPath)) {
throw 'Windows Terminal settings.json was not found. Launch Windows Terminal once before applying the default profile configuration.'
}
$settings = Get-Content -Path $terminalSettingsPath -Raw | ConvertFrom-Json
if ($null -eq $settings.profiles -or $null -eq $settings.profiles.list) {
throw 'Windows Terminal settings.json does not contain a profiles.list section.'
}
$targetProfile = $settings.profiles.list |
Where-Object {
$_.name -eq '{{ windows_terminal_default_profile_name }}' -and -not ($_.PSObject.Properties.Name -contains 'hidden' -and $_.hidden)
} |
Select-Object -First 1
if ($null -eq $targetProfile) {
throw "Windows Terminal visible profile '{{ windows_terminal_default_profile_name }}' was not found. Ensure the Ubuntu WSL profile exists and is not hidden in Windows Terminal first."
}
if ($settings.defaultProfile -eq $targetProfile.guid) {
$Ansible.Changed = $false
return
}
$settings.defaultProfile = $targetProfile.guid
$settings | ConvertTo-Json -Depth 100 | Set-Content -Path $terminalSettingsPath -Encoding utf8
$Ansible.Changed = $true

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LayoutModificationTemplate
xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification"
xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout"
xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout"
xmlns:taskbar="http://schemas.microsoft.com/Start/2014/TaskbarLayout"
Version="1">
<CustomTaskbarLayoutCollection PinListPlacement="Replace">
<defaultlayout:TaskbarLayout>
<taskbar:TaskbarPinList>
{% for pin in windows_taskbar_pins %}
{% if pin.type == 'desktop_application_id' %}
<taskbar:DesktopApp DesktopApplicationID="{{ pin.id }}" />
{% elif pin.type == 'desktop_application_link_path' %}
<taskbar:DesktopApp DesktopApplicationLinkPath="{{ pin.path }}" />
{% elif pin.type == 'app_user_model_id' %}
<taskbar:UWA AppUserModelID="{{ pin.id }}" />
{% endif %}
{% endfor %}
</taskbar:TaskbarPinList>
</defaultlayout:TaskbarLayout>
</CustomTaskbarLayoutCollection>
</LayoutModificationTemplate>

View File

@@ -1,5 +1,5 @@
---
- hosts: all:!workstation_host_windows
- hosts: all
become: true
pre_tasks:
- name: Load local vault variables when available
@@ -29,14 +29,6 @@
- profile_desktop_hyprland
- profile_desktop_host
- hosts: workstation_dev_ubuntu
become: true
roles:
- packages_ubuntu
- services_systemd
- profile_workstation_dev_common
- hosts: workstation_dev_fedora
become: true
@@ -60,53 +52,6 @@
- profile_workstation_dev_common
- profile_workstation_dev_wsl
- hosts: workstation_host_windows
gather_facts: false
pre_tasks:
- name: Load local vault variables when available
tags: [always]
ansible.builtin.include_vars:
file: "{{ playbook_dir }}/../secrets/vault.yml"
when: lookup('ansible.builtin.fileglob', playbook_dir + '/../secrets/vault.yml', errors='ignore', wantlist=True) | length > 0
- name: Load machine-local vault variables when available
tags: [always]
ansible.builtin.include_vars:
file: "{{ playbook_dir }}/../secrets/vault.local.yml"
when: lookup('ansible.builtin.fileglob', playbook_dir + '/../secrets/vault.local.yml', errors='ignore', wantlist=True) | length > 0
- name: Resolve Windows PSRP connection settings
tags: [always]
ansible.builtin.set_fact:
ansible_host: "{{ windows_psrp_host | default(vault_windows_psrp_host | default('')) }}"
ansible_user: "{{ windows_psrp_user | default(vault_windows_psrp_user | default('')) }}"
ansible_password: "{{ windows_psrp_password | default(vault_windows_psrp_password | default('')) }}"
windows_package_backend: "{{ windows_package_backend | default(vault_windows_package_backend | default('winget_psrp')) }}"
- name: Ensure Windows PSRP connection settings are defined
tags: [always]
ansible.builtin.assert:
that:
- (ansible_host | default('') | length) > 0
- (ansible_user | default('') | length) > 0
fail_msg: >-
Define windows_psrp_host and windows_psrp_user via extra vars, secrets/vault.yml,
or secrets/vault.local.yml
before running the workstation_host_windows play.
- name: Ensure Windows package backend is supported
tags: [always]
ansible.builtin.assert:
that:
- windows_package_backend in ['winget_psrp', 'winget_wsl_local']
fail_msg: >-
Unsupported windows_package_backend '{{ windows_package_backend }}'.
Supported values are winget_psrp and winget_wsl_local.
roles:
- profile_workstation_host_windows
- hosts: ubuntu_server
become: true