05. November 2022
This Guide setups terraform and a CICD pipeline to Control DNS records using Gitlab remote state backend and Gitops
Lets configure the main.tf file and add the required providers. We will be using Gitlab for a state backend
main.tf
1terraform {
2 required_providers {
3 pihole = {
4 source = "ryanwholey/pihole"
5 }
6 kubectl = {
7 source = "gavinbunney/kubectl"
8 version = ">= 1.7.0"
9 }
10 }
11
12 backend "http" {
13 }
14}
The locals.tf file needs to be configured with the following
Change to you pihole ips and correct email and the domain ip is the one you gave traefik. mine is 10.10.1.60
1locals {
2 pihole_primary_url = "http://x.x.x.x:8888" # IF you have it on a different port
3 pihole_secondary_url = "http://x.x.x.x" # If you didnt change the port setting
4 domain_name = "domain.name"
5 domain_ip = "x.x.x.x"
6}
7
Field | Description |
---|---|
pihole_primary_url | Url to the admin console of your piholes |
domain_name | The Domain Name to be used for creating the A record |
domain_ip | The target the A record will point to, example our traefik reverse proxy load balancer ip |
add this to variables.tf
1variable "PIHOLE_PASSWORD" {
2 type = string
3 sensitive = true
4}
Create a providers.tf
1provider "pihole" {
2 url = local.pihole_primary_url # PIHOLE_URL
3 password = var.PIHOLE_PASSWORD # PIHOLE_PASSWORD
4}
5
6provider "pihole" {
7 url = local.pihole_secondary_url # PIHOLE_URL
8 password = var.PIHOLE_PASSWORD # PIHOLE_PASSWORD
9 alias = "secondary"
10}
Now lets create a modules reference for our code to run
dns.tf
1module "pihole_1_io" {
2 source = "./modules/pihole"
3 domain_name = local.domain_name
4 domain_ip = local.domain_ip
5 providers = {
6 pihole = pihole
7 }
8}
9
10module "pihole_2_io" {
11 source = "./modules/pihole"
12 domain_name = local.domain_name
13 domain_ip = local.domain_ip
14 providers = {
15 pihole = pihole.secondary
16 }
17}
Create Folders modules/pihole/
create files
point a record to our load balancer
1resource "pihole_dns_record" "mantisd-io" {
2 domain = var.domain_name
3 ip = var.domain_ip
4}
Create records to both our piholes admin dashboard
1resource "pihole_cname_record" "pihole" {
2 domain = "pihole.${var.domain_name}"
3 target = "${var.domain_name}"
4}
5resource "pihole_cname_record" "pihole-2" {
6 domain = "pihole-2.${var.domain_name}"
7 target = "${var.domain_name}"
8}
1terraform {
2 required_version = ">=1.1.4"
3 required_providers {
4 pihole = {
5 source = "ryanwholey/pihole"
6 }
7 }
8}
9
10
11data "pihole_cname_records" "cname_records" {
12
13}
14
15data "pihole_dns_records" "dns_records" {
16
17}
1output "dns_records" {
2 value = data.pihole_dns_records.dns_records
3}
4
5output "cname_record" {
6 value = data.pihole_cname_records.cname_records
7}
1variable "domain_name" {
2 type = string
3}
4
5variable "domain_ip" {
6 type = string
7}
Add new Records to cname.tf and a-records.tf
Now lets create a pipeline to automatically deploy new routes in the main branch when they are commited to our git repo
1
2stages:
3 - pre
4 - build
5 - deploy
6
7default:
8 tags:
9 - your
10 - runner
11 - tags
12
13variables:
14 TF_ROOT: $CI_PROJECT_DIR # The relative path to the root directory of the Terraform project
15 TF_STATE_NAME: pihole-records # The name of the state file used by the GitLab Managed Terraform state backend
16 TF_IMAGE: registry.gitlab.com/gitlab-org/terraform-images/releases/terraform:1.1.9
17 ARTIFACT_VERSION: "1.0.0"
18 REALEASE_VERSION: $ARTIFACT_VERSION
19 TF_ADDRESS: "https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME}"
20
21
22tf_init_var_check:
23 stage: .pre
24 script:
25 - if [ -z "${TF_ADDRESS}"]; then echo "ERROR - TF_ADDRESS does not exist, add to .gitlab-ci.yml"; exit 1; fi
26 - if [ -z "${TF_USERNAME}"]; then echo "ERROR - TF_USERNAME does not exist, add to .gitlab-ci.yml"; exit 1; fi
27 - if [ -z "${TF_PASSWORD}"]; then echo "ERROR - TF_PASSWORD does not exist, add to .gitlab-ci.yml"; exit 1; fi
28
29.terraform_init:
30 script:
31 - echo $GITLAB_USER_NAME
32 - rm -rf .terraform
33 - terraform --version
34 - |
35 terraform init \
36 -backend-config=address=${TF_ADDRESS} \
37 -backend-config=lock_address=${TF_ADDRESS}/lock \
38 -backend-config=unlock_address=${TF_ADDRESS}/lock \
39 -backend-config=username=${TF_USERNAME} \
40 -backend-config=password=${TF_PASSWORD} \
41 -backend-config=lock_method=POST \
42 -backend-config=unlock_method=DELETE \
43 -backend-config=retry_wait_min=5
44
45tf_base_config_var_check:
46 stage: .pre
47 script:
48 - if [ -z "${TF_IMAGE}"]; then echo "ERROR - TF_IMAGE does not exist, add to .gitlab-ci.yml"; exit 1; fi
49 - if [ -z "${TF_ROOT}"]; then echo "ERROR - TF_ROOT does not exist, add to .gitlab-ci.yml"; exit 1; fi
50
51.tf_base_config:
52 image: ${TF_IMAGE}
53 cache:
54 key: "${TF_ROOT}"
55 paths:
56 - ${TF_ROOT}/.terraform/
57
58
59plan:
60 stage: build
61 extends:
62 - .tf_base_config
63 script:
64 - !reference [.terraform_init, script]
65 - terraform plan -out "plans"
66 artifacts:
67 paths:
68 - plans
69 expire_in: 20m
70
71
72deploy:
73 stage: deploy
74 extends:
75 - .tf_base_config
76 script:
77 - !reference [.terraform_init, script]
78 - terraform apply -input=false "plans"
79 only:
80 - master
Now When changes are added to master branch the pipeline will execute and deploy to your piholes