Enhance Ansible setup by introducing a Makefile for streamlined workflows, updating ansible.cfg for improved configuration, and adding .ansible/facts/ to .gitignore. Update README.md to include quick start instructions and usage examples for the Makefile. Refactor roles for SSH hardening, including comprehensive configuration options and security settings, while ensuring modern CLI tools are installed. Improve package management in the base role with additional utilities and symlink creation for compatibility.

This commit is contained in:
ilia 2025-08-29 21:54:50 -04:00
parent 67a5caef36
commit 5e4428447c
9 changed files with 482 additions and 27 deletions

2
.gitignore vendored
View File

@ -21,3 +21,5 @@ __pycache__/
# OS files
.DS_Store
Thumbs.db
.ansible/facts/

124
Makefile Normal file
View File

@ -0,0 +1,124 @@
.PHONY: help bootstrap lint test check apply dev local clean status
.DEFAULT_GOAL := help
## Colors for output
BOLD := \033[1m
RED := \033[31m
GREEN := \033[32m
YELLOW := \033[33m
BLUE := \033[34m
RESET := \033[0m
help: ## Show this help message
@echo "$(BOLD)Ansible Development Environment$(RESET)"
@echo ""
@echo "$(BOLD)Available commands:$(RESET)"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " $(BLUE)%-15s$(RESET) %s\n", $$1, $$2}'
@echo ""
@echo "$(BOLD)Examples:$(RESET)"
@echo " make bootstrap # Set up dependencies"
@echo " make check # Dry run all hosts"
@echo " make apply # Run on all dev hosts"
@echo " make dev HOST=devVM # Run on specific host"
@echo " make local # Run local playbook"
@echo ""
bootstrap: ## Install required collections and dependencies
@echo "$(YELLOW)Installing Ansible collections...$(RESET)"
ansible-galaxy collection install -r collections/requirements.yml
@echo "$(GREEN)✓ Collections installed$(RESET)"
lint: ## Run ansible-lint on all playbooks and roles
@echo "$(YELLOW)Running ansible-lint...$(RESET)"
ansible-lint
@echo "$(GREEN)✓ Linting completed$(RESET)"
test: lint ## Run all tests (lint + syntax check)
@echo "$(YELLOW)Testing playbook syntax...$(RESET)"
ansible-playbook dev-playbook.yml --syntax-check
ansible-playbook local-playbook.yml --syntax-check
@echo "$(GREEN)✓ Syntax check passed$(RESET)"
check: ## Dry-run the development playbook (--check mode)
@echo "$(YELLOW)Running dry-run on development hosts...$(RESET)"
ansible-playbook dev-playbook.yml --check --diff
check-local: ## Dry-run the local playbook
@echo "$(YELLOW)Running dry-run on localhost...$(RESET)"
ansible-playbook local-playbook.yml --check --diff -K
apply: ## Run the development playbook on all dev hosts
@echo "$(YELLOW)Applying development playbook...$(RESET)"
ansible-playbook dev-playbook.yml
local: ## Run the local playbook on localhost
@echo "$(YELLOW)Applying local playbook...$(RESET)"
ansible-playbook local-playbook.yml -K
# Host-specific targets
dev: ## Run on specific host (usage: make dev HOST=devVM)
ifndef HOST
@echo "$(RED)Error: HOST parameter required$(RESET)"
@echo "Usage: make dev HOST=devVM"
@exit 1
endif
@echo "$(YELLOW)Running on host: $(HOST)$(RESET)"
ansible-playbook dev-playbook.yml --limit $(HOST)
# Tag-based execution
security: ## Run only security-related roles
@echo "$(YELLOW)Running security roles...$(RESET)"
ansible-playbook dev-playbook.yml --tags security
maintenance: ## Run only maintenance tasks
@echo "$(YELLOW)Running maintenance...$(RESET)"
ansible-playbook dev-playbook.yml --tags maintenance
docker: ## Install/configure Docker only
@echo "$(YELLOW)Running Docker setup...$(RESET)"
ansible-playbook dev-playbook.yml --tags docker
shell: ## Configure shell only
@echo "$(YELLOW)Running shell configuration...$(RESET)"
ansible-playbook dev-playbook.yml --tags shell
apps: ## Install applications only
@echo "$(YELLOW)Installing applications...$(RESET)"
ansible-playbook dev-playbook.yml --tags apps
# Utility targets
status: ## Check connectivity to all hosts
@echo "$(YELLOW)Checking host connectivity...$(RESET)"
ansible all -m ping
facts: ## Gather facts from all hosts
@echo "$(YELLOW)Gathering facts...$(RESET)"
ansible all -m setup --tree /tmp/facts
clean: ## Clean up ansible artifacts
@echo "$(YELLOW)Cleaning up artifacts...$(RESET)"
rm -rf .ansible/facts/
find . -name "*.retry" -delete
@echo "$(GREEN)✓ Cleanup completed$(RESET)"
# Debug targets
debug: ## Run with debug output enabled
@echo "$(YELLOW)Running with debug output...$(RESET)"
ansible-playbook dev-playbook.yml -e "ansible_debug_output=true"
verbose: ## Run with verbose output
@echo "$(YELLOW)Running with verbose output...$(RESET)"
ansible-playbook dev-playbook.yml -vv
# Quick development workflow
quick: test check ## Quick test and check before applying
@echo "$(GREEN)✓ Ready to apply changes$(RESET)"
# Vault management
edit-vault: ## Edit encrypted host vars (usage: make edit-vault HOST=devVM)
ifndef HOST
@echo "$(RED)Error: HOST parameter required$(RESET)"
@echo "Usage: make edit-vault HOST=devVM"
@exit 1
endif
ansible-vault edit host_vars/$(HOST).yml

200
README.md
View File

@ -28,7 +28,28 @@ This Ansible playbook automates the setup of development environments across mul
## 🚀 Usage
### Prerequisites
### Quick Start with Makefile (Recommended)
```bash
# Setup dependencies
make bootstrap
# Test everything
make test
# Dry run to see what would change
make check
# Apply to all development hosts
make apply
# Run on specific host
make dev HOST=devVM
# Run locally
make local
```
### Prerequisites (Manual Setup)
```bash
# Install required collections
ansible-galaxy collection install -r collections/requirements.yml
@ -64,6 +85,30 @@ ansible-playbook dev-playbook.yml --limit bottom
```
### Selective Execution with Tags
#### Using Makefile (Recommended)
```bash
# Security-related roles only
make security
# Development tools only
make docker
make shell
# Applications only
make apps
# Maintenance only
make maintenance
# Check connectivity
make status
# Get detailed help
make help
```
#### Manual Commands
```bash
# Security-related roles only
ansible-playbook dev-playbook.yml --tags security
@ -99,13 +144,17 @@ ansible-playbook dev-playbook.yml --limit devVM -e "ansible_debug_output=true"
ansible_debug_output: true
```
### Dry Run
### Dry Run and Testing
```bash
# Check what would be changed
ansible-playbook dev-playbook.yml --check
# Using Makefile
make test # Lint + syntax check
make check # Dry run all hosts
make check-local # Dry run localhost
make quick # Test + check workflow
# Verbose output
ansible-playbook dev-playbook.yml -v
# Manual commands
ansible-playbook dev-playbook.yml --check # Check what would change
ansible-playbook dev-playbook.yml -v # Verbose output
```
## 🔧 Configuration
@ -118,6 +167,24 @@ ansible-playbook dev-playbook.yml -v
- `fail2ban_findtime`: Time window for failures
- `fail2ban_maxretry`: Max failures before ban
### SSH Configuration (`roles/ssh/defaults/main.yml`)
The SSH role provides comprehensive security hardening:
- `ssh_port`: SSH port (default: 22)
- `ssh_permit_root_login`: Root login setting (default: 'no')
- `ssh_password_authentication`: Password auth (default: 'no')
- `ssh_max_auth_tries`: Authentication attempts (default: 3)
- `ssh_allowed_users`: Restrict to specific users (default: [])
- `ssh_allowed_groups`: Restrict to specific groups (default: ['sudo', 'ssh'])
Override any setting in your host or group variables:
```yaml
# Example: Custom SSH port
ssh_port: 2222
# Example: Allow specific users
ssh_allowed_users: ['admin', 'deploy']
```
### Host Variables (`host_vars/`)
- `skip_reboot`: Skip automatic reboots
- Encrypted variables for sensitive data
@ -134,17 +201,26 @@ ansible-playbook dev-playbook.yml -v
- SSH access allowed
- Automatic enablement
### SSH Hardening
- Modern cryptographic algorithms (ChaCha20-Poly1305, AES-256-GCM)
- Secure key exchange (Curve25519, DH Group 16)
- Disabled password authentication
- Connection rate limiting and timeouts
- User/group access restrictions
- Configuration validation and automatic backup
### System Hardening
- Timezone and locale configuration
- Security package installation
- Monitoring tools (htop, iotop, nethogs, logwatch)
- Modern CLI tools and system monitoring
## 📦 Installed Packages
### Base System
- `htop`, `curl`, `wget`, `unzip`, `xclip`
- `net-tools`, `ufw`, `fail2ban`
- `iotop`, `nethogs`, `logwatch`
- **Core utilities**: `curl`, `wget`, `unzip`, `xclip`, `tree`
- **Network/Security**: `net-tools`, `ufw`, `fail2ban`, `mailutils`
- **Monitoring**: `iotop`, `nethogs`, `logwatch`, `btop` (via snap)
- **Modern CLI**: `jq`, `yq` (via snap), `ripgrep`, `fd-find`
### Development Tools
- `git`, `nodejs`, `npm`
@ -159,6 +235,40 @@ ansible-playbook dev-playbook.yml -v
- Docker Compose
- User added to docker group
## 🔧 Modern CLI Tools
The base role installs modern replacements for traditional Unix tools:
### Available Commands
```bash
# Fast searching
rg "pattern" files/ # ripgrep - faster than grep
fd "filename" # fd-find - intuitive find replacement
# Data processing
jq '.key' file.json # JSON processor and formatter
yq '.key' file.yaml # YAML processor and formatter
# System monitoring
btop # Modern system monitor (better than htop)
tree directory/ # Directory structure visualization
# File operations
tree -L 2 # Limit tree depth
rg -i "case insensitive" # Case-insensitive search
fd -e yml # Find only YAML files
jq -r '.items[].name' # Raw JSON output
```
### Integration Examples
```bash
# DevOps workflows
kubectl get pods -o json | jq '.items[].metadata.name'
docker ps --format json | jq '.Names'
rg "ansible.builtin" roles/ --type yaml
fd "main.yml" roles/ -x cat
```
## 🔄 Maintenance
### Automatic Updates
@ -193,34 +303,84 @@ ansible-playbook dev-playbook.yml --skip-tags maintenance
- Use `skip_reboot=true` for problematic hosts
- Check maintenance role handlers
4. **SSH Configuration Issues**
- Original config backed up to `/etc/ssh/sshd_config.backup`
- Test SSH config: `sudo sshd -t`
- Check SSH service: `sudo systemctl status ssh`
- Verify public key authentication is working before applying
5. **Modern CLI Tools Missing**
- Check if snap is installed: `snap --version`
- For fd command: Symlink created at `/usr/local/bin/fd`
- Alternative: Use `fdfind` directly on Ubuntu systems
### Debug Commands
```bash
# Test connectivity
ansible dev -m ping
# Using Makefile
make status # Test connectivity to all hosts
make facts # Gather facts from all hosts
make debug # Run with debug output
make verbose # Run with verbose output
# Check facts
ansible dev -m setup
# Manual commands
ansible dev -m ping # Test connectivity
ansible dev -m setup # Check facts
ansible-playbook dev-playbook.yml --tags base # Run specific role
# Run specific role
ansible-playbook dev-playbook.yml --tags base
# Verify installations
ansible dev -m shell -a "jq --version" # Check jq installation
ansible dev -m shell -a "rg --version" # Check ripgrep installation
ansible dev -m shell -a "fd --version" # Check fd installation
ansible dev -m shell -a "sudo sshd -t" # Validate SSH config
```
## 🛠️ Makefile Workflows
The included `Makefile` provides convenient shortcuts for common operations:
### Development Workflow
```bash
make bootstrap # Install collections
make test # Lint + syntax check
make check # Dry run
make apply # Deploy to all hosts
```
### Host-Specific Operations
```bash
make dev HOST=devVM # Deploy to specific host
make edit-vault HOST=devVM # Edit encrypted host variables
```
### Maintenance and Utilities
```bash
make clean # Clean up artifacts
make status # Check host connectivity
make install-tools # Install recommended CLI tools locally
```
Run `make help` for the complete list of available commands.
## 📝 File Structure
```
ansible/
├── ansible.cfg # Ansible configuration
├── ansible.cfg # Enhanced Ansible configuration
├── Makefile # Workflow automation
├── hosts # Inventory file
├── dev-playbook.yml # Main development playbook
├── local-playbook.yml # Local machine setup
├── collections/
│ └── requirements.yml # Required Ansible collections
├── group_vars/
│ └── all.yml # Global variables
├── host_vars/ # Host-specific variables
├── host_vars/ # Host-specific variables (encrypted)
└── roles/
├── maintenance/ # System maintenance
├── base/ # Core system setup
├── development/ # Development tools
├── shell/ # Shell configuration
├── shell/ # Shell configuration (zsh + oh-my-zsh)
├── docker/ # Docker installation
├── ssh/ # SSH configuration
├── ssh/ # SSH hardening and configuration
├── user/ # User management
├── applications/ # Desktop applications
└── snap/ # Snap applications

View File

@ -1,13 +1,23 @@
[defaults]
inventory = hosts
host_key_checking = True
timeout = 30
roles_path = roles
host_key_checking = False
stdout_callback = yaml
bin_ansible_callbacks = True
retry_files_enabled = False
gathering = smart
fact_caching = memory
stdout_callback = default
fact_caching = jsonfile
fact_caching_connection = .ansible/facts
fact_caching_timeout = 86400
interpreter_python = auto_silent
deprecation_warnings = False
forks = 20
pipelining = True
callbacks_enabled = profile_tasks,timer
vault_password_file = ~/.ansible-vault-pass
become_ask_pass = True
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
retries = 2
pipelining = True

View File

@ -3,11 +3,11 @@
ansible.builtin.apt:
name:
# Base utilities
- htop
- curl
- wget
- unzip
- xclip
- tree
# Network and admin tools
- net-tools
- ufw
@ -17,8 +17,26 @@
- iotop
- nethogs
- logwatch
# Modern CLI tools
- jq
- ripgrep
- fd-find
state: present
- name: Install modern tools via snap
community.general.snap:
name:
- yq
- btop
state: present
- name: Create fd symlink (Ubuntu uses fd-find)
ansible.builtin.file:
src: /usr/bin/fdfind
dest: /usr/local/bin/fd
state: link
when: ansible_distribution == "Ubuntu"
- name: Configure fail2ban
ansible.builtin.template:
src: jail.local.j2

View File

@ -1,2 +1,43 @@
---
# defaults file for ssh
# SSH server configuration
ssh_port: 22
ssh_listen_addresses: ['0.0.0.0']
ssh_permit_root_login: 'no'
ssh_password_authentication: 'no'
ssh_pubkey_authentication: 'yes'
ssh_max_auth_tries: 3
ssh_client_alive_interval: 300
ssh_max_sessions: 10
ssh_allowed_users: [] # Restrict to specific users
ssh_allowed_groups: ['sudo', 'ssh']
# Security hardening
ssh_kex_algorithms:
- curve25519-sha256@libssh.org
- diffie-hellman-group16-sha512
ssh_ciphers:
- chacha20-poly1305@openssh.com
- aes256-gcm@openssh.com
ssh_macs:
- hmac-sha2-256-etm@openssh.com
- hmac-sha2-512-etm@openssh.com
# Additional security settings
ssh_protocol: 2
ssh_use_dns: 'no'
ssh_permit_empty_passwords: 'no'
ssh_challenge_response_auth: 'no'
ssh_gss_api_authentication: 'no'
ssh_x11_forwarding: 'no'
ssh_print_motd: 'no'
ssh_tcp_keep_alive: 'yes'
ssh_compression: 'no'
# Log level (QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, DEBUG3)
ssh_log_level: 'INFO'
# Maximum number of concurrent unauthenticated connections
ssh_max_startups: '10:30:100'
# Timeout for authentication
ssh_login_grace_time: '2m'

View File

@ -1,4 +1,9 @@
---
- name: Restart sshd
ansible.builtin.systemd:
name: ssh
state: restarted
- name: Restart ssh
ansible.builtin.systemd:
name: ssh

View File

@ -4,10 +4,27 @@
name: openssh-server
state: present
- name: Backup original SSH configuration
ansible.builtin.copy:
src: /etc/ssh/sshd_config
dest: /etc/ssh/sshd_config.backup
remote_src: true
mode: '0600'
force: false
- name: Configure SSH daemon
ansible.builtin.template:
src: sshd_config.j2
dest: /etc/ssh/sshd_config
backup: true
mode: '0644'
validate: '/usr/sbin/sshd -t -f %s'
notify: Restart sshd
- name: Configure firewalls - allow SSH port
community.general.ufw:
rule: allow
port: '22'
port: "{{ ssh_port }}"
proto: tcp
- name: Configure firewalls - allow SSH by name (backup)

View File

@ -0,0 +1,78 @@
# SSH daemon configuration - Managed by Ansible
# See sshd_config(5) for more information
# Basic settings
Port {{ ssh_port }}
Protocol {{ ssh_protocol }}
{% for address in ssh_listen_addresses %}
ListenAddress {{ address }}
{% endfor %}
# Host keys
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
# Ciphers and keying
{% if ssh_kex_algorithms %}
KexAlgorithms {{ ssh_kex_algorithms | join(',') }}
{% endif %}
{% if ssh_ciphers %}
Ciphers {{ ssh_ciphers | join(',') }}
{% endif %}
{% if ssh_macs %}
MACs {{ ssh_macs | join(',') }}
{% endif %}
# Logging
SyslogFacility AUTH
LogLevel {{ ssh_log_level }}
# Authentication
LoginGraceTime {{ ssh_login_grace_time }}
PermitRootLogin {{ ssh_permit_root_login }}
StrictModes yes
MaxAuthTries {{ ssh_max_auth_tries }}
MaxSessions {{ ssh_max_sessions }}
MaxStartups {{ ssh_max_startups }}
# Public key authentication
PubkeyAuthentication {{ ssh_pubkey_authentication }}
# Password authentication
PasswordAuthentication {{ ssh_password_authentication }}
PermitEmptyPasswords {{ ssh_permit_empty_passwords }}
# Challenge-response authentication
ChallengeResponseAuthentication {{ ssh_challenge_response_auth }}
# Kerberos/GSSAPI authentication
KerberosAuthentication no
GSSAPIAuthentication {{ ssh_gss_api_authentication }}
GSSAPICleanupCredentials yes
# User/Group restrictions
{% if ssh_allowed_users %}
AllowUsers {{ ssh_allowed_users | join(' ') }}
{% endif %}
{% if ssh_allowed_groups %}
AllowGroups {{ ssh_allowed_groups | join(' ') }}
{% endif %}
# Networking
UseDNS {{ ssh_use_dns }}
TCPKeepAlive {{ ssh_tcp_keep_alive }}
ClientAliveInterval {{ ssh_client_alive_interval }}
ClientAliveCountMax 3
# Features
X11Forwarding {{ ssh_x11_forwarding }}
PrintMotd {{ ssh_print_motd }}
PrintLastLog yes
Compression {{ ssh_compression }}
# Subsystems
Subsystem sftp /usr/lib/openssh/sftp-server
# Banner (optional)
# Banner /etc/issue.net