Merge branch 'develop'

This commit is contained in:
2021-03-04 13:14:18 +00:00
34 changed files with 569 additions and 176 deletions

6
commands Normal file
View File

@@ -0,0 +1,6 @@
ansible-playbook -b test.yml --vault-password-file password --tags rust
ansible-playbook -b test.yml --vault-password-file password --tags "setup,terraform"
ansible-galaxy install -r requirements.yml
ansible-vault encrypt_string 'email-smtp.eu-west-1.amazonaws.com' --name 'vault_smtp_hostname' --vault-pass-file ./password

View File

@@ -55,6 +55,7 @@ packages_to_install:
- tk-dev
- tmux
- ufw
- unzip
- vim
- wget
- wget

15
group_vars/all/docker.yml Normal file
View File

@@ -0,0 +1,15 @@
docker__channel: ["stable"]
docker__edition: "ce"
docker__version: ""
docker__state: "present"
docker__users: ["{{ default_user }}"]
docker__daemon_flags:
- "-H unix://"
docker__cron_jobs_prune_flags: "af"
docker__cron_jobs:
- name: "Docker disk clean up"
job: "docker system prune -{{ docker__cron_jobs_prune_flags }} > /dev/null 2>&1"
schedule: ["0", "0", "*", "*", "0"]
cron_file: "docker-disk-clean-up"
user: "{{ (docker__users | first) | d('root') }}"
state: "present"

View File

@@ -0,0 +1,6 @@
fail2ban_loglevel: INFO
fail2ban_services:
- name: ssh
port: ssh
filter: sshd
logpath: /var/log/auth.log

View File

@@ -0,0 +1,3 @@
pyenv_python_version: 3.9.0
pipx_packages:
- awscli

2
group_vars/all/rust.yml Normal file
View File

@@ -0,0 +1,2 @@
---
install_cargo_packages: true

11
group_vars/all/setup.yml Normal file
View File

@@ -0,0 +1,11 @@
# Time
ntpserver: pool.ntp.org
timezone: Europe/London
# Email
dot_forward_email: dtomlinson@panaetius.co.uk
smtp_hostname: "{{ vault_smtp_hostname }}"
smtp_port: 25
smtp_auth_user: "{{ vault_smtp_auth_user }}"
smtp_auth_pass: "{{ vault_smtp_auth_pass }}"
smtp_mail_from: "test-server@panaetius.co.uk"

12
group_vars/all/ufw.yml Normal file
View File

@@ -0,0 +1,12 @@
# Not implemented: FW can be manually tweaked as necessary
# Local LAN IP-range addresses
# local_lan: "192.168.0.0/16"
# docker_overlay_ips: "172.0.0.0/8"
# ufw rules
# ufw_rules:
# - {rule: allow, port: 22, src: "{{local_lan}}", proto: tcp, direction: "in"}
# - {rule: allow, port: 22, src: "{{docker_overlay_ips}}", proto: tcp, direction: "in"}
# - {rule: allow, port: 80, src: "0.0.0.0/0", proto: tcp, direction: "in"}
# - {rule: allow, port: 443, src: "0.0.0.0/0", proto: tcp, direction: "in"}

View File

@@ -1,5 +1,2 @@
---
default_user: plex
default_user_password: "{{ vault_default_user_password }}"
pyenv_python_version: 3.9.0
...

30
group_vars/all/vault.yml Normal file
View File

@@ -0,0 +1,30 @@
vault_default_user_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
65616334373032636534383932373465623634363431323863393839663937613838383566383035
6133633038623361636630346233643838623533383333300a356332363165376330376236356665
37656230373838373038386234326563656637306236383162383866343163623366356631373862
6631616666363137620a363835316632313730623534353336303730363964653231336139383961
6361
vault_smtp_hostname: !vault |
$ANSIBLE_VAULT;1.1;AES256
38373930343363666238326563663338386232386265663663663732313165613437303663333232
6266373339613864386638323436373363623937326130610a373530366237626564303666386364
39313063346137373132363331373261653736316662666431636363613338303034623430653033
3764613532646232630a373032356364636566376638646162623034623663313263326630306564
38323835356437326431323637323432363630653738383936343737333634636662396535383164
6334343166613762373130653961663334393335363066643539
vault_smtp_auth_user: !vault |
$ANSIBLE_VAULT;1.1;AES256
66313165326136343630393030366662303639626237376563633035326636343866363933613436
3235333533353136333564363134626136326565383866650a343865626363346565336131643832
38656463393930376437356634633531656636666266623639663638613563613263356639313939
3838356561306466650a623066303265353361633238643161306562336163623436643736653535
64646164346366663766366136323661663731393136643238633435643739316531
vault_smtp_auth_pass: !vault |
$ANSIBLE_VAULT;1.1;AES256
36336437393838663665383465313432373866656461356635646331396165323132623163343762
3031666331323464326538373839373933336130303537350a326538393330303339626565646434
36656665313166653534663237633665633434643166633862326136643738636265396439613465
3661316235633830640a333939393762303035653632303664623465373431313061643438616363
30343535323764636437656431313430663536316132366361666436643732636363666266353162
3362343930306564656331643135363264346263663739616637

