Initial Commit

This commit is contained in:
Christer Warén 2024-05-05 18:10:54 +03:00
commit 923312b782
16 changed files with 693 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
!/collections/.gitkeep
/collections
/vault
__pycache__

6
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"editor.renderFinalNewline": false
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Warén Group
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

16
ansible.cfg Normal file
View File

@ -0,0 +1,16 @@
[defaults]
inventory = inventories/mkj
hash_behaviour = merge
gathering = smart
transport = local
display_skipped_hosts = false
interpreter_python = auto_silent
localhost_warning = false
collections_path = collections
inject_facts_as_vars = false
force_handlers = true
action_warnings = false
inventory_unparsed_warning = false
[inventory]
host_pattern_mismatch = ignore

5
files/certbot/nginx.sh Normal file
View File

@ -0,0 +1,5 @@
#!/bin/bash
echo -n "$CERTBOT_VALIDATION" > /root/nginx/html/.well-known/acme-challenge/$CERTBOT_TOKEN
mkdir -p /root/nginx/html/.well-known/acme-challenge
/opt/ansible/bin/ansible-pull -U ssh://git@github.com/MatteZ02/mkj-infra --vault-password-file ~/.ansible/vault.yml --private-key ~/.ssh/id_rsa tasks.yml -t nginx &> /dev/null

View File

@ -0,0 +1,81 @@
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
expires off;
etag off;
if_modified_since off;
gzip on;
gzip_min_length 1000;
gzip_proxied any;
gzip_types *;
gunzip on;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
return 301 https://$host$request_uri;
}
location /.well-known/acme-challenge/ {
root /usr/share/nginx/html;
index index.html index.htm;
}
if ($request_method !~ ^(GET|HEAD|POST)$ )
{
return 405;
}
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;
http2 on;
ssl_certificate /etc/nginx/certs/mkj/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/mkj/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-CCM:ECDHE-ARIA256-GCM-SHA384:DHE-RSA-ARIA256-GCM-SHA384:ECDHE-ARIA128-GCM-SHA256:DHE-RSA-ARIA128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-CCM';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 180m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/certs/mkj/chain.pem;
expires off;
etag off;
if_modified_since off;
gzip on;
gzip_min_length 1000;
gzip_proxied any;
gzip_types *;
gunzip on;
client_max_body_size 256M;
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE)$ )
{
return 405;
}
}

31
files/nginx/config.conf Normal file
View File

