From 8b403e3aa5b4c7747dfd1a231674fed4802cab18 Mon Sep 17 00:00:00 2001 From: ilia Date: Thu, 28 Aug 2025 11:53:59 -0400 Subject: [PATCH] Add Ansible configuration and roles for development environment setup. Introduced ansible.cfg for default settings, created README.md for documentation, and established roles for applications, base, and development tasks. Enhanced dev-playbook.yml with pre-tasks and streamlined application installations. --- README.md | 181 ++++++++++++++++++++++++++++ ansible.cfg | 11 ++ dev-playbook.yml | 90 ++------------ group_vars/all.yml | 10 ++ roles/applications/meta/main.yml | 2 + roles/applications/tasks/main.yml | 25 ++++ roles/base/handlers/main.yml | 9 ++ roles/base/tasks/main.yml | 37 ++++++ roles/base/templates/jail.local.j2 | 33 +++++ roles/development/tasks/main.yml | 13 ++ roles/docker/tasks/main.yml | 33 +++++ roles/maintenance/handlers/main.yml | 9 ++ roles/snap/handlers/main.yml | 5 + roles/snap/meta/main.yml | 2 + roles/snap/tasks/main.yml | 42 +++++++ roles/ssh/tasks/main.yml | 5 + roles/user/tasks/main.yml | 3 +- 17 files changed, 427 insertions(+), 83 deletions(-) create mode 100644 README.md create mode 100644 group_vars/all.yml create mode 100644 roles/applications/meta/main.yml create mode 100644 roles/applications/tasks/main.yml create mode 100644 roles/base/templates/jail.local.j2 create mode 100644 roles/snap/handlers/main.yml create mode 100644 roles/snap/meta/main.yml create mode 100644 roles/snap/tasks/main.yml diff --git a/README.md b/README.md new file mode 100644 index 0000000..f861b69 --- /dev/null +++ b/README.md @@ -0,0 +1,181 @@ +# Ansible Development Environment Setup + +This Ansible playbook automates the setup of development environments across multiple machines. + +## πŸ—οΈ Architecture + +### Host Groups +- `dev`: Development machines (devVM, bottom, debianDesktopVM) +- `gitea`: Gitea server +- `portainer`: Portainer container management +- `homepage`: Homepage dashboard +- `ansible`: Ansible control node + +### Roles + +#### Core Roles +- **`maintenance`**: System updates, package cleanup, and reboots +- **`base`**: Core system packages, security tools, and system hardening +- **`development`**: Development tools (git, nodejs, build-essential, python3) +- **`shell`**: Shell configuration (zsh + oh-my-zsh + powerlevel10k) +- **`docker`**: Docker CE installation and user configuration +- **`ssh`**: SSH server and firewall configuration +- **`user`**: User management + +#### Application Roles +- **`applications`**: Desktop applications (Brave, LibreOffice, Redshift, Evince) +- **`snap`**: Snap daemon and snap applications (VSCode, Cursor) + +## πŸš€ Usage + +### Basic Setup +```bash +# Run on all development machines +ansible-playbook dev-playbook.yml + +# Run on specific host +ansible-playbook dev-playbook.yml --limit devVM + +# Skip reboots for specific host +ansible-playbook dev-playbook.yml --limit bottom +``` + +### Skip Reboots +Add `skip_reboot=true` to host variables: +```ini +[dev] +bottom ansible_host=10.0.10.156 ansible_user=beast skip_reboot=true +``` + +### Dry Run +```bash +# Check what would be changed +ansible-playbook dev-playbook.yml --check + +# Verbose output +ansible-playbook dev-playbook.yml -v +``` + +## πŸ”§ Configuration + +### Global Variables (`group_vars/all.yml`) +- `timezone`: System timezone (default: UTC) +- `locale`: System locale (default: en_US.UTF-8) +- `fail2ban_bantime`: Ban duration in seconds +- `fail2ban_findtime`: Time window for failures +- `fail2ban_maxretry`: Max failures before ban + +### Host Variables (`host_vars/`) +- `skip_reboot`: Skip automatic reboots +- Encrypted variables for sensitive data + +## πŸ›‘οΈ Security Features + +### Fail2ban Configuration +- SSH brute force protection +- Configurable ban times and retry limits +- Email notifications (configured in template) + +### UFW Firewall +- Deny-by-default policy +- SSH access allowed +- Automatic enablement + +### System Hardening +- Timezone and locale configuration +- Security package installation +- Monitoring tools (htop, iotop, nethogs, logwatch) + +## πŸ“¦ Installed Packages + +### Base System +- `htop`, `curl`, `wget`, `unzip`, `xclip` +- `net-tools`, `ufw`, `fail2ban` +- `iotop`, `nethogs`, `logwatch` + +### Development Tools +- `git`, `nodejs`, `npm` +- `build-essential`, `python3`, `python3-pip` + +### Applications +- `brave-browser`, `libreoffice`, `evince`, `redshift` +- `code` (VSCode), `cursor` (via snap) + +### Docker +- Docker CE with all components +- Docker Compose +- User added to docker group + +## πŸ”„ Maintenance + +### Automatic Updates +The maintenance role handles: +- Package updates (`apt upgrade`) +- Unused package removal (`apt autoremove`) +- Cache cleanup (`apt autoclean`) +- Conditional reboots + +### Manual Maintenance +```bash +# Update only maintenance role +ansible-playbook dev-playbook.yml --tags maintenance + +# Skip maintenance +ansible-playbook dev-playbook.yml --skip-tags maintenance +``` + +## πŸ› Troubleshooting + +### Common Issues + +1. **SSH Connection Issues** + - Check `ansible.cfg` SSH settings + - Verify host keys and user permissions + +2. **Package Installation Failures** + - Run with `-v` for verbose output + - Check internet connectivity on target hosts + +3. **Reboot Issues** + - Use `skip_reboot=true` for problematic hosts + - Check maintenance role handlers + +### Debug Commands +```bash +# Test connectivity +ansible dev -m ping + +# Check facts +ansible dev -m setup + +# Run specific role +ansible-playbook dev-playbook.yml --tags base +``` + +## πŸ“ File Structure +``` +ansible/ +β”œβ”€β”€ ansible.cfg # Ansible configuration +β”œβ”€β”€ hosts # Inventory file +β”œβ”€β”€ dev-playbook.yml # Main development playbook +β”œβ”€β”€ group_vars/ +β”‚ └── all.yml # Global variables +β”œβ”€β”€ host_vars/ # Host-specific variables +└── roles/ + β”œβ”€β”€ maintenance/ # System maintenance + β”œβ”€β”€ base/ # Core system setup + β”œβ”€β”€ development/ # Development tools + β”œβ”€β”€ shell/ # Shell configuration + β”œβ”€β”€ docker/ # Docker installation + β”œβ”€β”€ ssh/ # SSH configuration + β”œβ”€β”€ user/ # User management + β”œβ”€β”€ applications/ # Desktop applications + └── snap/ # Snap applications +``` + +## 🀝 Contributing + +1. Test changes with `--check` first +2. Update documentation for new roles/tasks +3. Use proper handlers for service restarts +4. Follow existing naming conventions diff --git a/ansible.cfg b/ansible.cfg index e69de29..53a244e 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -0,0 +1,11 @@ +[defaults] +inventory = hosts +host_key_checking = True +timeout = 30 +gathering = smart +fact_caching = memory +stdout_callback = yaml + +[ssh_connection] +ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o IdentitiesOnly=yes +pipelining = True diff --git a/dev-playbook.yml b/dev-playbook.yml index a76fa9a..964a2b3 100644 --- a/dev-playbook.yml +++ b/dev-playbook.yml @@ -9,89 +9,17 @@ - docker - ssh - user + - applications + - snap - tasks: + pre_tasks: - name: Update apt cache apt: update_cache: yes + run_once: true - - name: Enable 'universe' repo (Ubuntu and Mint only) - command: add-apt-repository universe - when: ansible_facts['distribution'] in ["Ubuntu", "Linux Mint"] - changed_when: false - ignore_errors: true - - - name: Remove Mint’s nosnap.pref block (Mint only) - file: - path: /etc/apt/preferences.d/nosnap.pref - state: absent - when: ansible_facts['distribution'] == "Linux Mint" - - - name: Install Redshift - apt: - name: redshift - state: present - - # Modern Brave repo/key installation for all - - name: Download Brave APT key - get_url: - url: https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg - dest: /usr/share/keyrings/brave-browser-archive-keyring.gpg - mode: '0644' - - - name: Add Brave repo (all Debian family) - apt_repository: - repo: "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main" - filename: brave-browser - state: present - - - name: Update apt cache after repo add - apt: - update_cache: yes - - - name: Install Brave browser - apt: - name: brave-browser - state: present - - # Snap daemon install across all Debian family systems - - name: Install Snap daemon - apt: - name: snapd - state: present - when: ansible_facts['os_family'] == "Debian" - - # Ensure snapd is running on Debian (optional, improves reliability) - - name: Enable snapd socket on Debian - systemd: - name: snapd.socket - enabled: true - state: started - when: ansible_facts['distribution'] == "Debian" - - - name: Force Ansible to reload facts - setup: - - # Install IDE and other snaps everywhere Snap is available - - name: Install VSCode IDE (Snap, all distros) - community.general.snap: - name: code - classic: true - state: present - when: ansible_facts['os_family'] == "Debian" - - - name: Install Cursor (Snap, all distros) - community.general.snap: - name: cursor - state: present - when: ansible_facts['os_family'] == "Debian" - - - name: Install LibreOffice - apt: - name: libreoffice - state: present - - - name: Install PDF reader (Evince) - apt: - name: evince - state: present + tasks: + # Additional tasks can be added here if needed + - name: Display completion message + debug: + msg: "Development environment setup completed successfully!" diff --git a/group_vars/all.yml b/group_vars/all.yml new file mode 100644 index 0000000..ac27f2e --- /dev/null +++ b/group_vars/all.yml @@ -0,0 +1,10 @@ +--- +# Common variables for all hosts +timezone: UTC +locale: en_US.UTF-8 +ansible_python_interpreter: /usr/bin/python3 + +# Security settings +fail2ban_bantime: 3600 +fail2ban_findtime: 600 +fail2ban_maxretry: 3 diff --git a/roles/applications/meta/main.yml b/roles/applications/meta/main.yml new file mode 100644 index 0000000..23d65c7 --- /dev/null +++ b/roles/applications/meta/main.yml @@ -0,0 +1,2 @@ +--- +dependencies: [] diff --git a/roles/applications/tasks/main.yml b/roles/applications/tasks/main.yml new file mode 100644 index 0000000..46d7555 --- /dev/null +++ b/roles/applications/tasks/main.yml @@ -0,0 +1,25 @@ +--- +- name: Install desktop applications + apt: + name: + - redshift + - libreoffice + - evince + state: present + +- name: Download Brave APT key + get_url: + url: https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg + dest: /usr/share/keyrings/brave-browser-archive-keyring.gpg + mode: '0644' + +- name: Add Brave repo (all Debian family) + apt_repository: + repo: "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main" + filename: brave-browser + state: present + +- name: Install Brave browser + apt: + name: brave-browser + state: present diff --git a/roles/base/handlers/main.yml b/roles/base/handlers/main.yml index 2edada2..e38df8a 100644 --- a/roles/base/handlers/main.yml +++ b/roles/base/handlers/main.yml @@ -1,2 +1,11 @@ --- # handlers file for base + +- name: restart fail2ban + systemd: + name: fail2ban + state: restarted + +- name: reload ufw + ufw: + state: reloaded diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml index c213865..da83d22 100644 --- a/roles/base/tasks/main.yml +++ b/roles/base/tasks/main.yml @@ -10,3 +10,40 @@ state: present update_cache: yes +- name: Install admin tools + apt: + name: + - net-tools + - ufw + - fail2ban + state: present + +- name: Install monitoring tools + apt: + name: + - iotop + - nethogs + - logwatch + state: present + +- name: Configure fail2ban + template: + src: jail.local.j2 + dest: /etc/fail2ban/jail.local + mode: '0644' + notify: restart fail2ban + +- name: Enable UFW + ufw: + state: enabled + policy: deny + +- name: Set timezone + timezone: + name: "{{ timezone | default('UTC') }}" + +- name: Configure locale + locale_gen: + name: "{{ locale | default('en_US.UTF-8') }}" + state: present + diff --git a/roles/base/templates/jail.local.j2 b/roles/base/templates/jail.local.j2 new file mode 100644 index 0000000..fdf8e1d --- /dev/null +++ b/roles/base/templates/jail.local.j2 @@ -0,0 +1,33 @@ +[DEFAULT] +# Ban hosts for 1 hour +bantime = 3600 +# Check for repeated failures for 10 minutes +findtime = 600 +# Allow 3 failures before banning +maxretry = 3 + +# Email notifications (uncomment and configure if needed) +destemail = idobkin@gmail.com +sender = idobkin@gmail.com +action = %(action_mwl)s + +[sshd] +enabled = true +port = ssh +filter = sshd +logpath = /var/log/auth.log +maxretry = 3 + +[apache] +enabled = false +port = http,https +filter = apache-auth +logpath = /var/log/apache2/error.log +maxretry = 3 + +[nginx-http-auth] +enabled = false +port = http,https +filter = nginx-http-auth +logpath = /var/log/nginx/error.log +maxretry = 3 diff --git a/roles/development/tasks/main.yml b/roles/development/tasks/main.yml index 7d7c3d1..7b19d6b 100644 --- a/roles/development/tasks/main.yml +++ b/roles/development/tasks/main.yml @@ -6,3 +6,16 @@ - nodejs state: present +- name: Install build tools + apt: + name: + - build-essential + - python3 + - python3-pip + state: present + +- name: Install npm + apt: + name: npm + state: present + diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml index 0a097bc..74bfd86 100644 --- a/roles/docker/tasks/main.yml +++ b/roles/docker/tasks/main.yml @@ -10,3 +10,36 @@ state: present update_cache: yes +- name: Add Docker's official GPG key + apt_key: + url: https://download.docker.com/linux/ubuntu/gpg + state: present + +- name: Add Docker repository + apt_repository: + repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable" + state: present + +- name: Install Docker CE + apt: + name: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-buildx-plugin + - docker-compose-plugin + state: present + update_cache: yes + +- name: Start and enable Docker service + systemd: + name: docker + state: started + enabled: yes + +- name: Add user to docker group + user: + name: "{{ ansible_user }}" + groups: docker + append: yes + diff --git a/roles/maintenance/handlers/main.yml b/roles/maintenance/handlers/main.yml index 5e27bfd..bde5993 100644 --- a/roles/maintenance/handlers/main.yml +++ b/roles/maintenance/handlers/main.yml @@ -1,2 +1,11 @@ --- # handlers file for maintenance + +- name: restart fail2ban + systemd: + name: fail2ban + state: restarted + +- name: reload ufw + ufw: + state: reloaded diff --git a/roles/snap/handlers/main.yml b/roles/snap/handlers/main.yml new file mode 100644 index 0000000..13f5d95 --- /dev/null +++ b/roles/snap/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart snapd + systemd: + name: snapd + state: restarted diff --git a/roles/snap/meta/main.yml b/roles/snap/meta/main.yml new file mode 100644 index 0000000..23d65c7 --- /dev/null +++ b/roles/snap/meta/main.yml @@ -0,0 +1,2 @@ +--- +dependencies: [] diff --git a/roles/snap/tasks/main.yml b/roles/snap/tasks/main.yml new file mode 100644 index 0000000..fe3047b --- /dev/null +++ b/roles/snap/tasks/main.yml @@ -0,0 +1,42 @@ +--- +- name: Enable 'universe' repo (Ubuntu and Mint only) + command: add-apt-repository universe + when: ansible_facts['distribution'] in ["Ubuntu", "Linux Mint"] + changed_when: false + ignore_errors: true + +- name: Remove Mint's nosnap.pref block (Mint only) + file: + path: /etc/apt/preferences.d/nosnap.pref + state: absent + when: ansible_facts['distribution'] == "Linux Mint" + +- name: Install Snap daemon + apt: + name: snapd + state: present + when: ansible_facts['os_family'] == "Debian" + notify: restart snapd + +- name: Enable snapd socket on Debian + systemd: + name: snapd.socket + enabled: true + state: started + when: ansible_facts['distribution'] == "Debian" + +- name: Force Ansible to reload facts + setup: + +- name: Install VSCode IDE (Snap, all distros) + community.general.snap: + name: code + classic: true + state: present + when: ansible_facts['os_family'] == "Debian" + +- name: Install Cursor (Snap, all distros) + community.general.snap: + name: cursor + state: present + when: ansible_facts['os_family'] == "Debian" diff --git a/roles/ssh/tasks/main.yml b/roles/ssh/tasks/main.yml index fcd0dc2..40fd4c1 100644 --- a/roles/ssh/tasks/main.yml +++ b/roles/ssh/tasks/main.yml @@ -4,3 +4,8 @@ name: openssh-server state: present +- name: Configure firewalls + ufw: + rule: allow + name: OpenSSH + diff --git a/roles/user/tasks/main.yml b/roles/user/tasks/main.yml index 43258ac..f16e674 100644 --- a/roles/user/tasks/main.yml +++ b/roles/user/tasks/main.yml @@ -1,6 +1,5 @@ --- -- name: Ensure ladmin user exists +- name: Ensure user exists user: name: "{{ ansible_user }}" state: present - shell: /bin/bash