View File

@@ -1,7 +0,0 @@
vault_default_user_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
65616334373032636534383932373465623634363431323863393839663937613838383566383035
6133633038623361636630346233643838623533383333300a356332363165376330376236356665
37656230373838373038386234326563656637306236383162383866343163623366356631373862
6631616666363137620a363835316632313730623534353336303730363964653231336139383961
6361

7
requirements.yml Normal file
View File

@@ -0,0 +1,7 @@
---
- src: fubarhouse.golang
- src: nickjj.docker
- src: nickjj.fail2ban
- src: jnv.debian-backports
- src: jnv.unattended-upgrades
...

View File

@@ -0,0 +1,6 @@
- name: Remove temporary directory
tags: always
file:
path: "{{ temp_install_dir.path }}"
state: absent
when: temp_install_dir.path is defined

View File

@@ -0,0 +1,2 @@
if $syslogtag contains 'docker/' then /var/log/docker.log
& ~

View File

@@ -0,0 +1,12 @@
/var/log/docker.log
{
rotate 7
daily
missingok
notifempty
delaycompress
compress
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}

View File

@@ -0,0 +1,10 @@
---
- name: restart docker
service:
name: docker
state: restarted
- name: restart rsyslog
service:
name: rsyslog
state: restarted

View File

@@ -0,0 +1,34 @@
- name: Install and configure Docker
tags: [docker, server]
become: true
block:
- name: Install Docker
include_role:
name: nickjj.docker
- name: Ensure group "docker" exists
group:
name: docker
state: present
- name: Ensure default user belongs also to docker group
user:
name: "{{ default_user }}"
groups: docker
append: yes
- name: Add rsyslog custom rules for Docker
copy:
src: docker.conf
dest: /etc/rsyslog.d/docker.conf
owner: root
group: root
mode: u=rw,g=r,o=r
- name: Add logrotate custom rules for Docker logs
copy:
src: logrotate_docker
dest: /etc/logrotate.d/docker
owner: root
group: root
mode: u=rw,g=r,o=r

18
roles/go/tasks/main.yml Normal file
View File

@@ -0,0 +1,18 @@
- name: Install and configure GO
tags: go
become: true
# become_user: "{{ default_user }}"
block:
- name: Install and configure GO
include_role:
name: fubarhouse.golang
vars:
GOPATH: "{{ default_user_home }}/go"
- name: Set permissions on GOPATH
file:
path: "{{ default_user_home }}/go"
state: directory
recurse: true
owner: "{{ default_user }}"
group: "{{ default_user }}"

View File

@@ -0,0 +1,40 @@
- name: Install and configure Python + tools
tags: python
become: true
become_user: "{{ default_user }}"
block:
- name: Install Pyenv
shell: curl https://pyenv.run | zsh
args:
creates: "{{ default_user_home }}/.pyenv/bin/pyenv"
environment:
PYENV_ROOT: "{{ default_user_home }}/.pyenv"
- name: Install Pyenv version of Python
shell: "{{ default_user_home }}/.pyenv/bin/pyenv install {{ pyenv_python_version }}"
args:
creates: "{{ default_user_home }}/.pyenv/versions/{{ pyenv_python_version }}/bin/python"
- name: Install pipx
command: python3 -m pip install pipx --user
args:
creates: "{{ default_user_home }}/.local/bin/pipx"
- name: Install pipx packages
shell: "{{ default_user_home }}/.local/bin/pipx install {{ item }}"
loop: "{{ pipx_packages }}"
- name: Install Poetry
shell: curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3
args:
creates: "{{ default_user_home }}/.poetry/bin/poetry"
- name: Install Poetry plugin for oh-my-zsh
shell: |
mkdir {{ default_user_home }}/.oh-my-zsh/custom/plugins/poetry
{{ default_user_home }}/.poetry/bin/poetry completions zsh > {{ default_user_home }}/.oh-my-zsh/custom/plugins/poetry/_poetry
args:
creates: "{{ default_user_home }}/.oh-my-zsh/custom/plugins/poetry"
- name: Configure Poetry
command: "{{ default_user_home }}/.poetry/bin/poetry config virtualenvs.in-project true"

