diff --git a/roles/base_system/tasks/install_packages.yaml b/roles/base_system/tasks/install_packages.yaml new file mode 100644 index 0000000..e462163 --- /dev/null +++ b/roles/base_system/tasks/install_packages.yaml @@ -0,0 +1,43 @@ +--- +- name: Installing basic utils for comfort work (apt-based system) + when: (ansible_facts['distribution'] == "Debian") or + (ansible_facts['distribution'] == "Ubuntu") + ansible.builtin.apt: + name: + - vim + - neovim + - ranger + - zsh + - rsync + - git + - curl + - kitty + - unattended-upgrades + - ssh + - openssh-server + update-cache: true # Run apt update before installation + become: true + remote_user: ansible + +- name: Install qemu-guest-agent on VM + when: + - ansible_facts['os_family'] == "Debian" + - ansible_facts['virtualization_type'] == "kvm" + ansible.builtin.apt: + name: qemu-guest-agent + state: present + update-cache: true # Run apt update before installation + become: true + remote_user: ansible + tags: + - kvm-guests + - packages + + +# The same commands for Alpine +- name: Update and install packages on Alpine + when: (ansible_facts['distribution'] == "Alpine") + community.general.apk: + name: neovim vim ranger zsh rsync git curl kitty openssh + update_cache: true + remote_user: ansible diff --git a/roles/base_system/tasks/main.yaml b/roles/base_system/tasks/main.yaml index e462163..8f5debe 100644 --- a/roles/base_system/tasks/main.yaml +++ b/roles/base_system/tasks/main.yaml @@ -1,43 +1,7 @@ --- -- name: Installing basic utils for comfort work (apt-based system) - when: (ansible_facts['distribution'] == "Debian") or - (ansible_facts['distribution'] == "Ubuntu") - ansible.builtin.apt: - name: - - vim - - neovim - - ranger - - zsh - - rsync - - git - - curl - - kitty - - unattended-upgrades - - ssh - - openssh-server - update-cache: true # Run apt update before installation - become: true - remote_user: ansible +- name: Install basic utils + ansible.builtin.include_tasks: install_basic_utils.yaml -- name: Install qemu-guest-agent on VM - when: - - ansible_facts['os_family'] == "Debian" - - ansible_facts['virtualization_type'] == "kvm" - ansible.builtin.apt: - name: qemu-guest-agent - state: present - update-cache: true # Run apt update before installation - become: true - remote_user: ansible - tags: - - kvm-guests - - packages +- name: Remove unnecessary packages + ansible.builtin.include_tasks: remove_packages.yaml - -# The same commands for Alpine -- name: Update and install packages on Alpine - when: (ansible_facts['distribution'] == "Alpine") - community.general.apk: - name: neovim vim ranger zsh rsync git curl kitty openssh - update_cache: true - remote_user: ansible diff --git a/roles/base_system/tasks/remove_packages.yaml b/roles/base_system/tasks/remove_packages.yaml new file mode 100644 index 0000000..c0116fd --- /dev/null +++ b/roles/base_system/tasks/remove_packages.yaml @@ -0,0 +1,31 @@ +--- +# Remove multiple packages at once +- name: Remove unnecessary packages + remote_user: ansible + when: (ansible_facts['distribution'] == "Debian") or + (ansible_facts['distribution'] == "Ubuntu") + ansible.builtin.apt: + name: + - nano + state: absent + become: true + + +# Clean up all orphaned packages +- name: Remove all orphaned dependencies + remote_user: ansible + when: (ansible_facts['distribution'] == "Debian") or + (ansible_facts['distribution'] == "Ubuntu") + ansible.builtin.apt: + autoremove: true + purge: true + + +- name: Install sudo package on Alpine + remote_user: ansible + when: (ansible_facts['distribution'] == "Alpine") + community.general.apk: + name: + - nano + state: absent + become: true diff --git a/roles/basic_postinstall_/files/.vimrc b/roles/basic_postinstall_/files/.vimrc new file mode 100644 index 0000000..70d5a79 --- /dev/null +++ b/roles/basic_postinstall_/files/.vimrc @@ -0,0 +1,16 @@ +set number +set tabstop=2 +" Disable compatibility with vi which can cause unexpected issues. +set nocompatible + +" Enable type file detection. Vim will be able to try to detect the type of file in use. +filetype on + +" Enable plugins and load plugin for the detected file type. +filetype plugin on + +" Load an indent file for the detected file type. +filetype indent on + +" Turn syntax highlighting on. +syntax on diff --git a/roles/basic_postinstall_/files/.zshrc b/roles/basic_postinstall_/files/.zshrc new file mode 100644 index 0000000..4423d1f --- /dev/null +++ b/roles/basic_postinstall_/files/.zshrc @@ -0,0 +1,105 @@ +export PATH=$HOME/bin:$HOME/.local/bin:/usr/local/bin:/home/max/soft/gnu_linux:$PATH + +# Path to your Oh My Zsh installation. +export ZSH="$HOME/.oh-my-zsh" + +export GTK_THEME=Adwaita-dark + +# Set name of the theme to load --- if set to "random", it will +# load a random theme each time Oh My Zsh is loaded, in which case, +# to know which specific one was loaded, run: echo $RANDOM_THEME +# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes +ZSH_THEME="gnzh" + +# Set list of themes to pick from when loading at random +# Setting this variable when ZSH_THEME=random will cause zsh to load +# a theme from this variable instead of looking in $ZSH/themes/ +# If set to an empty array, this variable will have no effect. +# ZSH_THEME_RANDOM_CANDIDATES=( "robbyrussell" "agnoster" ) + +# Uncomment the following line to use case-sensitive completion. +# CASE_SENSITIVE="true" + +# Uncomment the following line to use hyphen-insensitive completion. +# Case-sensitive completion must be off. _ and - will be interchangeable. +# HYPHEN_INSENSITIVE="true" + +# Uncomment one of the following lines to change the auto-update behavior +# zstyle ':omz:update' mode disabled # disable automatic updates +# zstyle ':omz:update' mode auto # update automatically without asking +# zstyle ':omz:update' mode reminder # just remind me to update when it's time + +# Uncomment the following line to change how often to auto-update (in days). +# zstyle ':omz:update' frequency 13 + +# Uncomment the following line if pasting URLs and other text is messed up. +# DISABLE_MAGIC_FUNCTIONS="true" + +# Uncomment the following line to disable colors in ls. +# DISABLE_LS_COLORS="true" + +# Uncomment the following line to disable auto-setting terminal title. +# DISABLE_AUTO_TITLE="true" + +# Uncomment the following line to enable command auto-correction. +# ENABLE_CORRECTION="true" + +# Uncomment the following line to display red dots whilst waiting for completion. +# You can also set it to another string to have that shown instead of the default red dots. +# e.g. COMPLETION_WAITING_DOTS="%F{yellow}waiting...%f" +# Caution: this setting can cause issues with multiline prompts in zsh < 5.7.1 (see #5765) +# COMPLETION_WAITING_DOTS="true" + +# Uncomment the following line if you want to disable marking untracked files +# under VCS as dirty. This makes repository status check for large repositories +# much, much faster. +# DISABLE_UNTRACKED_FILES_DIRTY="true" + +# Uncomment the following line if you want to change the command execution time +# stamp shown in the history command output. +# You can set one of the optional three formats: +# "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd" +# or set a custom format using the strftime function format specifications, +# see 'man strftime' for details. +# HIST_STAMPS="mm/dd/yyyy" + +# Would you like to use another custom folder than $ZSH/custom? +# ZSH_CUSTOM=/path/to/new-custom-folder + +# Which plugins would you like to load? +# Standard plugins can be found in $ZSH/plugins/ +# Custom plugins may be added to $ZSH_CUSTOM/plugins/ +# Example format: plugins=(rails git textmate ruby lighthouse) +# Add wisely, as too many plugins slow down shell startup. +#plugins=(git) + +source $ZSH/oh-my-zsh.sh + +# User configuration + +# export MANPATH="/usr/local/man:$MANPATH" + +# You may need to manually set your language environment +# export LANG=en_US.UTF-8 + +# Preferred editor for local and remote sessions +# if [[ -n $SSH_CONNECTION ]]; then +# export EDITOR='vim' +# else +# export EDITOR='nvim' +# fi + +# Compilation flags +# export ARCHFLAGS="-arch $(uname -m)" + +# Set personal aliases, overriding those provided by Oh My Zsh libs, +# plugins, and themes. Aliases can be placed here, though Oh My Zsh +# users are encouraged to define aliases within a top-level file in +# the $ZSH_CUSTOM folder, with .zsh extension. Examples: +# - $ZSH_CUSTOM/aliases.zsh +# - $ZSH_CUSTOM/macos.zsh +# For a full list of active aliases, run `alias`. +# +# Example aliases +# alias zshconfig="mate ~/.zshrc" +# alias ohmyzsh="mate ~/.oh-my-zsh" diff --git a/roles/basic_postinstall_/files/hardened_ssh.conf b/roles/basic_postinstall_/files/hardened_ssh.conf new file mode 100644 index 0000000..012011c --- /dev/null +++ b/roles/basic_postinstall_/files/hardened_ssh.conf @@ -0,0 +1,4 @@ + Host * + HashKnownHosts yes + GSSAPIAuthentication yes + KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,curve25519-sha256 \ No newline at end of file diff --git a/roles/basic_postinstall_/files/hardened_sshd.conf b/roles/basic_postinstall_/files/hardened_sshd.conf new file mode 100644 index 0000000..21f4436 --- /dev/null +++ b/roles/basic_postinstall_/files/hardened_sshd.conf @@ -0,0 +1,29 @@ +PubkeyAuthentication yes +AuthorizedKeysFile .ssh/authorized_keys +PasswordAuthentication no +KbdInteractiveAuthentication no +UsePAM no +# Disable password authentication — keys only +PasswordAuthentication no +ChallengeResponseAuthentication no + + +AllowGroups sshusers +PrintMotd no +AcceptEnv LANG LC_* +ClientAliveCountMax 0 +ClientAliveInterval 300 +Port 22 + + +# Disable root login entirely +PermitRootLogin no + +# Limit authentication attempts +MaxAuthTries 3 +MaxSessions 3 + +# Use modern key exchange and ciphers, prioritize post-quantum algorithms (mlkem and sntrup) +KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com \ No newline at end of file diff --git a/roles/basic_postinstall_/files/install_omz.sh b/roles/basic_postinstall_/files/install_omz.sh new file mode 100644 index 0000000..e0e5f8d --- /dev/null +++ b/roles/basic_postinstall_/files/install_omz.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +FILE=/home/$USER/.oh-my-zsh/oh-my-zsh.sh +if [ -f "$FILE" ]; then + echo "$FILE exists and we not installing ohmyzsh" + exit 0 +else + echo "$FILE does not exist and we install ohmyzsh" + cd /home/max + wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh + chmod +x /home/max/install.sh + timeout -s 15 -k 30s 20s /home/max/install.sh --unattendend --keep-zshrc || exit 0 + exit 0 +fi + diff --git a/roles/basic_postinstall_/tasks/create_new_user.yaml b/roles/basic_postinstall_/tasks/create_new_user.yaml new file mode 100644 index 0000000..8ba891b --- /dev/null +++ b/roles/basic_postinstall_/tasks/create_new_user.yaml @@ -0,0 +1,66 @@ +--- +- name: Create a new user with a password, set shell + remote_user: ansible + ansible.builtin.user: + name: max + groups: sshusers,sudo + password: "{{ user_passwd_hash }}" + shell: /bin/zsh + +- name: Set authorized key taken from file + remote_user: ansible + ansible.posix.authorized_key: + user: max + state: present + key: "{{ lookup('file', lookup('env', 'HOME') + '/.ssh/ansible_key.pub') }}" + +- name: Copy omz installation wrapper script to the target machine + remote_user: ansible + ansible.builtin.copy: + src: "{{ role_path }}/files/install_omz.sh" + dest: /home/max/install_omz.sh + owner: max + group: max + mode: u=rwx,g=r,o-rwx + +# WARNING: UNPRIVILEGED USER (not ansible) COMMANDS +- name: Install oh my zsh + remote_user: max + become: false + ansible.builtin.command: /home/max/install_omz.sh + changed_when: true + +- name: Configure oh my zsh, by pushing the config file + remote_user: ansible + ansible.builtin.copy: + src: "{{ role_path }}/files/.zshrc" + dest: /home/max/.zshrc + owner: max + group: max + mode: u=rw,g=r,o-rwx + +- name: Configure vim, by pushing the config + remote_user: ansible + ansible.builtin.copy: + src: "{{ role_path }}/files/.vimrc" + dest: /home/max/.vimrc + owner: max + group: max + mode: u=rw,g=r,o-rwx + + +# WARNING: we've finished with the initial setup, drop ansible key +# Push regular user key +- name: Set authorized key taken from file + remote_user: ansible + ansible.posix.authorized_key: + user: max + state: absent + key: "{{ lookup('file', lookup('env', 'HOME') + '/.ssh/ansible_key.pub') }}" + +- name: Set authorized key taken from file + remote_user: ansible + ansible.posix.authorized_key: + user: max + state: present + key: "{{ lookup('file', lookup('env', 'HOME') + '/.ssh/max_regular_key.pub') }}" diff --git a/roles/basic_postinstall_/tasks/harden_ssh.yaml b/roles/basic_postinstall_/tasks/harden_ssh.yaml new file mode 100644 index 0000000..a1486dd --- /dev/null +++ b/roles/basic_postinstall_/tasks/harden_ssh.yaml @@ -0,0 +1,36 @@ +--- + +- name: Configure ssh-server daemon + ansible.builtin.copy: + src: "{{ role_path }}/files/hardened_sshd.conf" + dest: /etc/ssh/sshd_config.d/hardened_sshd.conf + mode: u=rw,g=r,o=r + when: ansible_facts['distribution'] == 'Ubuntu' + +- name: Configure ssh-server daemon + ansible.builtin.copy: + src: "{{ role_path }}/files/hardened_sshd.conf" + dest: /etc/ssh/sshd_config.d/hardened_sshd.conf + mode: u=rw,g=r,o=r + when: ansible_facts['distribution'] == 'Debian' + +- name: Configure ssh client + remote_user: ansible + ansible.builtin.copy: + src: "{{ role_path }}/files/hardened_ssh.conf" + dest: /etc/ssh/ssh_config.d/hardened_ssh.conf + mode: u=rw,g=r,o=r + +- name: Restart ssh-server Debian + remote_user: ansible + ansible.builtin.service: + name: sshd + state: restarted + when: ansible_facts['distribution'] == 'Debian' + +- name: Restart ssh-server Ubuntu + remote_user: ansible + ansible.builtin.service: + name: ssh + state: restarted + when: ansible_facts['distribution'] == 'Ubuntu' diff --git a/roles/basic_postinstall_/tasks/install_basic_utils.yaml b/roles/basic_postinstall_/tasks/install_basic_utils.yaml new file mode 100644 index 0000000..5a6ed89 --- /dev/null +++ b/roles/basic_postinstall_/tasks/install_basic_utils.yaml @@ -0,0 +1,42 @@ +--- +- name: Installing basic utils for comfort work (apt-based system) + when: (ansible_facts['distribution'] == "Debian") or + (ansible_facts['distribution'] == "Ubuntu") + ansible.builtin.apt: + name: + - vim + - ranger + - zsh + - rsync + - git + - curl + - kitty + - unattended-upgrades + - ssh + - openssh-server + update-cache: true # Run apt update before installation + become: true + remote_user: ansible + +- name: Install qemu-guest-agent on VM + when: + - ansible_facts['os_family'] == "Debian" + - ansible_facts['virtualization_type'] == "kvm" + ansible.builtin.apt: + name: qemu-guest-agent + state: present + update-cache: true # Run apt update before installation + become: true + remote_user: ansible + tags: + - kvm-guests + - packages + + +# The same commands for Alpine +- name: Update and install packages on Alpine + when: (ansible_facts['distribution'] == "Alpine") + community.general.apk: + name: vim ranger zsh rsync git curl kitty openssh + update_cache: true + remote_user: ansible diff --git a/roles/basic_postinstall_/tasks/main.yaml b/roles/basic_postinstall_/tasks/main.yaml new file mode 100644 index 0000000..b886049 --- /dev/null +++ b/roles/basic_postinstall_/tasks/main.yaml @@ -0,0 +1,18 @@ +--- +- name: Create and set up Ansible user and environment + ansible.builtin.include_tasks: prepare_ansible_user.yaml + +- name: Improve SSH configuration + ansible.builtin.include_tasks: harden_ssh.yaml + +- name: Install basic utils + ansible.builtin.include_tasks: install_basic_utils.yaml + +- name: Remove unnecessary packages + ansible.builtin.include_tasks: remove_packages.yaml + +- name: Create and set up a new user + ansible.builtin.include_tasks: create_new_user.yaml + +- name: Set locale and time + ansible.builtin.include_tasks: set_locale_and_time.yaml diff --git a/roles/basic_postinstall_/tasks/prepare_ansible_user.yaml b/roles/basic_postinstall_/tasks/prepare_ansible_user.yaml new file mode 100644 index 0000000..2097ae9 --- /dev/null +++ b/roles/basic_postinstall_/tasks/prepare_ansible_user.yaml @@ -0,0 +1,41 @@ +--- +## Installing packages +- name: Install sudo on apt systems + when: (ansible_facts['distribution'] == "Debian") or + (ansible_facts['distribution'] == "Ubuntu") + ansible.builtin.apt: + name: + - sudo + update-cache: true + +# The same commands for Alpine +- name: Update and install packages on Alpine + when: (ansible_facts['distribution'] == "Alpine") + community.general.apk: + name: sudo + update_cache: true + remote_user: ansible + + +## Creating and setting up the ansible user +## First, create sshusers group to grant ssh access +- name: Ensure group "sshusers" exists + ansible.builtin.group: + name: sshusers + state: present + +## Add the user to sshusers (for ssh access) and sudo (gain root access) +- name: Create a new user with a password for Ansible + ansible.builtin.user: + name: ansible + password: "{{ ansible_user_passwd_hash }}" + + groups: sshusers,sudo + append: true + +## Since password authentication in SSH will be disabled, we need to add an authorized key +- name: Set authorized key taken from file + ansible.posix.authorized_key: + user: ansible + state: present + key: "{{ ansible_ssh_key }}" diff --git a/roles/basic_postinstall_/tasks/remove_packages.yaml b/roles/basic_postinstall_/tasks/remove_packages.yaml new file mode 100644 index 0000000..c0116fd --- /dev/null +++ b/roles/basic_postinstall_/tasks/remove_packages.yaml @@ -0,0 +1,31 @@ +--- +# Remove multiple packages at once +- name: Remove unnecessary packages + remote_user: ansible + when: (ansible_facts['distribution'] == "Debian") or + (ansible_facts['distribution'] == "Ubuntu") + ansible.builtin.apt: + name: + - nano + state: absent + become: true + + +# Clean up all orphaned packages +- name: Remove all orphaned dependencies + remote_user: ansible + when: (ansible_facts['distribution'] == "Debian") or + (ansible_facts['distribution'] == "Ubuntu") + ansible.builtin.apt: + autoremove: true + purge: true + + +- name: Install sudo package on Alpine + remote_user: ansible + when: (ansible_facts['distribution'] == "Alpine") + community.general.apk: + name: + - nano + state: absent + become: true diff --git a/roles/basic_postinstall_/tasks/set_locale_and_time.yaml b/roles/basic_postinstall_/tasks/set_locale_and_time.yaml new file mode 100644 index 0000000..37eb4f6 --- /dev/null +++ b/roles/basic_postinstall_/tasks/set_locale_and_time.yaml @@ -0,0 +1,19 @@ +--- +- name: Generate locales + community.general.locale_gen: + name: + - en_US.UTF-8 + - ru_RU.UTF-8 + state: present + +- name: Set locale + ansible.builtin.copy: + dest: /etc/locale.conf + mode: '0644' + content: | + LANG=en_US.UTF-8 + LC_ALL=en_US.UTF-8 + +- name: Set time + community.general.timezone: + name: Europe/Samara