Refine bootstrap and consolidate base role management

This commit is contained in:
Graham McIntire 2025-10-15 11:47:34 -05:00
parent ef8b473681
commit 8c3257ecdf
No known key found for this signature in database
9 changed files with 279 additions and 184 deletions

View file

@ -7,39 +7,48 @@
vars:
ansible_user: graham
tasks:
- name: Install sudo package first (if needed)
raw: "which sudo || (apt-get update && apt-get install -y sudo) || (yum install -y sudo)"
- name: Ensure sudo is present
raw: |
if command -v sudo >/dev/null 2>&1; then
exit 0
fi
if command -v apt-get >/dev/null 2>&1; then
apt-get update && apt-get install -y sudo
elif command -v dnf >/dev/null 2>&1; then
dnf install -y sudo
elif command -v yum >/dev/null 2>&1; then
yum install -y sudo
elif command -v apk >/dev/null 2>&1; then
apk add --no-cache sudo
else
echo "Unsupported package manager for sudo installation" >&2
exit 1
fi
become: yes
become_method: su
become_user: root
- name: Configure sudo for graham user
raw: "echo 'graham ALL=NOPASSWD: ALL' | tee /etc/sudoers.d/graham && chmod 0440 /etc/sudoers.d/graham"
- name: Ensure Python 3 is present
raw: |
if command -v python3 >/dev/null 2>&1; then
exit 0
fi
if command -v apt-get >/dev/null 2>&1; then
apt-get update && apt-get install -y python3 python3-apt
elif command -v dnf >/dev/null 2>&1; then
dnf install -y python3
elif command -v yum >/dev/null 2>&1; then
yum install -y python3
elif command -v apk >/dev/null 2>&1; then
apk add --no-cache python3 py3-pip
else
echo "Unsupported package manager for python3 installation" >&2
exit 1
fi
changed_when: false
become: yes
become_method: su
become_user: root
- name: Test sudo access
raw: "sudo whoami"
register: sudo_test
changed_when: false
- name: Show sudo test result
debug:
msg: "Sudo test result: {{ sudo_test.stdout }}"
- name: Install Python if needed
raw: "which python3 || sudo apt-get update && sudo apt-get install -y python3 python3-apt"
changed_when: false
- name: Find Python interpreter
raw: "which python3 || which python"
register: python_path
changed_when: false
- name: Show Python path
debug:
msg: "Python path: {{ python_path.stdout }}"
- name: Bootstrap new host - Base configuration
hosts: all

View file

@ -4,37 +4,38 @@
# Timezone configuration
timezone: America/Chicago
# GitHub usernames for SSH key retrieval
github_users:
- username: graham
github: gmcintire
- username: andy
github: nsnw
# Managed groups and users
managed_groups:
- name: ansible
gid: 10001
# Base packages to install on all systems
managed_users:
- name: ansible
uid: 10001
shell: /bin/bash
home: /home/ansible
primary_group: ansible
authorized_keys:
- type: file
value: ansible.pub
exclusive: true
- name: graham
shell: /bin/bash
home: /home/graham
admin: true
authorized_keys:
- type: github
value: gmcintire
- name: andy
shell: /bin/bash
home: /home/andy
admin: true
authorized_keys:
- type: github
value: nsnw
# Base settings
base:
packages:
- git
- fzf
- zsh
- jq
- sysstat
- smartmontools
- lm-sensors
- debconf-utils
- ntp
- ntpdate
- samba
- samba-common
- sssd
- krb5-user
- zsh
- wget
- vim
- htop
- mosh
- tmux
ntp:
server: 0.us.pool.ntp.org
@ -50,4 +51,4 @@ network:
nameservers:
- 9.9.9.9
- 149.112.112.112
domain: local
domain: local

View file

@ -21,37 +21,6 @@
name: "*"
state: latest
- name: Install required software
ansible.builtin.dnf:
state: present
name:
- bind-utils
- lsof
- htop
- btop
- mosh
- rsync
- tmux
- nano
- the-silver-searcher
- net-tools
- plocate
- fail2ban
- munin-node
# - nethogs # Not available in AlmaLinux EPEL
- pv
- selinux-policy
- tar
- unzip
- qemu-guest-agent
- python3-libselinux
- name: Create a user for andys
ansible.builtin.user:
name: andy
groups:
- wheel
state: present
# - name: Put SELinux in permissive mode, logging actions that would be blocked.
# ansible.posix.selinux:
# policy: targeted

