Why
So, I’ve been on a ‘how can I make my life easier’ kick and started looking into different system management software. Ansible bubbled up to the top because it’s agent-less. This makes a lot of sense for the types of things I’m doing. It might make things slower in a huge setup/infrastructure since there’s some latency doing things through SSH.
Goal
Initial Goal - Automate the entire server baseline setup via Ansible.
Pre-requisites
Ok, I still haven’t gotten around to automating the actual install of the OS and loading of the initial keys on the system. Here are the initial requirements.
- Install the system with a username of choice.
- Make sure the SSH is running and accessible.
- Make sure that the system install username is accessible from
- Set vm.max_map_count to no less than 262144 (must run each time host is booted)
sudo sysctl -w vm.max_map_count=262144
- Set vm.max_map_count to no less than 262144 (one time configuration)
sudo echo "vm.max_map_count=262144" >> /etc/sysctl.conf
Ansible
Ansible is an open source, command-line IT automation software application written in Python. It can configure systems, deploy software, and orchestrate advanced workflows to support application deployment, system updates, and more.
Ansible’s main strengths are simplicity and ease of use. It also has a strong focus on security and reliability, featuring minimal moving parts. It uses OpenSSH for transport (with other transports and pull modes as alternatives), and uses a human-readable language that is designed for getting started quickly without a lot of training.
Here’s my home ansible playbook, it’s pretty basic and I run everything else through docker.
#!/usr/bin/env ansible-playbook -i ./ansible-hosts
---
- hosts: all
become: true
vars:
created_username: USERNAME
tasks:
- name: Install aptitude
apt:
name: aptitude
state: latest
update_cache: true
- name: Setup passwordless sudo
lineinfile:
path: /etc/sudoers
state: present
regexp: '^%sudo'
line: '%sudo ALL=(ALL) NOPASSWD: ALL'
validate: '/usr/sbin/visudo -cf %s'
- name: Create a new regular user with sudo privileges
user:
name: "{{ created_username }}"
state: present
groups: sudo
append: true
create_home: true
- name: Set authorized key for remote user
ansible.posix.authorized_key:
user: "{{ created_username }}"
state: present
key: "{{ lookup('file', './id_rsa.pub') }}" # Gets the local system SSH Key and copies to remote system.
- name: Disable password authentication for root
lineinfile:
path: /etc/ssh/sshd_config
state: present
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin prohibit-password'
register: ssh_conf
- name: Disable password authentication entirely on ssh
lineinfile:
path: /etc/ssh/sshd_config
state: present
regexp: '^PasswordAuthentication'
line: 'PasswordAuthentication no'
register: ssh_conf
- name: restart sshd
ansible.builtin.systemd:
name: sshd
state: restarted
when: ssh_conf.changed
- name: Update apt and install required system packages
apt:
pkg:
- curl
- vim
- git
- ufw
- apt-transport-https
- ca-certificates
- curl
- software-properties-common
- python3-pip
- virtualenv
- python3-setuptools
- unattended-upgrades
- gnupg
- lsb-release
- autofs
state: latest
update_cache: true
- name: UFW - Allow SSH connections
community.general.ufw:
rule: allow
name: OpenSSH
- name: UFW - Allow HTTP
community.general.ufw:
rule: allow
port: '80'
proto: tcp
- name: UFW - Allow HTTPS
community.general.ufw:
rule: allow
port: '443'
proto: tcp
- name: Allow Portainer access from home network
community.general.ufw:
rule: allow
proto: tcp
src: TRUSTEDIP
port: 9443
comment: Allow Portainer from Home
- name: Allow all access from RFC1918 networks to this host
ufw:
rule: allow
src: '{{ item }}'
loop:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- name: UFW - Enable and deny by default
community.general.ufw:
state: enabled
default: deny
- name: Set timezone to America/New_York
community.general.timezone:
name: America/New_York
- name: Update apt-cache and do dist upgrade
apt:
update_cache: yes
cache_valid_time: 3600
upgrade: dist
- name: Check if reboot required
stat:
path: /var/run/reboot-required
register: reboot_required_file
- name: Reboot if required
reboot:
when: reboot_required_file.stat.exists == true
# New method of loading keys on Ubuntu 22.04
- name: Add Docker GPG apt Key
block:
- name: Add Docker GPG apt Key
ansible.builtin.get_url:
url: https://download.docker.com/linux/ubuntu/gpg
dest: /etc/apt/trusted.gpg.d/docker-ce.asc
- name: Add Docker Repo
ansible.builtin.apt_repository:
repo: "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/docker-ce.asc] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
- name: Update apt and install docker-ce
apt:
name: docker-ce
state: latest
update_cache: true
- name: Install Docker Module for Python
pip:
name: docker
- name: Add additional Docker packages
apt:
pkg:
- docker-ce-cli
- containerd.io
- docker-compose-plugin
- docker-compose