17
roles/rust/tasks/main.yml Normal file
View File

@@ -0,0 +1,17 @@
- name: Install and configure Rust
tags: rust
become: true
become_user: "{{ default_user }}"
block:
- name: Install Rust toolchain
shell: curl https://sh.rustup.rs -sSf | sh -s -- -y
args:
creates: "{{ default_user_home }}/.cargo/bin/rustup"
environment:
RUSTUP_HOME: "{{ default_user_home }}/.rustup"
CARGO_HOME: "{{ default_user_home }}/.cargo"
- name: Install base rust programs
shell: "{{ default_user_home }}/.cargo/bin/cargo install {{ item }}"
loop: "{{ cargo_packages }}"
when: install_cargo_packages

View File

@@ -0,0 +1 @@
AUTH_CLIENT_ALLOW_NOTLS_PASSWORDS = 1

View File

@@ -0,0 +1,20 @@
---
- name: restart ntp
service:
name: ntp
state: restarted
- name: restart cron
service:
name: cron
state: restarted
- name: restart fail2ban
service:
name: fail2ban
state: restarted
- name: restart exim4
service:
name: exim4
state: restarted

118
roles/setup/tasks/main.yml Normal file
View File

@@ -0,0 +1,118 @@
- name: Initial server setup
tags: [setup, server]
block:
- name: Create default user
user:
name: "{{ default_user }}"
password: "{{ default_user_password | password_hash('sha512') }}"
groups: sudo
create_home: yes
shell: /bin/zsh
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
update_password: always
state: present
- name: Ensure sudo group has passwordless sudo privileges
lineinfile:
dest: /etc/sudoers
state: present
regexp: "^%sudo"
line: "%sudo ALL=(ALL) NOPASSWD:ALL"
validate: "/usr/sbin/visudo -cf %s"
- name: Upgrade apt packages
apt:
update_cache: yes
upgrade: full
- name: Install apt packages
apt:
name: "{{ packages_to_install }}"
- name: Add Debian backports
include_role:
name: jnv.debian-backports
- name: Add unattended-upgrades
include_role:
name: jnv.unattended-upgrades
- name: Install mozilla/sops
get_url:
url: https://github.com/mozilla/sops/releases/download/v3.5.0/sops-v3.5.0.linux
dest: /usr/bin/sops
mode: "0755"
owner: root
group: root
- name: Enable dm_crypt module
modprobe:
name: dm_crypt
state: present
- name: Enable compress on logrotate
lineinfile:
dest: /etc/logrotate.conf
regexp: "^#?compress"
line: "compress"
state: present
- name: Configure timezone
timezone:
name: "{{ timezone }}"
- name: Configure ntp client and restart it
template:
src: ntp.conf.j2
dest: /etc/ntp.conf
notify:
- restart ntp
- restart cron
- name: Set up exim4 conf
template:
src: update-exim4.conf.conf.j2
dest: /etc/exim4/update-exim4.conf.conf
owner: root
group: root
mode: 0644
- name: Set up exim4 password file
template:
src: passwd.client.j2
dest: /etc/exim4/passwd.client
owner: root
group: Debian-exim
mode: 0640
- name: Set up exim4 localmacros
copy:
src: exim4.conf.localmacros
dest: /etc/exim4/exim4.conf.localmacros
owner: root
group: root
mode: 0644
notify: restart exim4
- name: Set up FROM addresses
template:
src: email-addresses.j2
dest: /etc/email-addresses
owner: root
group: root
mode: 0644
notify: restart exim4
- name: Make fail2ban work with ufw
lineinfile:
dest: "{{ item }}"
regexp: "^banaction"
line: "banaction = ufw"
state: present
with_items:
- /etc/fail2ban/jail.conf
- /etc/fail2ban/jail.local
notify:
- restart fail2ban

View File

@@ -0,0 +1,2 @@
root: "{{ smtp_mail_from }}"
{{ default_user }}: "{{ smtp_mail_from }}"

View File

@@ -0,0 +1,8 @@
driftfile /var/lib/ntp/drift
restrict 127.0.0.1
restrict -6 ::1
restrict source notrap nomodify noquery
server {{ntpserver}}

View File

