From afb0513224718a82ee6f2937dd39296a35857b0b Mon Sep 17 00:00:00 2001 From: Andrea Galbusera <gizero@gmail.com> Date: Tue, 12 Jan 2021 16:53:44 +0100 Subject: [PATCH] initial infra on Hetzner Cloud --- .gitignore | 35 +++++++++++++++ .gitlab-ci.yml | 85 ++++++++++++++++++++++++++++++++++++ .terraform.lock.hcl | 21 +++++++++ backend.tf | 4 ++ infra.tf | 16 +++++++ provider-hcloud.tf | 5 +++ provision.tfvars.sample | 2 + templates/cloud-init.yml.tpl | 61 ++++++++++++++++++++++++++ versions.tf | 9 ++++ 9 files changed, 238 insertions(+) create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100755 .terraform.lock.hcl create mode 100644 backend.tf create mode 100644 infra.tf create mode 100644 provider-hcloud.tf create mode 100644 provision.tfvars.sample create mode 100644 templates/cloud-init.yml.tpl create mode 100644 versions.tf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28370b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log + +# Exclude all .tfvars files, which are likely to contain sentitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +# +*.tfvars + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* +*tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..907e070 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,85 @@ +image: + name: hashicorp/terraform:light + entrypoint: + - '' + +variables: + PLAN: plan.tfplan + JSON_PLAN_FILE: plan.json + GITLAB_TF_ADDRESS: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_PROJECT_NAME}" + TF_COMMON_ARGS: "-var hcloud_token=${HCLOUD_RW_TOKEN:=$HCLOUD_RO_TOKEN} -var theo_token=${THEO_TOKEN}" + +cache: + key: "$CI_COMMIT_SHA" + paths: + - .terraform + +.install-jq: &install-jq + - apk add --update jq + - alias convert_report="jq -r '([.resource_changes[].change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'" + +before_script: + - *install-jq + - terraform version + - terraform init + -input=false + -reconfigure + -backend-config="address=${GITLAB_TF_ADDRESS}" + -backend-config="lock_address=${GITLAB_TF_ADDRESS}/lock" + -backend-config="unlock_address=${GITLAB_TF_ADDRESS}/lock" + -backend-config="username=gitlab-ci-token" + -backend-config="password=${CI_JOB_TOKEN}" + -backend-config="lock_method=POST" + -backend-config="unlock_method=DELETE" + -backend-config="retry_wait_min=5" + +stages: + - validate + - plan + - apply + - provision + - destroy + +validate: + stage: validate + script: + - terraform validate + - terraform fmt -check=true + only: + - merge_requests + - pushes + +merge review: + stage: plan + script: + - terraform plan ${TF_COMMON_ARGS} -out $PLAN + - terraform show --json $PLAN | convert_report > $JSON_PLAN_FILE + artifacts: + expire_in: 1 week + name: plan + reports: + terraform: $JSON_PLAN_FILE + only: + - merge_requests + +apply: + stage: apply + script: + - terraform apply ${TF_COMMON_ARGS} -auto-approve + only: + - master + +provision: + stage: provision + trigger: + project: fcub/fcub-infra-ansible + only: + - master + +destroy: + stage: destroy + script: + - terraform destroy ${TF_COMMON_ARGS} -auto-approve + when: manual + only: + - master diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl new file mode 100755 index 0000000..633416c --- /dev/null +++ b/.terraform.lock.hcl @@ -0,0 +1,21 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hetznercloud/hcloud" { + version = "1.23.0" + constraints = "1.23.0" + hashes = [ + "h1:saM0Nkf+071U3kTYiPyOWFTxdLCPKEKAa5IK53Cu6JQ=", + "zh:158d1369f267ce292f6e278202c60a1b35f362d24b94d57c83ef460624ef4dc4", + "zh:237cf7934682a70b2a911ba7ad5ecef5e6f6c4c7e8c75d5419adee032b843ff3", + "zh:249a5c0c73852783ce9191076c1cb0cf9a1f53c7a1c3af08be83d7c51ab4d46c", + "zh:2d7e0cab7d54f4373c01210b178bdeca46279cfb0c794f8e564baa8cb95179ad", + "zh:5be24f23c00294363aeb07315a98f6c21e2718e6d28d24800d94a67f84ac1aee", + "zh:753e498bebb7e9f6423f3654528a429790f5e009a9d80b58733686de1970a05e", + "zh:848d8e300e92c5e35cf2dbf4d68a3624898f317e9f11cbbb35f4e5d8ff07b968", + "zh:85579efc6dd158dbc2eed22a628f4539e924cfbef2bf07f4173fa47ca6ccd37b", + "zh:879e7aa1d7825dd546b8edfc29037c60818e0ab87021430e0c06e051a96ab30a", + "zh:9354ff17884ff0fbdd5d81d5e430a6b8712ad763069a7345bc56bfc19b190813", + "zh:b2c52428c03ee7a438300692c18f2e1fe09afd4c107b69530a746574690b1bde", + ] +} diff --git a/backend.tf b/backend.tf new file mode 100644 index 0000000..4ca44e9 --- /dev/null +++ b/backend.tf @@ -0,0 +1,4 @@ +terraform { + backend "http" { + } +} diff --git a/infra.tf b/infra.tf new file mode 100644 index 0000000..980b55b --- /dev/null +++ b/infra.tf @@ -0,0 +1,16 @@ +# dummy key will be used to avoid servers root passwords being mailed +# will use AK to setup real authorization +resource "hcloud_ssh_key" "dummy-key" { + name = "dummy-key" + public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDG6KCXcL6bgJKD/ZbzLDeZms6TJwUz7K0yf+KCvfjxV dummy-key" +} + +variable "theo_token" {} + +resource "hcloud_server" "fcub01" { + name = "fcub01" + image = "ubuntu-20.04" + server_type = "cpx31" + ssh_keys = [hcloud_ssh_key.dummy-key.id] + user_data = templatefile("templates/cloud-init.yml.tpl", { theo_token = var.theo_token }) +} diff --git a/provider-hcloud.tf b/provider-hcloud.tf new file mode 100644 index 0000000..51c035d --- /dev/null +++ b/provider-hcloud.tf @@ -0,0 +1,5 @@ +variable "hcloud_token" {} + +provider "hcloud" { + token = var.hcloud_token +} diff --git a/provision.tfvars.sample b/provision.tfvars.sample new file mode 100644 index 0000000..8b544c5 --- /dev/null +++ b/provision.tfvars.sample @@ -0,0 +1,2 @@ +hcloud_token = "YOUR_HETZNER_TOKEN" +theo_token = "THEO_TOKEN_TO_REPLACE_IN_CLOUD_INIT_YML" diff --git a/templates/cloud-init.yml.tpl b/templates/cloud-init.yml.tpl new file mode 100644 index 0000000..75f00fd --- /dev/null +++ b/templates/cloud-init.yml.tpl @@ -0,0 +1,61 @@ +#cloud-config + +groups: + - sysadmins + +users: + - name: ansibleusr + shell: /bin/bash + groups: sysadmins + - name: theo-agent + shell: /bin/false + system: true + +write_files: + - path: /etc/sudoers.d/50-sysadmins + owner: root:root + permissions: '0440' + content: | + %sysadmins ALL=(ALL) NOPASSWD: ALL + - path: /etc/theo-agent/public.pem + owner: root:root + permissions: '0644' + content: | + -----BEGIN PUBLIC KEY----- + MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3gGExRviVBMSL0SZ9Ce9 + 99eWED96iPSKfmjv8Iz3faLmPLKWRDOaxwNdU8Sg48O9IEcAEbgx3jgubNLthiRB + U+F5N00ZpFHXByc7h2FxD/JMzxoyxDYSdaQ+JHt+GNYmFA6DYpE6KPaISrWjXgGT + KTzN3135qK14ByI0wOUHKESAKPRf/ZMPclwBxEDlfvrn0V1fjBzP1Xbnxv5LFWSl + CPGvUA7+msqcHdq0Ep3UPJbnSWO3HhynVevkgj0zVW1GKeps+fa+GFvcyD4N53Ya + uGZDefqZgfRxDXrb+vOtiOpVDVvIoicZPt2To9Cd4frpYtNWstDisDoLQBDc6v3p + 26OmSZlXbCZbEGyknJ7pz/bpOqRpNlElmfGVDKTmX5OAgL2dk1UdDzuxm/WlPXFv + SQv9/heZOiYuW7haMHkCELnk8kWnaUxKDC6+Hma8GLVgCP4YjUkpkU7FJD6wksKc + U408zgEEBWsk31KtA0BVS8462N24LunQcpB98ZAnL343SkrQcu/n/Nd9DTofInyP + NVIt7Sq1C0OqBFic+YoJTgig4mYAIbxGIhai/03IlkVzOf5AuAAX8ddbWX3k5Lnn + xFKLuHu71khcDaB1Jn7K22sN5meg+6qAED/xJV7bDXwVyBiknCwMxAiHfz0+kTyI + Ugm7jhITOZ0cipYzvPrwIWcCAwEAAQ== + -----END PUBLIC KEY----- + - path: /usr/sbin/download-install-theo.sh + owner: root:root + permissions: '0755' + content: | + #!/bin/bash + THEO_AGENT_LATEST=$(curl -L -s -H 'Accept: application/json' https://github.com/theoapp/theo-agent/releases/latest |sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/') + sudo curl -L -o /usr/sbin/theo-agent \ + https://github.com/theoapp/theo-agent/releases/download/$${THEO_AGENT_LATEST}/theo-agent-$(uname -s)-$(uname -m) + chmod 755 /usr/sbin/theo-agent + /usr/sbin/theo-agent \ + -install \ + -verify \ + -public-key /etc/theo-agent/public.pem \ + -no-interactive \ + -sshd-config \ + -url https://fluidware.authkeys.io \ + -token ${theo_token} + -hostname-prefix fcub- + chown -R theo-agent /etc/theo-agent + chmod 700 /etc/theo-agent + selinuxenabled 2>/dev/null && semanage permissive -a sshd_t +runcmd: + - /usr/sbin/download-install-theo.sh + - systemctl restart ssh.service diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..0940df2 --- /dev/null +++ b/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + hcloud = { + source = "hetznercloud/hcloud" + version = "1.23.0" + } + } + required_version = ">= 0.14" +} -- GitLab