diff --git a/inventory/group_vars/debian.yml b/inventory/group_vars/debian.yml index a7d4a89..8df1bdb 100644 --- a/inventory/group_vars/debian.yml +++ b/inventory/group_vars/debian.yml @@ -1 +1,2 @@ # Debian-specific variables go here +ACME_EMAIL: noehbernasol0@gmail.com diff --git a/inventory/hosts b/inventory/hosts index f7e3d16..7cc3811 100644 --- a/inventory/hosts +++ b/inventory/hosts @@ -1,7 +1,11 @@ [debian] -10.0.10.4 -10.0.10.64 -10.0.10.141 +# Hyper-V Test Nodes +172.22.88.4 ansible_ssh_common_args="-o StrictHostKeyChecking=no" +172.22.85.231 ansible_ssh_common_args="-o StrictHostKeyChecking=no" +# Bare Metal Nodes +10.0.10.4 ansible_ssh_common_args="-o StrictHostKeyChecking=no" +10.0.10.141 ansible_ssh_common_args="-o StrictHostKeyChecking=no" +10.0.10.64 ansible_ssh_common_args="-o StrictHostKeyChecking=no" [openwrt] 10.0.10.1 diff --git a/roles/files/debian/setup/crontabs/root b/roles/files/debian/setup/crontabs/root new file mode 100644 index 0000000..f0a2f77 --- /dev/null +++ b/roles/files/debian/setup/crontabs/root @@ -0,0 +1,22 @@ +# VIM Default Editor +@reboot export VISUAL=vim +@reboot export EDITOR=vim + +# Fix tmux bug +@reboot tmux + +# Network mount +* * * * * mount.cifs "//255.255.255.0/SAMBA-MOUNT" "/mnt/backups/" -o credentials="/root/.samba/credentials" + +# Start services +@reboot sleep 30 && tmux new-session -d -s "start_services" "bash /root/scripts/start_services.sh" + +# Backups +0 */4 * * * tmux new-session -d -s "Borg Backups" bash /root/scripts/backup.sh + +# Docker Cleanup +0 0 1 * * docker system prune --all --volumes --force + +# ACME +52 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null +0 */7 * * * tmux new-session -d -s "Acme SSL Updater" bash /root/scripts/acme_ssl.sh diff --git a/roles/files/debian/setup/samba/credentials b/roles/files/debian/setup/samba/credentials new file mode 100644 index 0000000..73af828 --- /dev/null +++ b/roles/files/debian/setup/samba/credentials @@ -0,0 +1,2 @@ +username=USERNAME +password=PASSWORD \ No newline at end of file diff --git a/roles/files/debian/setup/scripts/.env.sample b/roles/files/debian/setup/scripts/.env.sample new file mode 100644 index 0000000..1c692f8 --- /dev/null +++ b/roles/files/debian/setup/scripts/.env.sample @@ -0,0 +1,2 @@ +CF_Token=REPLACE_WITH_YOUR_TOKEN +DuckDNS_Token=REPLACE_WITH_YOUR_TOKEN \ No newline at end of file diff --git a/roles/files/debian/setup/scripts/acme_scripts/cloudflare.sh b/roles/files/debian/setup/scripts/acme_scripts/cloudflare.sh new file mode 100644 index 0000000..3a334e8 --- /dev/null +++ b/roles/files/debian/setup/scripts/acme_scripts/cloudflare.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Read CF_Token and ACME_Email from .env +source ".env" + +/root/.acme.sh/acme.sh --upgrade --auto-upgrade +/root/.acme.sh/acme.sh --register-account -m noehbernasol0@gmail.com + +# Array of domains +domains=("*.06222001.xyz" "06222001.xyz") +legacy_domains=() +all_domains=("${domains[@]}" "${legacy_domains[@]}") + +# Whether to force update or not +force_update=false +echo "===== Force update domains: " $force_update " =====" + +# Loop through the domains and execute the commands for each one +for domain in "${all_domains[@]}" +do + + # Issue the certificate using acme.sh + echo "====== Registering domain:" $domain " ======" + if $force_update ; then + /root/.acme.sh/acme.sh --force --issue --dns dns_cf --keylength 4096 -d "$domain" --server letsencrypt + else + /root/.acme.sh/acme.sh --issue --dns dns_cf --keylength 4096 -d "$domain" --server letsencrypt + fi + +done + +echo "===== Reloading firewall =====" +service nginx reload +echo "===== Done =====" \ No newline at end of file diff --git a/roles/files/debian/setup/scripts/acme_scripts/duckdns.sh b/roles/files/debian/setup/scripts/acme_scripts/duckdns.sh new file mode 100644 index 0000000..2a036e3 --- /dev/null +++ b/roles/files/debian/setup/scripts/acme_scripts/duckdns.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Read DuckDNS_Token and ACME_Email from .env +source ".env" + +/root/.acme.sh/acme.sh --upgrade --auto-upgrade +/root/.acme.sh/acme.sh --register-account -m noehbernasol0@gmail.com + +# Array of main domains +domains=("*.keannu1.duckdns.org" "keannu1.duckdns.org") +legacy_domains=() +all_domains=("${domains[@]}" "${legacy_domains[@]}") + +# Whether to force update or not +force_update=false +echo "===== Force update domains: " $force_update " =====" + +# Loop through the domains and execute the commands for each one +for domain in "${all_domains[@]}" +do + + # Issue the certificate using acme.sh + echo "====== Registering domain:" $domain " ======" + if $force_update ; then + /root/.acme.sh/acme.sh --insecure --force --issue --dns dns_duckdns -d "$domain" + else + /root/.acme.sh/acme.sh --insecure --issue --dns dns_duckdns -d "$domain" + fi + +done + +echo "===== Reloading firewall =====" +service nginx reload +echo "===== Done =====" \ No newline at end of file diff --git a/roles/files/debian/setup/scripts/backup.sh b/roles/files/debian/setup/scripts/backup.sh new file mode 100644 index 0000000..a85fa65 --- /dev/null +++ b/roles/files/debian/setup/scripts/backup.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +current_date=$(date "+%B %-d %Y%l:%M %p") + +env BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes +env BORG_RELOCATED_REPO_ACCESS_IS_OK=yes + +echo "Timestamp: $current_date" + +# Check if the required mount point exists +if ! df -h | grep -q "^//255\.255\.255\.255/SAMBA-MOUNT.*\/mnt/backups$"; then + echo "Error: Required mount point //255.255.255.255/SAMBA-MOUNT not found or not mounted at /mnt/backups." + exit 1 +fi + +function backup() { + # $1 - Backup Name + # $2 - Directory + # $3 - Extras + + if [ "$1" == "" ] || [ "$2" == "" ]; then + echo "Missing arguments!" + exit + fi + + # Root backup directory + root_directory="/mnt/backups/" + + echo "Starting backups for: $1" + + # Check if the backup directory exists + if [ ! -d "$root_directory/$1" ]; then + echo "Backup directory does not exist for $1. Initializing one" + borg init --encryption=none "$root_directory/$1" + else + echo "Backup directory already exists for $1" + fi + + borg create --stats --progress --compression lz4 "$root_directory/$1"::"$current_date" "$2" $3 + echo "Cleaning old backups" + borg prune --stats "$root_directory/$1" -d 6 + borg compact "$root_directory/$1" + echo "Backup for $1 finished" +} + +## Docker Projects + +## Root Docker Projects Directory +docker_projects="/mnt/nvme/files/docker projects/" + +# Sample Entry +backup "sample" "$docker_projects/sample_project" + +## Non-Docker Directories + +# Bash Scripts +backup "bash-scripts" "/root/scripts" + +# ACME +backup "acme" "/root/.acme.sh" '--exclude "*.tmp"' + +# Crontab +backup "cron" "/var/spool/cron/crontabs" + +# Nginx +backup "nginx" "/etc/nginx" '--exclude "*.tmp"' + +# Syncthing +backup "syncthing" "/root/.config/syncthing" '--exclude "*.tmp"' + +# Samba +backup "samba" "/etc/samba" + +# Samba Credentials +backup "samba_credentials" "/root/.samba" \ No newline at end of file diff --git a/roles/files/debian/setup/scripts/renew_ssl.sh b/roles/files/debian/setup/scripts/renew_ssl.sh new file mode 100644 index 0000000..2cad80b --- /dev/null +++ b/roles/files/debian/setup/scripts/renew_ssl.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +scripts_directory="/root/scripts/acme_scripts" + +# Execute all .sh files in the directory +for script in "$scripts_directory"/*.sh; do + echo "--Executing $script--" + bash "$script" +done \ No newline at end of file diff --git a/roles/files/debian/setup/scripts/start_services.sh b/roles/files/debian/setup/scripts/start_services.sh new file mode 100644 index 0000000..f974204 --- /dev/null +++ b/roles/files/debian/setup/scripts/start_services.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +## Docker Projects + +# Root Docker Projects Directory +docker_projects="/mnt/nvme/files/docker projects" + +# Sample Entry +cd "$docker_projects/sample_project" && docker-compose down && docker-compose up -d + +## Non-Docker Projects + +# Syncthing +systemctl start syncthing@root.service + + diff --git a/roles/tasks/debian/README.md b/roles/tasks/debian/README.md new file mode 100644 index 0000000..842b2a0 --- /dev/null +++ b/roles/tasks/debian/README.md @@ -0,0 +1,41 @@ +## Usage + +### Setup + +1. Run `setup.yml` using a non-sudo user, providing regular and sudo credentials. + +```bash +ansible-playbook roles/tasks/debian/setup.yml -u keannu125 -k --ask-become-pass +``` + +This will elevate to `root` user via `sudo` and set up root SSH access through the provided `id_rsa.pub` file in the control node's own `.ssh` directory + +2. Set up the necessary template scripts provided at `/root/scripts` + +- Rename `.env.sample` to `.env.` (via `mv .env.sample .env`) +- Provide your ACME SSL access tokens in the `.env` for `renew_ssl.sh` to parse +- Provide project directories to spin up on boot through `start_services.sh` +- Provide the same project directories to back up via Borg in `backup.sh` + +3. Update the Samba credentials file located at `/root/.samba` + +``` +# credentials +user=USERNAME +password=PASSWORD +``` + +4. Update the CIFS/Samba mount for backups located in `crontab` (via `crontab -e`) + +``` +# crontab entry +* * * * * mount.cifs "//255.255.255.0/SAMBA-MOUNT" "/mnt/backups" -o credentials="/root/.samba/credentials" +``` + +If you'd need to run the `setup.yml` playbook again for any reason. You can omit specifying user or sudo credentials and simply run + +```bash +ansible-playbook roles/tasks/debian/setup.yml +``` + +Any existing or additional scripts that have already been modified will not be overwritten (See `force: false` directives in [`setup.yml`](./setup.yml)) diff --git a/roles/tasks/debian/setup.yml b/roles/tasks/debian/setup.yml index 0f29358..f65f1c7 100644 --- a/roles/tasks/debian/setup.yml +++ b/roles/tasks/debian/setup.yml @@ -1,8 +1,8 @@ --- - hosts: - debian - # Runs on root user already - become: false + become: true + vars_files: "{{ playbook_dir | dirname | dirname | dirname }}/inventory/group_vars/debian.yml" tasks: - name: Add SSH key to authorized_hosts - Debian authorized_key: @@ -10,11 +10,27 @@ state: present key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" path: /root/.ssh/authorized_keys + - name: Enable Root Login + lineinfile: + dest: /etc/ssh/sshd_config + regexp: "^PermitRootLogin" + line: "PermitRootLogin yes" + state: present + notify: Restart SSHD on Config Change - name: Update all packages apt: update_cache: true autoremove: true state: latest + - name: Install Docker + apt: + name: + - docker + update_cache: false + autoremove: true + state: latest + # Safety net if this script is ran twice + notify: Restart Docker Containers - name: Install packages - Debian apt: name: @@ -23,7 +39,6 @@ - htop - tmux - samba - - docker - docker-compose - neofetch - cifs-utils @@ -32,9 +47,47 @@ - syncthing - socat - fish + - iperf3 # Cache is already updated from previous step update_cache: false autoremove: true state: latest - name: Install ACME - command: curl https://get.acme.sh | sh -s email=noehbernasol0@gmail.com + shell: curl https://get.acme.sh | sh -s email="{{ ACME_EMAIL }}" + - name: Enable Syncthing Service + command: systemctl enable syncthing@root.service + - name: Allow Syncthing Remote Management + replace: + path: /root/.config/syncthing/config.xml + regexp: "
127.0.0.1:8384
" + replace: "
0.0.0.0:8384
" + notify: Restart Syncthing Service + - name: Copy Template Scripts + copy: + src: "{{ playbook_dir | dirname | dirname }}/files/debian/setup/scripts/" + dest: /root/scripts/ + mode: "0644" + force: false + - name: Copy Crontab Template + copy: + src: "{{ playbook_dir | dirname | dirname }}/files/debian/setup/crontabs/" + dest: /var/spool/cron/crontabs/ + mode: "0600" + force: false + - name: Copy Samba Credentials Template + copy: + src: "{{ playbook_dir | dirname | dirname }}/files/debian/setup/samba/" + dest: /root/.samba/ + mode: "0644" + force: false + + handlers: + # Restart Syncthing on Config Change + - name: Restart Syncthing Service + command: systemctl restart syncthing@root.service + # Restart SSHD on Config Change + - name: Restart SSHD on Config Change + command: systemctl restart sshd + # Restart Docker Containers on Docker Update + - name: Restart Docker Containers + command: bash /root/scripts/start_services.sh diff --git a/roles/tasks/debian/restart_services.yml b/roles/tasks/debian/start_services.yml similarity index 80% rename from roles/tasks/debian/restart_services.yml rename to roles/tasks/debian/start_services.yml index 1315f38..b08af52 100644 --- a/roles/tasks/debian/restart_services.yml +++ b/roles/tasks/debian/start_services.yml @@ -4,5 +4,5 @@ # Runs on root user already become: false tasks: - - name: Restart all services + - name: Start all services command: bash /root/scripts/start_services.sh diff --git a/roles/tasks/debian/update.yml b/roles/tasks/debian/update.yml index 2fe30f2..ec81ef5 100644 --- a/roles/tasks/debian/update.yml +++ b/roles/tasks/debian/update.yml @@ -4,10 +4,23 @@ # Runs on root user already become: false tasks: + - name: Update Docker + apt: + name: + - docker + update_cache: true + autoremove: true + state: latest + notify: Restart Docker Containers - name: Update all packages apt: - update_cache: true + update_cache: false autoremove: true state: latest - name: Update ACME command: /root/.acme.sh/acme.sh --upgrade --auto-upgrade + + handlers: + # Restart Docker Containers on Docker Update + - name: Restart Docker Containers + command: bash /root/scripts/start_services.sh