From 217d2863709ebbe1ed766a360edb228e8899fc68 Mon Sep 17 00:00:00 2001 From: EuAndreh Date: Mon, 10 Jun 2019 22:21:38 -0300 Subject: Output all generated files on ./generated/, refactor .envrc variables --- .build.yml | 2 +- .envrc | 38 ++++++++++++++- .gitignore | 10 ---- ansible.cfg | 2 +- generated/.gitignore | 2 + provision.yaml | 6 +-- rotate-ssh-keys.sh | 10 ---- scripts/box/user-data.env.sh | 11 +++++ scripts/ci/deploy.sh | 87 ++++++++++++++++++++++++++++++++++ scripts/ci/mail.sh | 9 +--- scripts/ci/provision.sh | 99 --------------------------------------- scripts/ci/setup.sh | 24 ++++------ scripts/local/rotate-ssh-keys.sh | 11 +++++ secrets/envrc.sh | Bin 2772 -> 0 bytes secrets/secret-envrc.sh | Bin 0 -> 2537 bytes ssh.env.conf | 2 +- user-data.env.sh | 11 ----- vps.tf | 2 +- 18 files changed, 164 insertions(+), 162 deletions(-) mode change 120000 => 100644 .envrc create mode 100644 generated/.gitignore delete mode 100755 rotate-ssh-keys.sh create mode 100755 scripts/box/user-data.env.sh create mode 100755 scripts/ci/deploy.sh delete mode 100755 scripts/ci/provision.sh create mode 100755 scripts/local/rotate-ssh-keys.sh delete mode 100644 secrets/envrc.sh create mode 100644 secrets/secret-envrc.sh delete mode 100755 user-data.env.sh diff --git a/.build.yml b/.build.yml index b2cc924..87f463c 100644 --- a/.build.yml +++ b/.build.yml @@ -20,4 +20,4 @@ tasks: nix-build -A test - deploy: | cd vps/ - ./scripts/ci/provision.sh + ./scripts/ci/deploy.sh diff --git a/.envrc b/.envrc deleted file mode 120000 index c488fc8..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -secrets/envrc.sh \ No newline at end of file diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..6c6861e --- /dev/null +++ b/.envrc @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +set -Eeuo pipefail +cd "$(dirname "${BASH_SOURCE[0]}")" + +# +# Operational toggle +# +export DESTROY_VOLUME=1 + +# +# Variables defined by commands +# +VPS_COMMIT_SHA="$(git rev-parse HEAD)" +export VPS_COMMIT_SHA +SSH_SERVER_PRIVATE_KEY="$(cat ./secrets/ssh/vps-box-server)" +export SSH_SERVER_PRIVATE_KEY +SSH_SERVER_PUBLIC_KEY="$(cat ./secrets/ssh/vps-box-server.pub)" +export SSH_SERVER_PUBLIC_KEY +# Used for keeping bash variables for run-time substituion instead of execution time substitution. +# Taken from: +# https://stackoverflow.com/questions/24963705/is-there-an-escape-character-for-envsubst +export DOLLAR='$' + +# +# docker-compose +# +export VOLUME_HOME="/home/vps/volumes" + +# +# Nix +# +# Use the same $NIX_PATH as in the CI +# See also: +# https://discourse.nixos.org/t/inconsistent-hash-of-buildgomodule/3127/4 +export NIX_PATH=nixpkgs=channel:nixos-unstable + +source ./secrets/secret-envrc.sh \ No newline at end of file diff --git a/.gitignore b/.gitignore index c7dd6ca..a7e698a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,8 @@ # Terraform /.terraform/ -/terraform-provider-godaddy # Nix /result -# Template files -/docker-compose.yaml -/cloud-config.yaml -/hosts -/user-data.sh -/scripts/box/create-backup.sh -/scripts/box/restore-backup.sh -/generated-known-hosts.txt - # Logs /logs.txt diff --git a/ansible.cfg b/ansible.cfg index a8518f7..4b7160e 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,3 +1,3 @@ [defaults] -inventory = ./hosts +inventory = ./generated/hosts retry_files_enabled = False \ No newline at end of file diff --git a/generated/.gitignore b/generated/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/generated/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/provision.yaml b/provision.yaml index 9137a09..801c010 100644 --- a/provision.yaml +++ b/provision.yaml @@ -29,13 +29,13 @@ - name: Copy local interpolated files to remote copy: src={{ item.src }} dest={{ item.dest }} mode={{ item.mode }} with_items: - - { src: './scripts/box/create-backup.sh', dest: '/home/vps/create-backup.sh', mode: '500' } - - { src: './scripts/box/restore-backup.sh', dest: '/home/vps/restore-backup.sh', mode: '500' } + - { src: './generated/create-backup.sh', dest: '/home/vps/create-backup.sh', mode: '500' } + - { src: './generated/restore-backup.sh', dest: '/home/vps/restore-backup.sh', mode: '500' } - { src: './secrets/borg/borg-remote.pub', dest: '/root/.ssh/id_rsa.pub', mode: '400' } - { src: './secrets/borg/borg-remote', dest: '/root/.ssh/id_rsa', mode: '400' } - { src: './secrets/borg/known-hosts.txt', dest: '/root/.ssh/known_hosts', mode: '400' } - { src: './scripts/box/bash-profile.sh', dest: '/root/.bash_profile', mode: '400' } - - { src: './docker-compose.yaml', dest: '/home/vps/docker-compose.yaml', mode: '400' } + - { src: './generated/docker-compose.yaml', dest: '/home/vps/docker-compose.yaml', mode: '400' } - name: Restore borg backup when we have a fresh volume shell: /home/vps/restore-backup.sh when: lookup('env', 'DESTROY_VOLUME') == "1" diff --git a/rotate-ssh-keys.sh b/rotate-ssh-keys.sh deleted file mode 100755 index 7189657..0000000 --- a/rotate-ssh-keys.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -set -Eeuo pipefail -cd "$(dirname "${BASH_SOURCE[0]}")" - -rm -f ./secrets/ssh/* -ssh-keygen -t rsa -b 4096 -q -N '' -f ./secrets/ssh/vps-box-client -ssh-keygen -t rsa -b 4096 -q -N '' -f ./secrets/ssh/vps-box-server - -git add ./secrets/ssh/ -git commit -m "Script: rotate SSH keys" diff --git a/scripts/box/user-data.env.sh b/scripts/box/user-data.env.sh new file mode 100755 index 0000000..f9da5d7 --- /dev/null +++ b/scripts/box/user-data.env.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2016 + +echo '$SSH_SERVER_PRIVATE_KEY' > /etc/ssh/vps-box-server +chmod 400 /etc/ssh/vps-box-server +echo '$SSH_SERVER_PUBLIC_KEY' > /etc/ssh/vps-box-server.pub +echo 'HostKey /etc/ssh/vps-box-server' >> /etc/ssh/sshd_config +echo 'Port $SSH_PORT' >> /etc/ssh/sshd_config +systemctl restart sshd + +# SSH logs on /var/log/auth.log diff --git a/scripts/ci/deploy.sh b/scripts/ci/deploy.sh new file mode 100755 index 0000000..7fcfda7 --- /dev/null +++ b/scripts/ci/deploy.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash ../../shell.nix +# shellcheck shell=bash +set -Eeuo pipefail +cd "$(dirname "${BASH_SOURCE[0]}")" +cd ../../ + +mail_debug_log() { + local -r ec="${?}" + echo "Sending logs via email..." + ./scripts/ci/mail.sh "${ec}" + echo "Done." + + echo "Storing file changes to '.tfstate' files..." + pushd ../vps-state/ + git add . + git commit -m "CI: fallback add all after provision.sh failure for CI run $VPS_COMMIT_SHA" ||: + git push origin master + popd + echo "Done." +} +trap mail_debug_log EXIT + +create_known_hosts_file() { + echo "${TLD},$(terraform output public_floating_ip) ssh-rsa $(awk '{print $2}' < ./secrets/ssh/vps-box-server.pub)" > ./generated/generated-known-hosts.txt +} + +echo "Shutting down running containers and backing up data..." +create_known_hosts_file +ssh "$TLD" "cd /home/vps/ && docker-compose down" +scp ./secrets/borg/borg-remote.pub "$TLD":/root/.ssh/id_rsa.pub +scp ./secrets/borg/borg-remote "$TLD":/root/.ssh/id_rsa +scp ./secrets/borg/known-hosts.txt "$TLD":/root/.ssh/known_hosts +scp ./generated/create-backup.sh "$TLD":/home/vps/create-backup.sh +ssh "$TLD" 'chmod 400 /root/.ssh/id_rsa' +ssh "$TLD" "chmod +x /home/vps/create-backup.sh" +ssh "$TLD" /home/vps/create-backup.sh > ./logs/borg-create.txt 2>&1 +echo "Done." + +echo "Initializing Terraform..." +terraform --version +terraform init +echo "Done." + +if [[ "${DESTROY_VOLUME:-}" != "" ]]; then + echo "Destroying existing infrastructure..." + terraform destroy -input=false -auto-approve > ./logs/terraform-destroy.txt 2>&1 +else + echo "Skipping explicit intentional destruction of existing infrastructure..." +fi +echo "Done." + +echo "Running 'terraform plan' and storing the planfile..." +mkdir -p "../vps-state/secrets/plan-files/" +PLAN_FILE_NAME="$(date -Iseconds)-${VPS_COMMIT_SHA}.tfplan" +PLAN_FILE_PATH="../vps-state/secrets/plan-files/${PLAN_FILE_NAME}" +terraform plan -input=false -out="${PLAN_FILE_PATH}" > ./logs/terraform-plan.txt 2>&1 +pushd ../vps-state/ +git add "secrets/plan-files/${PLAN_FILE_NAME}" +git commit -m "CI: add .tfplan plan file for CI run ${VPS_COMMIT_SHA}" +git push origin master +popd +echo "Done." + +echo "Running 'terraform apply'..." +terraform apply -input=false -auto-approve "${PLAN_FILE_PATH}" > ./logs/terraform-apply.txt 2>&1 +echo "Done." + +echo "Storing .tfstate file..." +pushd ../vps-state/ +git add secrets/terraform.tfstate secrets/terraform.tfstate.backup +git commit -m "CI: update Terraform .tfstate files for CI run ${VPS_COMMIT_SHA}" +git push origin master +popd +echo "Done." + +echo "Running the Ansible playbook..." +create_known_hosts_file +ansible-playbook -v provision.yaml > ./logs/ansible.txt 2>&1 +echo "Done." + +echo "Locking git-crypt repositories back..." +git crypt lock +pushd ../vps-state/ +git crypt lock +popd +echo "Done." diff --git a/scripts/ci/mail.sh b/scripts/ci/mail.sh index 7058233..29420fa 100755 --- a/scripts/ci/mail.sh +++ b/scripts/ci/mail.sh @@ -3,14 +3,7 @@ set -Eeuo pipefail cd "$(dirname "${BASH_SOURCE[0]}")" cd ../../ -VPS_COMMIT_SHA="${1:-}" -EXIT_CODE="${2:-}" - -[[ -z "${VPS_COMMIT_SHA}" ]] && { - # shellcheck disable=SC2016 - echo 'Error: missing $VPS_COMMIT_SHA positional argument.' - exit 2 -} +EXIT_CODE="${1:-}" [[ -z "${EXIT_CODE}" ]] && { # shellcheck disable=SC2016 diff --git a/scripts/ci/provision.sh b/scripts/ci/provision.sh deleted file mode 100755 index d96d854..0000000 --- a/scripts/ci/provision.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env nix-shell -#!nix-shell -i bash ../../shell.nix -# shellcheck shell=bash -set -Eeuo pipefail -cd "$(dirname "${BASH_SOURCE[0]}")" -cd ../../ - -VPS_COMMIT_SHA="$(git rev-parse HEAD)" -export VPS_COMMIT_SHA -gpg --import "${GPG_TO}.gpg" - -mail_debug_log() { - local -r ec="${?}" - echo "Sending logs via email..." - ./scripts/ci/mail.sh "${VPS_COMMIT_SHA}" "${ec}" - echo "Done." - - echo "Storing file changes to '.tfstate' files..." - pushd ../vps-state/ - git add . - git commit -m "CI: fallback add all after provision.sh failure for CI run $VPS_COMMIT_SHA" ||: - git push origin master - popd - echo "Done." -} -trap mail_debug_log EXIT - -create_known_hosts_file() { - echo "${TLD},$(terraform output public_floating_ip) ssh-rsa $(awk '{print $2}' < ./secrets/ssh/vps-box-server.pub)" > ./generated-known-hosts.txt -} - -setup_borg_files() { - local -r template_file="${1}" - local -r destination_name="${2}" - scp ./secrets/borg/borg-remote.pub "$TLD":/root/.ssh/id_rsa.pub - scp ./secrets/borg/borg-remote "$TLD":/root/.ssh/id_rsa - scp ./secrets/borg/known-hosts.txt "$TLD":/root/.ssh/known_hosts - ssh "$TLD" 'chmod 400 /root/.ssh/id_rsa' - # shellcheck disable=SC2029 - envsubst < "${template_file}" | ssh "$TLD" "cat > /home/vps/${destination_name} && chmod +x /home/vps/${destination_name}" - # shellcheck disable=SC2029 - ssh "$TLD" "chmod +x /home/vps/${destination_name}" -} - -echo "Shutting down running containers and backing up data..." -create_known_hosts_file -ssh "$TLD" "cd /home/vps/ && docker-compose down" -setup_borg_files ./scripts/box/create-backup.env.sh create-backup.sh -ssh "$TLD" /home/vps/create-backup.sh > ./logs/borg-create.txt 2>&1 -echo "Done." - -echo "Initializing Terraform..." -terraform --version -terraform init -echo "Done." - -if [[ "${DESTROY_VOLUME:-}" != "" ]]; then - echo "Destroying existing infrastructure..." - terraform destroy -input=false -auto-approve > ./logs/terraform-destroy.txt 2>&1 -else - echo "Skipping explicit intentional destruction of existing infrastructure..." -fi -echo "Done." - -echo "Running 'terraform plan' and storing the planfile..." -mkdir -p "../vps-state/secrets/plan-files/" -PLAN_FILE_NAME="$(date -Iseconds)-$VPS_COMMIT_SHA.tfplan" -PLAN_FILE_PATH="../vps-state/secrets/plan-files/$PLAN_FILE_NAME" -terraform plan -input=false -out="$PLAN_FILE_PATH" > ./logs/terraform-plan.txt 2>&1 -pushd ../vps-state/ -git add "secrets/plan-files/$PLAN_FILE_NAME" -git commit -m "CI: add .tfplan plan file for CI run $VPS_COMMIT_SHA" -git push origin master -popd -echo "Done." - -echo "Running 'terraform apply'..." -terraform apply -input=false -auto-approve "$PLAN_FILE_PATH" > ./logs/terraform-apply.txt 2>&1 -echo "Done." - -echo "Storing .tfstate file..." -pushd ../vps-state/ -git add secrets/terraform.tfstate secrets/terraform.tfstate.backup -git commit -m "CI: update Terraform .tfstate files for CI run $VPS_COMMIT_SHA" -git push origin master -popd -echo "Done." - -echo "Running the Ansible playbook..." -create_known_hosts_file -ansible-playbook -vvv provision.yaml > ./logs/ansible.txt -echo "Done." - -echo "Locking git-crypt repositories back..." -git crypt lock -pushd ../vps-state/ -git crypt lock -popd -echo "Done." diff --git a/scripts/ci/setup.sh b/scripts/ci/setup.sh index d9ac70c..84958d0 100755 --- a/scripts/ci/setup.sh +++ b/scripts/ci/setup.sh @@ -6,7 +6,7 @@ cd "$(dirname "${BASH_SOURCE[0]}")" cd ../../ echo "Unlocking git-crypt repos and configuring git..." -git config --global user.email "ci@euandre.org" +git config --global user.email "${GIT_CI_USER}" git config --global user.name "sr.ht CI" git crypt unlock @@ -17,25 +17,17 @@ git remote set-url origin git@git.sr.ht:~euandreh/vps-state popd echo "Done." +gpg --import "${GPG_TO}.gpg" + # git smudge after git-crypt clears file permissions chmod 400 ./secrets/ssh/vps-box-client cat .envrc >> ~/.buildenv source .envrc -SSH_SERVER_PRIVATE_KEY="$(cat ./secrets/ssh/vps-box-server)" -export SSH_SERVER_PRIVATE_KEY -SSH_SERVER_PUBLIC_KEY="$(cat ./secrets/ssh/vps-box-server.pub)" -export SSH_SERVER_PUBLIC_KEY - -# Used for keeping bash variables for run-time substituion instead of execution time substitution. -# Taken from: -# https://stackoverflow.com/questions/24963705/is-there-an-escape-character-for-envsubst -export DOLLAR='$' - envsubst < ./ssh.env.conf >> ~/.ssh/config -envsubst < ./hosts.env > ./hosts -envsubst < ./docker-compose.env.yaml > ./docker-compose.yaml -envsubst < ./user-data.env.sh > ./user-data.sh -envsubst < ./scripts/box/create-backup.env.sh > ./scripts/box/create-backup.sh -envsubst < ./scripts/box/restore-backup.env.sh > ./scripts/box/restore-backup.sh +envsubst < ./hosts.env > ./generated/hosts +envsubst < ./docker-compose.env.yaml > ./generated/docker-compose.yaml +envsubst < ./scripts/box/user-data.env.sh > ./generated/user-data.sh +envsubst < ./scripts/box/create-backup.env.sh > ./generated/create-backup.sh +envsubst < ./scripts/box/restore-backup.env.sh > ./generated/restore-backup.sh diff --git a/scripts/local/rotate-ssh-keys.sh b/scripts/local/rotate-ssh-keys.sh new file mode 100755 index 0000000..337f351 --- /dev/null +++ b/scripts/local/rotate-ssh-keys.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -Eeuo pipefail +cd "$(dirname "${BASH_SOURCE[0]}")" +cd ../../ + +rm -f ./secrets/ssh/* +ssh-keygen -t rsa -b 4096 -q -N '' -f ./secrets/ssh/vps-box-client +ssh-keygen -t rsa -b 4096 -q -N '' -f ./secrets/ssh/vps-box-server + +git add ./secrets/ssh/ +git commit -m "Script: rotate SSH keys" diff --git a/secrets/envrc.sh b/secrets/envrc.sh deleted file mode 100644 index 1389181..0000000 Binary files a/secrets/envrc.sh and /dev/null differ diff --git a/secrets/secret-envrc.sh b/secrets/secret-envrc.sh new file mode 100644 index 0000000..3382e8f Binary files /dev/null and b/secrets/secret-envrc.sh differ diff --git a/ssh.env.conf b/ssh.env.conf index 6a7ba03..be34b28 100644 --- a/ssh.env.conf +++ b/ssh.env.conf @@ -1,7 +1,7 @@ Host $TLD User root IdentityFile $PWD/secrets/ssh/vps-box-client - UserKnownHostsFile $PWD/generated-known-hosts.txt + UserKnownHostsFile $PWD/generated/generated-known-hosts.txt Port $SSH_PORT Host git.sr.ht StrictHostKeyChecking no diff --git a/user-data.env.sh b/user-data.env.sh deleted file mode 100755 index f9da5d7..0000000 --- a/user-data.env.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -# shellcheck disable=SC2016 - -echo '$SSH_SERVER_PRIVATE_KEY' > /etc/ssh/vps-box-server -chmod 400 /etc/ssh/vps-box-server -echo '$SSH_SERVER_PUBLIC_KEY' > /etc/ssh/vps-box-server.pub -echo 'HostKey /etc/ssh/vps-box-server' >> /etc/ssh/sshd_config -echo 'Port $SSH_PORT' >> /etc/ssh/sshd_config -systemctl restart sshd - -# SSH logs on /var/log/auth.log diff --git a/vps.tf b/vps.tf index badc698..a329bcf 100644 --- a/vps.tf +++ b/vps.tf @@ -37,7 +37,7 @@ resource "digitalocean_droplet" "vps" { ipv6 = true monitoring = true - user_data = "${file("${path.module}/user-data.sh")}" + user_data = "${file("${path.module}/generated/user-data.sh")}" ssh_keys = [ "${digitalocean_ssh_key.client.fingerprint}", -- cgit v1.2.3