@@ -0,0 +1,8 @@
# password file used when the local exim is authenticating to a remote
# host as a client.
#
# see exim4_passwd_client(5) for more documentation
#
# Example:
### target.mail.server.example:login:password
*:{{smtp_auth_user}}:{{smtp_auth_pass}}

View File

@@ -0,0 +1,31 @@
# /etc/exim4/update-exim4.conf.conf
#
# Edit this file and /etc/mailname by hand and execute update-exim4.conf
# yourself or use 'dpkg-reconfigure exim4-config'
#
# Please note that this is _not_ a dpkg-conffile and that automatic changes
# to this file might happen. The code handling this will honor your local
# changes, so this is usually fine, but will break local schemes that mess
# around with multiple versions of the file.
#
# update-exim4.conf uses this file to determine variable values to generate
# exim configuration macros for the configuration file.
#
# Most settings found in here do have corresponding questions in the
# Debconf configuration, but not all of them.
#
# This is a Debian specific file
dc_eximconfig_configtype='satellite'
dc_other_hostnames='{{ansible_host}}'
dc_local_interfaces='127.0.0.1 ; ::1'
dc_readhost='{{ansible_host}}'
dc_relay_domains=''
dc_minimaldns='false'
dc_relay_nets=''
dc_smarthost='{{smtp_hostname}}::{{smtp_port}}'
CFILEMODE='644'
dc_use_split_config='false'
dc_hide_mailname='true'
dc_mailname_in_oh='true'
dc_localdelivery='mail_spool'

View File

@@ -1,44 +1,25 @@
---
- name: Create default user
user:
name: "{{ default_user }}"
password: "{{ default_user_password | password_hash('sha512') }}"
groups: sudo
create_home: yes
shell: /bin/zsh
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
update_password: always
state: present
- name: Ensure sudo group has passwordless sudo privileges
lineinfile:
dest: /etc/sudoers
state: present
regexp: "^%sudo"
line: "%sudo ALL=(ALL) NOPASSWD:ALL"
validate: "/usr/sbin/visudo -cf %s"
- name: Upgrade apt packages
apt:
update_cache: yes
upgrade: full
- name: Install apt packages
apt:
name: "{{ packages_to_install }}"
- name: Configure shell for default user
tags: shell
become: true
become_user: "{{ default_user }}"
block:
- name: Get default user home
getent:
database: passwd
key: "{{ default_user }}"
split: ":"
tags: always
- name: Set default user home
set_fact:
default_user_home: "{{ getent_passwd[default_user][4] }}"
tags: always
- name: Install and configure default user environment
become: true
become_user: "{{ default_user }}"
block:
- name: Install .tmux.conf to default user
copy:
src: .tmux.conf
@@ -55,23 +36,18 @@
suffix: .tmp
register: temp_install_dir
changed_when: false
become: true
become_user: "{{ default_user }}"
tags: always
- name: Download oh-my-zsh
get_url:
url: https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh
dest: "{{ temp_install_dir.path }}"
mode: 0777
become: true
become_user: "{{ default_user }}"
- name: Install oh-my-zsh
shell: "sh {{ temp_install_dir.path }}/install.sh --unattended"
args:
creates: "{{ default_user_home }}/.oh-my-zsh"
become: true
become_user: "{{ default_user }}"
- name: Install powerlevel10k theme
git:
@@ -113,63 +89,3 @@
group: "{{default_user}}"
force: yes
mode: 0644
- name: Install Rustup
shell: curl https://sh.rustup.rs -sSf | sh -s -- -y
args:
creates: "{{ default_user_home }}/.cargo/bin/rustup"
environment:
RUSTUP_HOME: "{{ default_user_home }}/.rustup"
CARGO_HOME: "{{ default_user_home }}/.cargo"
become: true
become_user: "{{ default_user }}"
- name: Install pyenv
shell: curl https://pyenv.run | zsh
args:
creates: "{{ default_user_home }}/.pyenv/bin/pyenv"
environment:
PYENV_ROOT: "{{ default_user_home }}/.pyenv"
become: true
become_user: "{{ default_user }}"
- name: Install pyenv version of python
shell: "{{ default_user_home }}/.pyenv/bin/pyenv install {{ pyenv_python_version }}"
args:
creates: "{{ default_user_home }}/.pyenv/versions/{{ pyenv_python_version }}/bin/python"
become: true
become_user: "{{ default_user }}"
- name: Install pipx
command: python3 -m pip install pipx --user
args:
creates: "{{ default_user_home }}/.local/bin/pipx"
become: true
become_user: "{{ default_user }}"
- name: Install poetry
shell: curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3
args:
creates: "{{ default_user_home }}/.poetry/bin/poetry"
become: true
become_user: "{{ default_user }}"
- name: Install poetry plugin for oh-my-zsh
shell: |
mkdir {{ default_user_home }}/.oh-my-zsh/custom/plugins/poetry
{{ default_user_home }}/.poetry/bin/poetry completions zsh > {{ default_user_home }}/.oh-my-zsh/custom/plugins/poetry/_poetry
args:
creates: "{{ default_user_home }}/.oh-my-zsh/custom/plugins/poetry"
become: true
become_user: "{{ default_user }}"
- name: Configure poetry
command: "{{ default_user_home }}/.poetry/bin/poetry config virtualenvs.in-project true"
become: true
become_user: "{{ default_user }}"
- name: Install base rust programs
shell: "{{ default_user_home }}/.cargo/bin/cargo install {{ item }}"
loop: "{{ cargo_packages }}"
become: true
become_user: "{{ default_user }}"

