A modular system configuration tool for fresh Linux installations, powered by Ansible. Supports Ubuntu, Debian, Fedora, RHEL, OpenSUSE, and Arch-based distributions.
# Clone the repository
git clone <repository-url> ~/linux-setup
cd ~/linux-setup
# Install Ansible
sudo apt install ansible-core # Ubuntu/Debian
# OR
sudo dnf install ansible-core # Fedora/RHEL
# Install everything
cd ansible
ansible-playbook playbooks/site.yml --tags all- Automatic Distribution Detection: Identifies your Linux distribution and uses the correct package manager
- Modular Architecture: Each component is independently configurable and testable
- Base Packages: htop, git, neovim, curl, wget
- Modern CLI Tools: eza, bat, ripgrep, fd, fzf, zoxide, lazygit, btop, tldr, and more
- Development Tools: Go, C/C++, and Python development environments
- Neovim Configuration: Minimal
config/nvim/init.luasetup with statusline and ergonomic keybindings - Desktop Settings: GNOME configuration (dash-to-dock, etc.)
- Fish Shell: Install fish, set as default shell, and deploy basic config
- Bash Configuration: Best-practice
~/.bashrcand~/.bash_profilewith SSH agent, aliases, and git-aware prompt - Smart Package Filtering: Version-aware package filtering (e.g. lazygit skipped on Ubuntu < 26.04)
- Container Tools: Podman and Distrobox for containerized environments
- Fonts: JetBrains Mono Nerd Font
| Distribution | Package Manager |
|---|---|
| Ubuntu, Debian, Pop!_OS, Linux Mint | apt |
| Fedora, RHEL, CentOS, Rocky, Alma | dnf |
| OpenSUSE, OpenSUSE Tumbleweed | zypper |
| Arch, Manjaro, EndeavourOS | pacman |
All commands should be run from the ansible/ directory:
cd ansibleansible-playbook playbooks/site.yml --tags all# Base packages only
ansible-playbook playbooks/site.yml --tags base
# Development tools (Go, C, Python)
ansible-playbook playbooks/site.yml --tags dev
# Neovim configuration
ansible-playbook playbooks/site.yml --tags nvim
# JetBrains Mono Nerd Font
ansible-playbook playbooks/site.yml --tags font
# Fish shell
ansible-playbook playbooks/site.yml --tags fish
# Bash configuration
ansible-playbook playbooks/site.yml --tags bash
# Desktop settings (GNOME)
ansible-playbook playbooks/site.yml --tags desktop# Base packages + Neovim + Fish
ansible-playbook playbooks/site.yml --tags base,nvim,fish# Install only Go and Python (not C)
ansible-playbook playbooks/site.yml --tags dev \
-e linux_setup_dev_languages=go,pythonansible-playbook playbooks/detect.ymlansible-playbook playbooks/site.yml --tags all --checkansible-playbook playbooks/site.yml --tags all -vvvCreate an isolated development container with everything pre-installed:
# Ubuntu 24.04 devbox
./scripts/create-devbox.sh ubuntu 24.04 ~/devbox-ubuntu
# Fedora 42 devbox with custom prefix
./scripts/create-devbox.sh fedora 42 ~/devbox-fedora --prefix work
# Arch Linux devbox
./scripts/create-devbox.sh arch latest ~/devbox-arch --prefix test1Supported distributions:
- Ubuntu: 22.04, 24.04, latest
- Debian: 12, testing, unstable
- Fedora: 41, 42, rawhide
- Arch: latest
- openSUSE: tumbleweed
The script creates a distrobox container with an isolated home directory, installs ansible-core, and runs the full setup playbook automatically. Enter the container with distrobox enter <name>.
Core utilities:
- htop, btop - System monitors
- git - Version control
- neovim - Text editor
- curl, wget - Download tools
- jq - JSON processor
Modern CLI tools:
- eza - Modern
lsreplacement - bat -
catwith syntax highlighting - ripgrep - Fast text search
- fd - Fast
findreplacement - fzf - Fuzzy finder
- zoxide - Smart
cdreplacement - lazygit - Git TUI
- tldr - Simplified man pages
- httpie - HTTP client
- trash-cli - Safe
rmreplacement - duf - Disk usage tool
- fish - Modern shell
Container tools:
- podman - Rootless container engine
- distrobox - Containerized development environments
Go:
- Go compiler and tools
- gopls (LSP)
- delve (debugger)
C/C++:
- gcc, g++, make, cmake
- clang, clangd (LSP)
- gdb (debugger)
- valgrind
Python:
- python3, pip
- python3-venv
- pylint, black, mypy
- python-lsp-server
Deploys a minimal, plugin-free Neovim configuration:
- Location:
~/.config/nvim/init.lua - Features: Statusline, ergonomic keybindings, basic settings
- Backup: Existing config backed up to
~/.config/nvim.backup.<timestamp>
- Installs fish via package manager
- Registers fish in
/etc/shells - Sets fish as default shell
- Deploys configuration to
~/.config/fish/config.fish- Main configconf.d/ssh_agent.fish- SSH agent setup
Deploys best-practice bash configuration:
~/.bashrc: Aliases, functions, prompt, SSH agent~/.bash_profile: Login shell entry point- Backup: Existing files backed up automatically
Installs JetBrains Mono Nerd Font:
- Location:
~/.local/share/fonts/ - Source: Official Nerd Fonts release
- Font cache automatically refreshed
Applies GNOME desktop settings (if GNOME available):
- dash-to-dock click action: minimize
Core variables are defined in ansible/group_vars/all.yml:
| Variable | Default | Description |
|---|---|---|
linux_setup_target_user |
Current user | Target user for configs |
linux_setup_target_home |
Current home | Target home directory |
linux_setup_dev_languages |
['go', 'c', 'python'] |
Dev languages to install |
Use -e flag:
# Custom dev languages
ansible-playbook playbooks/site.yml --tags dev \
-e linux_setup_dev_languages=go,python
# Force specific distribution
ansible-playbook playbooks/site.yml --tags all \
-e linux_setup_force_distro=ubuntuNote: Component selection is controlled by --tags, not by variables.
Run the test suite to verify all roles:
cd ansible
# Run all tests
ansible-playbook tests/test.yml
# Run specific test
ansible-playbook tests/test.yml --tags packages
# Use test runner script
./tests/run_tests.shTests verify:
- Distribution detection works correctly
- Package definitions are valid
- Config files exist in source directories
- Roles run successfully in check mode
- Variables are properly defined
Test the full ansible setup on real distributions using distrobox containers:
# Test all supported distros (auto-cleanup)
./scripts/test-distrobox.sh
# Test a specific distro
./scripts/test-distrobox.sh --distro ubuntu
# Keep containers after tests (for debugging)
./scripts/test-distrobox.sh --keepEach test creates an isolated container, runs the full ansible playbook, and verifies that all packages, configs, and tools are correctly installed.
linux-setup/
├── ansible/
│ ├── ansible.cfg # Ansible configuration
│ ├── group_vars/ # Global variables
│ │ └── all.yml
│ ├── inventories/ # Inventory files
│ │ └── localhost.yml
│ ├── playbooks/ # Playbooks
│ │ ├── site.yml # Main playbook
│ │ └── detect.yml # Distribution detection
│ ├── roles/ # Ansible roles
│ │ ├── distro_facts/ # Distribution detection
│ │ ├── packages_base/ # Base package installation
│ │ ├── packages_dev/ # Dev tools installation
│ │ ├── nvim/ # Neovim config
│ │ ├── fonts/ # Font installation
│ │ ├── fish/ # Fish shell
│ │ ├── bash/ # Bash config
│ │ └── desktop/ # Desktop settings
│ ├── tests/ # Test suite
│ │ ├── test.yml # Main test runner
│ │ ├── test_*.yml # Role tests
│ │ └── run_tests.sh # Test script
│ └── README.md # Quick reference
├── config/ # Source configurations
│ ├── nvim/ # Neovim config files
│ ├── fish/ # Fish config files
│ └── bash/ # Bash config files
├── scripts/ # Utility scripts
│ ├── create-devbox.sh # Create distrobox dev environment
│ └── test-distrobox.sh # Integration tests via distrobox
└── docs/ # Documentation
├── MANUAL.md # Detailed manual
└── FILEMAP.md # File reference
┌─────────────────────────────────────────┐
│ ansible-playbook (user runs) │
│ playbooks/site.yml │
├─────────────────────────────────────────┤
│ Ansible Roles │
│ distro_facts → packages → nvim → │
│ fonts → fish → bash → desktop │
├─────────────────────────────────────────┤
│ Source Configurations │
│ config/nvim, config/fish, etc │
└─────────────────────────────────────────┘
Flow:
- User runs
ansible-playbookwith desired tags distro_factsrole detects distribution and package manager- Selected roles execute based on tags
- Configurations deployed from
config/to target directories
Edit ansible/roles/packages/defaults/main.yml:
linux_setup_base_packages:
apt:
- htop
- git
- your-custom-package- Add mapping in
ansible/roles/distro_facts/defaults/main.yml - Add package lists in
ansible/roles/packages/defaults/main.yml - Test with
ansible-playbook playbooks/detect.yml
# Check playbook syntax
ansible-playbook playbooks/site.yml --syntax-check
# Lint with ansible-lint (if installed)
ansible-lint playbooks/*.yml roles/*/tasks/*.yml
# Validate YAML
yamllint ansible/**/*.ymlMost operations require sudo. Ansible will prompt when needed, or use:
ansible-playbook playbooks/site.yml --tags all --ask-become-passForce a specific distribution:
ansible-playbook playbooks/site.yml --tags all \
-e linux_setup_force_distro=ubuntu-
Update package cache first:
sudo apt update # Ubuntu/Debian sudo dnf check-update # Fedora
-
Check package availability:
apt search <package> # Ubuntu/Debian dnf search <package> # Fedora
-
Run with verbose output:
ansible-playbook playbooks/site.yml --tags base -vvv
If Neovim doesn't work after installation:
- Check Neovim version:
nvim --version(requires 0.8+) - Check config syntax:
nvim --headless +quit - Restore backup:
mv ~/.config/nvim.backup.* ~/.config/nvim
Minimal configuration with:
- Line numbers, relative numbers
- Smart indentation (2 spaces)
- Search highlighting
- Custom statusline
- Ergonomic keybindings
config.fish: Aliases, environment variablesconf.d/ssh_agent.fish: SSH agent auto-start
.bashrc: Interactive shell config, aliases, prompt.bash_profile: Login shell entry point
- No secrets or credentials stored in repository
- All files deployed with appropriate permissions (644 for configs, 755 for dirs)
- Existing configurations backed up before overwriting
- Package installation requires sudo (as expected)
- Downloads verified from official sources
- Fork the repository
- Create a feature branch
- Make your changes
- Update tests:
ansible/tests/test_<role>.yml - Run tests:
cd ansible && ansible-playbook tests/test.yml - Test in check mode:
ansible-playbook playbooks/site.yml --check - Submit a pull request
See repository for license information.
# Install Ansible
sudo apt install ansible-core # Ubuntu/Debian
# Full setup
cd ansible && ansible-playbook playbooks/site.yml --tags all
# Individual components
ansible-playbook playbooks/site.yml --tags base # Base packages
ansible-playbook playbooks/site.yml --tags dev # Dev tools
ansible-playbook playbooks/site.yml --tags nvim # Neovim
ansible-playbook playbooks/site.yml --tags fish # Fish shell
ansible-playbook playbooks/site.yml --tags bash # Bash config
ansible-playbook playbooks/site.yml --tags font # Font
ansible-playbook playbooks/site.yml --tags desktop # GNOME settings
# Multiple components
ansible-playbook playbooks/site.yml --tags base,nvim,fish
# Dry run
ansible-playbook playbooks/site.yml --tags all --check
# Run tests
ansible-playbook tests/test.yml
# Run integration tests (distrobox)
./scripts/test-distrobox.sh
# Detect distribution
ansible-playbook playbooks/detect.yml
# Create devbox (containerized dev environment)
./scripts/create-devbox.sh ubuntu 24.04 ~/devbox-ubuntuFor more details, see:
ansible/README.md- Quick Ansible referencedocs/MANUAL.md- Detailed manualdocs/FILEMAP.md- File documentation