This playbook installs and configures most of the software I use on my Windows 11 machine for software development.
- Playbook capabilities
- Installation
- Windows host prerequisites installation
- Ansible control node prerequisites installation
- Running a specific set of tagged tasks
- Overriding Defaults
- Included Applications / Configuration (Default)
- Available Parameters
NOTE: The Playbook is fully configurable. You can skip or reconfigure any task by Overriding Defaults.
- Software
- Remove Bloatware (see default config for a complete list of Bloatware).
- Install software and packages selected by the user via Chocolatey.
- Install software and packages selected by the user via WinGet.
- Windows apps & features
- Install and Enable Optional Windows Features chosen by the user.
- Install and Enable the WSL2 distro selected by the user.
- Run defragmentation on volumes selected by the user (in parallel).
- Windows Settings
- Explorer
- Enable Explorer file extensions in file names.
- Open Explorer in the Computer view by default.
- Disable the Ribbon menu in Windows Explorer.
- Enable Right-click Context Menu (Windows 11).
- Start Menu
- Disable Automatic Install of Suggested Apps.
- Disable the "App Suggestions" in the Start menu.
- Disable the "tips" popup.
- Disable 'Windows Welcome Experience'.
- Taskbar
- Unpin 'Search' from Taskbar.
- Unpin Task View, Chat, and Cortana from Taskbar.
- Unpin 'News and Interests' from Taskbar.
- Unpin 'People' from Taskbar.
- Unpin 'Edge', 'Store' and other built-in shortcuts from the Taskbar.
- Desktop
- Remove Desktop icons (Ink).
- General
- Set the hostname selected by the user is assigned.
- Configure remote desktop services.
- Set the sound scheme to 'No sounds'.
- Set the power plan selected by the user.
- Install Windows updates categories selected by the user.
- Disable mouse acceleration.
- Explorer
- Terminal Settings
- Install oh-my-posh with the theme chosen by the user and it set as a default PowerShell theme engine.
This playbook was tested on Windows 10 2004 and Windows 11 21H2 (Pro, Ent). Other versions may work but have not tried.
Copy and paste the code below into your PowerShell terminal to get your Windows machine ready to work with Ansible.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = "https://github.com/AlexNabokikh/windows-playbook/master/setup.ps1"
$file = "$env:temp\setup.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy ByPass -File $file -Verbose-
- Upgrade Pip:
pip3 install --upgrade pip - Install Ansible:
pip3 install ansible
- Upgrade Pip:
-
Clone or download this repository to your local drive.
-
Run
ansible-galaxy install -r requirements.ymlinside this directory to install required Ansible collections. -
Add the IP address and credentials of your Windows machine into the
inventoryfile -
Run
ansible-playbook main.ymlinside this directory.
You can filter which part of the provisioning process to run by specifying a set of tags using ansible-playbook --tags flag. The tags available are choco , debloat , desktop , explorer , fonts , hostname , mouse , power , sounds , start_menu , taskbar , updates , windows_features , wsl, winget.
ansible-playbook main.yml --tags "choco,wsl"NOTE: You can override any of the defaults configured in default.config.yml by creating a config.yml file and setting the overrides in that file. For example, you can customize the installed packages and enable/disable specific tasks with something like:
configure_hostname: true
custom_hostname: myhostname
install_windows_updates: true
update_categories:
- Critical Updates
- Security Updates
- * # Installs all updates
choco_installed_packages:
# installs latest version of the Google Chrome while ignoring the package checksum
- name: googlechrome
state: latest
choco_args: --ignorechecksum
# installs 2.37.1 version of the git
- name: git
version: "2.37.1"
# installs GO, but won't update it
- golang
install_fonts: true
installed_nerdfonts:
- Meslo
install_ohmyposh: true
ohmyposh_theme: agnoster
install_windows_features: true
windows_features:
Microsoft-Hyper-V: true
install_wsl2: true
wsl2_distribution: wsl-archlinux
remove_bloatware: true
bloatware:
- Microsoft.MessagingPackages (installed with Chocolatey):
- adobereader
- auto-dark-mode
- awscli
- Firefox
- git
- golang
- jre8
- kubernetes-cli
- microsoft-windows-terminal
- peazip
- powertoys
- python3
- sharex
- telegram
- terraform
- vlc
- vscode
- zoom
| Name | Description | Type | Default |
|---|---|---|---|
| configure_hostname | (Optional) Whether or not to set a custom hostname. | bool |
false |
| custom_hostname | (Optional) The hostname to set for the computer. | string |
windows-ansible |
| install_windows_updates | (Optional) Whether or not to install Windows updates. | bool |
true |
| update_categories | (Optional) A list of categories to install updates from. The value * will match all categories. | list |
["CriticalUpdates", "SecurityUpdates", "UpdateRollups"] |
| windows_updates_reboot | (Optional) Whether or not to reboot the host if it is required and continue to install updates after the reboot. | bool |
true |
| remove_bloatware | (Optional) Whether or not to uninstall Windows bloatware. | bool |
true |
| bloatware | (Optional) A list of applications (bloatware) to be uninstalled | list |
full_list |
| choco_installed_packages | (Optional) A list of Chocolatey packages to be installed. | dict |
full_list |
| choco_installed_packages.state | (Optional) State of the package on the system. (present, latest) | string |
present |
| choco_installed_packages.version | (Optional) Specific version of the package to be installed. | string |
omit |
| choco_installed_packages.choco_args | (Optional) Additional parameters to pass to choco.exe. | string |
omit |
| install_windows_features | (Optional) Whether or not to install Windows features. | bool |
false |
| windows_features | (Optional) A list of dicts with Windows features to be installed. | list(dict) |
Microsoft-Hyper-V: true |
| install_wsl2 | (Optional) Whether or not to install Windows Subsystem for Linux. | bool |
true |
| wsl2_distribution | (Optional) The valid name of Linux distribution that will be installed. | string |
wsl-ubuntu-2004 |
| install_fonts | (Optional) Whether or not to install Nerd Fonts. | bool |
true |
| installed_nerdfonts | (Optional) A list of Nerd Fonts to be installed. | list |
["FiraCode", "FantasqueSansMono"] |
| install_ohmyposh | (Optional) Whether or not to Oh My Posh. | bool |
true |
| configure_explorer | (Optional) Whether or not to configure Windows Explorer with sane defaults. | bool |
true |
| configure_taskbar | (Optional) Whether or not to configure Windows TaskBar with sane defaults. | bool |
true |
| configure_start_menu | (Optional) Whether or not to configure Windows Start menu with sane defaults. | bool |
true |
| set_sound_scheme | (Optional) Whether or not to set default Windows Sound Scheme to "No Sounds". | bool |
true |
| disable_mouse_acceleration | (Optional) Whether or not to disable mouse acceleration. | bool |
true |
| remote_desktop_enabled | (Optional) Whether or not enable Remote Desktop. | bool |
true |
| remove_desktop_icons | (Optional) Whether or not remove desktop icons (*.lnk files only). | bool |
false |
| defrag_volumes | (Optional) Whether or not to perform disk defragmentation. | bool |
true |
| include_volumes | (Optional) A list of volumes to be defragmented. | list |
["C"] |
| change_power_plan | (Optional) Whether or not change Power Plan. | bool |
true |
| power_plan | (Optional) Choose a power plan (high_performance, balanced, power_saver). | string |
high_performance |
| install_winget_packages | (Optional) Whether or not to install WinGet packages. | bool |
true |
| winget_packages | (Required) A list of WinGet packages to be installed. | dict |
|
| winget_packages.name | (Optional) A name of the WinGet package to be installed. | string |
|
| winget_packages.source | (Optional) The source of the WinGet package (msstore or winget). |
string |
|
| configure_storage_sense | (Optional) Whether or not configure Windows Storage Sense. | string |
|
| storage_sense | (Optional) A map of storage_sense options. | dict |
|
| storage_sense.enabled | (Optional) Enable or Disable Windows Storage Sense. | bool |
true |
| storage_sense.run_frequency | (Optional) How often Windows Storage Sense has to run (once in 1, 7 or 30 days). | int |
1 |
| storage_sense.delete_unused_files | (Optional) Delete temporary files that my apps aren’t using. | bool |
true |
| storage_sense.delete_recycle_bin_files | (Optional) Delete files in my recycle bin. | bool |
true |
| storage_sense.recycle_bin_age | (Optional) How often recycle bin has to be cleaned up (once in 1, 14, 30 or 60 days). | int |
14 |
| storage_sense.delete_downloads_files | (Optional) Delete files in my Downloads folder. | bool |
true |
| storage_sense.downloads_age | (Optional) How often downloaded files has to be cleaned up (once in 1, 14, 30 or 60 days). | int |
14 |
This project was created by Alexander Nabokikh (initially inspired by geerlingguy/mac-dev-playbook).
This software is available under the following licenses:
This guide walks you through manually setting up OpenSSH Server on Windows 10/11 and Windows Server 2019+.
- Windows 10 version 1809 or later, Windows 11, or Windows Server 2019+
- Administrator privileges
- PowerShell 5.1 or later
Right-click on PowerShell and select "Run as Administrator", or press Win+X and select "Windows PowerShell (Admin)".
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH.Server*'If the State shows "NotPresent", proceed to Step 3. If it shows "Installed", skip to Step 4.
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0Wait for the installation to complete. You should see "Online: True" when finished.
# Start the service
Start-Service sshd
# Set the service to start automatically
Set-Service -Name sshd -StartupType 'Automatic'
# Verify the service is running
Get-Service sshdCheck if the firewall rule already exists:
Get-NetFirewallRule -Name *OpenSSH-Server* | Select-Object Name, EnabledIf no rule exists, create one:
New-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -DisplayName "OpenSSH SSH Server (sshd)" -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22Check if your user account is an administrator:
# Check your current username
$env:USERNAME
# Check if you're in the Administrators group
net localgroup administratorsImportant: The location of your authorized_keys file depends on whether you're an administrator:
- Administrators:
C:\ProgramData\ssh\administrators_authorized_keys - Standard Users:
C:\Users\[YourUsername]\.ssh\authorized_keys
# Create .ssh directory in your user profile
New-Item -ItemType Directory -Force -Path ~\.ssh
# Generate an Ed25519 key (recommended)
ssh-keygen -t ed25519 -C "your-email@example.com"
# Or generate an RSA key (legacy compatibility)
ssh-keygen -t rsa -b 4096 -C "your-email@example.com"When prompted:
- Press Enter to accept the default file location
- Enter a passphrase (recommended) or press Enter for no passphrase
Your public key will be saved in:
- Ed25519:
~\.ssh\id_ed25519.pub - RSA:
~\.ssh\id_rsa.pub
If you already have SSH keys on another machine, you'll need to copy the public key (the .pub file) to this Windows machine.
# Create the ssh directory in ProgramData if it doesn't exist
New-Item -ItemType Directory -Force -Path C:\ProgramData\ssh
# Create the administrators_authorized_keys file
New-Item -ItemType File -Force -Path C:\ProgramData\ssh\administrators_authorized_keys
# Add your public key to the file (replace with your actual public key)
Add-Content -Path C:\ProgramData\ssh\administrators_authorized_keys -Value "ssh-ed25519 AAAAC3... your-email@example.com"
# Set the correct permissions (CRITICAL for security)
icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r
icacls C:\ProgramData\ssh\administrators_authorized_keys /grant "NT AUTHORITY\SYSTEM:(F)"
icacls C:\ProgramData\ssh\administrators_authorized_keys /grant "BUILTIN\Administrators:(F)"# Create the .ssh directory in your user profile
New-Item -ItemType Directory -Force -Path ~\.ssh
# Create the authorized_keys file
New-Item -ItemType File -Force -Path ~\.ssh\authorized_keys
# Add your public key to the file (replace with your actual public key)
Add-Content -Path ~\.ssh\authorized_keys -Value "ssh-ed25519 AAAAC3... your-email@example.com"
# Set the correct permissions (CRITICAL for security)
icacls $env:USERPROFILE\.ssh\authorized_keys /inheritance:r
icacls $env:USERPROFILE\.ssh\authorized_keys /grant "$($env:USERDOMAIN)\$($env:USERNAME):(F)"
icacls $env:USERPROFILE\.ssh\authorized_keys /grant "NT AUTHORITY\SYSTEM:(F)"Restart-Service sshdFirst, find your machine's IP address:
# Get your IP address
(Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.InterfaceAlias -notlike "*Loopback*"}).IPAddressFrom another machine, test the connection:
# Test with password authentication
ssh username@your-windows-ip
# Test with key authentication (if you set up keys)
ssh -i /path/to/private/key username@your-windows-ipWARNING: Only do this after confirming you can log in with your SSH key!
- First, make a backup of the config file:
Copy-Item C:\ProgramData\ssh\sshd_config C:\ProgramData\ssh\sshd_config.backup- Edit the configuration file:
notepad C:\ProgramData\ssh\sshd_config- Find and modify these lines (remove # if present):
PasswordAuthentication no
PubkeyAuthentication yes
- Save the file and restart the SSH service:
Restart-Service sshd- Use strong passphrases for your SSH keys
- Regularly update Windows and OpenSSH
- Monitor SSH logs in Event Viewer under Applications and Services Logs > OpenSSH
- Consider using fail2ban or similar tools for brute-force protection
- Restrict SSH access to specific IP addresses if possible
- Check permissions on authorized_keys:
icacls C:\ProgramData\ssh\administrators_authorized_keys
# or
icacls $env:USERPROFILE\.ssh\authorized_keys- Check SSH logs:
Get-WinEvent -LogName OpenSSH/Operational | Select-Object -First 20- Test in verbose mode from client:
ssh -vvv username@windows-host- Check if another service is using port 22:
netstat -an | findstr :22- Check service status and errors:
Get-Service sshd | Select-Object *
Get-WinEvent -LogName System | Where-Object {$_.Message -like "*ssh*"} | Select-Object -First 10If you need to remove OpenSSH Server:
# Stop the service
Stop-Service sshd
# Remove the capability
Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# Remove firewall rule
Remove-NetFirewallRule -Name "OpenSSH-Server-In-TCP"Security Note: This guide requires you to manually enter all commands, eliminating the risk of injection attacks that could occur with automated scripts. Always verify commands before executing them, especially when running as Administrator.