@ -0,0 +1,31 @@
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log error;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '[$time_local] $host - $remote_addr - $remote_user "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
server_tokens off;
sendfile off;
#tcp_nopush on;
keepalive_timeout 65;
resolver 1.1.1.1;
include /etc/nginx/conf.d/*.conf;
}

50
install.sh Normal file
View File

@ -0,0 +1,50 @@
#!/bin/bash
if [ ! "$BASH_VERSION" ] ; then
exit 1
fi
echo "
==============================
MKJ - Infra
Install Script
------------------------------
"
stop () {
echo "
==============================
"
exit 1
}
mkdir -p ~/.ssh &> /dev/null
apt-get install -y python3-pip python3-venv jq git curl &> /dev/null
python3 -m venv /opt/ansible &> /dev/null
/opt/ansible/bin/pip3 install ansible hvac netaddr jmespath pexpect &> /dev/null
/opt/ansible/bin/ansible-galaxy collection install -r requirements.yml --upgrade &> /dev/null
mkdir -p ~/.ansible &> /dev/null
if [[ ! -f ~/.ansible/vault.yml ]]
then
echo -n "Vault Password: "
read PASSWORD
echo "$PASSWORD" > ~/.ansible/vault.yml
fi
ssh-keyscan github.com 1> ~/.ssh/known_hosts 2> /dev/null
/opt/ansible/bin/ansible-pull -U ssh://git@github.com/MatteZ02/mkj-ansible --vault-password-file ~/.ansible/vault.yml --private-key ~/.ssh/id_rsa tasks.yml -t installer
echo "
==============================
"

View File

@ -0,0 +1,14 @@
$ANSIBLE_VAULT;1.1;AES256
34366533383537636563363238346530306364323437633062363834363738613462666632653730
3231376531356466333161643535353433633834633765300a343462663562663065326131663765
33356238666332326130643662386265666665303566643330326466353334366635626232386465
3937366161663038340a386134616234653635313339663031366137343362663262616166376262
36666461326634376262613362393139623230326238363736643133656537303332393234616566
31646338313832663462656638313833336135663336316634616332636663386230306665623337
30666131393732356337613530393238633733653162313631323766643563366134326265376163
37666564656664323035343132336564343861643030396266616538353165376230393636663134
62313063336538636464396134666134336662633534376435656363633632623964343338663866
35623832633033363532303831366530363834393363333333623832616461323464393761333664
34386262343338306164353539363230613562633231386436653134333235336638646334643332
31663430333230663363316437336332303633633263336437313761396164656564666539393264
3632

7
inventories/mkj/hosts Normal file
View File

@ -0,0 +1,7 @@
---
all:
hosts:
mkj:
vars:
ansible_connection: local
ansible_python_interpreter: "{{ansible_playbook_python}}"

57
protect.sh Executable file
View File

@ -0,0 +1,57 @@
#!/bin/bash
underline=`tput smul`
nounderline=`tput rmul`
bold=$(tput bold)
normal=$(tput sgr0)
echo "${bold}MKJ / Infra / Protect${normal}"
action=$1
encrypt() {
echo "${underline}Encrypting...${nounderline}"
execute "ansible-vault encrypt --vault-id default@vault/mkj"
}
decrypt() {
echo "${underline}Decrypting...${nounderline}"
execute "ansible-vault decrypt --vault-id default@vault/mkj"
}
list() {
echo "${underline}Listing...${nounderline}"
i=0
for file in inventories/*/group_vars/* inventories/*/host_vars/*;
do
i=$((i + 1))
echo $i")"$file
done
}
execute() {
for file in inventories/*/group_vars/* inventories/*/host_vars/*;
do
i=$((i + 1))
echo $i")"$file
$1 $file
done
}
case $action in
encrypt)
encrypt
;;
decrypt)
decrypt
;;
list)
list
;;
help)
echo "encrypt, decrypt, list"
;;
*)
echo "..."
;;
esac

3
requirements.yml Normal file
View File

@ -0,0 +1,3 @@
---
collections:
- containers.podman

25
tasks.yml Normal file
View File

@ -0,0 +1,25 @@
---
- name: "Tasks"
hosts: all
module_defaults:
ansible.builtin.gather_facts:
gather_timeout: 10
tasks:
- name: "Installer"
import_tasks: tasks/installer.yml
tags:
- installer
- never
- name: "Maintenance"
import_tasks: tasks/maintenance.yml
tags:
- maintenance
- never
- name: "Deployer"
import_tasks: tasks/deployer.yml
tags:
- deployer
- never

152
tasks/deployer.yml Normal file
View File

@ -0,0 +1,152 @@
---
- name: "Deployer - Certbot - Renew Certificates"
command: "certbot renew"
register: task
changed_when: task.stdout.find("No renewals were attempted.") == -1
tags:
- certbot
- tls
- name: "Deployer - Certbot - Copy Certificates"
copy:
src: "/etc/letsencrypt/live/mkj/"
dest: "/root/certs/mkj/"
follow: true
register: task
tags:
- certbot
- tls
- name: "Deployer - MariaDB - Pull Image"
containers.podman.podman_image:
name: docker.io/mariadb
tag: latest
force: on
register: deployerTask101
- name: "Deployer - MariaDB - Run Container"
containers.podman.podman_container:
name: mariadb
image: docker.io/mariadb:latest
state: started
restart: on
network: host
volumes:
- "/root/mariadb:/var/lib/mysql"
restart_policy: always
env:
MYSQL_ROOT_PASSWORD: "{{ secrets.mariadb.root.password }}"
register: deployerTask102
when:
- (deployerTask101 is defined and deployerTask101.changed) or deployerTask101 is undefined
tags:
- mariadb
- name: "Deployer - MariaDB - Wait"
wait_for:
host: "127.0.0.1"
port: "3306"
delay: 10
when:
- (deployerTask102 is defined and deployerTask102.changed) or deployerTask102 is undefined
tags:
- mariadb
- name: "Deployer - MariaDB - Upgrade"
containers.podman.podman_container_exec:
name: mariadb
command: "mariadb-upgrade --host=127.0.0.1 --user=root --password={{ secrets.mariadb.root.password }}"
register: task
ignore_errors: yes
changed_when:
- task.stdout is defined
- task.stdout.find("This installation of MariaDB is already upgraded") == -1
when:
- (deployerTask102 is defined and deployerTask102.changed) or deployerTask102 is undefined
tags:
- mariadb
- name: "Deployer - MariaDB - Create Users"
mysql_user:
login_host: "127.0.0.1"
login_user: root
login_password: "{{ secrets.mariadb.root.password }}"
name: "mkj"
host: "%"
password: "{{ secrets.mariadb.mkj.password }}"
priv: "mkj.*:ALL"
vars:
ansible_python_interpreter: "/opt/ansible/bin/python3"
when:
- (deployerTask102 is defined and deployerTask102.changed) or deployerTask102 is undefined
tags:
- mariadb
- name: "Deployer - MariaDB - Create Database"
mysql_db:
login_host: "127.0.0.1"
login_user: "mkj"
login_password: "{{ secrets.mariadb.mkj.password }}"
name: "mkj"
vars:
ansible_python_interpreter: "/opt/ansible/bin/python3"
when:
- (deployerTask102 is defined and deployerTask102.changed) or deployerTask102 is undefined
tags:
- mariadb
- name: "Deployer - Nginx - Configure - Create Folder"
file:
path: "/root/nginx/"
state: directory
tags:
- nginx
- name: "Deployer - Nginx - Configure - Create Subfolders"
file:
dest: '/root/nginx/{{ item.path }}'
state: directory
with_filetree: './files/nginx/'
loop_control:
label: "{{ item.path }}"
when:
- item.state == 'directory'
tags:
- nginx
- name: "Deployer - Nginx - Configure - Generating & Transferring Files"
template:
src: '{{ item.src }}'
dest: '/root/nginx/{{ item.path }}'
with_filetree: './files/nginx/'
loop_control:
label: "{{ item.path }}"
when:
- item.state == 'file'
tags:
- nginx
- name: "Deployer - Nginx - Pull Image"
containers.podman.podman_image:
name: docker.io/nginx
tag: latest
force: on
register: deployerTask3
- name: "Deployer - Nginx - Run Container"
containers.podman.podman_container:
name: nginx
image: docker.io/nginx
state: started
recreate: on
network: host
volumes:
- "/root/nginx/html:/usr/share/nginx/html:ro"
- "/root/nginx/config.conf:/etc/nginx/nginx.conf:ro"
- "/root/nginx/conf/:/etc/nginx/conf.d/:ro"
- "/root/certs/:/etc/nginx/certs/:ro"
restart_policy: always
when:
- (deployerTask3 is defined and deployerTask3.changed) or deployerTask3 is undefined
tags:
- nginx

184
tasks/installer.yml Normal file
View File

@ -0,0 +1,184 @@
---
- name: "Installer - Ansible - Python Library"
pip:
name: ansible
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"
tags:
- ansible
- name: "Installer - Ansible - Create Symbolic Links"
ansible.builtin.file:
src: /opt/ansible/bin/{{ binary }}
dest: /usr/bin/{{ binary }}
state: link
vars:
binaries:
- ansible
- ansible-community
- ansible-config
- ansible-connection
- ansible-console
- ansible-doc
- ansible-galaxy
- ansible-inventory
- ansible-playbook
- ansible-pull
- ansible-test
- ansible-vault
loop: "{{ binaries }}"
loop_control:
label: "{{ binary }}"
loop_var: "binary"
tags:
- ansible
- name: "Installer - Ansible - Dependencies / Python Library : hvac"
pip:
name: hvac
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"
tags:
- ansible
- name: "Installer - Ansible - Dependencies / Python Library : netaddr"
pip:
name: netaddr
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"
tags:
- ansible
- name: "Installer - Ansible - Dependencies / Python Library : jmespath"
pip:
name: jmespath
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"
tags:
- ansible
- name: "Installer - Ansible - Dependencies / Python Library : pexpect"
pip:
name: pexpect
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"
tags:
- ansible
- name: "Installer - Podman"
apt:
name: podman
state: latest
tags:
- podman
- name: "Installer : Podman : Configure - Subordinate Ids : Users : root"
lineinfile:
path: /etc/subuid
regexp: "^root"
line: "root:100000:65536"
- name: "Installer : Podman : Configure - Subordinate Ids : Groups : root"
lineinfile:
path: /etc/subgid
regexp: "^root"
line: "root:100000:65536"
- name: "Installer - Certbot - Python Library"
pip:
name: certbot
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"
tags:
- certbot
- name: "Installer - Certbot - Create Symbolic Links"
ansible.builtin.file:
src: /opt/ansible/bin/{{ binary }}
dest: /usr/bin/{{ binary }}
state: link
vars:
binaries:
- certbot
loop: "{{ binaries }}"
loop_control:
label: "{{ binary }}"
loop_var: "binary"
tags:
- certbot
- name: "Installer - Certbot - Auth Hook"
copy:
src: "../files/certbot/nginx.sh"
dest: "/etc/letsencrypt/renewal-hooks/pre/nginx.sh"
mode: '700'
force: true
tags:
- certbot
- name: "Installer - Certbot - Create Certificates"
command: "certbot certonly --cert-name {{ cert.name }} --manual --preferred-challenges http-01 --email {{ cert.email }} --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -n --manual-auth-hook /etc/letsencrypt/renewal-hooks/pre/nginx.sh --debug-challenges --preferred-chain='ISRG Root X1' --key-type rsa -d {{ cert.domains | join(' -d ') }}"
register: task
changed_when: task.stdout.find("Certificate not yet due for renewal; no action taken.") == -1
vars:
cert:
name: mkj
email: "{{ config.certbot.email }}"
domains:
- "{{ ansible_facts.fqdn }}"
tags:
- certbot
- name: "Installer - MariaDB - Dependencies / Python Library : pymysql"
pip:
name: pymysql
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"
tags:
- mariadb
- name: "Installer - MariaDB - Dependencies / Package : mariadb-client"
apt:
name: "mariadb-client"
state: latest
when:
- ansible_facts.distribution == "Debian" or ansible_facts.distribution == "Ubuntu" or ansible_facts.distribution == "Linux Mint"
tags:
- mariadb
- name: "Installer - Schedule - Setup"
cron:
name: PATH
env: yes
value: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
- name: "Installer - Schedule - Maintenance"
cron:
name: Maintenance
hour: "*/3"
minute: "0"
job: "/opt/ansible/bin/ansible-pull -U ssh://git@github.com/MatteZ02/mkj-infra --accept-host-key --vault-password-file ~/.ansible/vault.yml --private-key ~/.ssh/id_rsa tasks.yml -t maintenance"
tags:
- cron
- name: "Installer - Schedule - Deployer"
cron:
name: Deployer
minute: "*/5"
job: "/opt/ansible/bin/ansible-pull -U ssh://git@github.com/MatteZ02/mkj-infra --accept-host-key --vault-password-file ~/.ansible/vault.yml --private-key ~/.ssh/id_rsa tasks.yml -t deployer"
tags:
- cron

37
tasks/maintenance.yml Normal file
View File

@ -0,0 +1,37 @@
---
- name: "Maintenance - OS Update"
apt:
upgrade: dist
update_cache: yes
- name: "Maintenance - Ansible : Dependencies - Python Library : hvac"
pip:
name: hvac
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"
- name: "Maintenance - Ansible : Dependencies - Python Library : netaddr"
pip:
name: netaddr
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"
- name: "Maintenance - Ansible : Dependencies - Python Library : jmespath"
pip:
name: jmespath
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"
- name: "Maintenance - Ansible : Dependencies - Python Library : pexpect"
pip:
name: pexpect
state: latest
extra_args: --upgrade
virtualenv: /opt/ansible
virtualenv_command: "python3 -m venv"