refactor: restructured project for higher-utility naming practices and optimized data structures for variables
This commit is contained in:
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
collections:
|
|
||||||
- name: community.general
|
|
||||||
version: "11.2.1"
|
|
||||||
source: "https://galaxy.ansible.com"
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
Match Group ftp
|
|
||||||
ForceCommand internal-sftp -u 003 -d /%u
|
|
||||||
AuthorizedKeysFile /srv/.ftp/authorized_keys
|
|
||||||
ChrootDirectory /srv/ftp
|
|
||||||
PasswordAuthentication no
|
|
||||||
AllowAgentForwarding no
|
|
||||||
AllowTcpForwarding no
|
|
||||||
X11Forwarding no
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#SPDX-License-Identifier: MIT-0
|
|
||||||
---
|
|
||||||
# defaults file for lockdown
|
|
||||||
files_mode: no
|
|
||||||
create_users:
|
|
||||||
- username: "{{ hostvars[inventory_hostname]['passwords'][0].username }}"
|
|
||||||
password: "{{ hostvars[inventory_hostname]['passwords'][0].password }}"
|
|
||||||
ssh_pubkey_filename_pattern: '.*\.pub'
|
|
||||||
include_root_lock: yes
|
|
||||||
gpg_private_keys_origin_host: localhost
|
|
||||||
ssh_keypairs_origin_host: localhost
|
|
||||||
gpg_origin_private_keyids: [] # @NOTE list of gpg key ids from origin or source server
|
|
||||||
gpg_origin_private_key_passwords: "{{ vaulted_gpg_origin_private_key_passwords }}" # @NOTE list of gpg key passwords from origin or source server
|
|
||||||
ssh_origin_keypairs_filenames: [] # @NOTE list of basenames (filename sans extension) of SSH keypairs
|
|
||||||
git_config_name: ~ # @NOTE: has equivalent field under lockdown role vars example YAML file, but different value
|
|
||||||
git_config_email: ~ # @NOTE: has equivalent field under lockdown role vars example YAML file, but different value
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/usr/bin/bash
|
|
||||||
# ssh aliases
|
|
||||||
alias ssh_send="scp -C"
|
|
||||||
# @NOTE consider adding aliases for scp source or destination hosts
|
|
||||||
|
|
||||||
# flatpak aliases
|
|
||||||
alias clone="rsync -pogAXtlHrDx --stats --info=progress2"
|
|
||||||
alias flatshell="flatpak run --user --command=sh"
|
|
||||||
alias codium="flatpak run --user com.vscodium.codium"
|
|
||||||
|
|
||||||
# podman aliases
|
|
||||||
alias docker="podman"
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/bash
|
|
||||||
# podman bash function
|
|
||||||
conman () {
|
|
||||||
if command -v podman &> /dev/null; then
|
|
||||||
CONTAINER_MANAGER="podman"
|
|
||||||
elif command -v docker &> /dev/null; then
|
|
||||||
CONTAINER_MANAGER="docker"
|
|
||||||
else
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
$CONTAINER_MANAGER
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
Host local
|
|
||||||
HostName localhost
|
|
||||||
Port 22
|
|
||||||
# IdentitiesOnly yes
|
|
||||||
# IdentityFile ~/.ssh/*.ppk
|
|
||||||
# AddKeysToAgent yes
|
|
||||||
|
|
||||||
Host local.me
|
|
||||||
HostName localhost
|
|
||||||
Port 22
|
|
||||||
# User admin
|
|
||||||
# IdentitiesOnly yes
|
|
||||||
# IdentityFile ~/.ssh/*.ppk
|
|
||||||
# AddKeysToAgent yes
|
|
||||||
|
|
||||||
Host *.local.local
|
|
||||||
HostName localhost
|
|
||||||
# IdentitiesOnly yes
|
|
||||||
# IdentityFile ~/.ssh/*.ppk
|
|
||||||
# AddKeysToAgent yes
|
|
||||||
|
|
||||||
Host ip4.local.local
|
|
||||||
# HostName 127.0.0.1
|
|
||||||
Port 22
|
|
||||||
AddressFamily inet
|
|
||||||
|
|
||||||
Host ip6.local.local
|
|
||||||
# HostName ::1
|
|
||||||
Port 22
|
|
||||||
AddressFamily inet6
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
PasswordAuthentication no
|
|
||||||
PermitEmptyPasswords no
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
PermitRootLogin no
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# This file is written by xdg-user-dirs-update
|
|
||||||
# If you want to change or add directories, just edit the line you're
|
|
||||||
# interested in. All local changes will be retained on the next run.
|
|
||||||
# Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped
|
|
||||||
# homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an
|
|
||||||
# absolute path. No other format is supported.
|
|
||||||
#
|
|
||||||
XDG_DESKTOP_DIR="$HOME/Desktop"
|
|
||||||
XDG_DOWNLOAD_DIR="$HOME/Downloads"
|
|
||||||
XDG_TEMPLATES_DIR="$HOME/Templates"
|
|
||||||
XDG_PUBLICSHARE_DIR="$HOME/Public"
|
|
||||||
XDG_DOCUMENTS_DIR="$HOME/Documents"
|
|
||||||
XDG_MUSIC_DIR="$HOME/Music"
|
|
||||||
XDG_PICTURES_DIR="$HOME/Pictures"
|
|
||||||
XDG_VIDEOS_DIR="$HOME/Videos"
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# SPDX-License-Identifier: MIT-0
|
|
||||||
---
|
|
||||||
# handlers file for lockdown
|
|
||||||
- name: Restart SSH server
|
|
||||||
when: ansible_facts["user_id"] == "root"
|
|
||||||
ansible.builtin.service:
|
|
||||||
name: ssh
|
|
||||||
state: restarted
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- finalize
|
|
||||||
register: restarted_ssh
|
|
||||||
listen: "restart ssh"
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# SPDX-License-Identifier: MIT-0
|
|
||||||
---
|
|
||||||
# tasks file for lockdown
|
|
||||||
- name: Disable shell for root user
|
|
||||||
when: ansible_facts["user_id"] != "root"
|
|
||||||
become: true
|
|
||||||
ansible.builtin.user:
|
|
||||||
name: root
|
|
||||||
shell: /sbin/nologin
|
|
||||||
tags:
|
|
||||||
- deshell_root
|
|
||||||
register: root_shell_disabled
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
# 'preferred_signing_key' -> 'gpg_preferred_signing'
|
|
||||||
# 'gpg_or_ssh_git_signing' -> 'git_signing_key_type'
|
|
||||||
- name: Install git package
|
|
||||||
ansible.builtin.package:
|
|
||||||
name: git
|
|
||||||
state: latest
|
|
||||||
- name: Configure git name and email
|
|
||||||
block:
|
|
||||||
- name: Configure git name
|
|
||||||
community.general.git_config:
|
|
||||||
name: user.name
|
|
||||||
scope: global
|
|
||||||
state: present
|
|
||||||
value: "{{ git_config_name }}"
|
|
||||||
- name: Configure git email
|
|
||||||
community.general.git_config:
|
|
||||||
name: user.email
|
|
||||||
scope: global
|
|
||||||
state: present
|
|
||||||
value: "{{ git_config_email }}"
|
|
||||||
- name: Configure git signing GPG key
|
|
||||||
when: git_signing_key_type == "gpg"
|
|
||||||
block:
|
|
||||||
- name: Configure specified git signing GPG key
|
|
||||||
when: preferred_signing_key > -1
|
|
||||||
community.general.git_config:
|
|
||||||
name: user.signingkey
|
|
||||||
scope: global
|
|
||||||
state: present
|
|
||||||
value: "{{ gpg_origin_private_keyids[preferred_signing_key] }}"
|
|
||||||
register: selected_signing_key
|
|
||||||
- name: Configure random git signing GPG key
|
|
||||||
when: preferred_signing_key <= -1
|
|
||||||
community.general.git_config:
|
|
||||||
name: user.signingkey
|
|
||||||
scope: global
|
|
||||||
state: present
|
|
||||||
value: "{{ gpg_origin_private_keyids | random }}"
|
|
||||||
register: selected_signing_key
|
|
||||||
- name: Configure git signing SSH key
|
|
||||||
when: git_signing_key_type == "ssh"
|
|
||||||
block:
|
|
||||||
- name: Acquire SSH key-pairs from other system
|
|
||||||
when: not files_mode
|
|
||||||
block:
|
|
||||||
- name: Acquire private SSH keys from other system
|
|
||||||
delegate_to: "{{ ssh_keypairs_origin_host }}"
|
|
||||||
ansible.builtin.command:
|
|
||||||
argv:
|
|
||||||
- cat
|
|
||||||
- "~/.ssh/{{ item }}.ppk"
|
|
||||||
loop: "{{ ssh_origin_keypairs_filenames }}"
|
|
||||||
register: ssh_secrets
|
|
||||||
- name: Find SSH public keys in other system
|
|
||||||
delegate_to: "{{ ssh_keypairs_origin_host }}"
|
|
||||||
ansible.builtin.command:
|
|
||||||
argv:
|
|
||||||
- cat
|
|
||||||
- "~/.ssh/{{ item }}.pub"
|
|
||||||
loop: "{{ ssh_origin_keypairs_filenames }}"
|
|
||||||
register: ssh_nonsecrets
|
|
||||||
- name: Create private SSH keys
|
|
||||||
ansible.builtin.copy:
|
|
||||||
content: "{{ item }}"
|
|
||||||
dest: "{{ ansible_facts['user_dir'] }}/.ssh/{{ ssh_origin_keypairs_filenames[idx] }}.ppk"
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0600"
|
|
||||||
state: present
|
|
||||||
loop: "{{ ssh_secrets.results }}"
|
|
||||||
loop_control:
|
|
||||||
index_var: idx
|
|
||||||
register: created_ssh_private_keys
|
|
||||||
- name: Create public SSH keys
|
|
||||||
ansible.builtin.copy:
|
|
||||||
content: "{{ item }}"
|
|
||||||
dest: "{{ ansible_facts['user_dir'] }}/.ssh/{{ ssh_origin_keypairs_filenames[idx] }}.pub"
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0644"
|
|
||||||
state: present
|
|
||||||
loop: "{{ ssh_nonsecrets.results }}"
|
|
||||||
loop_control:
|
|
||||||
index_var: idx
|
|
||||||
register: created_ssh_public_keys
|
|
||||||
- name: Acquire SSH key-pairs
|
|
||||||
when: files_mode
|
|
||||||
block:
|
|
||||||
- name: Transfer private SSH keys
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: ssh/{{ ansible_facts['user_id'] }}/{{ item }}.ppk
|
|
||||||
dest: "{{ ansible_facts['user_dir'] }}/.ssh/{{ item }}.ppk"
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0600"
|
|
||||||
state: present
|
|
||||||
loop: "{{ ssh_origin_keypairs_filenames }}"
|
|
||||||
loop_control:
|
|
||||||
index_var: idx
|
|
||||||
register: created_ssh_private_keys
|
|
||||||
- name: Transfer public SSH keys
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: ssh/{{ ansible_facts['user_id'] }}/{{ item }}.pub
|
|
||||||
dest: "{{ ansible_facts['user_dir'] }}/.ssh/{{ item }}.pub"
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0644"
|
|
||||||
state: present
|
|
||||||
loop: "{{ ssh_origin_keypairs_filenames }}"
|
|
||||||
loop_control:
|
|
||||||
index_var: idx
|
|
||||||
register: created_ssh_public_keys
|
|
||||||
- name: Configure acquired, specified SSH public key as git signing key
|
|
||||||
when: preferred_signing_key > -1
|
|
||||||
community.general.git_config:
|
|
||||||
name: user.signingkey
|
|
||||||
scope: global
|
|
||||||
state: present
|
|
||||||
value: "{{ created_ssh_public_keys.results[preferred_signing_key] }}"
|
|
||||||
register: selected_signing_key
|
|
||||||
- name: Configure acquired, random SSH public key as git signing key
|
|
||||||
when: preferred_signing_key <= -1
|
|
||||||
community.general.git_config:
|
|
||||||
name: user.signingkey
|
|
||||||
scope: global
|
|
||||||
state: present
|
|
||||||
value: "{{ created_ssh_public_keys.results | random }}"
|
|
||||||
register: selected_signing_key
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Acquire GPG private keys from other system
|
|
||||||
when: not files_mode
|
|
||||||
block:
|
|
||||||
- name: Acquire GPG private keys' contents from other system
|
|
||||||
delegate_to: "{{ gpg_private_keys_origin_host }}"
|
|
||||||
ansible.builtin.command:
|
|
||||||
argv:
|
|
||||||
- gpg
|
|
||||||
- -a
|
|
||||||
- --export-secret-key
|
|
||||||
- "{{ item }}"
|
|
||||||
loop: "{{ gpg_origin_private_keyids }}"
|
|
||||||
register: gpg_secrets
|
|
||||||
- name: Create GPG private keys using acquired GPG private keys' contents
|
|
||||||
ansible.builtin.copy:
|
|
||||||
content: "{{ item }}"
|
|
||||||
dest: "{{ ansible_facts['user_dir'] }}/.gnupg/{{ gpg_origin_private_keyids[idx] }}.priv.asc"
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0600"
|
|
||||||
state: present
|
|
||||||
loop: "{{ gpg_secrets.results }}"
|
|
||||||
loop_control:
|
|
||||||
index_var: idx
|
|
||||||
register: created_gpg_private_keys
|
|
||||||
- name: Acquire GPG private keys
|
|
||||||
when: files_mode
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: gnupg/{{ ansible_facts['user_id'] }}/{{ item }}.asc
|
|
||||||
dest: "{{ ansible_facts['user_dir'] }}/.gnupg/{{ item }}.priv.asc"
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0600"
|
|
||||||
state: present
|
|
||||||
loop: "{{ gpg_origin_private_keyids }}"
|
|
||||||
loop_control:
|
|
||||||
index_var: idx
|
|
||||||
register: created_gpg_private_keys
|
|
||||||
- name: Import GPG private keys
|
|
||||||
when: (gpg_origin_private_key_passwords | length) == (gpg_origin_private_keyids | length)
|
|
||||||
ansible.builtin.command:
|
|
||||||
argv:
|
|
||||||
- gpg
|
|
||||||
- --batch
|
|
||||||
- --import
|
|
||||||
- --yes
|
|
||||||
- --passphrase-fd
|
|
||||||
- 0
|
|
||||||
- "{{ item.dest }}"
|
|
||||||
stdin: "{{ gpg_origin_private_key_passwords[idx] }}"
|
|
||||||
loop: "{{ created_gpg_private_keys.results }}"
|
|
||||||
loop_control:
|
|
||||||
index_var: idx
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
# SPDX-License-Identifier: MIT-0
|
|
||||||
---
|
|
||||||
# tasks file for lockdown
|
|
||||||
# @NOTE: assumes one logged in to SSH server as root to begin with, hence no need for privilege escalation
|
|
||||||
- name: Create users
|
|
||||||
when: ansible_facts["user_id"] == "root"
|
|
||||||
block:
|
|
||||||
- name: Create sys-admin user
|
|
||||||
ansible.builtin.user:
|
|
||||||
name: "{{ create_users[0].username }}"
|
|
||||||
uid: 1000
|
|
||||||
password: "{{ create_users[0].password }}"
|
|
||||||
append: yes
|
|
||||||
groups:
|
|
||||||
- sudo
|
|
||||||
shell: /bin/bash
|
|
||||||
generate_ssh_key: yes
|
|
||||||
password_expire_min: 93
|
|
||||||
password_expire_max: 186
|
|
||||||
password_expire_warn: 45
|
|
||||||
comment: sysadmin
|
|
||||||
# ssh_key_passphrase: "{{ item.password }}"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- administrative_user
|
|
||||||
register: created_admin
|
|
||||||
- name: Create new user
|
|
||||||
ansible.builtin.user:
|
|
||||||
name: "{{ item.username }}"
|
|
||||||
uid: 1000
|
|
||||||
password: "{{ item.password }}"
|
|
||||||
append: yes
|
|
||||||
shell: /bin/bash
|
|
||||||
generate_ssh_key: yes
|
|
||||||
password_expire_min: 93
|
|
||||||
password_expire_max: 186
|
|
||||||
password_expire_warn: 45
|
|
||||||
comment: administrator
|
|
||||||
# ssh_key_passphrase: "{{ item.password }}"
|
|
||||||
state: present
|
|
||||||
loop: "{{ create_users[1:] }}"
|
|
||||||
tags:
|
|
||||||
- other_users
|
|
||||||
register: created_users
|
|
||||||
- name: Specify authorized SSH keys for users based on local public keys
|
|
||||||
when: not files_mode and ansible_facts["user_id"] == "root"
|
|
||||||
block:
|
|
||||||
- name: Acquire list of SSH public keys for sys-admin user
|
|
||||||
delegate_to: "{{ ssh_keypairs_origin_host }}"
|
|
||||||
ansible.builtin.find:
|
|
||||||
paths: "{{ lookup('env', 'HOME') }}/.ssh"
|
|
||||||
patterns:
|
|
||||||
- '{{ ssh_pubkey_filename_pattern }}'
|
|
||||||
use_regex: yes
|
|
||||||
recurse: no
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- administrative_user
|
|
||||||
- admin_ssh
|
|
||||||
register: ssh_public_keys
|
|
||||||
- name: Acquire contents of SSH public keys for sys-admin user
|
|
||||||
delegate_to: "{{ ssh_keypairs_origin_host }}"
|
|
||||||
ansible.builtin.command:
|
|
||||||
argv:
|
|
||||||
- cat
|
|
||||||
- "{{ item.path }}"
|
|
||||||
loop: "{{ ssh_public_keys.files }}"
|
|
||||||
register: ssh_public_keys_contents
|
|
||||||
- name: Register SSH public keys as sys-admin user's authorized keys
|
|
||||||
ansible.builtin.lineinfile:
|
|
||||||
path: "{{ created_admin.home }}/.ssh/authorized_keys"
|
|
||||||
line: "{{ item }}"
|
|
||||||
owner: "{{ created_admin.name }}"
|
|
||||||
group: "{{ created_admin.name }}"
|
|
||||||
mode: "0600"
|
|
||||||
create: yes
|
|
||||||
insertafter: EOF
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- administrative_user
|
|
||||||
- admin_ssh
|
|
||||||
loop: "{{ ssh_public_keys_contents.results }}"
|
|
||||||
- name: Register SSH public keys as other users' authorized keys
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "ssh/{{ item.name }}/authorized_keys"
|
|
||||||
dest: "{{ item.home }}/.ssh/authorized_keys"
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
owner: "{{ item.name }}"
|
|
||||||
group: "{{ item.name }}"
|
|
||||||
mode: "0600"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- other_users
|
|
||||||
- others_ssh
|
|
||||||
loop: "{{ created_users.results }}"
|
|
||||||
register: authorized_ssh_pubkeys
|
|
||||||
- name: Specify authorized SSH keys for users
|
|
||||||
when: files_mode and ansible_facts["user_id"] == "root"
|
|
||||||
block:
|
|
||||||
- name: Specify authorized keys file for sys-admin user
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: ssh/authorized_keys
|
|
||||||
dest: "{{ created_admin.home }}/.ssh/authorized_keys"
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
owner: "{{ created_admin.name }}"
|
|
||||||
group: "{{ created_admin.name }}"
|
|
||||||
mode: "0600"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- administrative_user
|
|
||||||
- admin_ssh
|
|
||||||
register: authorized_admin_ssh_pubkeys
|
|
||||||
- name: Specify authorized keys file for other users
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "ssh/{{ item.name }}/authorized_keys"
|
|
||||||
dest: "{{ item.home }}/.ssh/authorized_keys"
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
owner: "{{ item.name }}"
|
|
||||||
group: "{{ item.name }}"
|
|
||||||
mode: "0600"
|
|
||||||
tags:
|
|
||||||
- other_users
|
|
||||||
- others_ssh
|
|
||||||
loop: "{{ created_users.results }}"
|
|
||||||
register: authorized_ssh_pubkeys
|
|
||||||
- name: Lock down root SSH access
|
|
||||||
when: ansible_facts["user_id"] == "root"
|
|
||||||
block:
|
|
||||||
- name: Constrain SSH authentication methods to using SSH key
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: sshd_config.d/auth.conf
|
|
||||||
dest: /etc/ssh/sshd_config.d/auth.conf
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0644"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- depass_root
|
|
||||||
register: constrained_auth
|
|
||||||
- name: Prohibit access to root via SSH
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: sshd_config.d/denyroot.conf
|
|
||||||
dest: /etc/ssh/sshd_config.d/denyroot.conf
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: "0644"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- prohib_root_ssh
|
|
||||||
register: prohibited_root_ssh_login
|
|
||||||
- name: Lock the root account
|
|
||||||
when: include_root_lock
|
|
||||||
ansible.builtin.user:
|
|
||||||
name: root
|
|
||||||
password_lock: yes
|
|
||||||
tags:
|
|
||||||
- delog_root
|
|
||||||
register: prohibited_root_login
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- deroot
|
|
||||||
notify: "restart ssh"
|
|
||||||
71
.gitignore
vendored
71
.gitignore
vendored
@@ -1,65 +1,10 @@
|
|||||||
/.env/
|
.env/
|
||||||
/.tmp/
|
|
||||||
rika/
|
|
||||||
senpai/
|
|
||||||
.galaxy_cache/
|
|
||||||
/galaxy_token
|
|
||||||
.ansible/log.txt
|
|
||||||
.ansible/facts/
|
|
||||||
.ansible/collections/ansible_collections/
|
|
||||||
*.bak
|
*.bak
|
||||||
|
|
||||||
group_vars/**/main.yml
|
|
||||||
host_vars/**/main.yml
|
|
||||||
**/group_vars/**/main.yml
|
|
||||||
**/host_vars/**/main.yml
|
|
||||||
group_vars/**/vault.yml
|
|
||||||
host_vars/**/vault.yml
|
|
||||||
**/group_vars/**/vault.yml
|
|
||||||
**/host_vars/**/vault.yml
|
|
||||||
|
|
||||||
.ansible/roles/**/vars/*
|
|
||||||
playbooks/vars/ssh_keys_vault.yml
|
|
||||||
playbooks/vars/ssh_keys.yml
|
|
||||||
**/playbooks/vars/ssh_keys_vault.yml
|
|
||||||
**/playbooks/vars/ssh_keys.yml
|
|
||||||
playbooks/vars/main.yml
|
|
||||||
playbooks/vars/vault.yml
|
|
||||||
**/playbooks/vars/main.yml
|
|
||||||
**/playbooks/vars/vault.yml
|
|
||||||
|
|
||||||
files/**/**/config
|
|
||||||
**/files/**/**/config
|
|
||||||
files/**/**/authorized_keys
|
|
||||||
**/files/**/**/authorized_keys
|
|
||||||
files/**/**/*.conf
|
|
||||||
**/files/**/**/*.conf
|
|
||||||
files/**/**/*.dirs
|
|
||||||
**/files/**/**/*.dirs
|
|
||||||
files/**/**/*.defaults
|
|
||||||
**/files/**/**/*.defaults
|
|
||||||
files/**/**/bash_aliases
|
|
||||||
**/files/**/**/bash_aliases
|
|
||||||
files/**/**/bash_functions
|
|
||||||
**/files/**/**/bash_functions
|
|
||||||
|
|
||||||
templates/**/**/config
|
|
||||||
**/templates/**/**/config
|
|
||||||
templates/**/**/authorized_keys
|
|
||||||
**/templates/**/**/authorized_keys
|
|
||||||
templates/**/**/*.conf
|
|
||||||
**/templates/**/**/*.conf
|
|
||||||
templates/**/**/*.dirs
|
|
||||||
**/templates/**/**/*.dirs
|
|
||||||
templates/**/**/*.defaults
|
|
||||||
**/templates/**/**/*.defaults
|
|
||||||
templates/**/**/bash_aliases
|
|
||||||
**/templates/**/**/bash_aliases
|
|
||||||
templates/**/**/bash_functions
|
|
||||||
**/templates/**/**/bash_functions
|
|
||||||
|
|
||||||
hosts.ini
|
|
||||||
hosts.yml
|
hosts.yml
|
||||||
hosts.yaml
|
.secrets/*
|
||||||
hosts.json
|
**/*.key
|
||||||
vault.yml
|
**/*.gpg
|
||||||
|
**/*.asc
|
||||||
|
**/*.pem
|
||||||
|
**/*.ppk
|
||||||
|
log.txt
|
||||||
@@ -54,7 +54,7 @@ fact_caching_connection=.ansible/facts
|
|||||||
|
|
||||||
# (pathspec) Colon separated paths in which Ansible will search for collections content. Collections must be in nested *subdirectories*, not directly in these directories. For example, if ``COLLECTIONS_PATHS`` includes ``'{{ ANSIBLE_HOME ~ "/collections" }}'``, and you want to add ``my.collection`` to that directory, it must be saved as ``'{{ ANSIBLE_HOME} ~ "/collections/ansible_collections/my/collection" }}'``.
|
# (pathspec) Colon separated paths in which Ansible will search for collections content. Collections must be in nested *subdirectories*, not directly in these directories. For example, if ``COLLECTIONS_PATHS`` includes ``'{{ ANSIBLE_HOME ~ "/collections" }}'``, and you want to add ``my.collection`` to that directory, it must be saved as ``'{{ ANSIBLE_HOME} ~ "/collections/ansible_collections/my/collection" }}'``.
|
||||||
|
|
||||||
collections_path=collections:.ansible/collections:/usr/share/ansible/collections
|
collections_path=.ansible/collections:collections:/usr/share/collections:/etc/ansible/collections
|
||||||
|
|
||||||
# (boolean) A boolean to enable or disable scanning the sys.path for installed collections
|
# (boolean) A boolean to enable or disable scanning the sys.path for installed collections
|
||||||
;collections_scan_sys_path=True
|
;collections_scan_sys_path=True
|
||||||
@@ -223,7 +223,7 @@ netconf_plugins=plugins/netconf:.ansible/netconf:/usr/share/ansible/plugins/netc
|
|||||||
;remote_user=
|
;remote_user=
|
||||||
|
|
||||||
# (pathspec) Colon separated paths in which Ansible will search for Roles.
|
# (pathspec) Colon separated paths in which Ansible will search for Roles.
|
||||||
roles_path=roles:.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
|
roles_path=.ansible/roles:roles:/usr/share/ansible/roles:/etc/ansible/roles
|
||||||
|
|
||||||
# (string) Set the main callback used to display Ansible output. You can only have one at a time.
|
# (string) Set the main callback used to display Ansible output. You can only have one at a time.
|
||||||
# You can have many other callbacks, but just one can be in charge of stdout.
|
# You can have many other callbacks, but just one can be in charge of stdout.
|
||||||
@@ -357,7 +357,7 @@ host_key_checking=False
|
|||||||
;old_plugin_cache_clear=False
|
;old_plugin_cache_clear=False
|
||||||
|
|
||||||
# (path) A number of non-playbook CLIs have a ``--playbook-dir`` argument; this sets the default value for it.
|
# (path) A number of non-playbook CLIs have a ``--playbook-dir`` argument; this sets the default value for it.
|
||||||
playbook_dir=playbooks
|
playbook_dir=playbooks:/etc/ansible/playbooks
|
||||||
|
|
||||||
# (string) This sets which playbook dirs will be used as a root to process vars plugins, which includes finding host_vars/group_vars
|
# (string) This sets which playbook dirs will be used as a root to process vars plugins, which includes finding host_vars/group_vars
|
||||||
;playbook_vars_root=top
|
;playbook_vars_root=top
|
||||||
|
|||||||
37
group_vars/all
Normal file
37
group_vars/all
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# vars file
|
||||||
|
custom_vars: ~
|
||||||
|
fqdn: ~
|
||||||
|
vps_service:
|
||||||
|
# @DOC <bool>
|
||||||
|
exists: true
|
||||||
|
# @DOC <vault<str>>
|
||||||
|
password: ~
|
||||||
|
# @DOC <vault<str>>
|
||||||
|
api_key: ~
|
||||||
|
# @DOC <str>
|
||||||
|
type: "linode"
|
||||||
|
# @DOC <str>
|
||||||
|
region: "us-east"
|
||||||
|
# @DOC <list<str>>
|
||||||
|
ssh_authorized_keys: []
|
||||||
|
# @DOC <str>
|
||||||
|
root_fate: disposal
|
||||||
|
# @DOC <list<str>>
|
||||||
|
keywords: []
|
||||||
|
groups:
|
||||||
|
sample_group:
|
||||||
|
group_name: ~
|
||||||
|
type: ~
|
||||||
|
users:
|
||||||
|
admin:
|
||||||
|
username: admin
|
||||||
|
password: "password123"
|
||||||
|
shell: /bin/bash
|
||||||
|
home: ~
|
||||||
|
admin: true
|
||||||
|
type: regular
|
||||||
|
group: ~
|
||||||
|
groups: [sudo]
|
||||||
|
ssh_authorized_keys:
|
||||||
129
host_vars/vps1
Normal file
129
host_vars/vps1
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# vars file
|
||||||
|
custom_vars:
|
||||||
|
generality:
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIO0sbFLwfgSWpWwn4cy4cddKvV74efUMZVYTTjX2vnjAAAABHNzaDo= rika@hikiki
|
||||||
|
- sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIHJqHHMplgqm8yiq4Qwisk67p9+f9sLM8tIAzuw2qkwpAAAABHNzaDo= rika@hikiki
|
||||||
|
ssh_private_key_paths:
|
||||||
|
- ~/.ssh/id_ed25519_sukaato_yubikey.ppk
|
||||||
|
- ~/.ssh/id_ed25519_sukaato_miniyubikey.ppk
|
||||||
|
fqdn: sukaato.moe
|
||||||
|
vps_service:
|
||||||
|
exists: true
|
||||||
|
password: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.2;AES256;vps1-root
|
||||||
|
39303536373434346134346536653462623164373265646430636330616666323437363365366364
|
||||||
|
3030303736323432636631306361313031376238356335350a653032376432333562663361623236
|
||||||
|
30313766633662656637623033313461633662303763306361313337623965396130616531323061
|
||||||
|
6538316265376536630a616330666430323631393035313933346332353939313833623666636164
|
||||||
|
61653264643933636666613665633461646336656337383730396262633239376439
|
||||||
|
api_key: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.2;AES256;vps1-api
|
||||||
|
36353161313366323930643037643637636664373266356433616632313766386161666663336366
|
||||||
|
3462666366646338616561643939333134666162616465320a376364363833653136366434633264
|
||||||
|
63643364626235666333363335656536396239646562393837343138653737346537316536303739
|
||||||
|
6565633730326234350a366435653637373061336162343134643431613034623761666264393134
|
||||||
|
61343062323933366235356132376366636534343530316432336265316632393531303161316632
|
||||||
|
64323431666361303137313937316631393266643961613863643035333237613931343533303537
|
||||||
|
66643166303733333761313566343030343762306633613733613762386339653663323730666637
|
||||||
|
38663634383531633838
|
||||||
|
type: "linode"
|
||||||
|
region: "us-east"
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNoC2Z4oLDEEeX7SmRpUlyXVQ+uJg3ZdjMaDONzJtMuZa9/bVzAByiNTXM0yYzas/lFLpOKh3tUw8NCS+3QMjkIAAAAEc3NoOg== rika@hikiki
|
||||||
|
- sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBDJjW/BGw3Rkr7pB69hwGGCD3poBWMRLPdUlrTjYqP/Lam5FZATRlzpDbCyub0tgBZwWIiGGvS88XWosESk2lToAAAAEc3NoOg== rika@hikiki
|
||||||
|
root_fate: disposal
|
||||||
|
ssh_private_key_paths:
|
||||||
|
- ~/.ssh/id_ecdsa-sha2_sukaato_yubikey.ppk
|
||||||
|
- ~/.ssh/id_ecdsa-sha2_sukaato_miniyubikey.ppk
|
||||||
|
ssh_private_key_path_pref: 0
|
||||||
|
keywords:
|
||||||
|
- social media
|
||||||
|
- internet
|
||||||
|
- chat
|
||||||
|
- web
|
||||||
|
- cloud
|
||||||
|
- "file-share"
|
||||||
|
- stream
|
||||||
|
groups:
|
||||||
|
# @NOTE key/field names SHOULD match value of 'group_name' key or field of its object
|
||||||
|
remote:
|
||||||
|
group_name: remote
|
||||||
|
type: system
|
||||||
|
users:
|
||||||
|
# @NOTE key/field names MUST match value of 'username' key or field of its object
|
||||||
|
senpai:
|
||||||
|
username: senpai
|
||||||
|
password: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.2;AES256;vps1-senpai
|
||||||
|
62626662666239376237616464626630393562373130623934653764333139346337313539613863
|
||||||
|
3163623834636235323433323066373435393432303234320a343433343334386131613062353761
|
||||||
|
30323832666333366330306261386435303066626664336332393263366262626430386230356161
|
||||||
|
3863383530616135390a383361383136366565363066326332306631323730663533623163666133
|
||||||
|
62646339613864356264656362326562636336376136656336323962616236396562623833313531
|
||||||
|
38633938386435656437383033656630373238366663323265326533333035376233646465626363
|
||||||
|
33316364356533616437343439653635626637393137633034613432383530376132656138333636
|
||||||
|
66376535346164393630383532373963663439366339646666336264393731313135343962613932
|
||||||
|
33316433656236353230643332333231623730323262363831396437656331626539
|
||||||
|
shell: /bin/bash
|
||||||
|
home: ~
|
||||||
|
admin: true
|
||||||
|
type: regular
|
||||||
|
group: ~
|
||||||
|
groups:
|
||||||
|
- sudo
|
||||||
|
- "{{ groups.remote.group_name }}"
|
||||||
|
services: []
|
||||||
|
ssh_authorized_keys: "{{ custom_vars.generality.ssh_authorized_keys }}"
|
||||||
|
ssh_private_key_paths: "{{ custom_vars.generality.ssh_private_key_paths }}"
|
||||||
|
ssh_private_key_path_pref: 0
|
||||||
|
gpg_keys:
|
||||||
|
- id: 558041D5CF2AB23B # @NOTE professional
|
||||||
|
name: professional
|
||||||
|
password: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.2;AES256;vps1-senpai
|
||||||
|
30326232323038346232663635343439393130376666616165626339646461663165393539353733
|
||||||
|
3666346333366237643964653633306263373365373731660a663361633030613630623434353332
|
||||||
|
35363939356339623732623061323866353739623936353234636133303534363863666462633133
|
||||||
|
3462653139366138330a336433343566633066643834613836353331316163653739656230663164
|
||||||
|
6131
|
||||||
|
- id: F0CA546935C02C76 # @NOTE personal
|
||||||
|
name: personal
|
||||||
|
password: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.2;AES256;vps1-senpai
|
||||||
|
62373636643365623161643266313734633632633066373863666661306433393464396565363636
|
||||||
|
3638353234393838623133633839316130393539356464370a346262313262623164623637323066
|
||||||
|
37333432313438343761636330663332383035306131643339326261386231643231353930373961
|
||||||
|
3466643062396465330a656362316336376338653963376137663632646266343335333036656461
|
||||||
|
3964
|
||||||
|
- id: CE245A7D7CEE3639 # @NOTE undercover
|
||||||
|
name: undercover
|
||||||
|
password: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.2;AES256;vps1-senpai
|
||||||
|
38343338373839336436396431366665383437646233613036393666613339363062616134383631
|
||||||
|
3938333066323838623938353231623034643635663031620a646631346233653535643337623737
|
||||||
|
63373437653665623361663131346137336435623862396262353764323161323338663731613266
|
||||||
|
6466323838306131390a383962616461616237343261666630393166303932623765633239353631
|
||||||
|
3230
|
||||||
|
gpg_keyid_pref: 0
|
||||||
|
git_profile:
|
||||||
|
name: Alex Tavarez
|
||||||
|
email: ajt95@prole.biz
|
||||||
|
ftp:
|
||||||
|
username: ftp
|
||||||
|
password: ~
|
||||||
|
shell: /sbin/nologin
|
||||||
|
home: /srv/ftp
|
||||||
|
admin: false
|
||||||
|
type: system
|
||||||
|
group: ~
|
||||||
|
groups:
|
||||||
|
- "{{ groups.remote.group_name }}"
|
||||||
|
services: [proftpd,sftp]
|
||||||
|
ssh_authorized_keys: "{{ custom_vars.generality.ssh_authorized_keys }}"
|
||||||
|
ssh_private_key_paths: "{{ custom_vars.generality.ssh_private_key_paths }}"
|
||||||
|
ssh_private_key_path_pref: 0
|
||||||
|
gpg_keys: []
|
||||||
|
gpg_keyid_pref: 0
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
ungrouped:
|
|
||||||
hosts:
|
|
||||||
localhost:
|
|
||||||
ansible_host: "localhost"
|
|
||||||
localhost4:
|
|
||||||
ansible_host: "127.0.0.1"
|
|
||||||
localhost6:
|
|
||||||
ansible_host: "::1"
|
|
||||||
sukaato:
|
|
||||||
ansible_host: ~
|
|
||||||
sukaato4:
|
|
||||||
ansible_host: ~
|
|
||||||
sukaato6:
|
|
||||||
ansible_host: ~
|
|
||||||
localhost_hosts:
|
|
||||||
hosts:
|
|
||||||
localhost:
|
|
||||||
localhost4:
|
|
||||||
localhost6:
|
|
||||||
sukaato_hosts:
|
|
||||||
hosts:
|
|
||||||
sukaato:
|
|
||||||
sukaato4:
|
|
||||||
sukaato6:
|
|
||||||
locals:
|
|
||||||
children:
|
|
||||||
localhost_hosts:
|
|
||||||
vars:
|
|
||||||
ansible_connection: local
|
|
||||||
name_surname:
|
|
||||||
surname_household:
|
|
||||||
servers:
|
|
||||||
children:
|
|
||||||
sukaato_hosts:
|
|
||||||
vars:
|
|
||||||
ansible_port: 22
|
|
||||||
19
playbooks/deroot.yml
Normal file
19
playbooks/deroot.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
- name: Create new users and lock down VPS
|
||||||
|
hosts: vps1
|
||||||
|
remote_user: root
|
||||||
|
vars:
|
||||||
|
ansible_user: root
|
||||||
|
ansible_ssh_private_key_file: "{{ vps_service.ssh_private_key_paths[vps_service.ssh_private_key_path_pref] }}"
|
||||||
|
tasks:
|
||||||
|
- name: Engage in SSH hardening and user creation
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
# allow_duplicates: true
|
||||||
|
defaults_from: main
|
||||||
|
handlers_from: main
|
||||||
|
name: bootstrap
|
||||||
|
# public: false
|
||||||
|
# rolespec_validate: true
|
||||||
|
tasks_from: "init@{{ ansible_facts['system'].lowercase() }}"
|
||||||
|
vars_from: main
|
||||||
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Default settings for user directories
|
|
||||||
#
|
|
||||||
# The values are relative pathnames from the home directory and
|
|
||||||
# will be translated on a per-path-element basis into the users locale
|
|
||||||
DESKTOP=Desktop
|
|
||||||
DOWNLOAD=Downloads
|
|
||||||
TEMPLATES=Templates
|
|
||||||
PUBLICSHARE=Public
|
|
||||||
DOCUMENTS=Documents
|
|
||||||
MUSIC=Music
|
|
||||||
PICTURES=Pictures
|
|
||||||
VIDEOS=Videos
|
|
||||||
# Another alternative is:
|
|
||||||
#MUSIC=Documents/Music
|
|
||||||
#PICTURES=Documents/Pictures
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Default settings for user directories
|
|
||||||
#
|
|
||||||
# The values are relative pathnames from the home directory and
|
|
||||||
# will be translated on a per-path-element basis into the users locale
|
|
||||||
DESKTOP=Desktop
|
|
||||||
DOWNLOAD=Downloads
|
|
||||||
TEMPLATES=Templates
|
|
||||||
PUBLICSHARE=Public
|
|
||||||
DOCUMENTS=Documents
|
|
||||||
MUSIC=Music
|
|
||||||
PICTURES=Pictures
|
|
||||||
VIDEOS=Videos
|
|
||||||
# Another alternative is:
|
|
||||||
#MUSIC=Documents/Music
|
|
||||||
#PICTURES=Documents/Pictures
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
passwords:
|
|
||||||
- username: admin
|
|
||||||
password: "{{ vaulted_passwords.admin.password }}"
|
|
||||||
local_ssh_private_key_files: [] # @NOTE list paths to SSH private keys
|
|
||||||
chosen_local_ssh_private_key_file: "{{ local_ssh_private_key_files | random }}"
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
# @TODO encrypt as vault
|
|
||||||
# @NOTE see https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module
|
|
||||||
# Specifically, section for hashing using python passlib library
|
|
||||||
vaulted_passwords:
|
|
||||||
admin:
|
|
||||||
password: ~
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
passwords:
|
|
||||||
- username: admin
|
|
||||||
password: "{{ vaulted_passwords.admin.password }}"
|
|
||||||
local_ssh_private_key_files: [] # @NOTE list paths to SSH private keys
|
|
||||||
chosen_local_ssh_private_key_file: "{{ local_ssh_private_key_files | random }}"
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
# @TODO encrypt as vault
|
|
||||||
# @NOTE see https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module
|
|
||||||
# Specifically, section for hashing using python passlib library
|
|
||||||
vaulted_passwords:
|
|
||||||
admin:
|
|
||||||
password: ~
|
|
||||||
20
playbooks/init.yml
Normal file
20
playbooks/init.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
- name: Initialize VPS
|
||||||
|
hosts: localhost
|
||||||
|
connection: local
|
||||||
|
tasks:
|
||||||
|
- name: Create a VPS using Linode
|
||||||
|
when: vps_service.type == "linode"
|
||||||
|
community.general.linode_v4:
|
||||||
|
access_token: "{{ vps_service.api_key }}"
|
||||||
|
authorized_keys: "{{ vps_service.ssh_authorized_keys }}"
|
||||||
|
image: linode/debian13
|
||||||
|
label: sukaato
|
||||||
|
private_ip: true
|
||||||
|
region: "{{ vps_service.region }}"
|
||||||
|
root_pass: "{{ vps_service.password }}"
|
||||||
|
tags: "{{ hostvars[inventory_hostname].keywords }}"
|
||||||
|
state: "{{ 'present' if vps_service.exists else 'absent' }}"
|
||||||
|
tags:
|
||||||
|
- vps_step
|
||||||
|
- linode_step
|
||||||
@@ -1,197 +0,0 @@
|
|||||||
---
|
|
||||||
- name: init_login
|
|
||||||
hosts: servers # @NOTE for IPv6, switch to 'servers6' instead of 'servers4'--for both, 'servers'
|
|
||||||
vars_files:
|
|
||||||
# @NOTE if second line is uncommented with its variables actively in use, first line should too be uncommented
|
|
||||||
# - vars/ssh_keys_vault.yml
|
|
||||||
- vars/ssh_keys.yml
|
|
||||||
vars:
|
|
||||||
ansible_user: "{{ passwords[0].username }}"
|
|
||||||
# @NOTE one of below two lines should be commented/uncommented in a mutually exclusive fashion
|
|
||||||
# ansible_ssh_private_key_file: "{{ chosen_native_ssh_private_key_file | default(chosen_local_ssh_private_key_file, true) }}" # @NOTE only works with soft-coded SSH key list building
|
|
||||||
ansible_ssh_private_key_file: "{{ chosen_local_ssh_private_key_file }}" # @NOTE references an inventory / group variable
|
|
||||||
# @NOTE below three lines should only be uncommented when above two are commented and vice versa; key-based authentication should have already been enabled prior to running this playbook
|
|
||||||
# ansible_password: "{{ passwords[0].password }}"
|
|
||||||
ansible_python_interpreter: “{{ ansible_playbook_python }}”
|
|
||||||
personal_computers: locals # @NOTE can change to *_households group or {{ name }}_{{ surname }} group name
|
|
||||||
vars_prompt:
|
|
||||||
- name: gpg_or_ssh_git_signing
|
|
||||||
prompt: Enter preferred signing key type (e.g., ssh or gpg)
|
|
||||||
unsafe: yes
|
|
||||||
private: no
|
|
||||||
default: "ssh"
|
|
||||||
- name: git_preferred_signing
|
|
||||||
prompt: Enter index or number of preferred signing key (negative number for random)
|
|
||||||
unsafe: yes
|
|
||||||
private: no
|
|
||||||
default: -1
|
|
||||||
tasks:
|
|
||||||
- name: Disable shell access for root
|
|
||||||
ansible.builtin.include_role:
|
|
||||||
name: lockdown
|
|
||||||
defaults_from: main
|
|
||||||
vars_from: main
|
|
||||||
handlers_from: main
|
|
||||||
tasks_from: deshell
|
|
||||||
apply:
|
|
||||||
become: yes
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- name: Create global bash aliases
|
|
||||||
become: yes
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: bash/bash_aliases
|
|
||||||
dest: /etc/bash_aliases
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
follow: yes
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0644"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- source_sys_bashrc
|
|
||||||
- name: Create global bash functions
|
|
||||||
become: yes
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: bash/bash_functions
|
|
||||||
dest: /etc/bash_functions
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
follow: yes
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0644"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- source_sys_bashrc
|
|
||||||
- name: Register bash aliases and functions to global bashrc
|
|
||||||
become: yes
|
|
||||||
ansible.builtin.blockinfile:
|
|
||||||
block: |
|
|
||||||
if [ -f /etc/bash_aliases ]; then
|
|
||||||
. /etc/bash_aliases
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f /etc/bash_functions ]; then
|
|
||||||
. /etc/bash_functions
|
|
||||||
fi
|
|
||||||
path: /etc/bash.bashrc
|
|
||||||
prepend_newline: yes
|
|
||||||
marker: "# {mark} ANSIBLE MANAGED SYSTEM-WIDE BASH ALIASES AND FUNCTIONS BLOCK"
|
|
||||||
insertafter: EOF
|
|
||||||
create: yes
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
backup: yes
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- source_sys_bashrc
|
|
||||||
- name: Start XDG configuration tasks if current host in servers group
|
|
||||||
when: "'servers' in group_names and ansible_connection != 'local'"
|
|
||||||
become: yes
|
|
||||||
block:
|
|
||||||
- name: Create XDG user home directory environment variables
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: files/servers/xdg/user-dirs.defaults
|
|
||||||
dest: /etc/xdg/user-dirs.defaults
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
follow: yes
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0644"
|
|
||||||
state: present
|
|
||||||
- name: Create XDG user home directory environment variables
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "xdg/{{ ansible_facts['user_id'] }}/user-dirs.dirs"
|
|
||||||
dest: "{{ ansible_facts['user_dir'] }}/.config/user-dirs.dirs"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
follow: yes
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0644"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- create_xdg_config
|
|
||||||
- servers_exclusive
|
|
||||||
- name: Start XDG configuration tasks if current host is local or personal
|
|
||||||
when: "personal_computers in group_names or ansible_connection == 'local'"
|
|
||||||
become: yes
|
|
||||||
block:
|
|
||||||
- name: Create XDG user home directory environment variables
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: files/locals/xdg/user-dirs.defaults
|
|
||||||
dest: /etc/xdg/user-dirs.defaults
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
follow: yes
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0644"
|
|
||||||
state: present
|
|
||||||
- name: Create XDG user home directory environment variables
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "xdg/{{ ansible_facts['user_id'] }}/user-dirs.dirs"
|
|
||||||
dest: "{{ ansible_facts['user_dir'] }}/.config/user-dirs.dirs"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
follow: yes
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
mode: "0644"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- create_xdg_config
|
|
||||||
- locals_exclusive
|
|
||||||
- name: Start SSH configuration tasks if current host is local or personal
|
|
||||||
when: "personal_computers in group_names or ansible_connection == 'local'"
|
|
||||||
become: yes
|
|
||||||
block:
|
|
||||||
- name: Create user SSH configuration
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "ssh/{{ ansible_facts['user_id'] }}/config"
|
|
||||||
dest: "{{ ansible_facts['user_dir'] }}/.ssh/config"
|
|
||||||
follow: yes
|
|
||||||
force: yes
|
|
||||||
backup: yes
|
|
||||||
owner: "{{ ansible_facts['user_id'] }}"
|
|
||||||
group: "{{ ansible_facts['user_id'] }}"
|
|
||||||
mode: "0600"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- create_ssh_config
|
|
||||||
- locals_exclusive
|
|
||||||
- name: Import GPG private keys
|
|
||||||
ansible.builtin.include_role:
|
|
||||||
name: lockdown
|
|
||||||
defaults_from: main
|
|
||||||
vars_from: main
|
|
||||||
handlers_from: main
|
|
||||||
tasks_from: gpg
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- import_gpg_privkeys
|
|
||||||
- name: Set up git
|
|
||||||
ansible.builtin.include_role:
|
|
||||||
name: lockdown
|
|
||||||
defaults_from: main
|
|
||||||
vars_from: main
|
|
||||||
handlers_from: main
|
|
||||||
tasks_from: git
|
|
||||||
vars:
|
|
||||||
git_signing_key_type: gpg_or_ssh_git_signing
|
|
||||||
preferred_signing_key: git_preferred_signing
|
|
||||||
tags:
|
|
||||||
- default
|
|
||||||
- configure_git
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
- name: manage_root
|
|
||||||
hosts: servers # @NOTE for IPv6, switch to 'servers6' instead of 'servers4'--for both, 'servers'
|
|
||||||
remote_user: root # MUST be run as root
|
|
||||||
vars:
|
|
||||||
ansible_user: root
|
|
||||||
# ansible_ssh_user: root
|
|
||||||
vars_prompt:
|
|
||||||
- name: ansible_password
|
|
||||||
prompt: Enter pasword for root user of VPS
|
|
||||||
unsafe: yes
|
|
||||||
private: yes
|
|
||||||
# - name: ansible_ssh_pass
|
|
||||||
# prompt: Enter pasword for root user of VPS
|
|
||||||
# unsafe: yes
|
|
||||||
# private: yes
|
|
||||||
tasks:
|
|
||||||
- name: Set up sys-admin account on VPS and secure VPS
|
|
||||||
ansible.builtin.include_role:
|
|
||||||
name: lockdown
|
|
||||||
defaults_from: main
|
|
||||||
vars_from: main
|
|
||||||
handlers_from: main
|
|
||||||
tasks_from: main
|
|
||||||
tags:
|
|
||||||
- init
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Lock down VPS
|
|
||||||
ansible.builtin.import_playbook: manage_root.yml
|
|
||||||
- name: Bootstrap VPS
|
|
||||||
ansible.builtin.import_playbook: init_login.yml
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
native_ssh_private_keys: "{{ vaulted_native_ssh_private_keys }}"
|
|
||||||
native_ssh_private_key_files: []
|
|
||||||
chosen_native_ssh_private_key_file: "{{ native_ssh_private_key_files | random }}"
|
|
||||||
9
roles/bootstrap/files/gitconfig.d/commit.msg
Normal file
9
roles/bootstrap/files/gitconfig.d/commit.msg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# @NOTE possible commit types: https://github.com/qoomon/git-conventional-commits?tab=readme-ov-file#config-file
|
||||||
|
# @NOTE for description or body consider: motivation for or cause of change, impact and domain of change
|
||||||
|
<type>[optional scope]: <description{<50char}>
|
||||||
|
|
||||||
|
[optional body]
|
||||||
|
|
||||||
|
# @NOTE footer should almost be treated as metadata of/for commit, or alerts of significant impact
|
||||||
|
# @NOTE for footer purpose, see: https://dev.to/mochafreddo/a-comprehensive-guide-to-using-footers-in-conventional-commit-messages-37g6
|
||||||
|
[optional footer(s)]
|
||||||
0
roles/bootstrap/files/gitconfig.d/exclude.rules
Normal file
0
roles/bootstrap/files/gitconfig.d/exclude.rules
Normal file
18
roles/bootstrap/files/sshd_config.d/sftp.example.conf
Normal file
18
roles/bootstrap/files/sshd_config.d/sftp.example.conf
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Match Group ftp
|
||||||
|
ForceCommand internal-sftp -d /%u
|
||||||
|
ChrootDirectory /srv/ftp
|
||||||
|
AllowAgentForwarding no
|
||||||
|
AllowTcpForwarding no
|
||||||
|
X11Forwarding no
|
||||||
|
|
||||||
|
Match User ftp
|
||||||
|
ForceCommand internal-sftp -d /public
|
||||||
|
AuthorizedKeysFile /srv/ftp/.ssh/authorized_keys
|
||||||
|
|
||||||
|
Match User caddy,www-data
|
||||||
|
ForceCommand internal-sftp -d /domain1.tld
|
||||||
|
AuthorizedKeysFile /srv/www/.ssh/authorized_keys
|
||||||
|
ChrootDirectory /srv/www
|
||||||
|
AllowAgentForwarding no
|
||||||
|
AllowTcpForwarding no
|
||||||
|
X11Forwarding no
|
||||||
3
roles/bootstrap/handlers/caddy.yml
Normal file
3
roles/bootstrap/handlers/caddy.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# handlers file for bootstrap
|
||||||
306
roles/bootstrap/handlers/git.yml
Normal file
306
roles/bootstrap/handlers/git.yml
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
# SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# handlers file for bootstrap
|
||||||
|
- name: Configure git
|
||||||
|
listen: git
|
||||||
|
block:
|
||||||
|
# @NOTE below are system git configuration
|
||||||
|
- name: Configure git aliases
|
||||||
|
become: true
|
||||||
|
block:
|
||||||
|
- name: Configure non-coding alias for merge subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.assimilate
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: merge
|
||||||
|
- name: Configure alias for merge subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.mrg
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: merge
|
||||||
|
- name: Configure non-coding alias for add subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.approve
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: add
|
||||||
|
- name: Configure non-coding alias for status subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.revisions
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: status
|
||||||
|
- name: Configure alias for status subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.stat
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: status
|
||||||
|
- name: Configure non-coding alias for commit subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.finalize
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: commit
|
||||||
|
- name: Configure alias for commit subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.cit
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: commit
|
||||||
|
- name: Configure alias for config subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.cfg
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: config
|
||||||
|
- name: Configure non-coding alias for commit subcommand with signing flag
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.claim
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: commit -S
|
||||||
|
- name: Configure alias for commit subcommand with signing flag
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.sig
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: commit -S
|
||||||
|
- name: Configure non-coding alias for show subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.review
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: show
|
||||||
|
- name: Configure alias for show subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.peek
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: show
|
||||||
|
- name: Configure alias for add subcommand with universal staging flag
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.badd
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: add -A
|
||||||
|
- name: Configure non-coding alias for add subcommand with universal staging flag
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.approve-all
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: add -A
|
||||||
|
- name: Configure non-coding alias for rm subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.redact
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: rm
|
||||||
|
- name: Configure non-coding alias for init subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.author
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: init
|
||||||
|
- name: Configure non-coding alias for mv subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.revise
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: mv
|
||||||
|
- name: Configure non-coding alias for rebase subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.retroact
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: rebase
|
||||||
|
- name: Configure alias for rebase subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.rb
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: rebase
|
||||||
|
- name: Configure non-coding alias for push subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.publish
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: push
|
||||||
|
- name: Configure non-coding alias for pull subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.publication
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: pull
|
||||||
|
- name: Configure non-coding alias for fetch subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.manuscript
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: fetch
|
||||||
|
- name: Configure alias for fetch subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.get
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: fetch
|
||||||
|
- name: Configure non-coding alias for clone subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.copy
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: clone
|
||||||
|
- name: Configure alias for clone subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.cp
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: clone
|
||||||
|
- name: Configure non-coding alias for branch subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.draft
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: branch
|
||||||
|
- name: Configure alias for branch subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.br
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: branch
|
||||||
|
- name: Configure non-coding alias for switch subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.edit
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: switch
|
||||||
|
- name: Configure alias for switch subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.cd
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: switch
|
||||||
|
- name: Configure non-coding alias for restore subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.revert
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: restore
|
||||||
|
- name: Configure alias for restore subcommand
|
||||||
|
community.general.git_config:
|
||||||
|
name: alias.rs
|
||||||
|
add_mode: replace-all
|
||||||
|
state: present
|
||||||
|
value: restore
|
||||||
|
- name: Set default editor for git
|
||||||
|
become: true
|
||||||
|
community.general.git_config:
|
||||||
|
add_mode: replace-all
|
||||||
|
name: core.editor
|
||||||
|
state: present
|
||||||
|
value: "{{ config.git.sys.editor }}"
|
||||||
|
- name: Create a directory for storing system-level templates for git
|
||||||
|
become: true
|
||||||
|
ansible.builtin.file:
|
||||||
|
group: root
|
||||||
|
owner: root
|
||||||
|
path: /etc/gitconfig.d
|
||||||
|
state: directory
|
||||||
|
- name: Create a commit message template file for git
|
||||||
|
become: true
|
||||||
|
ansible.builtin.copy:
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
backup: true
|
||||||
|
dest: /etc/gitconfig.d/commit.msg
|
||||||
|
force: true
|
||||||
|
src: gitconfig.d/commit.msg
|
||||||
|
- name: Set system-level commit message template file path for git
|
||||||
|
become: true
|
||||||
|
community.general.git_config:
|
||||||
|
add_mode: replace-all
|
||||||
|
name: commit.template
|
||||||
|
state: present
|
||||||
|
value: /etc/gitconfig.d/commit.msg
|
||||||
|
- name: Set UI to have color for git at system-level
|
||||||
|
become: true
|
||||||
|
community.general.git_config:
|
||||||
|
add_mode: replace-all
|
||||||
|
name: color.ui
|
||||||
|
state: present
|
||||||
|
value: "true"
|
||||||
|
- name: Set line-end conversion behavior for git
|
||||||
|
become: true
|
||||||
|
community.general.git_config:
|
||||||
|
add_mode: replace-all
|
||||||
|
name: core.autocrlf
|
||||||
|
state: present
|
||||||
|
value: input
|
||||||
|
# @NOTE below are user git configuration
|
||||||
|
- name: Create a user directory for a user gitignore file for git
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users
|
||||||
|
ansible.builtin.file:
|
||||||
|
owner: "{{ ansible_facts['user_id'] }}"
|
||||||
|
group: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].group | default(ansible_facts['user_id']) }}"
|
||||||
|
path: "{{ ansible_facts['user_dir'] }}/.config/git"
|
||||||
|
state: directory
|
||||||
|
- name: Create a user gitignore file for git
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users
|
||||||
|
ansible.builtin.copy:
|
||||||
|
owner: "{{ ansible_facts['user_id'] }}"
|
||||||
|
group: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].group | default(ansible_facts['user_id']) }}"
|
||||||
|
backup: true
|
||||||
|
dest: "{{ ansible_facts['user_dir'] }}/.config/git/gitignore"
|
||||||
|
force: true
|
||||||
|
src: gitconfig.d/exclude.rules
|
||||||
|
- name: Set user gitignore file path for git
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users
|
||||||
|
community.general.git_config:
|
||||||
|
add_mode: replace-all
|
||||||
|
name: core.excludesfile
|
||||||
|
scope: global
|
||||||
|
state: present
|
||||||
|
value: "{{ ansible_facts['user_dir'] }}/.config/git/gitignore"
|
||||||
|
- name: Create link from user config directory git config file to user home directory git config file
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users
|
||||||
|
community.general.file:
|
||||||
|
src: "{{ ansible_facts['user_dir'] }}/.gitconfig"
|
||||||
|
dest: "{{ ansible_facts['user_dir'] }}/.config/git/config"
|
||||||
|
# @TODO check whether below two attributes make sense for links
|
||||||
|
owner: "{{ ansible_facts['user_id'] }}"
|
||||||
|
group: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].group | default(ansible_facts['user_id']) }}"
|
||||||
|
state: hard
|
||||||
|
- name: Set format for keys used by git
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users
|
||||||
|
community.general.git_config:
|
||||||
|
add_mode: replace-all
|
||||||
|
name: gpg.format
|
||||||
|
scope: global
|
||||||
|
state: present
|
||||||
|
value: openpgp
|
||||||
|
- name: Set signing key to be used by git
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users and hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keys is not None and len(hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keys) > 0
|
||||||
|
community.general.git_config:
|
||||||
|
add_mode: replace-all
|
||||||
|
name: user.signingkey
|
||||||
|
scope: global
|
||||||
|
state: present
|
||||||
|
value: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keys[hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keyid_pref].id | default((hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keys | random).id) }}"
|
||||||
|
- name: Set name of user of git
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users
|
||||||
|
community.general.git_config:
|
||||||
|
add_mode: replace-all
|
||||||
|
name: user.name
|
||||||
|
scope: global
|
||||||
|
state: present
|
||||||
|
value: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].git_profile.name }}"
|
||||||
|
- name: Set email of user of git
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users
|
||||||
|
community.general.git_config:
|
||||||
|
add_mode: replace-all
|
||||||
|
name: user.email
|
||||||
|
scope: global
|
||||||
|
state: present
|
||||||
|
value: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].git_profile.email }}"
|
||||||
6
roles/bootstrap/handlers/main.yml
Normal file
6
roles/bootstrap/handlers/main.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# handlers file for bootstrap
|
||||||
|
- name: Postinstall set-up of git
|
||||||
|
ansible.builtin.import_tasks:
|
||||||
|
file: git.yml
|
||||||
38
roles/bootstrap/tasks/configure_gpg@linux.yml
Normal file
38
roles/bootstrap/tasks/configure_gpg@linux.yml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# tasks file for bootstrap
|
||||||
|
- name: Create GNUPGP directory in user home directory
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users
|
||||||
|
ansible.builtin.file:
|
||||||
|
group: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].group | default(ansible_facts['user_id']) }}"
|
||||||
|
mode: "0700"
|
||||||
|
owner: "{{ ansible_facts['user_id'] }}"
|
||||||
|
path: "{{ ansible_facts['user_dir'] }}/.gnupg"
|
||||||
|
state: directory
|
||||||
|
- name: Create GPG key files
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users and hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keys is not None and len(hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keys) > 0
|
||||||
|
ansible.builtin.copy:
|
||||||
|
backup: true
|
||||||
|
dest: "{{ ansible_facts['user_dir'] }}/.gnupg/{{ item.id }}.key"
|
||||||
|
force: true
|
||||||
|
group: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].group | default(ansible_facts['user_id']) }}"
|
||||||
|
mode: "0600"
|
||||||
|
owner: "{{ ansible_facts['user_id'] }}"
|
||||||
|
src: "gnupg/{{ item.id }}.key"
|
||||||
|
# validate: "gpg --verify {{ item.id }}.sig %s"
|
||||||
|
loop: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keys }}"
|
||||||
|
register: created_gpg_keys
|
||||||
|
- name: Import GPG key files
|
||||||
|
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users and hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keys is not None and len(hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keys) > 0
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- gpg
|
||||||
|
- --batch
|
||||||
|
- --passphrase-fd 0
|
||||||
|
- --import
|
||||||
|
- "{{ ansible_facts['user_dir'] }}/.gnupg/{{ item.id }}.key"
|
||||||
|
stdin: "{{ item.password }}"
|
||||||
|
loop: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].gpg_keys }}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
131
roles/bootstrap/tasks/configure_ssh@linux.yml
Normal file
131
roles/bootstrap/tasks/configure_ssh@linux.yml
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# tasks file for bootstrap
|
||||||
|
- name: Create hidden SSH directories under users' home directories
|
||||||
|
when: hostvars[inventory_hostname].groups.remote.group_name in item.value.groups
|
||||||
|
ansible.builtin.file:
|
||||||
|
group: "{{ item.value.group | default(item.value.username) }}"
|
||||||
|
mode: "0700"
|
||||||
|
owner: "{{ item.value.username }}"
|
||||||
|
path: "{{ item.value.home | default('/home/' ~ item.value.username) }}/.ssh"
|
||||||
|
state: directory
|
||||||
|
loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}"
|
||||||
|
tags:
|
||||||
|
- ensure_paths
|
||||||
|
- ensure_files
|
||||||
|
- name: Add authorized SSH public keys for users
|
||||||
|
when: hostvars[inventory_hostname].groups.remote.group_name in item.value.groups and item.value.ssh_authorized_keys is not None and len(item.value.ssh_authorized_keys) > 0
|
||||||
|
ansible.builtin.copy:
|
||||||
|
backup: true
|
||||||
|
content: "{{ item.value.ssh_authorized_keys.join('\n') }}"
|
||||||
|
dest: "{{ item.value.home | default('/home/' ~ item.value.username) }}/.ssh/authorized_keys"
|
||||||
|
# follow: true
|
||||||
|
force: true
|
||||||
|
group: "{{ item.value.group | default(item.value.username) }}"
|
||||||
|
mode: "0600"
|
||||||
|
owner: "{{ item.value.username }}"
|
||||||
|
loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}"
|
||||||
|
tags:
|
||||||
|
- ensure_files
|
||||||
|
- name: Harden SSH security
|
||||||
|
block:
|
||||||
|
- name: Set users in group ftp to only be usable with SSH's SFTP service
|
||||||
|
when: "'sftp' in item.value.services"
|
||||||
|
ansible.builtin.blockinfile:
|
||||||
|
backup: true
|
||||||
|
block: |
|
||||||
|
Match Group {{ item.value.group | default(item.value.username) }}
|
||||||
|
ForceCommand internal-sftp -d /%u
|
||||||
|
ChrootDirectory {{ item.value.home | default('/home/' ~ item.value.username) }}
|
||||||
|
AllowAgentForwarding no
|
||||||
|
AllowTcpForwarding no
|
||||||
|
X11Forwarding no
|
||||||
|
|
||||||
|
Match User {{ item.value.username }}
|
||||||
|
ForceCommand internal-sftp -d /public
|
||||||
|
AuthorizedKeysFile {{ item.value.home | default('/home/' ~ item.value.username) }}/.ssh/authorized_keys
|
||||||
|
create: true
|
||||||
|
group: root
|
||||||
|
insertafter: EOF
|
||||||
|
marker: "# {mark} ANSIBLE-MANAGED SFTP BLOCK"
|
||||||
|
marker_begin: BEGIN
|
||||||
|
marker_end: END
|
||||||
|
owner: root
|
||||||
|
path: /etc/ssh/sshd_config.d/sftp.conf
|
||||||
|
append_newline: true
|
||||||
|
state: present
|
||||||
|
validate: /bin/sshd -t
|
||||||
|
loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}"
|
||||||
|
tags:
|
||||||
|
- sftp_auth_step
|
||||||
|
- name: Switch to preferred SSH authentication method
|
||||||
|
ansible.builtin.template:
|
||||||
|
backup: true
|
||||||
|
comment_end_string: "#}"
|
||||||
|
comment_start_string: "{#"
|
||||||
|
dest: /etc/ssh/sshd_config.d/auth.conf
|
||||||
|
# follow: true
|
||||||
|
force: true
|
||||||
|
group: root
|
||||||
|
owner: root
|
||||||
|
src: sshd_config.d/auth.conf.j2
|
||||||
|
validate: /bin/sshd -t
|
||||||
|
vars:
|
||||||
|
empty_auth_used: false
|
||||||
|
pass_auth_used: false
|
||||||
|
pam_auth_used: false
|
||||||
|
key_auth_used: true
|
||||||
|
tags:
|
||||||
|
- ssh_auth_step
|
||||||
|
- name: Constrain idle online user accounts
|
||||||
|
ansible.builtin.template:
|
||||||
|
backup: true
|
||||||
|
comment_end_string: "#}"
|
||||||
|
comment_start_string: "{#"
|
||||||
|
dest: /etc/ssh/sshd_config.d/harden.conf
|
||||||
|
force: true
|
||||||
|
group: root
|
||||||
|
owner: root
|
||||||
|
src: sshd_config.d/harden.conf.j2
|
||||||
|
validate: /bin/sshd -t
|
||||||
|
vars:
|
||||||
|
client_subsistence: 900
|
||||||
|
client_subsist_warn_max: 3
|
||||||
|
tags:
|
||||||
|
- ssh_timeout_step
|
||||||
|
- name: Toggle ability to log in as root via SSH
|
||||||
|
when: "hostvars[inventory_hostname].vps_service.root_fate == 'disposal'"
|
||||||
|
ansible.builtin.template:
|
||||||
|
backup: true
|
||||||
|
comment_end_string: "#}"
|
||||||
|
comment_start_string: "{#"
|
||||||
|
dest: /etc/ssh/sshd_config.d/denyroot.conf
|
||||||
|
force: true
|
||||||
|
group: root
|
||||||
|
owner: root
|
||||||
|
src: sshd_config.d/denyroot.conf.j2
|
||||||
|
validate: /bin/sshd -t
|
||||||
|
vars:
|
||||||
|
root_login_allowed: false
|
||||||
|
tags:
|
||||||
|
- ssh_root_step
|
||||||
|
- name: Specify users or groups to whitelist or blacklist for SSH login
|
||||||
|
when: "hostvars[inventory_hostname].vps_service.root_fate == 'disposal'"
|
||||||
|
ansible.builtin.template:
|
||||||
|
backup: true
|
||||||
|
comment_end_string: "#}"
|
||||||
|
comment_start_string: "{#"
|
||||||
|
dest: /etc/ssh/sshd_config.d/allowance.conf
|
||||||
|
force: true
|
||||||
|
group: root
|
||||||
|
owner: root
|
||||||
|
src: sshd_config.d/allowance.conf.j2
|
||||||
|
validate: /bin/sshd -t
|
||||||
|
vars:
|
||||||
|
list_type: whitelist
|
||||||
|
policed_groups:
|
||||||
|
- "{{ hostvars[inventory_hostname].groups.remote.group_name }}"
|
||||||
|
tags:
|
||||||
|
- ssh_gate_step
|
||||||
|
tags:
|
||||||
|
- ssh_harden_step
|
||||||
62
roles/bootstrap/tasks/create_users@linux.yml
Normal file
62
roles/bootstrap/tasks/create_users@linux.yml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# tasks file for bootstrap
|
||||||
|
- name: Create groups
|
||||||
|
ansible.builtin.group:
|
||||||
|
name: "{{ item.value.group_name }}"
|
||||||
|
state: present
|
||||||
|
system: "{{ 'true' if item.value.type == 'system' else 'false' }}"
|
||||||
|
loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].groups) }}"
|
||||||
|
- name: Create users
|
||||||
|
block:
|
||||||
|
- name: Create administrative users
|
||||||
|
when: "item.value.admin and item.value.type != 'system'"
|
||||||
|
ansible.builtin.user:
|
||||||
|
comment: "administrator for {{ fqdn.split('.')[0].lowercase }}"
|
||||||
|
create_home: false
|
||||||
|
home: "{{ item.value.home | default('/home/' ~ item.value.username) }}"
|
||||||
|
generate_ssh_key: true
|
||||||
|
ssh_key_comment: "ansible-generated for {{ item.value.username }}@{{ hostvars[inventory_hostname].fqdn.split('.')[0].lowercase() }}"
|
||||||
|
ssh_key_type: "ed25519"
|
||||||
|
group: "{{ item.value.group | default(item.value.username) }}"
|
||||||
|
name: "{{ item.value.username }}"
|
||||||
|
shell: "{{ item.value.shell }}"
|
||||||
|
password: "{{ item.value.password }}"
|
||||||
|
state: present
|
||||||
|
system: "{{ 'true' if item.value.type == 'system' else 'false' }}"
|
||||||
|
update_password: always
|
||||||
|
loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}"
|
||||||
|
- name: Create regular users
|
||||||
|
when: "not item.value.admin and item.value.type != 'system'"
|
||||||
|
ansible.builtin.user:
|
||||||
|
comment: "user of {{ fqdn.split('.')[0].lowercase }}"
|
||||||
|
create_home: true
|
||||||
|
home: "{{ item.value.home | default('/home/' ~ item.value.username) }}"
|
||||||
|
generate_ssh_key: true
|
||||||
|
group: "{{ item.value.group | default(item.value.username) }}"
|
||||||
|
name: "{{ item.value.username }}"
|
||||||
|
shell: "{{ item.value.shell }}"
|
||||||
|
password: "{{ item.value.password }}"
|
||||||
|
state: present
|
||||||
|
system: "{{ 'true' if item.value.type == 'system' else 'false' }}"
|
||||||
|
update_password: always
|
||||||
|
loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}"
|
||||||
|
- name: Create users for managing data related to services
|
||||||
|
when: "not item.value.admin and item.value.type == 'system' and item.value.service is not None"
|
||||||
|
ansible.builtin.user:
|
||||||
|
comment: "service data user for {{ item.value.services | random }} at {{ hostvars[inventory_hostname].fqdn.split('.')[0].lowercase() }}"
|
||||||
|
create_home: false
|
||||||
|
home: "{{ item.value.home | default('/home/' ~ item.value.username) }}"
|
||||||
|
group: "{{ item.value.group | default(item.value.username) }}"
|
||||||
|
name: "{{ item.value.username }}"
|
||||||
|
shell: "{{ item.value.shell }}"
|
||||||
|
state: present
|
||||||
|
system: "{{ 'true' if item.value.type == 'system' else 'false' }}"
|
||||||
|
loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}"
|
||||||
|
- name: Adjust users' groups
|
||||||
|
when: item.value.groups is not None and len(item.value.groups) > 0
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ item.value.username }}"
|
||||||
|
append: true
|
||||||
|
groups: "{{ item.value.groups }}"
|
||||||
|
loop: "{{ lookup('ansible.builtin.dict', hostvars[inventory_hostname].users) }}"
|
||||||
9
roles/bootstrap/tasks/init@linux.yml
Normal file
9
roles/bootstrap/tasks/init@linux.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# tasks file for bootstrap
|
||||||
|
- name: Populate system with groups and user accounts
|
||||||
|
ansible.builtin.import_tasks:
|
||||||
|
file: "create_users@{{ ansible_facts['system'].lowercase() }}.yml"
|
||||||
|
- name: Configure SSH for root
|
||||||
|
ansible.builtin.import_tasks:
|
||||||
|
file: "configure_ssh@{{ ansible_facts['system'].lowercase() }}.yml"
|
||||||
86
roles/bootstrap/tasks/install@linux.yml
Normal file
86
roles/bootstrap/tasks/install@linux.yml
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# tasks file for bootstrap
|
||||||
|
# @TODO create bootstrap tasks for installation and configuration of software
|
||||||
|
- name: Update and upgrade software
|
||||||
|
block:
|
||||||
|
- name: Update Aptitude package cache and upgrade Aptitude packages
|
||||||
|
when: "ansible_facts['pkg_mgr'] == 'apt'"
|
||||||
|
become: true
|
||||||
|
ansible.builtin.apt:
|
||||||
|
upgrade: yes
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 86400
|
||||||
|
- name: Install NeoVim editor
|
||||||
|
become: true
|
||||||
|
block:
|
||||||
|
- name: Install NeoVim using Aptitude package manager
|
||||||
|
when: "ansible_facts['pkg_mgr'] == 'apt'"
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: neovim
|
||||||
|
use: "{{ ansible_facts['pkg_mgr'] }}"
|
||||||
|
state: present
|
||||||
|
# @TODO create handler to notify to for configuring neovim
|
||||||
|
# notify: neovim
|
||||||
|
- name: Install kitty-terminfo for SSH client xterm-kitty compatibility
|
||||||
|
become: true
|
||||||
|
block:
|
||||||
|
- name: Install kitty-terminfo using Aptitude package manager
|
||||||
|
when: "ansible_facts['pkg_mgr'] == 'apt'"
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: kitty-terminfo
|
||||||
|
use: "{{ ansible_facts['pkg_mgr'] }}"
|
||||||
|
state: present
|
||||||
|
- name: Install necessary software managers and container engines
|
||||||
|
become: true
|
||||||
|
block:
|
||||||
|
- name: Install snapd
|
||||||
|
when: "ansible_facts['pkg_mgr'] == 'apt'"
|
||||||
|
block:
|
||||||
|
- name: Install snapd using Aptitude package manager
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: snapd
|
||||||
|
use: "{{ ansible_facts['pkg_mgr'] }}"
|
||||||
|
state: present
|
||||||
|
- name: Install flatpak
|
||||||
|
when: "ansible_facts['pkg_mgr'] == 'apt'"
|
||||||
|
block:
|
||||||
|
- name: Install flatpak using Aptitude package manager
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: flatpak
|
||||||
|
use: "{{ ansible_facts['pkg_mgr'] }}"
|
||||||
|
state: present
|
||||||
|
- name: Install podman
|
||||||
|
when: "ansible_facts['pkg_mgr'] == 'apt'"
|
||||||
|
block:
|
||||||
|
- name: Install podman using Aptitude package manager
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: podman
|
||||||
|
use: "{{ ansible_facts['pkg_mgr'] }}"
|
||||||
|
state: present
|
||||||
|
- name: Install podman-compose
|
||||||
|
when: "ansible_facts['pkg_mgr'] == 'apt'"
|
||||||
|
block:
|
||||||
|
- name: Install podman-compose using Aptitude package manager
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: podman-compose
|
||||||
|
use: "{{ ansible_facts['pkg_mgr'] }}"
|
||||||
|
state: present
|
||||||
|
- name: Install git
|
||||||
|
block:
|
||||||
|
- name: Install git using Aptitude package manager
|
||||||
|
when: "ansible_facts['pkg_mgr'] == 'apt'"
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: git
|
||||||
|
use: "{{ ansible_facts['pkg_mgr'] }}"
|
||||||
|
state: present
|
||||||
|
notify: git
|
||||||
|
- name: Install packages
|
||||||
|
when: ansible_facts['pkg_mgr'] in item.value.name
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: "{{ item.value.name[ansible_facts['pkg_mgr']] }}"
|
||||||
|
use: "{{ ansible_facts['pkg_mgr'] }}"
|
||||||
|
state: present
|
||||||
|
# @TODO research what happens when nonexistent handler is called or notify field is null
|
||||||
|
notify: "{{ item.key }}"
|
||||||
|
loop: "{{ lookup('ansible.builtin.dict', software.pkgs) }}"
|
||||||
9
roles/bootstrap/tasks/main.yml
Normal file
9
roles/bootstrap/tasks/main.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# tasks file for bootstrap
|
||||||
|
- name: Configure GPG for user
|
||||||
|
ansible.builtin.import_tasks:
|
||||||
|
file: "configure_gpg@{{ ansible_facts['system'].lowercase() }}.yml"
|
||||||
|
- name: Install and configure software on system
|
||||||
|
ansible.builtin.import_tasks:
|
||||||
|
file: "install@{{ ansible_facts['system'].lowercase() }}.yml"
|
||||||
15
roles/bootstrap/templates/sshd_config.d/allowance.conf.j2
Normal file
15
roles/bootstrap/templates/sshd_config.d/allowance.conf.j2
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{% if list_type == 'whitelist' %}
|
||||||
|
{% if policed_groups is not None and len(policed_groups) > 0 %}
|
||||||
|
AllowGroups {{ policed_groups.join(' ') }}
|
||||||
|
{% endif %}
|
||||||
|
{% if policed_users is not None and len(policed_users) > 0 %}
|
||||||
|
AllowUsers {{ policed_users.join(' ') }}
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{% if policed_groups is not None and len(policed_groups) > 0 %}
|
||||||
|
DenyGroups {{ policed_groups.join(' ') }}
|
||||||
|
{% endif %}
|
||||||
|
{% if policed_users is not None and len(policed_users) > 0 %}
|
||||||
|
DenyGroups {{ policed_users.join(' ') }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
27
roles/bootstrap/templates/sshd_config.d/auth.conf.j2
Normal file
27
roles/bootstrap/templates/sshd_config.d/auth.conf.j2
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{% if empty_auth_used %}
|
||||||
|
PermitEmptyPasswords yes
|
||||||
|
{% else %}
|
||||||
|
PermitEmptyPasswords no
|
||||||
|
{% endif %}
|
||||||
|
{% if pass_auth_used %}
|
||||||
|
PasswordAuthentication yes
|
||||||
|
{% else %}
|
||||||
|
PasswordAuthentication no
|
||||||
|
{% endif %}
|
||||||
|
{% if kbd_auth_used is not None %}
|
||||||
|
{% if kbd_auth_used %}
|
||||||
|
KbdInteractiveAuthentication yes
|
||||||
|
{% else %}
|
||||||
|
KbdInteractiveAuthentication no # enable if implementing TOTP 2FA
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if pam_auth_used %}
|
||||||
|
UsePAM yes
|
||||||
|
{% else %}
|
||||||
|
UsePAM no # enable if implementing TOTP 2FA
|
||||||
|
{% endif %}
|
||||||
|
{% if key_auth_used %}
|
||||||
|
PubkeyAuthentication yes
|
||||||
|
{% else %}
|
||||||
|
PubkeyAuthentication no
|
||||||
|
{% endif %}
|
||||||
5
roles/bootstrap/templates/sshd_config.d/denyroot.conf.j2
Normal file
5
roles/bootstrap/templates/sshd_config.d/denyroot.conf.j2
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{% if root_login_allowed %}
|
||||||
|
PermitRootLogin yes
|
||||||
|
{% else %}
|
||||||
|
PermitRootLogin no
|
||||||
|
{% endif %}
|
||||||
2
roles/bootstrap/templates/sshd_config.d/harden.conf.j2
Normal file
2
roles/bootstrap/templates/sshd_config.d/harden.conf.j2
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ClientAliveInterval {{ client_subsistence }}
|
||||||
|
ClientAliveCountMax {{ client_subsist_warn_max }}
|
||||||
@@ -3,4 +3,4 @@
|
|||||||
- hosts: localhost
|
- hosts: localhost
|
||||||
remote_user: root
|
remote_user: root
|
||||||
roles:
|
roles:
|
||||||
- lockdown
|
- bootstrap
|
||||||
208
roles/bootstrap/vars/main/software.yml
Normal file
208
roles/bootstrap/vars/main/software.yml
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# vars file for bootstrap
|
||||||
|
# @TODO make list or dictionary of software to be installed in bootstrap task
|
||||||
|
software:
|
||||||
|
pkgs:
|
||||||
|
# @NOTE keep fields or keys constant; otherwise will have to edit handler notifiers and listeners elsewhere
|
||||||
|
gocryptfs:
|
||||||
|
name:
|
||||||
|
apt: gocryptfs
|
||||||
|
lua-lang:
|
||||||
|
name:
|
||||||
|
apt: lua5.4
|
||||||
|
lua-docs:
|
||||||
|
name:
|
||||||
|
apt: luadoc
|
||||||
|
lua-pkg:
|
||||||
|
name:
|
||||||
|
apt: luarocks
|
||||||
|
python-lang:
|
||||||
|
name:
|
||||||
|
apt: python3
|
||||||
|
python-pkg:
|
||||||
|
name:
|
||||||
|
apt: python3-pip
|
||||||
|
python-linter:
|
||||||
|
name:
|
||||||
|
apt: python3-doc8
|
||||||
|
python-docs:
|
||||||
|
name:
|
||||||
|
apt: python3-doc
|
||||||
|
rust-lang:
|
||||||
|
name:
|
||||||
|
apt: rustc # @NOTE alternative: rustup
|
||||||
|
rust-pkg:
|
||||||
|
name:
|
||||||
|
apt: cargo
|
||||||
|
rust-debugger:
|
||||||
|
name:
|
||||||
|
apt: rust-analyzer
|
||||||
|
rust-linter:
|
||||||
|
name:
|
||||||
|
apt: rust-clippy
|
||||||
|
rust-docs:
|
||||||
|
name:
|
||||||
|
apt: rust-doc
|
||||||
|
java-lang:
|
||||||
|
name:
|
||||||
|
apt: default-jdk-headless
|
||||||
|
java-docs:
|
||||||
|
name:
|
||||||
|
apt: default-jdk-doc
|
||||||
|
java-runtime:
|
||||||
|
name:
|
||||||
|
apt: default-jre-headless
|
||||||
|
kotlin-lang:
|
||||||
|
name:
|
||||||
|
apt: kotlin
|
||||||
|
swift-lang:
|
||||||
|
name:
|
||||||
|
apt: swiftlang
|
||||||
|
swift-docs:
|
||||||
|
name:
|
||||||
|
apt: swiftlang-doc
|
||||||
|
erlang-lang:
|
||||||
|
name:
|
||||||
|
apt: erlang
|
||||||
|
erlang-pkg:
|
||||||
|
name:
|
||||||
|
apt: erlang-hex
|
||||||
|
erlang-docs:
|
||||||
|
name:
|
||||||
|
apt: erlang-doc
|
||||||
|
elixir-lang:
|
||||||
|
name:
|
||||||
|
apt: elixir
|
||||||
|
crystal-lang:
|
||||||
|
name:
|
||||||
|
apt: crystal
|
||||||
|
crystal-docs:
|
||||||
|
name:
|
||||||
|
apt: crystal-doc
|
||||||
|
javascript-lang:
|
||||||
|
name:
|
||||||
|
apt: nodejs
|
||||||
|
javascript-docs:
|
||||||
|
name:
|
||||||
|
apt: nodejs-doc
|
||||||
|
javascript-pkg:
|
||||||
|
name:
|
||||||
|
apt: npm
|
||||||
|
javascript-linter:
|
||||||
|
name:
|
||||||
|
apt: eslint
|
||||||
|
php-lang:
|
||||||
|
name:
|
||||||
|
apt: php
|
||||||
|
php-docs:
|
||||||
|
name:
|
||||||
|
apt: php-common
|
||||||
|
php-debugger:
|
||||||
|
name:
|
||||||
|
apt: php-xdebug
|
||||||
|
php-pkg:
|
||||||
|
name:
|
||||||
|
apt: composer
|
||||||
|
html-linter:
|
||||||
|
name:
|
||||||
|
apt: tidy
|
||||||
|
json-linter:
|
||||||
|
name:
|
||||||
|
apt: jsonlint
|
||||||
|
yaml-linter:
|
||||||
|
name:
|
||||||
|
apt: yamllint
|
||||||
|
pandoc:
|
||||||
|
name:
|
||||||
|
apt: pandoc
|
||||||
|
distrobox:
|
||||||
|
name:
|
||||||
|
apt: distrobox
|
||||||
|
# @TODO manually install the commented below on current active new VPS, then uncomment
|
||||||
|
# duplicity:
|
||||||
|
# name:
|
||||||
|
# apt: duplicity
|
||||||
|
# pass:
|
||||||
|
# name:
|
||||||
|
# apt: pass
|
||||||
|
# sonicpi:
|
||||||
|
# name:
|
||||||
|
# apt: sonic-pi-server
|
||||||
|
# sonicpi-docs:
|
||||||
|
# name:
|
||||||
|
# apt: sonic-pi-server-doc
|
||||||
|
# supercollider:
|
||||||
|
# name:
|
||||||
|
# apt: supercollider
|
||||||
|
# supercollider-docs:
|
||||||
|
# name:
|
||||||
|
# apt: supercollider-common
|
||||||
|
# supercollider-plugins:
|
||||||
|
# name:
|
||||||
|
# apt: sc3-plugins-language
|
||||||
|
qrencode:
|
||||||
|
name:
|
||||||
|
apt: qrencode
|
||||||
|
ffmpeg:
|
||||||
|
name:
|
||||||
|
apt: ffmpeg
|
||||||
|
ffmpeg-docs:
|
||||||
|
name:
|
||||||
|
apt: ffmpeg-doc
|
||||||
|
graphicsmagick:
|
||||||
|
name:
|
||||||
|
apt: graphicsmagick
|
||||||
|
graphicsmagick-compatibility:
|
||||||
|
name:
|
||||||
|
apt: graphicsmagick-imagemagick-compat
|
||||||
|
timg:
|
||||||
|
name:
|
||||||
|
apt: timg
|
||||||
|
tmux:
|
||||||
|
name:
|
||||||
|
apt: tmux
|
||||||
|
# @TODO add glow apt repository in install@linux bootstrap role play before uncommenting the below
|
||||||
|
# glow:
|
||||||
|
# name:
|
||||||
|
# apt: glow
|
||||||
|
# @TODO add ZFS apt repository in install@linux bootstrap role play before uncommenting the below
|
||||||
|
# zfs:
|
||||||
|
# name:
|
||||||
|
# apt: zfsutils-linux
|
||||||
|
# @TODO manually install the commented below on current active new VPS, then uncomment
|
||||||
|
# dpkg-dev:
|
||||||
|
# name:
|
||||||
|
# apt: dpkg-dev
|
||||||
|
# ldap-utils:
|
||||||
|
# name:
|
||||||
|
# apt: ldap-utils
|
||||||
|
# slapd:
|
||||||
|
# name:
|
||||||
|
# apt: slapd
|
||||||
|
# proftpd:
|
||||||
|
# name:
|
||||||
|
# apt: proftpd
|
||||||
|
# rsync:
|
||||||
|
# name:
|
||||||
|
# apt: rsync
|
||||||
|
# rclone:
|
||||||
|
# name:
|
||||||
|
# apt: rsync
|
||||||
|
# aria:
|
||||||
|
# name:
|
||||||
|
# apt: aria2
|
||||||
|
# mopidy:
|
||||||
|
# name:
|
||||||
|
# apt: mopidy
|
||||||
|
# mopidy-mpd:
|
||||||
|
# name:
|
||||||
|
# apt: mopidy-mpd
|
||||||
|
# caddy:
|
||||||
|
# name:
|
||||||
|
# apt: caddy
|
||||||
|
config:
|
||||||
|
git:
|
||||||
|
sys:
|
||||||
|
editor: nvim
|
||||||
|
|
||||||
Reference in New Issue
Block a user