diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..7aa0a46
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,14 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.{json,sh}]
+indent_size = 4
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..4ef8545
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,25 @@
+version: 2
+
+updates:
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: monthly
+ commit-message:
+ prefix: fix(deps)
+ groups:
+ actions-deps:
+ patterns:
+ - "*"
+
+ - package-ecosystem: terraform
+ directories:
+ - modules/pihole
+ schedule:
+ interval: monthly
+ commit-message:
+ prefix: fix(deps)
+ groups:
+ terraform-deps:
+ patterns:
+ - "*"
diff --git a/.github/workflows/pre-commit-run.yml b/.github/workflows/pre-commit-run.yml
new file mode 100644
index 0000000..ee68d7a
--- /dev/null
+++ b/.github/workflows/pre-commit-run.yml
@@ -0,0 +1,76 @@
+name: Pre-commit run
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches-ignore:
+ - pre-commit-run/**
+ workflow_dispatch:
+
+env:
+ TFDOCS_VERSION: v0.21.0
+ TFLINT_VERSION: v0.61.0
+
+permissions:
+ contents: write
+ pull-requests: write
+
+jobs:
+ run:
+ name: Pre-commit check
+ runs-on: ubuntu-slim
+ timeout-minutes: 5
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Evaluate branch name
+ id: ref
+ run: echo "name=${REF##refs/heads/}" >>$GITHUB_OUTPUT
+ env:
+ REF: ${{ github.head_ref || github.ref }}
+
+ # Install pre-commit dependencies
+ - uses: hashicorp/setup-terraform@v3
+
+ - name: Install tflint
+ run: |
+ wget -nv -O /dev/shm/tflint.zip https://github.com/terraform-linters/tflint/releases/download/${TFLINT_VERSION}/tflint_linux_amd64.zip
+ unzip -d $HOME/bin /dev/shm/tflint.zip
+ echo "$HOME/bin" >>$GITHUB_PATH
+
+ - name: Install terraform-docs
+ run: |
+ wget -nv -O - https://github.com/terraform-docs/terraform-docs/releases/download/${TFDOCS_VERSION}/terraform-docs-${TFDOCS_VERSION}-linux-amd64.tar.gz | tar -zxvf - -C $HOME/bin terraform-docs
+ echo "$HOME/bin" >>$GITHUB_PATH
+
+ # Setup pre-commit
+ - name: Install pre-commit
+ run: pip install pre-commit
+
+ - name: Add cache
+ uses: actions/cache@v4
+ with:
+ path: ~/.cache/pre-commit
+ key: ${{ runner.os }}-pre-commit-${{ hashFiles('**/.pre-commit-config.yaml') }}
+
+ - name: Initialize pre-commit
+ run: pre-commit install
+
+ - name: Check
+ run: pre-commit run --all-files
+
+ # Create PR if needed
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v7
+ if: always()
+ with:
+ title: "chore(pre-commit): auto-format code on ${{ steps.ref.outputs.name }}"
+ commit-message: "chore(pre-commit): auto-format code"
+ body: Reformat code according to pre-defined rules
+ branch: pre-commit-run/${{ steps.ref.outputs.name }}
+ base: ${{ steps.ref.outputs.name }}
+ delete-branch: true
+ labels: bot
diff --git a/.github/workflows/pre-commit-update.yml b/.github/workflows/pre-commit-update.yml
new file mode 100644
index 0000000..d2d7f24
--- /dev/null
+++ b/.github/workflows/pre-commit-update.yml
@@ -0,0 +1,35 @@
+name: Pre-commit update
+
+on:
+ schedule:
+ - cron: 0 6 1 * *
+ workflow_dispatch:
+
+permissions:
+ contents: write
+ pull-requests: write
+
+jobs:
+ update:
+ runs-on: ubuntu-slim
+ timeout-minutes: 5
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Install pre-commit
+ run: pip install pre-commit
+
+ - name: Auto update
+ run: pre-commit autoupdate
+
+ # Create PR if needed
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v7
+ with:
+ title: "ci(pre-commit): updated pre-commit modules on ${{ github.ref_name }}"
+ commit-message: "ci(pre-commit): updated pre-commit modules"
+ body: Updated pre-commit repos to latest versions
+ branch: pre-commit-update/${{ github.ref_name }}
+ delete-branch: true
+ labels: bot,ci
diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml
new file mode 100644
index 0000000..4984f27
--- /dev/null
+++ b/.github/workflows/release-please.yml
@@ -0,0 +1,16 @@
+on:
+ push:
+ branches:
+ - main
+
+permissions:
+ contents: write
+ pull-requests: write
+
+name: release-please
+
+jobs:
+ release-please:
+ runs-on: ubuntu-slim
+ steps:
+ - uses: googleapis/release-please-action@v4
diff --git a/.gitignore b/.gitignore
index 9b8a46e..6304eb3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,8 +10,8 @@ crash.log
crash.*.log
# Exclude all .tfvars files, which are likely to contain sensitive 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
+# 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
*.tfvars.json
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..63016c6
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,35 @@
+# See https://pre-commit.com for more information
+# See https://pre-commit.com/hooks.html for more hooks
+default_install_hook_types:
+ - pre-commit
+ - commit-msg
+
+repos:
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v6.0.0
+ hooks:
+ - id: trailing-whitespace
+ - id: end-of-file-fixer
+ - id: check-yaml
+ - id: check-added-large-files
+
+ - repo: https://github.com/antonbabenko/pre-commit-terraform
+ rev: v1.105.0
+ hooks:
+ - id: terraform_tflint
+ - id: terraform_fmt
+ - id: terraform_docs
+
+ - repo: https://github.com/bridgecrewio/checkov
+ rev: 3.2.504
+ hooks:
+ - id: checkov
+ args:
+ - --quiet
+
+ - repo: https://github.com/compilerla/conventional-pre-commit
+ rev: v4.4.0
+ hooks:
+ - id: conventional-pre-commit
+ stages: [commit-msg]
+ args: []
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
new file mode 100644
index 0000000..f5b6b2a
--- /dev/null
+++ b/.release-please-manifest.json
@@ -0,0 +1,3 @@
+{
+ ".": "0.0.0"
+}
diff --git a/README.md b/README.md
index 1999b71..1c7c504 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,73 @@
-# terraform
\ No newline at end of file
+[](.github/dependabot.yml)
+[](.editorconfig)
+[](.pre-commit-config.yaml)
+[](.github/workflows/release-please.yml)
+
+# Terraform modules
+
+## pihole
+
+- add **Project IAM Admin** role in [Google Cloud Console (GCP)](https://console.cloud.google.com/iam-admin/iam) to the Terraform service account
+- create new key for the service account in [GCP](https://console.cloud.google.com/iam-admin/serviceaccounts)
+- [add credentials](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/getting_started#adding-credentials) for Terraform
+
+## Development
+
+Required software:
+
+- [Terraform](https://developer.hashicorp.com/terraform/install)
+- [pre-commit](https://pre-commit.com/#install)
+- [tflint](https://github.com/terraform-linters/tflint?tab=readme-ov-file#installation)
+- [terraform-docs](https://github.com/terraform-docs/terraform-docs?tab=readme-ov-file#installation)
+- [Checkov](https://www.checkov.io/2.Basics/Installing%20Checkov.html)
+
+### pre-commit
+
+This repository uses [pre-commit](https://pre-commit.com/) hooks. Please install it during development and install hooks after every `git clone`:
+
+```bash
+pre-commit install --install-hooks
+pre-commit run --all-files
+```
+
+It is also used in two GitHub workflows:
+
+1. [Pre-commit run](.github/workflows/pre-commit-run.yml): used as a **Required status check** to validate the whole repository contents. It creates a pull request if any changes were made during the workflow run.
+2. [Pre-commit update](.github/workflows/pre-commit-update.yml): a periodic maintenance workflow to keep the pre-commit hooks versions up-to-date.
+
+### Run
+
+Enter module directory, initialize, plan and apply the module:
+
+```bash
+cd modules/$MODULE_NAME
+
+terraform init
+terraform plan
+terraform apply
+```
+
+### Test
+
+Execute unit tests in module's **tests** directory:
+
+```bash
+cd modules/$MODULE_NAME
+
+terraform test
+```
+
+### Dependencies
+
+Dependencies are maintained by [Dependabot](https://docs.github.com/en/code-security/dependabot). Its configuration can be found in [dependabot.yml](.github/workflows/build.yml).
+
+> NOTE: Make sure it is enabled in the repository [Settings](https://github.com/stanislavbebej/terraform/settings/security_analysis).
+
+### Releases
+
+Module is versioned and released as a "GitHub Release" by [release-please](https://github.com/googleapis/release-please). Its configuration can be found in:
+
+- [release-please.yml](.github/release-please.yml)
+- [release-please-config.json](release-please-config.json)
+
+> NOTE: New versions should not be created manually.
diff --git a/modules/pihole/README.md b/modules/pihole/README.md
new file mode 100644
index 0000000..6eca2bf
--- /dev/null
+++ b/modules/pihole/README.md
@@ -0,0 +1,45 @@
+# PiHole Terraform module
+
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | ~> 1.14.5 |
+| [google](#requirement\_google) | 7.20.0 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [google](#provider\_google) | 7.20.0 |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [google_compute_firewall.default](https://registry.terraform.io/providers/hashicorp/google/7.20.0/docs/resources/compute_firewall) | resource |
+| [google_compute_instance.vm_instance](https://registry.terraform.io/providers/hashicorp/google/7.20.0/docs/resources/compute_instance) | resource |
+| [google_project_iam_member.logging_log_writer](https://registry.terraform.io/providers/hashicorp/google/7.20.0/docs/resources/project_iam_member) | resource |
+| [google_project_iam_member.monitoring_metric_writer](https://registry.terraform.io/providers/hashicorp/google/7.20.0/docs/resources/project_iam_member) | resource |
+| [google_service_account.default](https://registry.terraform.io/providers/hashicorp/google/7.20.0/docs/resources/service_account) | resource |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [environment](#input\_environment) | Environment name used as suffix in resource names | `string` | n/a | yes |
+| [gcp\_project](#input\_gcp\_project) | Google Cloud Platform Project value | `string` | n/a | yes |
+| [machine\_type](#input\_machine\_type) | Google Compute Engine machine type | `string` | `"e2-micro"` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [ip-external](#output\_ip-external) | n/a |
+| [ip-local](#output\_ip-local) | n/a |
+
diff --git a/modules/pihole/bootstrap.sh b/modules/pihole/bootstrap.sh
new file mode 100644
index 0000000..bbc18d5
--- /dev/null
+++ b/modules/pihole/bootstrap.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+
+# Notes:
+# sudo journalctl -fu google-startup-scripts.service
+
+# Install PiHole
+if ! which pihole &>/dev/null; then
+ mkdir -p /etc/pihole
+ cat >/etc/pihole/setupVars.conf </dev/null; then
+ cat >/dev/shm/wireguard-setupVars.conf <