diff options
36 files changed, 64 insertions, 979 deletions
@@ -7,17 +7,7 @@ triggers: to: EuAndreh <ci@euandre.org> sources: - https://git.sr.ht/~euandreh/vps - - https://git.sr.ht/~euandreh/vps-state -secrets: - - 814bb9d2-99ac-4070-aceb-d6b11183f574 # GPG keypair - - b715d3df-a0e2-4d5a-a6f3-ece5d0025cad tasks: - - setup: | - cd vps/ - ./scripts/ci/setup.sh - tests: | cd vps/ nix-build -A test - - deploy: | - cd vps/ - ./scripts/ci/deploy.sh @@ -1,43 +1 @@ -#!/usr/bin/env bash -set -Eeuo pipefail - -# -# Operational toggle -# -export DESTROY_VOLUME= - -# -# Variables defined by commands -# -VPS_COMMIT_SHA="$(cat .git/refs/heads/master)" -export VPS_COMMIT_SHA -# 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 - -if [[ "$(file -b ./secrets/secret-envrc.sh 2> /dev/null)" = "data" ]]; -then - echo 'The ./secrets/secret-envrc.sh is encrypted, not sourcing it.' - return -fi - -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 - -source ./secrets/secret-envrc.sh +secrets/secret-envrc.sh
\ No newline at end of file @@ -2,10 +2,4 @@ /.terraform/ # Nix -/result - -# Logs -/logs.txt - -# envsubst -/provision.yaml
\ No newline at end of file +/result
\ No newline at end of file @@ -1,4 +1,7 @@ * Tasks - v4 +** TODO Run =sudo= as =nixos= user in server +** TODO nginx magic =sslCiphers= value +Why not the default? What do those mean? ** TODO How to handle IP changes in mail server? ** TODO Add borg backup to crontab ** TODO Add 2FA to Vultr @@ -55,6 +58,8 @@ If I move vps-state into vps, I'll have to remove the terraform steps from the p It makes the deploying less automatic, but this removes the IP reputation email issue. This means that the Terraform provisioning should stay out of the CI and be run only locally. +** Run locally instead of on CI +It makes it less automagic, but greatly simplifies the configuration, like removing custom =ssh.env.conf=, =mail.sh=, =vps-box-client.pub=, etc. ** Configuration of =StrictHostKeyChecking= We have 3 cases where I'm pushing things to the server and I'm dealing with it differently: *** 1. Pushing updates to the =vps-state= repository diff --git a/ansible.cfg b/ansible.cfg deleted file mode 100644 index 4b7160e..0000000 --- a/ansible.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[defaults] -inventory = ./generated/hosts -retry_files_enabled = False
\ No newline at end of file diff --git a/colors.sh b/colors.sh deleted file mode 100644 index ce21da0..0000000 --- a/colors.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env bash -# shellcheck disable=1117 disable=1004 disable=2034 disable=2154 - -export end="\033[0m" -export black="\033[0;30m" -export blackb="\033[1;30m" -export white="\033[0;37m" -export whiteb="\033[1;37m" -export red="\033[0;31m" -export redb="\033[1;31m" -export green="\033[0;32m" -export greenb="\033[1;32m" -export yellow="\033[0;33m" -export yellowb="\033[1;33m" -export blue="\033[0;34m" -export blueb="\033[1;34m" -export purple="\033[0;35m" -export purpleb="\033[1;35m" -export lightblue="\033[0;36m" -export lightblueb="\033[1;36m" - -function black { - echo -e "${black}${1}${end}" -} -export -f black - -function blackb { - echo -e "${blackb}${1}${end}" -} -export -f blackb - -function white { - echo -e "${white}${1}${end}" -} -export -f white - -function whiteb { - echo -e "${whiteb}${1}${end}" -} -export -f whiteb - -function red { - echo -e "${red}${1}${end}" -} -export -f red - -function redb { - echo -e "${redb}${1}${end}" -} -export -f redb - -function green { - echo -e "${green}${1}${end}" -} -export -f green - -function greenb { - echo -e "${greenb}${1}${end}" -} -export -f greenb - -function yellow { - echo -e "${yellow}${1}${end}" -} -export -f yellow - -function yellowb { - echo -e "${yellowb}${1}${end}" -} -export -f yellowb - -function blue { - echo -e "${blue}${1}${end}" -} -export -f blue - -function blueb { - echo -e "${blueb}${1}${end}" -} -export -f blueb - -function purple { - echo -e "${purple}${1}${end}" -} -export -f purple - -function purpleb { - echo -e "${purpleb}${1}${end}" -} -export -f purpleb - -function lightblue { - echo -e "${lightblue}${1}${end}" -} -export -f lightblue - -function lightblueb { - echo -e "${lightblueb}${1}${end}" -} -export -f lightblueb - -function colors { - black "black" - blackb "blackb" - white "white" - whiteb "whiteb" - red "red" - redb "redb" - green "green" - greenb "greenb" - yellow "yellow" - yellowb "yellowb" - blue "blue" - blueb "blueb" - purple "purple" - purpleb "purpleb" - lightblue "lightblue" - lightblueb "lightblueb" -} diff --git a/default.nix b/default.nix index 171a3a9..7078a01 100644 --- a/default.nix +++ b/default.nix @@ -18,20 +18,6 @@ in rec { touch $out ''; }); - dockerComposeLint = utils.baseTask.overrideAttrs (baseAttrs: { - name = "${baseAttrs.name}-docker-compose-lint"; - buildInputs = baseAttrs.buildInputs ++ [ pkgs.docker-compose ]; - buildPhase = '' - source .envrc - # =docker-compose config= doesn't accept files with different names - cp docker-compose.env.yaml docker-compose.yaml - docker-compose config &> /dev/null || { - echo "Invalid docker-compose.yml file." - exit 1 - } - touch $out - ''; - }); shellBuildInputs = with pkgs; [ file gitMinimal @@ -48,7 +34,6 @@ in rec { (utils.shellEnvironmentBuild subtasks.shellBuildInputs) utils.formatNix subtasks.formatTerraform - subtasks.dockerComposeLint ]; shell = utils.shellEnvironment subtasks.shellBuildInputs; } diff --git a/derived-configuration.env.nix b/derived-configuration.env.nix deleted file mode 100644 index b2bc8ea..0000000 --- a/derived-configuration.env.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ - nextcloudTLD = "$NEXTCLOUD_TLD"; - gitTLD = "$GIT_TLD"; -} diff --git a/docker-compose.env.yaml b/docker-compose.env.yaml deleted file mode 100644 index 8785b68..0000000 --- a/docker-compose.env.yaml +++ /dev/null @@ -1,80 +0,0 @@ -version: '3' - -networks: - nginx-proxy-network: - -services: - nginx-proxy: - image: jwilder/nginx-proxy - container_name: nginx-proxy - restart: always - ports: - - '80:80' - - '443:443' - volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - "${VOLUME_HOME}/vhost-conf:/etc/nginx/vhost.d" - - "${VOLUME_HOME}/docker/nginx-proxy/html:/usr/share/nginx/html" - - "${VOLUME_HOME}/docker/nginx-proxy/certs:/etc/nginx/certs:ro" - - "${VOLUME_HOME}/docker/nginx-proxy/conf:/etc/nginx/conf.d" - - "${VOLUME_HOME}/docker/nginx-proxy/dhparam:/etc/nginx/dhparam" - networks: - - nginx-proxy-network - - letsencrypt: - image: jrcs/letsencrypt-nginx-proxy-companion - container_name: letsencrypt-nginx-proxy-companion - restart: always - volumes: - - "${VOLUME_HOME}/docker/nginx-proxy/certs:/etc/nginx/certs" - - "${VOLUME_HOME}/docker/nginx-proxy/vhost:/etc/nginx/vhost.d" - - "${VOLUME_HOME}/docker/nginx-proxy/html:/usr/share/nginx/html" - - "${VOLUME_HOME}/docker/nginx-proxy/dhparam:/etc/nginx/dhparam:ro" - - /var/run/docker.sock:/var/run/docker.sock:ro - depends_on: - - nginx-proxy - environment: - - NGINX_PROXY_CONTAINER=nginx-proxy - networks: - - nginx-proxy-network - - static: - image: nginx - container_name: static-nginx - restart: always - volumes: - - "${VOLUME_HOME}/static:/usr/share/nginx/html" - ports: - - "${STATIC_PORT}:80" - environment: - - VIRTUAL_HOST=${STATIC_TLD} - - VIRTUAL_PORT=${STATIC_PORT} - - LETSENCRYPT_HOST=${STATIC_TLD} - - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} - networks: - - nginx-proxy-network - - nextcloud: - image: nextcloud:latest - container_name: nextcloud - restart: always - volumes: - - "${VOLUME_HOME}/applications/nextcloud/data:/var/www/html" - - "${VOLUME_HOME}/applications/nextcloud/config:/var/www/config" - - "${VOLUME_HOME}/applications/nextcloud/apps:/var/www/apps" - ports: - - "${NEXTCLOUD_PORT}:80" - environment: - - SQLITE_DATABASE=my-nextcloud-database.sqlite - - NEXTCLOUD_UPDATE=1 - - NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER} - - NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD} - - NEXTCLOUD_TABLE_PREFIX=${NEXTCLOUD_TABLE_PREFIX} - - NEXTCLOUD_HOSTNAME=${NEXTCLOUD_TLD} - - NEXTCLOUD_TRUSTED_DOMAINS=${NEXTCLOUD_TLD} - - VIRTUAL_HOST=${NEXTCLOUD_TLD} - - VIRTUAL_PORT=${NEXTCLOUD_PORT} - - LETSENCRYPT_HOST=${NEXTCLOUD_TLD} - - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} - networks: - - nginx-proxy-network diff --git a/docs/README.css b/docs/README.css deleted file mode 100644 index c744528..0000000 --- a/docs/README.css +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Taken from: - * https://gist.github.com/killercup/5917178 - * Inspired by: - * https://github.com/jerieljan/posaune-pandoc-theme - */ - -/* - * I add this to html files generated with pandoc. - */ - -html { - font-size: 100%; - overflow-y: scroll; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -body { - color: #444; - font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; - font-size: 12px; - line-height: 1.7; - padding: 1em; - margin: auto; - max-width: 42em; - background: #fefefe; -} - -a { - color: #0645ad; - text-decoration: none; -} - -a:visited { - color: #0b0080; -} - -a:hover { - color: #06e; -} - -a:active { - color: #faa700; -} - -a:focus { - outline: thin dotted; -} - -*::-moz-selection { - background: rgba(255, 255, 0, 0.3); - color: #000; -} - -*::selection { - background: rgba(255, 255, 0, 0.3); - color: #000; -} - -a::-moz-selection { - background: rgba(255, 255, 0, 0.3); - color: #0645ad; -} - -a::selection { - background: rgba(255, 255, 0, 0.3); - color: #0645ad; -} - -p { - margin: 1em 0; -} - -img { - max-width: 100%; -} - -h1, h2, h3, h4, h5, h6 { - color: #111; - line-height: 125%; - margin-top: 2em; - font-weight: normal; -} - -h4, h5, h6 { - font-weight: bold; -} - -h1 { - font-size: 2.5em; -} - -h2 { - font-size: 2em; -} - -h3 { - font-size: 1.5em; -} - -h4 { - font-size: 1.2em; -} - -h5 { - font-size: 1em; -} - -h6 { - font-size: 0.9em; -} - -blockquote { - color: #666666; - margin: 0; - padding-left: 3em; - border-left: 0.5em #EEE solid; -} - -hr { - display: block; - height: 2px; - border: 0; - border-top: 1px solid #aaa; - border-bottom: 1px solid #eee; - margin: 1em 0; - padding: 0; -} - -pre, code, kbd, samp { - color: #000; - font-family: monospace, monospace; - _font-family: 'courier new', monospace; - font-size: 0.98em; -} - -pre { - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; -} - -b, strong { - font-weight: bold; -} - -dfn { - font-style: italic; -} - -ins { - background: #ff9; - color: #000; - text-decoration: none; -} - -mark { - background: #ff0; - color: #000; - font-style: italic; - font-weight: bold; -} - -sub, sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -ul, ol { - margin: 1em 0; - padding: 0 0 0 2em; -} - -li p:last-child { - margin-bottom: 0; -} - -ul ul, ol ol { - margin: .3em 0; -} - -dl { - margin-bottom: 1em; -} - -dt { - font-weight: bold; - margin-bottom: .8em; -} - -dd { - margin: 0 0 .8em 2em; -} - -dd:last-child { - margin-bottom: 0; -} - -img { - border: 0; - -ms-interpolation-mode: bicubic; - vertical-align: middle; -} - -figure { - display: block; - text-align: center; - margin: 1em 0; -} - -figure img { - border: none; - margin: 0 auto; -} - -figcaption { - font-size: 0.8em; - font-style: italic; - margin: 0 0 .8em; -} - -table { - margin-bottom: 2em; - border-bottom: 1px solid #ddd; - border-right: 1px solid #ddd; - border-spacing: 0; - border-collapse: collapse; -} - -table th { - padding: .2em 1em; - background-color: #eee; - border-top: 1px solid #ddd; - border-left: 1px solid #ddd; -} - -table td { - padding: .2em 1em; - border-top: 1px solid #ddd; - border-left: 1px solid #ddd; - vertical-align: top; -} - -.author { - font-size: 1.2em; - text-align: center; -} - -@media only screen and (min-width: 480px) { - body { - font-size: 14px; - } -} -@media only screen and (min-width: 768px) { - body { - font-size: 16px; - } -} -@media print { - * { - background: transparent !important; - color: black !important; - filter: none !important; - -ms-filter: none !important; - } - - body { - font-size: 12pt; - max-width: 100%; - } - - a, a:visited { - text-decoration: underline; - } - - hr { - height: 1px; - border: 0; - border-bottom: 1px solid black; - } - - a[href]:after { - content: " (" attr(href) ")"; - } - - abbr[title]:after { - content: " (" attr(title) ")"; - } - - .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { - content: ""; - } - - pre, blockquote { - border: 1px solid #999; - padding-right: 1em; - page-break-inside: avoid; - } - - tr, img { - page-break-inside: avoid; - } - - img { - max-width: 100% !important; - } - - @page :left { - margin: 15mm 20mm 15mm 10mm; -} - - @page :right { - margin: 15mm 10mm 15mm 20mm; -} - - p, h2, h3 { - orphans: 3; - widows: 3; - } - - h2, h3 { - page-break-after: avoid; - } -} diff --git a/generated/.gitignore b/generated/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/generated/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/hosts.env b/hosts.env deleted file mode 100644 index 62fa199..0000000 --- a/hosts.env +++ /dev/null @@ -1,2 +0,0 @@ -[vps] -$TLD diff --git a/logs/.gitignore b/logs/.gitignore deleted file mode 100644 index af144f4..0000000 --- a/logs/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -* -!.gitignore -!placeholder.txt diff --git a/logs/placeholder.txt b/logs/placeholder.txt deleted file mode 100644 index e126580..0000000 --- a/logs/placeholder.txt +++ /dev/null @@ -1 +0,0 @@ -Placeholder log file so =cat logs/*= won't fail after being trapped. diff --git a/nextcloud-vhost.conf b/nextcloud-vhost.conf deleted file mode 100644 index efc1540..0000000 --- a/nextcloud-vhost.conf +++ /dev/null @@ -1 +0,0 @@ -client_max_body_size 4096M; diff --git a/nixos-update.sh b/nixos-update.sh new file mode 100755 index 0000000..7db0bf8 --- /dev/null +++ b/nixos-update.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash +# shellcheck shell=bash +set -Eeuo pipefail +cd "$(dirname "${BASH_SOURCE[0]}")" + +git crypt unlock +direnv allow + +envsubst < vps-configuration.env.nix | ssh "$TLD" 'cat > /etc/nixos/vps-configuration.nix' +ssh "$TLD" sudo nixos-rebuild switch --upgrade diff --git a/provision.env.yaml b/provision.env.yaml deleted file mode 100644 index 8c3e1c8..0000000 --- a/provision.env.yaml +++ /dev/null @@ -1,47 +0,0 @@ ---- -- hosts: all - any_errors_fatal: true - tasks: - - name: Update Ubuntu server - apt: - update_cache: yes - upgrade: dist - - name: Install apt packages - apt: - name: [ 'docker-compose', 'borgbackup' ] - state: latest - - name: Create /home/vps/ base directory - file: - path: /home/vps/ - state: directory - - name: Create symlink to attached volume - file: - src: /mnt/${VPS_VOLUME_NAME} - dest: /home/vps/volumes - state: link - - name: Create required vhost conf directory - file: - path: /home/vps/volumes/vhost-conf - state: directory - mode: '0755' - - name: Copy local interpolated files to remote - copy: src={{ item.src }} dest={{ item.dest }} mode={{ item.mode }} - with_items: - - { 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: './generated/docker-compose.yaml', dest: '/home/vps/docker-compose.yaml', mode: '400' } - - { src: './nextcloud-vhost.conf', dest: '/home/vps/volumes/vhost-conf/${NEXTCLOUD_TLD}', mode: '400' } - - name: Restore borg backup when we have a fresh volume - shell: /home/vps/restore-backup.sh - when: lookup('env', 'DESTROY_VPS') == "1" - - name: Create the required Docker network - docker_network: - name: nginx-proxy-network - - name: Start docker-compose - docker_compose: - project_src: /home/vps/ - pull: yes - state: present diff --git a/scripts/box/bash-profile.sh b/scripts/box/bash-profile.sh deleted file mode 100755 index c024dbd..0000000 --- a/scripts/box/bash-profile.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -# shellcheck disable=SC2164 - -alias l="ls -lahp --color" -cd /home/vps/ diff --git a/scripts/box/create-backup.env.sh b/scripts/box/create-backup.env.sh deleted file mode 100755 index f5cd3b0..0000000 --- a/scripts/box/create-backup.env.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash -set -Eeuo pipefail - -export BORG_REMOTE_PATH="${BORG_REMOTE_PATH}" -export BORG_PASSPHRASE="${BORG_PASSPHRASE}" -# The configured $BORG_REPO is already the rsync remote. -# No need to send the files after the backup is done. -borg create \ - --verbose \ - --stats \ - --progress \ - --compression lzma,6 \ - "${BORG_REPO}::{hostname}-{now}-${VPS_COMMIT_SHA}" \ - "${VOLUME_HOME}"/* diff --git a/scripts/box/restore-backup.env.sh b/scripts/box/restore-backup.env.sh deleted file mode 100755 index 151ded5..0000000 --- a/scripts/box/restore-backup.env.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -Eeuo pipefail - -export BORG_REMOTE_PATH="${BORG_REMOTE_PATH}" -export BORG_PASSPHRASE="${BORG_PASSPHRASE}" - -pushd "$(mktemp -d)" || exit 1 - -# It is actually being used below using the DOLLAR interpolation -# shellcheck disable=SC2034 -ARCHIVE="$(borg list "${BORG_REPO}" --last 1 --short)" - -echo "Extracting archive ${DOLLAR}{ARCHIVE}" -borg extract \ - --verbose \ - --progress \ - "${BORG_REPO}::${DOLLAR}{ARCHIVE}" -echo "Done." - -mv home/vps/volumes/* /home/vps/volumes/ -popd || exit 1 diff --git a/scripts/box/user-data.env.sh b/scripts/box/user-data.env.sh deleted file mode 100755 index f9da5d7..0000000 --- a/scripts/box/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/scripts/ci/deploy.sh b/scripts/ci/deploy.sh deleted file mode 100755 index 9be5758..0000000 --- a/scripts/ci/deploy.sh +++ /dev/null @@ -1,105 +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 ../../ -PROJECT_ROOT="${PWD}" - -finish-phase() { - local -r exit_code="${?}" - - cd "${PROJECT_ROOT}" - - if [[ "${exit_code}" = 0 ]]; then - echo "Finished successfully." - else - echo "TRAPPED ERROR!" - fi - echo "Running final steps..." - - echo "Sending logs via email..." - ./scripts/ci/mail.sh "${exit_code}" - echo "Done." - - echo "Storing file changes to '.tfstate' files..." - pushd ../vps-state/ - git add . - git commit -m "CI: fallback add all after deploy.sh failure for CI run $VPS_COMMIT_SHA" ||: - git push origin master - popd - echo "Done." - - echo "Locking git-crypt repositories back..." - git crypt lock - pushd ../vps-state/ - git crypt lock - popd - echo "Done." - - echo "Finished cleanup." -} -trap finish-phase 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 "Interpolating files with envsubst..." -envsubst < ./ssh.env.conf >> ~/.ssh/config -envsubst < ./hosts.env > ./generated/hosts -envsubst < ./docker-compose.env.yaml > ./generated/docker-compose.yaml -envsubst < ./provision.env.yaml > ./generated/provision.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 -echo "Done." - -echo "Running the Ansible shutdown.yaml playbook..." -create-known-hosts-file -ansible-playbook -v shutdown.yaml > ./logs/ansible-shutdown.txt -echo "Done." - -echo "Initializing Terraform..." -terraform --version -terraform init -echo "Done." - -if [[ "${DESTROY_VPS:-}" != "" ]]; then - echo "Destroying existing infrastructure..." - terraform destroy -input=false -auto-approve > ./logs/terraform-destroy.txt 2>&1 -else - echo 'Refreshing view on existing infrastructure...' - terraform refresh > ./logs/terraform-refresh.txt 2>&1 -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}" --allow-empty -git push origin master -popd -echo "Done." - -echo "Running the Ansible provision.yaml playbook..." -create-known-hosts-file -cp ./generated/provision.yaml ./provision.yaml -ansible-playbook -v provision.yaml > ./logs/ansible-provision.txt -echo "Done." diff --git a/scripts/ci/mail.sh b/scripts/ci/mail.sh deleted file mode 100755 index 9caebd4..0000000 --- a/scripts/ci/mail.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash -set -Eeuo pipefail -cd "$(dirname "${BASH_SOURCE[0]}")" -cd ../../ - -EXIT_CODE="${1:-}" - -[[ -z "${EXIT_CODE}" ]] && { - # shellcheck disable=SC2016 - echo 'Error: missing $EXIT positional argument.' - exit 2 -} - -if [[ "${EXIT_CODE}" = 0 ]]; then - SUBJECT_SUFFIX=' (successful build)' -else - SUBJECT_SUFFIX=' (FAILED BUILD)' -fi - -SUBJECT="VPS CI run #${JOB_ID} logs${SUBJECT_SUFFIX}" -ATTACHMENT_PATH='logs.txt' -BODY=$(cat <<EOF -CI run for commit ${VPS_COMMIT_SHA}. -See run: -https://builds.sr.ht/~euandreh/job/${JOB_ID} - -Logs are attached. - -EOF -) - -tail -n +1 ./logs/*.txt > "${ATTACHMENT_PATH}" - -[[ "${USER}" = "build" ]] || { - echo "Not running on CI." - echo "Early exit on sending email logs." - exit -} - -gpg --always-trust \ - -r "${GPG_TO}" \ - -e "${ATTACHMENT_PATH}" - -curl "${MAILGUN_URL}" \ - -s \ - --user "${MAILGUN_USER}" \ - -F from="${MAILGUN_FROM}" \ - -F to="${MAILGUN_TO}" \ - -F subject="${SUBJECT}" \ - -F text="${BODY}" \ - -F attachment="@${ATTACHMENT_PATH}.gpg" diff --git a/scripts/ci/setup.sh b/scripts/ci/setup.sh deleted file mode 100755 index d876df7..0000000 --- a/scripts/ci/setup.sh +++ /dev/null @@ -1,26 +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 ../../ - -echo "Unlocking git-crypt repos..." -git crypt unlock -# Assumes vps-state was already cloned -pushd ../vps-state/ -git crypt unlock -git remote set-url origin git@git.sr.ht:~euandreh/vps-state -popd -# git smudge after git-crypt clears file permissions -chmod 400 ./secrets/ssh/vps-box-client -echo "Done." - -echo "cd ./vps/ && source .envrc && cd ../" >> ~/.buildenv - -source .envrc - -git config --global user.email "${GIT_CI_USER}" -git config --global user.name "sr.ht CI" - -curl https://euandre.org/public-key.txt | gpg --import diff --git a/scripts/local/rotate-ssh-keys.sh b/scripts/local/rotate-ssh-keys.sh deleted file mode 100755 index 323d27c..0000000 --- a/scripts/local/rotate-ssh-keys.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/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 -C "${SSH_EMAIL}" -ssh-keygen -t rsa -b 4096 -q -N '' -f ./secrets/ssh/vps-box-server -C "${SSH_EMAIL}" - -git add ./secrets/ssh/ -git commit -m "Script: rotate SSH keys" diff --git a/secrets/nix/private-configuration.nix b/secrets/nix/private-configuration.nix Binary files differdeleted file mode 100644 index 9796247..0000000 --- a/secrets/nix/private-configuration.nix +++ /dev/null diff --git a/secrets/secret-envrc.sh b/secrets/secret-envrc.sh Binary files differindex 29469b3..6b8f06c 100644 --- a/secrets/secret-envrc.sh +++ b/secrets/secret-envrc.sh diff --git a/secrets/ssh/vps-box-client b/secrets/ssh/id_rsa Binary files differindex 439d0fe..439d0fe 100644 --- a/secrets/ssh/vps-box-client +++ b/secrets/ssh/id_rsa diff --git a/secrets/ssh/vps-box-client.pub b/secrets/ssh/id_rsa.pub Binary files differindex 78fb062..78fb062 100644 --- a/secrets/ssh/vps-box-client.pub +++ b/secrets/ssh/id_rsa.pub diff --git a/secrets/ssh/vps-box-server b/secrets/ssh/vps-box-server Binary files differdeleted file mode 100644 index df5c34e..0000000 --- a/secrets/ssh/vps-box-server +++ /dev/null diff --git a/secrets/ssh/vps-box-server.pub b/secrets/ssh/vps-box-server.pub Binary files differdeleted file mode 100644 index 4cca320..0000000 --- a/secrets/ssh/vps-box-server.pub +++ /dev/null diff --git a/secrets/terraform/plan-files/2020-08-10T12:02:19-03:00.tfplan b/secrets/terraform/plan-files/2020-08-10T12:02:19-03:00.tfplan Binary files differnew file mode 100644 index 0000000..5807aee --- /dev/null +++ b/secrets/terraform/plan-files/2020-08-10T12:02:19-03:00.tfplan diff --git a/shutdown.yaml b/shutdown.yaml deleted file mode 100644 index a190d1a..0000000 --- a/shutdown.yaml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- hosts: all - any_errors_fatal: true - tasks: - - name: Copy files for performing the backup - copy: src={{ item.src }} dest={{ item.dest }} mode={{ item.mode }} - with_items: - - { src: './generated/create-backup.sh', dest: '/home/vps/create-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' } - - name: Stop docker-compose - docker_compose: - project_src: /home/vps/ - state: absent - - name: Create a borg backup of the volume - shell: /home/vps/create-backup.sh diff --git a/ssh.env.conf b/ssh.env.conf deleted file mode 100644 index be34b28..0000000 --- a/ssh.env.conf +++ /dev/null @@ -1,7 +0,0 @@ -Host $TLD - User root - IdentityFile $PWD/secrets/ssh/vps-box-client - UserKnownHostsFile $PWD/generated/generated-known-hosts.txt - Port $SSH_PORT -Host git.sr.ht - StrictHostKeyChecking no diff --git a/terraform-update.sh b/terraform-update.sh new file mode 100755 index 0000000..436d7a1 --- /dev/null +++ b/terraform-update.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash +# shellcheck shell=bash +set -Eeuo pipefail +cd "$(dirname "${BASH_SOURCE[0]}")" + +git crypt unlock +direnv allow + +terraform init +PLAN_FILE="./secrets/terraform/plan-files/$(date -Iseconds)" +terraform plan -input=false -out="${PLAN_FILE}" +terraform apply -input=false "${PLAN_FILE}" diff --git a/configuration.nix b/vps-configuration.nix index fad5305..8afa57d 100644 --- a/configuration.nix +++ b/vps-configuration.nix @@ -1,10 +1,14 @@ { config, pkgs, ... }: let - privateConfiguration = import ./private-configuration.nix; - derivedConfiguration = import ./derived-configuration.nix; + envsubstConfiguration = { + nextcloudTLD = "$NEXTCLOUD_TLD"; + gitTLD = "$GIT_TLD"; + letsencryptEmail = "$LETSENCRYPT_EMAIL"; + authorizedKey = "$AUTHORIZED_KEY"; + }; in { - imports = [ ./hardware-configuration.nix]; + imports = [ ./hardware-configuration.nix ]; boot.loader.grub = { enable = true; @@ -17,15 +21,13 @@ in { interfaces.ens3.useDHCP = true; }; - environment.systemPackages = with pkgs; [ - vim - ]; + environment.systemPackages = with pkgs; [ vim ]; networking.firewall.allowedTCPPorts = [ 80 443 22 ]; security.acme = { acceptTerms = true; - email = privateConfiguration.letsencryptEmail; + email = envsubstConfiguration.letsencryptEmail; }; services = { @@ -41,36 +43,31 @@ in { recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; - sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL"; # FIXME: ????? + sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL"; virtualHosts = let - customConfigTLDs = {}; - defaultConfigTLDs = [ - derivedConfiguration.nextcloudTLD - derivedConfiguration.gitTLD - ]; - buildDefaultConfiguration = tld: - { - "${tld}" = { - forceSSL = true; - enableACME = true; - }; + customConfigTLDs = { }; + defaultConfigTLDs = + [ envsubstConfiguration.nextcloudTLD envsubstConfiguration.gitTLD ]; + buildDefaultConfiguration = tld: { + "${tld}" = { + forceSSL = true; + enableACME = true; }; - in - pkgs.lib.fold - (tldString: acc: acc // buildDefaultConfiguration tldString) - customConfigTLDs - defaultConfigTLDs; + }; + in pkgs.lib.fold + (tldString: acc: acc // buildDefaultConfiguration tldString) + customConfigTLDs defaultConfigTLDs; gitweb = { enable = true; location = "/"; - virtualHost = derivedConfiguration.gitTLD; + virtualHost = envsubstConfiguration.gitTLD; }; }; nextcloud = { enable = true; - hostName = derivedConfiguration.nextcloudTLD; + hostName = envsubstConfiguration.nextcloudTLD; nginx.enable = true; https = true; autoUpdateApps.enable = true; @@ -80,7 +77,8 @@ in { dbtype = "pgsql"; dbuser = "nextcloud"; - dbhost = "/run/postgresql"; # nextcloud will add /.s.PGSQL.5432 by itself + dbhost = + "/run/postgresql"; # nextcloud will add /.s.PGSQL.5432 by itself dbname = "nextcloud"; dbpassFile = "/var/nextcloud-db-pass"; @@ -92,12 +90,10 @@ in { postgresql = { enable = true; ensureDatabases = [ "nextcloud" ]; - ensureUsers = [ - { - name = "nextcloud"; - ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES"; - } - ]; + ensureUsers = [{ + name = "nextcloud"; + ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES"; + }]; }; gitweb = { @@ -106,18 +102,16 @@ in { }; }; - # FIXME: is this required? systemd.services."nextcloud-setup" = { - requires = ["postgresql.service"]; - after = ["postgresql.service"]; + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; }; users.users.nixos = { uid = 1000; - extraGroups = ["wheel"]; + extraGroups = [ "wheel" ]; useDefaultShell = true; - # FIXME: password hash file? - openssh.authorizedKeys.keyFiles = [ "/etc/nixos/nixos-user-authorized-key"]; + openssh.authorizedKeys.keys = [ envsubstConfiguration.authorizedKey ]; }; system.stateVersion = "19.09"; |