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.

This commit is contained in:
ilia 2025-08-28 11:53:59 -04:00
parent fe5c39f487
commit 8b403e3aa5
17 changed files with 427 additions and 83 deletions

181
README.md Normal file
View File

@ -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

View File

@ -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

View File

@ -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 Mints 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!"

10
group_vars/all.yml Normal file
View File

@ -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

View File

@ -0,0 +1,2 @@
---
dependencies: []

View File

@ -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

View File

@ -1,2 +1,11 @@
---
# handlers file for base
- name: restart fail2ban
systemd:
name: fail2ban
state: restarted
- name: reload ufw
ufw:
state: reloaded

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,2 +1,11 @@
---
# handlers file for maintenance
- name: restart fail2ban
systemd:
name: fail2ban
state: restarted
- name: reload ufw
ufw:
state: reloaded

View File

@ -0,0 +1,5 @@
---
- name: restart snapd
systemd:
name: snapd
state: restarted

2
roles/snap/meta/main.yml Normal file
View File

@ -0,0 +1,2 @@
---
dependencies: []

42
roles/snap/tasks/main.yml Normal file
View File

@ -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"

View File

@ -4,3 +4,8 @@
name: openssh-server
state: present
- name: Configure firewalls
ufw:
rule: allow
name: OpenSSH

View File

@ -1,6 +1,5 @@
---
- name: Ensure ladmin user exists
- name: Ensure user exists
user:
name: "{{ ansible_user }}"
state: present
shell: /bin/bash