View File

@@ -191,11 +191,17 @@ export PATH="$HOME/.poetry/bin:$PATH"
################################################################
source "$HOME/.cargo/env"
################################################################
# GO #
################################################################
export GOBIN="$HOME/go/bin"
export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"
################################################################
# APPS #
################################################################
# AWS
# complete -C "$HOME/.local/bin/aws_completer" aws
complete -C "$HOME/.local/bin/aws_completer" aws
# TFEnv
export PATH="$PATH:$HOME/.tfenv/bin"

View File

@@ -0,0 +1,5 @@
---
- name: restart ssh
service:
name: ssh
state: restarted

19
roles/ssh/tasks/main.yml Normal file
View File

@@ -0,0 +1,19 @@
---
- name: Configure SSH access
tags: [ssh, server]
become: true
block:
- name: Remove any PermitRootLogin instruction
lineinfile:
dest: /etc/ssh/sshd_config
regexp: "^PermitRootLogin"
state: absent
notify: restart ssh
- name: Disable SSH root login
lineinfile:
dest: /etc/ssh/sshd_config
regexp: "^PermitRootLogin"
line: "PermitRootLogin prohibit-password"
state: present
notify: restart ssh

View File

@@ -0,0 +1,19 @@
- name: Install and configure Terraform
tags: terraform
become: true
become_user: "{{ default_user }}"
block:
- name: Install tfenv
git:
repo: https://github.com/tfutils/tfenv.git
version: master
dest: "{{ default_user_home }}/.tfenv"
depth: 1
- name: Install latest version of Terraform
shell: "{{ default_user_home }}/.tfenv/bin/tfenv install latest"
args:
creates: "{{ default_user_home }}/.tfenv/version"
- name: Use latest version of Terraform
shell: "{{ default_user_home }}/.tfenv/bin/tfenv use latest"

View File

@@ -1,12 +1,19 @@
Tasks:
Create initial folder layout @started(21-02-28 23:29)
Create initial folder layout @started(21-02-28 23:29) @done(21-03-03 14:30) @lasted(2d15h1m16s)
✔ Create test playbook with a task @done(21-03-01 00:16)
✔ Document creating a hosts file, and an `ansible.cfg` to create an inventory @done(21-03-01 00:07)
<https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html>
Alternative to using an `ansible.cfg` is using the flag `-i hosts`
Hosts file can contain `ansible_user` and `ansible_ssh_pass` under a `vars` header
✔ Test a connection with `ansible all -m ping` @done(21-03-01 00:08)
Document commands
Document commands @done(21-03-03 14:30)
Run a playbook with `ansible-playbook -b test.yml`
If using vault do `--ask-vault-pass`
Point to an inventory with `-i hosts`
☐ Configure nebula
☐ Still to configure:
☐ Monit
✔ UFW @done(21-03-04 12:57)
✔ Networking @done(21-03-04 12:59)
✔ Configure /etc/email-addresses with from addresses for root and default_user @done(21-03-04 12:57)
<https://serverfault.com/questions/377821/exim-send-every-emails-with-a-predefined-sender>

View File

@@ -1,5 +1,16 @@
---
- hosts: all
vars:
install_cargo_packages: true
roles:
- role: nickjj.fail2ban
tags: [server, fail2ban]
- role: setup
- role: ssh
- role: shell
tags: shell
- role: python
- role: rust
- role: terraform
- role: go
- role: docker
- role: cleanup