View file

@ -18,26 +18,6 @@
name: sudo
state: present
- name: Install base packages
apk:
name:
- bash
- curl
- git
- htop
- iotop
- nano
- net-tools
- openssh-server
- python3
- py3-pip
- rsync
- shadow # For useradd/usermod commands
- tmux
- vim
- wget
state: present
- name: Ensure sshd is running and enabled
service:
name: sshd
@ -62,4 +42,4 @@
name: ansible
groups: sudo
append: yes
when: ansible_user == "ansible"
when: ansible_user == "ansible"

View file

@ -0,0 +1,106 @@
---
managed_groups: []
managed_users: []
admin_group_map:
Debian: sudo
RedHat: wheel
Alpine: wheel
admin_group: "{{ admin_group_map.get(ansible_os_family, 'sudo') }}"
base_common_packages:
- git
- vim
- wget
- htop
- tmux
- rsync
- zsh
base_packages_by_os_family:
Debian:
- sudo
- jq
- sysstat
- smartmontools
- lm-sensors
- debconf-utils
- ntp
- ntpdate
- samba
- samba-common
- sssd
- krb5-user
- python3
- python3-apt
RedHat:
- sudo
- jq
- sysstat
- smartmontools
- lm_sensors
- python3
Alpine:
- sudo
- bash
- curl
- python3
- py3-pip
- shadow
base_packages_by_distribution:
Ubuntu:
- lsof
- mosh
- unattended-upgrades
- silversearcher-ag
- net-tools
- locate
- fail2ban
- munin-node
- nethogs
- pv
- fzf
- qemu-guest-agent
- python3-apt
Debian:
- lsof
- mosh
- unattended-upgrades
- silversearcher-ag
- net-tools
- locate
- fail2ban
- munin-node
- nethogs
- pv
- fzf
- qemu-guest-agent
AlmaLinux:
- bind-utils
- lsof
- btop
- mosh
- nano
- net-tools
- mlocate
- fail2ban
- munin-node
- pv
- selinux-policy
- tar
- unzip
- qemu-guest-agent
- python3-libselinux
Alpine:
- git
- htop
- iotop
- nano
- net-tools
- openssh-server
- rsync
- tmux
- vim
- wget

View file

@ -16,6 +16,12 @@
msg: "{{ ansible_default_ipv6.address }}"
when: ansible_default_ipv6.address is defined
# Base package installation
- import_tasks: packages.yml
tags:
- packages
- common
# User and group setup
- import_tasks: users.yml
tags:
@ -39,4 +45,4 @@
- include_role:
name: alpine
when: ansible_os_family == "Alpine"
when: ansible_os_family == "Alpine"

View file

@ -0,0 +1,19 @@
---
- name: Determine base package set
ansible.builtin.set_fact:
base_packages_combined: >-
{{ (base_common_packages
+ base_packages_by_os_family.get(ansible_os_family, [])
+ base_packages_by_distribution.get(ansible_distribution, [])) | unique }}
tags:
- packages
- common
- name: Install base packages
ansible.builtin.package:
name: "{{ base_packages_combined }}"
state: present
when: base_packages_combined | length > 0
tags:
- packages
- common

View file

