aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2019-06-05 16:38:53 -0300
committerEuAndreh <eu@euandre.org>2019-06-05 16:42:06 -0300
commit54fd61c887f266f8e2e6b1419a86fc6681116069 (patch)
tree74a9923d75be46dad6c967acd271cdb5d80fca45
parentUse =nix build= instead of =nix-build= (diff)
downloadserver-54fd61c887f266f8e2e6b1419a86fc6681116069.tar.gz
server-54fd61c887f266f8e2e6b1419a86fc6681116069.tar.xz
Use Ansible instead of Bash for provisioning
The deployment is not quite working, and I'm unable to test right now: DigitalOcean is returning 503 for my requests. As of this commit, I can run =ansible-playbook provider.yml= more than once and it will actually be idempotent. Notes: - SSH fingerprint are now taken from the public key file instead of manually supplying it in the terraform template using the =digitalocean_ssh_key= resource; - use Ansible instead of ad-hoc Bash scripts for provisioning the Droplets created by Terraform; - use the =filename.env.extension= to create the concrete files in CI; - use the =user_data= to add the know SSH key pair to the newly created Droplet; - add =rotate-ssh-keys.sh= utils;
-rw-r--r--.gitignore8
-rw-r--r--TODOs.org32
-rw-r--r--ansible.cfg2
-rw-r--r--cloud-config.env.yaml7
-rwxr-xr-xdeploy.sh41
-rw-r--r--docker-compose.env.yaml (renamed from docker-compose.yaml)0
-rw-r--r--hosts.env2
-rw-r--r--provision.yaml31
-rwxr-xr-xrotate-ssh-keys.sh28
-rwxr-xr-xscripts/box/bash-profile.sh (renamed from scripts/box/bash-aliases.sh)1
-rwxr-xr-xscripts/box/run-backup.env.sh (renamed from scripts/box/run-backup-template.sh)2
-rwxr-xr-xscripts/ci/provision.sh13
-rwxr-xr-xscripts/ci/setup.sh14
-rw-r--r--secrets/borg/borg_remote49
-rw-r--r--secrets/borg/borg_remote.pub1
-rw-r--r--secrets/borg_remotebin3411 -> 0 bytes
-rw-r--r--secrets/borg_remote.pubbin769 -> 0 bytes
-rw-r--r--secrets/envrc.shbin1541 -> 1495 bytes
-rw-r--r--secrets/ssh/known-hosts.txt0
-rw-r--r--secrets/ssh/vps-box-client49
-rw-r--r--secrets/ssh/vps-box-client.pub1
-rw-r--r--secrets/ssh/vps-box-server49
-rw-r--r--secrets/ssh/vps-box-server.pub1
-rw-r--r--secrets/vps_boxbin3403 -> 0 bytes
-rw-r--r--secrets/vps_box.pubbin763 -> 0 bytes
-rw-r--r--ssh.conf6
-rw-r--r--ssh.env.conf6
-rwxr-xr-xuser-data.env.sh6
-rw-r--r--vps.tf16
29 files changed, 301 insertions, 64 deletions
diff --git a/.gitignore b/.gitignore
index f785cc6..4a2ab4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,10 @@
/.terraform/
# Nix
-/result \ No newline at end of file
+/result
+
+# Template files
+/docker-compose.yaml
+/cloud-config.yaml
+/hosts
+/user-data.sh \ No newline at end of file
diff --git a/TODOs.org b/TODOs.org
index 28318e0..1475260 100644
--- a/TODOs.org
+++ b/TODOs.org
@@ -82,7 +82,8 @@ In this situation, I if go on with automating the deployment I'd rather pick the
I'll start with other services other than email and consider alternatives later.
** TODO Use Digital Ocean's Volumes for persistent extended storage
** TODO Make VPS provisioning more robust
-*** TODO Use Ansible (or an equivalent tool) instead of custom Bash scripts
+*** DONE Use Ansible (or an equivalent tool) instead of custom Bash scripts
+CLOSED: [2019-06-05 Wed 16:41]
They are now more fragile, ad-hoc and imperative than I would like.
Today Terraform won't run the =deploy.sh= if no infrastructure changes are required. Split infrastructure provisioning from server configuration with somethong like Ansible or =nix copy closure= and add extra command in the pipeline run.
@@ -97,7 +98,7 @@ borg list --short --sort-by timestamp | tail -n 1
#+END_SOURCE
** WAITING Configure DNS from Terraform
*** TODO Test provisioning DNS entries with other DNS registrars
-*** TODO Have dynamic Floating IP
+*** TODO Have dynamic Floating IP (a.k.a. =$PINNED_IP=)
** TODO Create snapshots before destroying resources
This way the previous good state can be reverted if the deployment fails or the backup can't be restored.
@@ -107,6 +108,13 @@ https://www.reddit.com/r/selfhosted/comments/bw8hqq/top_3_measures_to_secure_you
https://docs.nextcloud.com/server/stable/admin_manual/installation/harden_server.html
https://ownyourbits.com/2017/03/25/nextcloud-a-security-analysis/
** TODO Use git-remote-gcrypt instead of git-crypt for vps-state
+Also put all of the content of =secrets/*= into vps-state? Maybe rename it to vps-secret?
+
+Right now, secrets are scattered between the two repositories. By moving I can completely remove =git-crypt= from this repository.
+** TODO Run backup on Terraform destroy action instead of manually in =provision.sh=
+** TODO Explicitly destroy Droplets before running Terraform apply?
+** TODO Store updated =.tfstate= even in case of deployment failure
+Right now the script fails on Terraform commands before reaching git commands. I should trap the error, store on git and only then fail.
* Must
** Fully deployable from code
Use NixOps and Terraform to fully automate all of the configuration.
@@ -166,7 +174,7 @@ The ultimate goal would be to upsert a Floating IP address? If no Floating IP ad
In other words, I don't want any hardcoded IPs in the recipe. The IP address has to be fixed, and the same on the DNS registrar and DigitalOcean's Floating IP.
** TODO Critiques of Docker?
-What does NixOps, DisNix and Dysnomia are trying to accomplish that overlap with Docker?
+What does NixOps, DisNix and Dysnomia are trying to accomplish that overlap with Docker? Use sqldiff for NixOps?
Do they do a better job? Why? Why not?
@@ -223,3 +231,21 @@ All data stored on git is encrypted with [[https://www.agwa.name/projects/git-cr
By taking advantage of the sourcehut ecosystem, it was easier to setup the access of the pipeline to the ad-hoc Terraform backend.
I created a repository called [[https://git.sr.ht/~euandreh/vps-state/][=vps-state=]] to store the encrypted =.tfstate= and =.tfplan= files. During the CI run, the pipeline creates new a =.tfplan= file and commits it into =vps-state=, and after applying the plan it updates the =.tfstate= file and adds this change to =vps-state=.
+** Configuration of =StrictHostKeyChecking=
+We have 2 cases where I'm pushing things to the server and I'm dealing with it differently:
+*** 1. Pushing updates to the =vps-state= repository
+I could whitelist the SSH keys from the =git.sr.ht= servers, but this could break on every key rotation of the server.
+
+In can of the server address being spoofed, the content would be readable by the attacker, since we're doing all the encryption on the client. We would, however, lose a Terraform state file update. As of right now, I'm OK with this trade-off.
+*** 2. Running =scp= to the deployed VPS
+On this situation I want to be sure I know where I'm pushing to.
+
+In order to avoid adding =StrictHostKeyChecking= when running =ssh= and =scp=, every time the SSH key is rotated I generate a new =./secrets/ssh/known-hosts.txt= file with the proper SSH public key.
+
+This way we can avoid prompting for SSH server fingerprint trust on the CI and avoid adding =StrictHostKeyChecking= on those calls.
+** Don't use Ansible as a =local-exec= provisioner from Terraform
+Instead, explicitly call =ansible-playbook= after =terraform apply= finished running.
+
+This way we test the DNS A record -> Floating IP -> Droplet IP path. We can't do that inside Terraform declaration because the =local-exec= provisioning command runs before the =digitalocean_floating_ip_assignment= is created, and we can't create a cyclic dependency between the two resources.
+
+We could use the raw Droplet IP instead of the DNS A record, but I prefer calling it later in order to always test the full DNS resolution.
diff --git a/ansible.cfg b/ansible.cfg
new file mode 100644
index 0000000..f9af32d
--- /dev/null
+++ b/ansible.cfg
@@ -0,0 +1,2 @@
+[defaults]
+inventory = ./hosts \ No newline at end of file
diff --git a/cloud-config.env.yaml b/cloud-config.env.yaml
new file mode 100644
index 0000000..dc8664e
--- /dev/null
+++ b/cloud-config.env.yaml
@@ -0,0 +1,7 @@
+#cloud-config
+
+ssh_deletekeys: true
+ssh_keys:
+ ssh_rsa_private: |
+${PRIVATE}
+ ssh_rsa_public: ${PUBLIC}
diff --git a/deploy.sh b/deploy.sh
deleted file mode 100755
index 9172803..0000000
--- a/deploy.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env bash
-set -Eeuo pipefail
-cd "$(dirname "${BASH_SOURCE[0]}")"
-
-apt_wait() {
- local i=0
- tput sc
- while fuser /var/lib/apt/lists/lock >/dev/null 2>&1 ; do
- case $((i % 4)) in
- 0 ) j="-" ;;
- 1 ) j="\\" ;;
- 2 ) j="|" ;;
- 3 ) j="/" ;;
- esac
- tput rc
- echo -en "\r[$j] Waiting for other software managers to finish..."
- sleep 0.5
- ((i=i+1))
- done
-}
-
-apt_wait
-
-echo "Ubuntu update and install docker-compose..."
-ssh "$TLD" sudo apt-get update
-ssh "$TLD" sudo apt-get upgrade -y
-ssh "$TLD" sudo apt-get install -y docker-compose
-ssh "$TLD" sudo apt-get autoremove -y
-echo "Done."
-
-echo "Copy over files..."
-ssh "$TLD" mkdir -p /home/vps/
-ssh "$TLD" 'grep /home/vps/ /root/.profile || echo "cd /home/vps/" >> /root/.profile'
-scp ./scripts/box/bash-aliases.sh "$TLD":/root/.bash_aliases
-envsubst < docker-compose.yaml | ssh "$TLD" 'cat > /home/vps/docker-compose.yaml'
-echo "Done."
-
-echo "Restart docker-compose"
-ssh "$TLD" "cd /home/vps/ && docker-compose pull"
-ssh "$TLD" "cd /home/vps/ && docker-compose up -d"
-echo "Done."
diff --git a/docker-compose.yaml b/docker-compose.env.yaml
index f5acf14..f5acf14 100644
--- a/docker-compose.yaml
+++ b/docker-compose.env.yaml
diff --git a/hosts.env b/hosts.env
new file mode 100644
index 0000000..62fa199
--- /dev/null
+++ b/hosts.env
@@ -0,0 +1,2 @@
+[vps]
+$TLD
diff --git a/provision.yaml b/provision.yaml
new file mode 100644
index 0000000..d23bbc9
--- /dev/null
+++ b/provision.yaml
@@ -0,0 +1,31 @@
+---
+- hosts: all
+ gather_facts: no
+ pre_tasks:
+ - name: Install Python 2 for Ansible fact gathering
+ raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
+
+- hosts: all
+ tasks:
+ - name: Update Ubuntu server
+ apt:
+ update_cache: yes
+ upgrade: dist
+ - name: Install docker-compose
+ apt:
+ name: docker-compose
+ state: latest
+ - name: Create /home/vps/ base directory
+ file:
+ path: /home/vps/
+ state: directory
+ - name: Copy file
+ copy: src={{ item.src }} dest={{ item.dest }}
+ with_items:
+ - { src: './scripts/box/bash-profile.sh', dest: '/etc/profile.d/bash-profile.sh' }
+ - { src: './docker-compose.yaml', dest: '/home/vps/docker-compose.yaml' }
+ - name: Start docker-compose
+ docker_service:
+ project_src: /home/vps/
+ pull: yes
+ state: present
diff --git a/rotate-ssh-keys.sh b/rotate-ssh-keys.sh
new file mode 100755
index 0000000..2e3f1fb
--- /dev/null
+++ b/rotate-ssh-keys.sh
@@ -0,0 +1,28 @@
+#!/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
+PUBLIC_KEY="$(awk '{print $2}' < ./secrets/ssh/vps-box-server.pub)"
+echo "${TLD},${PINNED_IP} ssh-rsa ${PUBLIC_KEY}" > ./secrets/ssh/known-hosts.txt
+
+# git add ./secrets/ssh/
+# git commit -m "Script: rotate SSH keys"
+
+# rotate() {
+# # FIXME: add email address?
+# # FIXME: use 4096 instead of (default) 2048
+# ssh-keygen -t rsa \
+# -q \
+# -N '' \
+# -f "${1}"
+# }
+
+# rotate ./secrets/ssh/vps-box-client
+# rotate ./secrets/ssh/vps-box-server
+
+
+# FIXME:
+# Commit to repo the rotated files
diff --git a/scripts/box/bash-aliases.sh b/scripts/box/bash-profile.sh
index 4ef035d..e24d333 100755
--- a/scripts/box/bash-aliases.sh
+++ b/scripts/box/bash-profile.sh
@@ -1,3 +1,4 @@
#!/usr/bin/env bash
alias l="ls -lahp --color"
+cd /home/vps/
diff --git a/scripts/box/run-backup-template.sh b/scripts/box/run-backup.env.sh
index 34184b9..e1ecdf0 100755
--- a/scripts/box/run-backup-template.sh
+++ b/scripts/box/run-backup.env.sh
@@ -2,6 +2,8 @@
export BORG_REMOTE_PATH="${BORG_REMOTE_PATH}"
export BORG_PASSPHRASE="${BORG_PASSPHRASE}"
+# The configured $BORG_REPO is already the rsync.net remote.
+# No need to send the files after the backup is done.
borg create \
--verbose \
--stats \
diff --git a/scripts/ci/provision.sh b/scripts/ci/provision.sh
index 3ba89d9..56e481a 100755
--- a/scripts/ci/provision.sh
+++ b/scripts/ci/provision.sh
@@ -9,22 +9,21 @@ VPS_COMMIT_SHA="$(git rev-parse HEAD)"
export VPS_COMMIT_SHA
echo "Shutting down running containers and backing up data..."
ssh "$TLD" "cd /home/vps/ && docker-compose down"
-scp ./secrets/borg_remote.pub "$TLD":/root/.ssh/id_rsa.pub
-scp ./secrets/borg_remote "$TLD":/root/.ssh/id_rsa
-envsubst < ./scripts/box/run-backup-template.sh | ssh "$TLD" 'cat > /home/vps/run-backup.sh && chmod +x /home/vps/run-backup.sh'
+scp ./secrets/borg/borg_remote.pub "$TLD":/root/.ssh/id_rsa.pub
+scp ./secrets/borg/borg_remote "$TLD":/root/.ssh/id_rsa
+envsubst < ./scripts/box/run-backup.env.sh | ssh "$TLD" 'cat > /home/vps/run-backup.sh && chmod +x /home/vps/run-backup.sh'
ssh "$TLD" /home/vps/run-backup.sh
echo "Done."
echo "Running 'terraform plan' and storing the planfile..."
-# Terraform plan
terraform --version
terraform init
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"
-# Store on git repo
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"
@@ -44,6 +43,10 @@ git push origin master
popd
echo "Done."
+echo "Running the Ansible playbook..."
+ansible-playbook provision.yaml
+echo "Done."
+
echo "Locking git-crypt repositories back..."
git crypt lock
pushd ../vps-state/
diff --git a/scripts/ci/setup.sh b/scripts/ci/setup.sh
index ee5ecf2..e6e85c9 100755
--- a/scripts/ci/setup.sh
+++ b/scripts/ci/setup.sh
@@ -18,9 +18,17 @@ popd
echo "Done."
# git smudge after git-crypt clears file permissions
-chmod 600 ./secrets/vps_box
-chmod 600 ./secrets/borg_remote
+chmod 600 ./secrets/ssh/vps-box-client
+chmod 600 ./secrets/borg/borg_remote
cat .envrc >> ~/.buildenv
source .envrc
-envsubst < ./ssh.conf >> ~/.ssh/config
+
+export SSH_SERVER_PRIVATE_KEY="$(cat ./secrets/ssh/vps-box-server)"
+export SSH_SERVER_PUBLIC_KEY="$(cat ./secrets/ssh/vps-box-server.pub)"
+
+envsubst < ./cloud-config.env.yaml > ./cloud-config.yaml
+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
diff --git a/secrets/borg/borg_remote b/secrets/borg/borg_remote
new file mode 100644
index 0000000..ba43489
--- /dev/null
+++ b/secrets/borg/borg_remote
@@ -0,0 +1,49 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+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
+-----END OPENSSH PRIVATE KEY-----
diff --git a/secrets/borg/borg_remote.pub b/secrets/borg/borg_remote.pub
new file mode 100644
index 0000000..2f7af58
--- /dev/null
+++ b/secrets/borg/borg_remote.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9U9FKW80XIqmRjnXXcCdKjS2Z4O3fkPrlilD2Bw4jqo0gLfn37ohzSuStE/9/d00u8WkeG37BHRSI77qmkgKMlKgfB5BAQMMorH64KgPZ0dErMAWv89txxsoZjX8VZwXQawVwUeI71sK38BCN5PW+BolZWJ8wn/pioKmlkqxXayOc6brYq+6TLN0yIj8b0YzNz++Z3r+K7WDrR6TPqCr0ItSHAoE0qEEiM9NBEtZgw6R4zp7umj8w5tfd9LY7faeGTILmF4z8gpIeQNtuEGOtv8vaXWYJ4bk3IU6zir4LTbLer6zCpt11729rVKpbx+kQibAtilMSvxCyu1Ml6anxSyemqDlfrF29xp+JfMkih1Y12TWjJcOKy8S6a65OMo3jW0+YllCB/o9j2XYqjRiFrV761oo51MyobPFdbnlJmfy1zwxgtK2+sqvIuzFR3gu5QgccWqoXL4r98tTYBkbI7XOiu7LR9rQn3nfokwqQkkGZ6ROPHi7CCNDu/nTmRXpswAN29+eNR93rgVODdqrvQy8J+ieThzxYEcglBQLj7kc+ewBOze6jRavTYHw23n/dYW7nBA1aJc+BorNJ3R9QhlN+4h9LcN6t9b//b7xlQWGjJoGF5eNH3wOOXEOW8hvuywfs8saK3gTJU5KIHHjtejtSxTD18v1htR0HUycnzw== rsync.net@euandre.org
diff --git a/secrets/borg_remote b/secrets/borg_remote
deleted file mode 100644
index 7f71805..0000000
--- a/secrets/borg_remote
+++ /dev/null
Binary files differ
diff --git a/secrets/borg_remote.pub b/secrets/borg_remote.pub
deleted file mode 100644
index 184b9ad..0000000
--- a/secrets/borg_remote.pub
+++ /dev/null
Binary files differ
diff --git a/secrets/envrc.sh b/secrets/envrc.sh
index fb573ba..7894b79 100644
--- a/secrets/envrc.sh
+++ b/secrets/envrc.sh
Binary files differ
diff --git a/secrets/ssh/known-hosts.txt b/secrets/ssh/known-hosts.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/secrets/ssh/known-hosts.txt
diff --git a/secrets/ssh/vps-box-client b/secrets/ssh/vps-box-client
new file mode 100644
index 0000000..e85c977
--- /dev/null
+++ b/secrets/ssh/vps-box-client
@@ -0,0 +1,49 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+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
+-----END OPENSSH PRIVATE KEY-----
diff --git a/secrets/ssh/vps-box-client.pub b/secrets/ssh/vps-box-client.pub
new file mode 100644
index 0000000..5e62df9
--- /dev/null
+++ b/secrets/ssh/vps-box-client.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCzWSn7tTK0KQ3OHZkeWP2lh7+ljn+E3GBTzGnIhU2Ou25g4T/2kHMC2huaX0uQIa68NxKGqJpPXvSwBqdpRAeMZkVtukJelR5qSdA1/1mRn6L9vG4IlQpw1exdXcQG4ADx71BU8uvrX6NLo+xwvoj+FOQzCzCQcxzR2GF6LfPG/qz3g3sc0s+Lt9yTKG7akDJH1lUa4EwWOVfvV+uOYqFIQr1LmlmRXj5zQEHnzbF2Rw/KLC9sWIzb5mL+TucJ10gdwWUAFOor8XiY1Kxt7I3s8ELYdBfKzqDPP+TQomG2K2VVjLQR3/0KowKrj+nzfe7ymOFrSOc4jj0a2ZmOE8ogpzEVYq6lw6qYk6PSnSEPMVC2JQLkhVVHdPMfiMW8EPLNdARK9oa8ER/Qm03kbkVBlz8eTWTwieHnCYwtqDC34SBcVwF0lAkWSE/UutztpS7//XAjXmtjBQbaMEWQslfA3EHYfj35O9EQJn/m9L91UMmpGxtGWV8Kuk3+Sg6iosoLSdVjr0SgaacPASmqGn4VfCOVdm2sLVjQGSYwznIddK2lhVP8gELhLrRnF4QDKQsZoO3So2JwVLmWpR9DgoGG1WxHy+rhcu9cHwe65rY68D44e2Z5K4GXLZpzX4zjMitDprnXiS/V9CAAqarh3hCEo9PSRubQd+ZihBVoZVo10Q== andreh@velhinho-nixos
diff --git a/secrets/ssh/vps-box-server b/secrets/ssh/vps-box-server
new file mode 100644
index 0000000..e59b2fb
--- /dev/null
+++ b/secrets/ssh/vps-box-server
@@ -0,0 +1,49 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+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
+-----END OPENSSH PRIVATE KEY-----
diff --git a/secrets/ssh/vps-box-server.pub b/secrets/ssh/vps-box-server.pub
new file mode 100644
index 0000000..5a7605e
--- /dev/null
+++ b/secrets/ssh/vps-box-server.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC39owceNl4f5AGHZ+cZt3y7JRMmZo3LSp1xXLNh6q8V2AJxatfvOYl7zejClGeN2WM0uHBi9y7WYwGnmSKV3qGFwxFysIQALZ2LjbHfqCjOrlCf9FdHVGUA5ROUzeYLhAlTzxoTGFWRqHOVh4SVq6iMP0ciit869a0cnFS/KS2+9SazC0EOpRJ13I+9/bk9Lt6Jstuxlks2waAaYxRoxS4hOjnqfrQGnbZnSOYdBcFS/0SS67zs0HoFmWU8lVUGD5Q6ne8oCwQjwdU3kV0f5OCp5Fz/ECKJ87EvLgSaIXwQwK9I0mtPCXSQDw4RwFFDVBzKgplP/yvomb2r1zQUL8CBxrHTjQiy0BBErtL/FBoTnpVKSv5dL+/k3wEUcL9sGiTN28XllWkjO/AJs9u/U9vyf/ypLHSA1SpisoN28vzPYG8U/0I3eeOAH2/OaeBQNF7e4SOIoE/rH4g3isFzhL84fvWWHfrcFx0upyWP5Uch0dMUJurgTpwGj8fDyuvFvBje7WNRzCA0AjZprxRAgMxDsEf/UCkzYkAbh5YkiLJeMrph9i31J+D/x1LKkW/ea1IyWsdv2nqIImfi+NQBY5dErrWFWy5/Cr+V4lt6ENpJmXaqF5zapH1t4NDAioQ7TlkAjkwDWWkcmrEbLFDsUYEV+PnvVTUA3peBMi6FgRyyQ== andreh@velhinho-nixos
diff --git a/secrets/vps_box b/secrets/vps_box
deleted file mode 100644
index 8bd910b..0000000
--- a/secrets/vps_box
+++ /dev/null
Binary files differ
diff --git a/secrets/vps_box.pub b/secrets/vps_box.pub
deleted file mode 100644
index 1301181..0000000
--- a/secrets/vps_box.pub
+++ /dev/null
Binary files differ
diff --git a/ssh.conf b/ssh.conf
deleted file mode 100644
index 7ceedb6..0000000
--- a/ssh.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-Host $TLD
- User root
- IdentityFile $PWD/secrets/vps_box
- StrictHostKeyChecking no
-Host git.sr.ht
- StrictHostKeyChecking no
diff --git a/ssh.env.conf b/ssh.env.conf
new file mode 100644
index 0000000..6ce50ed
--- /dev/null
+++ b/ssh.env.conf
@@ -0,0 +1,6 @@
+Host $TLD
+ User root
+ IdentityFile $PWD/secrets/ssh/vps-box-client
+ UserKnownHostsFile $PWD/secrets/ssh/known-hosts.txt
+Host git.sr.ht
+ StrictHostKeyChecking no
diff --git a/user-data.env.sh b/user-data.env.sh
new file mode 100755
index 0000000..15d491c
--- /dev/null
+++ b/user-data.env.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+echo '$SSH_SERVER_PRIVATE_KEY' > /etc/ssh/vps-box-server
+echo '$SSH_SERVER_PUBLIC_KEY' > /etc/ssh/vps-box-server.pub
+echo 'HostKey /etc/ssh/vpx-box-server' >> /etc/ssh/sshd_config
+systemctl restart sshd
diff --git a/vps.tf b/vps.tf
index 27bc8c8..34d186b 100644
--- a/vps.tf
+++ b/vps.tf
@@ -1,5 +1,4 @@
variable "do_token" {}
-variable "ssh_fingerprint" {}
variable "floating_ip" {}
provider "digitalocean" {
@@ -7,6 +6,11 @@ provider "digitalocean" {
version = "~> 1.1"
}
+resource "digitalocean_ssh_key" "client" {
+ name = "terraform-vps-client"
+ public_key = "${file("${path.module}/secrets/ssh/vps-box-client.pub")}"
+}
+
resource "digitalocean_droplet" "vps" {
image = "ubuntu-18-04-x64"
name = "sovereignty"
@@ -16,23 +20,25 @@ resource "digitalocean_droplet" "vps" {
ipv6 = true
monitoring = true
+ user_data = "${file("${path.module}/user-data.sh")}"
+
ssh_keys = [
- "${var.ssh_fingerprint}",
+ "${digitalocean_ssh_key.client.fingerprint}",
]
connection {
user = "root"
type = "ssh"
- private_key = "${file("${path.module}/secrets/vps_box")}"
+ private_key = "${file("${path.module}/secrets/ssh/vps-box-client")}"
timeout = "2m"
}
provisioner "remote-exec" {
- script = "./deploy.sh"
+ inline = ["echo 'SSH is up! Noop remote-exec is done.'"]
}
}
resource "digitalocean_floating_ip_assignment" "vps" {
ip_address = "${var.floating_ip}"
droplet_id = "${digitalocean_droplet.vps.id}"
-}
+} \ No newline at end of file