fix ci to use nix
This commit is contained in:
parent
67ee289043
commit
1bda4d5e9c
|
@ -1,3 +1,5 @@
|
||||||
|
*.bck
|
||||||
|
|
||||||
# sops
|
# sops
|
||||||
/secrets.yaml
|
/secrets.yaml
|
||||||
|
|
||||||
|
@ -21,12 +23,13 @@ hetzner.nix
|
||||||
crash.log
|
crash.log
|
||||||
crash.*.log
|
crash.*.log
|
||||||
|
|
||||||
# Ignore CLI configuration files
|
|
||||||
.terraformrc
|
|
||||||
terraform.rc
|
|
||||||
|
|
||||||
# Ignore local .tfvars
|
# Ignore local .tfvars
|
||||||
*.tfvars
|
*.tfvars
|
||||||
|
|
||||||
# generated terraform files
|
# generated terraform files
|
||||||
*.json
|
*.json
|
||||||
|
|
||||||
|
# Ignore CLI configuration files
|
||||||
|
*.tfrc
|
||||||
|
.terraformrc
|
||||||
|
terraform.rc
|
||||||
|
|
|
@ -1,19 +1,9 @@
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
validate:
|
validate:
|
||||||
image: alpine:3.16
|
image: nixos/nix:2.19.2
|
||||||
# when:
|
# when:
|
||||||
# event: pull_request
|
# event: pull_request
|
||||||
commands:
|
commands:
|
||||||
- apk add --no-cache terraform
|
- NIX_CONFIG="experimental-features = nix-command flakes" nix run .#plan
|
||||||
- terraform version
|
secrets: [ sops_age_key ]
|
||||||
- |
|
|
||||||
cat << EOF > terraform.rc
|
|
||||||
credentials "app.terraform.io" {
|
|
||||||
token = "$TERRAFORM_CLOUD_TOKEN"
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
- terraform init
|
|
||||||
- terraform validate
|
|
||||||
- terraform plan -var ""
|
|
||||||
secrets: [ terraform_cloud_token ]
|
|
||||||
|
|
91
README.md
91
README.md
|
@ -5,24 +5,95 @@ Contains [Terraform](https://terraform.io/) code used to manage our infrastructu
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- [Nix](https://nix.dev/) with [Flakes](https://nixos.wiki/wiki/Flakes) enabled
|
- [Nix](https://nix.dev/) with [Flakes](https://nixos.wiki/wiki/Flakes) enabled
|
||||||
- [Hetzner Cloud API token](https://docs.hetzner.com/cloud/api/getting-started/generating-api-token)
|
- Credentials (see [configuring](#configuring)), if not using the [shared secrets](#secrets):
|
||||||
- [Terraform Cloud](https://app.terraform.io/) to use shared state
|
- `tf_cloud_token`: [Terraform Cloud](https://app.terraform.io/) token to use shared state
|
||||||
|
- `hcloud_api_token`: [Hetzner Cloud API token](https://docs.hetzner.com/cloud/api/getting-started/generating-api-token)
|
||||||
|
|
||||||
### Usage
|
## Usage
|
||||||
|
|
||||||
- Run `nix develop -c $SHELL` to enter the development environment if not using [`direnv`](https://zero-to-flakes.com/direnv).
|
- Before issuing any other commands, enter the development environment (if not using [`direnv`](https://zero-to-flakes.com/direnv)):
|
||||||
- Run `tofu login app.terraform.io` to log in to the Terraform Cloud backend
|
|
||||||
- Run `nix run` to apply changes.
|
```sh
|
||||||
- Run `nix flake update` to update dependencies.
|
nix develop -c $SHELL
|
||||||
|
```
|
||||||
|
|
||||||
|
- Applying changes:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix run
|
||||||
|
```
|
||||||
|
|
||||||
|
- Validating logic:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix run .#check
|
||||||
|
```
|
||||||
|
|
||||||
|
- Showing the generated plan:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix run .#plan
|
||||||
|
```
|
||||||
|
|
||||||
|
- Applying changes, approving automatically:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix run .#cd
|
||||||
|
```
|
||||||
|
|
||||||
|
- Removing local state and derived credentials:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix run .#destroy
|
||||||
|
```
|
||||||
|
|
||||||
|
- Updating dependencies:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix flake update
|
||||||
|
```
|
||||||
|
|
||||||
|
- Simulating a CI test ([substituting](#secrets) `<SOPS_AGE_KEY>`):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
woodpecker-cli exec --env "SOPS_AGE_KEY=<SOPS_AGE_KEY>"
|
||||||
|
```
|
||||||
|
|
||||||
### Secrets
|
### Secrets
|
||||||
|
|
||||||
- if you want to reset secrets:
|
- if you want to reset secrets:
|
||||||
- generate an [`age`](https://age-encryption.org/) key pair, using [`rage`](https://github.com/str4d/rage) installed as part of the nix shell: `rage-keygen -o keys.txt`
|
- generate an [`age`](https://age-encryption.org/) key pair, using [`rage`](https://github.com/str4d/rage) installed as part of the nix shell:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
rage-keygen -o keys.txt
|
||||||
|
```
|
||||||
|
|
||||||
- list it in [`sops`](https://getsops.io/) config file `.sops.yaml`
|
- list it in [`sops`](https://getsops.io/) config file `.sops.yaml`
|
||||||
- key setup: set environment variable `SOPS_AGE_KEY_FILE` or `SOPS_AGE_KEY` so `sops` can locate the secret key to an `age` key pair that has its public key listed in `.sops.yaml`
|
- key setup: set environment variable `SOPS_AGE_KEY_FILE` or `SOPS_AGE_KEY` so `sops` can locate the secret key to an `age` key pair that has its public key listed in `.sops.yaml`
|
||||||
- encoding secrets: `sops -e secrets.yaml > secrets.enc.yaml`
|
- encoding secrets:
|
||||||
- decoding secrets: `sops -d secrets.enc.yaml > secrets.yaml`
|
|
||||||
|
```sh
|
||||||
|
sops -e secrets.yaml > secrets.enc.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
- decoding secrets:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sops -d secrets.enc.yaml > secrets.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
- setting Terraform Cloud credentials, either by:
|
||||||
|
- reusing the shared session:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
source login.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
- log in to the Terraform Cloud backend:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
tofu login app.terraform.io
|
||||||
|
```
|
||||||
|
|
||||||
### Configuring
|
### Configuring
|
||||||
|
|
||||||
|
|
11
flake.nix
11
flake.nix
|
@ -46,6 +46,8 @@
|
||||||
treefmt
|
treefmt
|
||||||
sops
|
sops
|
||||||
rage
|
rage
|
||||||
|
woodpecker-cli
|
||||||
|
jq
|
||||||
inputs.terranix.defaultPackage.${system}
|
inputs.terranix.defaultPackage.${system}
|
||||||
(opentofu.withPlugins (p: with p; [
|
(opentofu.withPlugins (p: with p; [
|
||||||
sops # https://registry.terraform.io/providers/carlpett/sops/latest/docs
|
sops # https://registry.terraform.io/providers/carlpett/sops/latest/docs
|
||||||
|
@ -57,6 +59,13 @@
|
||||||
apps = let
|
apps = let
|
||||||
tfCommand = cmd: ''
|
tfCommand = cmd: ''
|
||||||
if [[ -e config.tf.json ]]; then rm -f config.tf.json; fi;
|
if [[ -e config.tf.json ]]; then rm -f config.tf.json; fi;
|
||||||
|
export TERRAFORM_CLOUD_TOKEN=$(${pkgs.sops}/bin/sops -d --extract '["tf_cloud_token"]' secrets.enc.yaml)
|
||||||
|
export TF_CLI_CONFIG_FILE="ci.tfrc"
|
||||||
|
cat << EOF > "$TF_CLI_CONFIG_FILE"
|
||||||
|
credentials "app.terraform.io" {
|
||||||
|
token = "$TERRAFORM_CLOUD_TOKEN"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
cp ${terraformConfiguration} config.tf.json \
|
cp ${terraformConfiguration} config.tf.json \
|
||||||
&& ${tf} init \
|
&& ${tf} init \
|
||||||
&& ${tf} ${cmd}
|
&& ${tf} ${cmd}
|
||||||
|
@ -78,6 +87,8 @@
|
||||||
${tfCommand "destroy"}
|
${tfCommand "destroy"}
|
||||||
rm ${toString ./.}/config.tf.json
|
rm ${toString ./.}/config.tf.json
|
||||||
rm ${toString ./.}/terraform.tfstate*
|
rm ${toString ./.}/terraform.tfstate*
|
||||||
|
rm ${toString ./.}/secrets.yaml
|
||||||
|
rm ${toString ./.}/ci.tfrc
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
hcloud_api_token: ENC[AES256_GCM,data:vXsyffsjp5yiMWepyq8KNR8fJNbMB1sj1wAvc7eJm5smysww+Jm8sNCso8dn0X3M4eMCUx9SZUJx3qVh6Mr6Kw==,iv:RQK3mvKPtUmFSZjvlkh9Iffv8vYeEV+G95JcCp88W1o=,tag:CSsVCl35muqlTq5VYvsZIQ==,type:str]
|
tf_cloud_token: ENC[AES256_GCM,data:3vx1n4s7eQxMR2ntOlmnASUuCMxhMMHKLuhf644mNLWbv99aPLsqoUQ+cP01hW/Ra98v3U0C0uYZWfkFn/X8CaVIeu1QPv12D1+XSJB0SJal8NZHJTNVTgzL,iv:W0H4lftTD96/ENjV8tA2a8QqAGI2z/jRvgMtQmaGeB0=,tag:MuXGtyDTbRlNW1xshtCH0g==,type:str]
|
||||||
|
hcloud_api_token: ENC[AES256_GCM,data:HojFdI9gGnO8IkfOREx4bTqrCNBsCDxnUUOmb+VuLMNIEWEifo9tBhm25I+xAogRd0TuYcY4fkARboGL9qsgrw==,iv:18QLpHdNnG82603FxLL38KJaB9sPJ9gj0vmqQWNb1e0=,tag:/6QPhVZy5P5dvP92HUQR6g==,type:str]
|
||||||
sops:
|
sops:
|
||||||
kms: []
|
kms: []
|
||||||
gcp_kms: []
|
gcp_kms: []
|
||||||
|
@ -8,14 +9,14 @@ sops:
|
||||||
- recipient: age1d53yeje0ggysc93uptlpufyhpchyyfs006368j8mw9r20uyeeydse3n7aw
|
- recipient: age1d53yeje0ggysc93uptlpufyhpchyyfs006368j8mw9r20uyeeydse3n7aw
|
||||||
enc: |
|
enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzdytpNTZ3M3JpWlBKR1Nr
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHa2EzMFlLdTQvMUtzL3FL
|
||||||
S0xXK2krNDVvRk5vYzl1dEhUYkdtZDN4S3pnCkFFanIraGZlelJTVGpwOXBKM1dO
|
Rk5JZEdoVkpEQkk3eTR6QkFKY01CaGVwUnpFCm00OWg2bmJ3U2xRMExyeFZ6WVRB
|
||||||
Q0lXcnZPU0dtUDNUV2NIMHhDL3pPUmMKLS0tIDlpV25BRnlXMm1pNk81bDFySk5B
|
UWVjVzY5Y01EOUpDNHYrMFYzVE9GUUEKLS0tIE1LYm80b3V3OUkrNWxQVTRaRGhk
|
||||||
M1Q2Q2V4RUxxVGpIRVc4aHZCUzVHaXcKePAXhBPzLQnfzhklXqY2uM9vBQqh4ZAS
|
TkxRZlprc0I3Q3dQRS82bEd4b1VxTUkKvHZc4c7+9Tsny8w5Cm5L6H+enU1R0tY4
|
||||||
EglXonol4QVUJNBj6hMwepUeeeyLw5foWxJbBwzfdyPWdeSM+zkctw==
|
9OcNPXGv8II5OJp1eT14U/sNecPbiBaQSeK4xHaRDKbGyqx92DtQ8A==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2024-01-16T16:09:37Z"
|
lastmodified: "2024-01-16T21:29:11Z"
|
||||||
mac: ENC[AES256_GCM,data:H1IXPgNzGwnbz27kc/M9kfsWLFWX7pWLfpPU3F6LDz3c76Ap8kgjlwc52r2thOfQhky14iaZgP+9EqAL7wP7WK3ZcN18mq9PHePsqAIQBkb8+80YFcEBel8yUPJFUFpeJGq4Ty+JBbADY9hbJKteLvkoOA0BaeIckMkAQXNB7nU=,iv:+XgndQValWgwSL+16Zr/q7aeQpxWvmNQ2ECD7298MX8=,tag:txLiO/MilTx9H6GoSCHxZg==,type:str]
|
mac: ENC[AES256_GCM,data:eIoSEDuND1O5XPisSs/kq7N1UsiZMer9+Ok43o+8HwfH/HAoElM/0fXNhKQWcQQVUdwLIQnJZzHEXIJ77Uh5sDsWynj3ihJBhruDPu3FxOXTvRHBcdxU31b3iQGliaChRD19L2GDhsNO2Pfvhpoovsy2PHoFtpqtYt4+7UmcOCw=,iv:Zz1czzz+3Tb5f81o6adhO7eJSSr+ksXhMQwendPAhM0=,tag:bjF2pXTkGxef9+1kKw0FlQ==,type:str]
|
||||||
pgp: []
|
pgp: []
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.8.1
|
version: 3.8.1
|
||||||
|
|
Loading…
Reference in New Issue