Opinionated Ansible automation for bootstrapping Linux workstations and servers.
ansible-linux-day0 is a personal day-zero configuration repo for getting a
fresh Linux machine into a useful working state. It installs common terminal
tools, developer runtimes, shells, workstation applications, desktop utilities,
and a small amount of user configuration.
The playbooks are intentionally opinionated, but each feature is controlled by
an install_* variable so the default workstation can be trimmed down per host
or inventory.
- Supported Platforms
- Omarchy Notes
- Quick Start
- Playbooks
- Feature Toggles
- Roles
- Validation
- Repository Layout
- Cross-Distro Development
Support is being expanded from Ubuntu-first coverage toward a broader cross-distro workstation bootstrap.
| Platform | Bootstrap | Workstation | Server | Notes |
|---|---|---|---|---|
| Ubuntu | Supported | Best supported | Supported | Primary historical target. Regolith is Ubuntu-only. |
| Debian family | Partial | Partial | Partial | Many tasks work, but Ubuntu-only PPAs/repos are guarded or still being refined. |
| RHEL | Supported | Partial | Partial | Uses RPM/DNF paths where available. |
| Rocky / AlmaLinux | Partial | Partial | Partial | Expected to follow RedHat-family paths; test per feature. |
| Fedora | Not in bootstrap yet | Partial | Not verified | Many RedHat-family package tasks should work, but bootstrap coverage is not complete. |
| Arch Linux | Supported | Partial | Not verified | The tested Arch target is Omarchy, not a generic hand-rolled Arch install. |
| Omarchy / Hyprland on Arch | N/A | Active support | N/A | Tested against the Omarchy spin by DHH. Install Omarchy first, then run this playbook to tune it. |
Desktop-environment assumptions are intentionally conservative:
- KDE Plasma is opt-in only with
install_kde: true. - Regolith is only attempted on Ubuntu.
- AUR-only applications are limited to explicit app tasks such as Chrome and Microsoft Edge on Arch.
Omarchy describes itself as "Beautiful, Modern & Opinionated Linux by DHH" and links its manual, ISO, and GitHub project from the main site. The Arch workflow in this repository assumes that Omarchy has already been installed on the machine.
Recommended flow:
- Follow the Omarchy website and manual to install Omarchy onto a fresh computer.
- Boot into the completed Omarchy system.
- Clone this repository.
- Run
./bootstrap.sh. - Run the workstation playbook.
This playbook is intended to layer personal day-zero workstation preferences on top of Omarchy. It deliberately supersedes some Omarchy opinions, including installing this repo's Neovim configuration and tmux bindings. Tasks that replace preexisting user configuration should preserve the original directory or file with a backup before installing the playbook-managed version.
Current Omarchy/Hyprland-specific behavior includes:
- Tuning
~/.config/hypr/looknfeel.confwhen Hyprland is installed and the file exists. - Enabling the Omarchy screenshot binding in
~/.config/hypr/bindings.confwhen the commented binding exists. - Backing up unmanaged
~/.config/nvimbefore installing the playbook-managed Neovim config.
Clone the repository on the target host, install Ansible and role dependencies, then run the workstation playbook locally.
For Omarchy systems, install Omarchy first from the official Omarchy project, then run this repo on top of that completed install.
./bootstrap.sh
./install-workstation.shinstall-workstation.sh runs:
ansible-playbook -i localhost, day0-workstation.yml --connection=local -KThe wrapper prompts for the sudo password and reboots after completion. Run the
raw ansible-playbook command directly if you want more control over tags,
check mode, or reboot timing.
ansible-playbook -i localhost, day0-workstation.yml --connection=local -KThe workstation playbook applies:
commonworkstation_coreworkstation_desktop
Run a single feature by tag:
ansible-playbook -i localhost, day0-workstation.yml --connection=local -K --tags dockerServer targets should be listed under inventory/.
ansible-playbook -i inventory/server.yml day0-server.yml -KThe server playbook applies:
commonserver_core
Each role exposes defaults in defaults/main.yml. Set an install_* variable
to false to skip a feature.
Example:
install_regolith: false
install_kde: false
install_chrome: falseFeature variables can be set in inventory, host vars, group vars, or an extra vars file:
ansible-playbook -i localhost, day0-workstation.yml \
--connection=local \
-K \
-e @vars.ymlRole entry point: roles/common/tasks/main.yml
Shared server and workstation setup.
| Feature | Task file | Toggle |
|---|---|---|
| Baseline packages | install_packages.yml |
install_packages |
| tmux | install_tmux.yml |
install_tmux |
| zsh | install_zsh.yml |
install_zsh |
| SSH key | install_ssh_key.yml |
install_ssh_key |
| NodeJS via nvm | install_nodejs.yml |
install_nodejs |
| AWS CLI | install_aws_cli.yml |
install_aws_cli |
Role entry point: roles/server_core/tasks/main.yml
Server-only configuration.
| Feature | Notes |
|---|---|
| Hostname | Sets hostname from inventory name. |
| Package upgrades | Debian-family upgrade task. |
| Unattended upgrades | Configured through the role dependency in meta/main.yml. |
| tmux/zsh config | Deploys role templates for server sessions. |
Role entry point: roles/workstation_core/tasks/main.yml
Developer tooling and CLI applications.
| Feature | Task file | Toggle |
|---|---|---|
| Dotfiles | install_dotfiles.yml |
install_dotfiles |
| Build libraries | install_libraries.yml |
install_libraries |
| Python | install_python.yml |
install_python |
| Go | install_go.yml |
install_go |
| TypeScript | install_typescript.yml |
install_typescript |
| Ruby | install_ruby.yml |
install_ruby |
| LuaRocks | install_luarocks.yml |
install_luarocks |
| Neovim | install_neovim.yml |
install_neovim |
| Fastfetch | install_fastfetch.yml |
install_fastfetch |
| Docker | install_docker.yml |
install_docker |
| Cloud utilities | install_cloud_utilities.yml |
install_cloud_utilities |
| Cisco Secure Client | install_cisco_secure_client.yml |
install_cisco_secure_client |
| ProxyChains-NG | install_proxychains_ng.yml |
install_proxychains_ng |
| LazyDocker | install_lazydocker.yml |
install_lazydocker |
| LazyGit | install_lazygit.yml |
install_lazygit |
| Minicom | install_minicom.yml |
install_minicom |
| Terraform | install_terraform.yml |
install_terraform |
| PowerShell | install_powershell.yml |
install_powershell |
Role entry point: roles/workstation_desktop/tasks/main.yml
GUI applications and desktop-specific behavior.
| Feature | Task file | Toggle |
|---|---|---|
| Alacritty | install_alacritty.yml |
install_alacritty |
| Flameshot | install_flameshot.yml |
install_flameshot |
| Hyprland settings | install_hyprland_settings.yml |
install_hyprland_settings |
| Regolith | install_regolith.yml |
install_regolith |
| KDE Plasma | install_kde.yml |
install_kde |
| Chrome | install_chrome.yml |
install_chrome |
| Microsoft Edge | install_microsoft_edge.yml |
install_microsoft_edge |
| VSCode / Code - OSS | install_vscode.yml |
install_vscode |
| Ulauncher | install_ulauncher.yml |
install_ulauncher |
| Remmina | install_remmina.yml |
install_remmina |
| KeePassXC | install_keepassxc.yml |
install_keepassxc |
Run syntax checks before applying changes:
ansible-playbook -i localhost, day0-workstation.yml --connection=local --syntax-check
ansible-playbook -i localhost, day0-server.yml --connection=local --syntax-checkRun a feature in check mode with tags:
ansible-playbook -i localhost, day0-workstation.yml \
--connection=local \
--check \
--tags goIf available, run:
ansible-lint.
├── ansible.cfg
├── bootstrap.sh
├── day0-server.yml
├── day0-workstation.yml
├── install-workstation.sh
├── inventory/
└── roles/
├── common/
├── server_core/
├── workstation_core/
└── workstation_desktop/
When adding features, follow the existing role structure:
- Add an
install_<feature>default in the role'sdefaults/main.yml. - Add an
include_tasksentry in the role'stasks/main.yml. - Put implementation in
tasks/install_<feature>.yml. - Add a tag matching the feature name.
- Use
ansible_facts['os_family']for broad package-manager paths. - Use
ansible_distributiononly for distro-specific repositories or apps.
Prefer ansible.builtin.package when package names are shared across distros.
Use package-manager-specific modules only when necessary.
Important platform notes:
- Ubuntu-only PPAs or repositories must be guarded with
ansible_distribution == 'Ubuntu'. - RedHat-family work should use DNF/RPM paths where needed.
- Arch work should be tested against Omarchy unless a task explicitly targets generic Arch. Prefer official pacman packages where possible.
- AUR support is limited to specific application tasks that need it.
- Desktop environment installs should be opt-in unless they are lightweight app installs.
For more detailed agent guidance, see AGENTS.md.