From e7b9546f7fa813767e2da9e077d5cb5fd6df9b3c Mon Sep 17 00:00:00 2001 From: Jeremie Fraeys Date: Sat, 21 Feb 2026 18:30:16 -0500 Subject: [PATCH] Update infrastructure tooling and configuration - Rename setup.sh to setup (drop extension for cleaner CLI) - Update ansible.cfg for improved playbook execution - Update .env.example with current environment variables --- .env.example | 29 +++++++- ansible.cfg | 1 - setup | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 226 insertions(+), 2 deletions(-) create mode 100755 setup diff --git a/.env.example b/.env.example index 89f82b8..b6a41a3 100644 --- a/.env.example +++ b/.env.example @@ -14,4 +14,31 @@ TF_VAR_object_storage_region=us-east-1 S3_BUCKET= S3_REGION=us-east-1 -S3_ENDPOINT=https://us-east-1.linodeobjects.com \ No newline at end of file +S3_ENDPOINT=https://us-east-1.linodeobjects.com + +RESTIC_REPOSITORY= +RESTIC_AWS_DEFAULT_REGION=us-east-1 +INFRA_BACKUP_ONCALENDAR=daily +RESTIC_KEEP_DAILY=7 +RESTIC_KEEP_WEEKLY=4 +RESTIC_KEEP_MONTHLY=6 + +ALERTMANAGER_SLACK_CHANNEL=#alerts +ALERTMANAGER_SLACK_USERNAME=alertmanager + +AUTHELIA_SMTP_ADDRESS= +AUTHELIA_SMTP_USERNAME= +AUTHELIA_SMTP_PASSWORD= +AUTHELIA_SMTP_SENDER= +AUTHELIA_SMTP_IDENTIFIER= +AUTHELIA_SMTP_STARTUP_CHECK_ADDRESS= +AUTHELIA_NOTIFIER_DISABLE_STARTUP_CHECK=false +# AUTHELIA_NOTIFIER_TYPE=filesystem + +# AUTHELIA_USE_POSTFIX=false +# POSTFIX_RELAYHOST= +# POSTFIX_RELAYHOST_USERNAME= +# POSTFIX_RELAYHOST_PASSWORD= +# POSTFIX_SMTP_TLS_SECURITY_LEVEL=may +# POSTFIX_ALLOWED_SENDER_DOMAINS= +# POSTFIX_ALLOW_EMPTY_SENDER_DOMAINS=true \ No newline at end of file diff --git a/ansible.cfg b/ansible.cfg index 8924d2b..78d0d84 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -7,4 +7,3 @@ interpreter_python=/usr/bin/python3 [ssh_connection] ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=~/.ansible/cp/ansible-ssh-%%h-%%p-%%r -o StrictHostKeyChecking=accept-new -o IdentitiesOnly=yes - diff --git a/setup b/setup new file mode 100755 index 0000000..8dd2c5f --- /dev/null +++ b/setup @@ -0,0 +1,198 @@ +#! /usr/bin/env bash + +set -euo pipefail + +vault_args=() +temp_vault_pass_file="" + +usage() { + cat <<'EOF' +Usage: ./setup [--no-ansible] [--no-terraform|--ansible-only] [--] [terraform ] + +Defaults: + - Runs Terraform (plan/apply) in terraform/ + - Generates Ansible inventory from Terraform outputs + - Runs Ansible playbooks + +Options: + --no-ansible Run Terraform only (no Ansible). + --no-terraform Skip Terraform; requires existing inventory/hosts.yml. + --ansible-only Alias for --no-terraform. + --help Show this help. + +Terraform passthrough: + ./setup -- terraform [args] + ./setup -- [args] +EOF +} + +cleanup() { + if [[ -n "${temp_vault_pass_file}" ]] && [[ -f "${temp_vault_pass_file}" ]]; then + rm -f "${temp_vault_pass_file}" + fi +} +trap cleanup EXIT +ansible_extra_args=() +terraform_apply_args=() +terraform_passthrough=() + +run_ansible=true +run_terraform=true + +if [[ "${1:-}" == "--help" ]] || [[ "${1:-}" == "-h" ]]; then + usage + exit 0 +fi + +if [[ "${1:-}" == "--no-ansible" ]]; then + run_ansible=false + shift +fi + +if [[ "${1:-}" == "--no-terraform" ]] || [[ "${1:-}" == "--ansible-only" ]]; then + run_terraform=false + shift +fi + +if [[ "${1:-}" == "--" ]]; then + shift + if [[ "${1:-}" == "terraform" ]]; then + shift + terraform_passthrough=("$@") + else + case "${1:-}" in + output|state|workspace|providers|version|validate|fmt|taint|untaint|graph|show|console|import) + terraform_passthrough=("$@") + ;; + *) + terraform_apply_args=("$@") + ;; + esac + fi +fi + +if [[ -f ".env" ]]; then + set -a + source .env + set +a +fi + +if [[ "${run_terraform}" == "true" ]]; then + if ! command -v terraform >/dev/null 2>&1; then + echo "terraform is required (install terraform or run with --no-terraform)" >&2 + exit 2 + fi +fi + +if [[ "${run_ansible}" == "true" ]]; then + if ! command -v ansible-playbook >/dev/null 2>&1; then + echo "ansible-playbook is required (install ansible or run with --no-ansible)" >&2 + exit 2 + fi +fi + +if [[ -f "secrets/vault.yml" ]]; then + if ! command -v ansible-vault >/dev/null 2>&1; then + echo "ansible-vault is required to read secrets/vault.yml" >&2 + exit 2 + fi + if [[ -f "secrets/.vault_pass" ]]; then + vault_args+=(--vault-password-file "secrets/.vault_pass") + elif [[ -f ".vault_pass" ]]; then + vault_args+=(--vault-password-file ".vault_pass") + else + read -rsp "Vault password: " vault_password + echo + temp_vault_pass_file=$(mktemp) + chmod 600 "${temp_vault_pass_file}" + printf '%s' "${vault_password}" > "${temp_vault_pass_file}" + unset vault_password + vault_args+=(--vault-password-file "${temp_vault_pass_file}") + fi + + if (( ${#vault_args[@]} )); then + vault_plain=$(ansible-vault view secrets/vault.yml "${vault_args[@]}") + else + vault_plain=$(ansible-vault view secrets/vault.yml) + fi + while IFS= read -r line; do + [[ -z "${line}" ]] && continue + [[ "${line}" == "---" ]] && continue + [[ "${line}" != TF_VAR_*:* ]] && [[ "${line}" != CF_DNS_API_TOKEN:* ]] && [[ "${line}" != CF_ZONE_API_TOKEN:* ]] && [[ "${line}" != S3_ACCESS_KEY_ID:* ]] && [[ "${line}" != S3_SECRET_ACCESS_KEY:* ]] && continue + key="${line%%:*}" + value="${line#*:}" + value="${value# }" + [[ -z "${value}" ]] && continue + escaped=$(printf '%q' "${value}") + eval "export ${key}=${escaped}" + done <<< "${vault_plain}" + + if [[ -z "${TF_VAR_cloudflare_api_token:-}" ]] && [[ -n "${CF_DNS_API_TOKEN:-}" ]]; then + export TF_VAR_cloudflare_api_token="${CF_DNS_API_TOKEN}" + fi + + if [[ -z "${TF_VAR_cloudflare_zone_id:-}" ]] && [[ -n "${CF_ZONE_API_TOKEN:-}" ]]; then + export TF_VAR_cloudflare_zone_id="${CF_ZONE_API_TOKEN}" + fi +fi + +if [[ "${run_terraform}" == "true" ]]; then + terraform -chdir=terraform init + + if (( ${#terraform_passthrough[@]} )); then + terraform -chdir=terraform "${terraform_passthrough[@]}" + exit 0 + fi + + if (( ${#terraform_apply_args[@]} )); then + terraform -chdir=terraform apply "${terraform_apply_args[@]}" + else + terraform -chdir=terraform plan -out=tfplan + terraform -chdir=terraform apply tfplan + fi + + rm -f terraform/tfplan + + web_ipv4=$(terraform -chdir=terraform output -raw web_ip) + web_ipv6=$(terraform -chdir=terraform output -raw web_ipv6) + services_ipv4=$(terraform -chdir=terraform output -raw services_ip) + + ssh_user=${TF_VAR_user:-ansible} + + mkdir -p inventory/host_vars + + cat > inventory/hosts.yml < inventory/host_vars/web.yml <&2 + exit 2 + fi +fi + +if [[ "${run_ansible}" == "true" ]]; then + if [[ -n "${vault_args+x}" ]] && (( ${#vault_args[@]} )); then + ansible_extra_args=("${vault_args[@]}") + fi + ansible-playbook playbooks/services.yml ${ansible_extra_args[@]+"${ansible_extra_args[@]}"} + ansible-playbook playbooks/web.yml ${ansible_extra_args[@]+"${ansible_extra_args[@]}"} +fi