Initial Server Setup Using Ansible

Posted by Terrence's Site on Saturday, January 21, 2023

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.

  1. Install the system with a username of choice.
  2. Make sure the SSH is running and accessible.
  3. Make sure that the system install username is accessible from
  4. 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
  1. 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 Logo 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