@ -1,73 +1,106 @@
---
# User and group management tasks
- name: Install sudo package (Debian)
apt:
name: sudo
state: present
when: ansible_os_family == "Debian"
- name: Ensure admin group exists when defined
ansible.builtin.group:
name: "{{ admin_group }}"
when: admin_group | default('') | length > 0
- name: Create ansible group
group:
name: ansible
gid: 10001
state: present
- name: Ensure managed groups exist
ansible.builtin.group:
name: "{{ item.name }}"
gid: "{{ item.gid | default(omit) }}"
state: "{{ item.state | default('present') }}"
loop: "{{ managed_groups | default([]) }}"
loop_control:
label: "{{ item.name }}"
- name: Create ansible user
user:
name: ansible
group: ansible
uid: 10001
shell: /bin/bash
home: /home/ansible
- name: Ensure primary groups for managed users exist
ansible.builtin.group:
name: "{{ item.primary_group }}"
gid: "{{ item.primary_gid | default(omit) }}"
state: present
loop: "{{ managed_users | default([]) }}"
loop_control:
label: "{{ item.name }}"
when: item.primary_group is defined
- name: Create graham user
user:
name: graham
shell: /bin/bash
home: /home/graham
state: present
- name: Ensure managed users are present
ansible.builtin.user:
name: "{{ item.name }}"
uid: "{{ item.uid | default(omit) }}"
shell: "{{ item.shell | default('/bin/bash') }}"
home: "{{ item.home | default(omit) }}"
group: "{{ item.primary_group | default(omit) }}"
groups: "{{ (user_groups | join(',')) if user_groups else omit }}"
append: true
create_home: "{{ item.create_home | default(true) }}"
state: "{{ item.state | default('present') }}"
vars:
user_groups: >-
{{ ((item.groups | default([])) +
([admin_group] if item.admin | default(false) and admin_group | default('') | length > 0 else []))
| unique }}
loop: "{{ managed_users | default([]) }}"
loop_control:
label: "{{ item.name }}"
when: item.state | default('present') != 'absent'
- name: Create andy user
user:
name: andy
shell: /bin/bash
home: /home/andy
state: present
- name: Remove managed users marked absent
ansible.builtin.user:
name: "{{ item.name }}"
state: absent
remove: "{{ item.remove | default(false) }}"
loop: "{{ managed_users | default([]) }}"
loop_control:
label: "{{ item.name }}"
when: item.state | default('present') == 'absent'
- name: Set up SSH key for ansible user
authorized_key:
user: ansible
key: "{{ lookup('file', 'ansible.pub') }}"
exclusive: true
state: present
- name: Install authorized keys from GitHub
ansible.posix.authorized_key:
user: "{{ item.0.name }}"
state: "{{ item.1.state | default('present') }}"
key: "https://github.com/{{ item.1.value }}.keys"
manage_dir: "{{ item.1.manage_dir | default(true) }}"
exclusive: "{{ item.1.exclusive | default(false) }}"
loop: "{{ managed_users | default([]) | subelements('authorized_keys', skip_missing=True) }}"
loop_control:
label: "{{ item.0.name }} (github: {{ item.1.value }})"
when:
- item.1.type | default('github') == 'github'
- item.0.state | default('present') != 'absent'
- name: Install authorized keys from files
ansible.posix.authorized_key:
user: "{{ item.0.name }}"
state: "{{ item.1.state | default('present') }}"
key: "{{ lookup('file', item.1.value) }}"
manage_dir: "{{ item.1.manage_dir | default(true) }}"
exclusive: "{{ item.1.exclusive | default(false) }}"
loop: "{{ managed_users | default([]) | subelements('authorized_keys', skip_missing=True) }}"
loop_control:
label: "{{ item.0.name }} (file: {{ item.1.value }})"
when:
- item.1.type | default('github') == 'file'
- item.0.state | default('present') != 'absent'
- name: Configure sudo for ansible user
template:
ansible.builtin.template:
src: sudoers_ansible.j2
dest: /etc/sudoers.d/ansible
mode: '0440'
validate: 'visudo -cf %s'
- name: Configure sudo for graham user
template:
ansible.builtin.template:
src: sudoers_graham.j2
dest: /etc/sudoers.d/graham
mode: '0440'
validate: 'visudo -cf %s'
- name: Enable passwordless sudo for %sudo
lineinfile:
ansible.builtin.lineinfile:
path: /etc/sudoers
state: present
regexp: '^%sudo'
line: '%sudo ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
- name: Install SSH keys from GitHub
ansible.posix.authorized_key:
user: "{{ item.username }}"
state: present
key: "https://github.com/{{ item.github }}.keys"
loop: "{{ github_users }}"

View file

@ -17,28 +17,6 @@
autoremove: true
autoclean: true
- name: Install required software
ansible.builtin.apt:
autoremove: true
autoclean: true
state: present
name:
- lsof
- htop
- mosh
- rsync
- tmux
- unattended-upgrades
- silversearcher-ag
- net-tools
- locate
- fail2ban
- munin-node
- nethogs
- pv
- fzf
- qemu-guest-agent
- name: Remove ubuntu advantage
ansible.builtin.apt:
autoremove: true
@ -47,12 +25,6 @@
name:
- ubuntu-advantage-tools
- name: Create a user for andys
ansible.builtin.user:
name: andy
groups:
- sudo
state: present
# - name: Allow SSH in ufw
# community.general.ufw:
# rule: limit