Skip to content

Automates the creation of a server on Hetzner Cloud, and join it into a tailscale network. In addition it deploys the docker-compose files located in the specified 'apps' directory and optionally injects the secrets from infisical.

License

Notifications You must be signed in to change notification settings

lefterisALEX/terraform-hetzner-cloudstack

Repository files navigation

Project Description

This project automates the deployment and management of selfhosted applications on a Hetzner cloud instance. It leverages Terraform to provision infrastructure, clones your code from a GitHub repository, manages secrets using Infisical, and utilizes Docker Compose for deploying your applications. The setup ensures that applications are kept up-to-date with the latest code changes from your upstream repository.

How it works

This setup is designed to function as a modular Docker Compose configuration, featuring a primary docker-compose.yaml file that incorporates additional child docker-compose.yaml files. If Infisical integration is enabled:

  • An .env file is generated in the parent directory, containing all the secrets from the parent directory of your Infisical project.
  • A .secret file is created in each subdirectory, containing all the secrets from the directory with the same name as your Infisical project.
/
│
├── docker-compose.yaml           # Parent compose file
├── .env                          # Environment variables for parent compose file
│
├── traefik/
│   ├── docker-compose.yaml       # Child compose file
│   └── .secret                   # Secret variables for traefik
│
├── immich/
│   ├── docker-compose.yaml       # Child compose file
│   └── .secret                   # Secret variables for immich
│
└── uptime/
    ├── docker-compose.yaml       # Child compose file
    └── .secret                   # Secret variables for uptime

  1. Deploys an instance in your Hetzner project, accessible via a pre-configured SSH key.
  2. Clones your GitHub repository containing the docker-compose file(s).
  3. Retrieves secrets from your Infisical project and saves them in a .env file for the root docker-compose file.
  4. Retrieves secrets from your Infisical project and saves them in a .secrets file for each subdirectory in your repository.
  5. Executes the root docker-compose.yaml file.
  6. Regularly checks for new commits in the upstream repository. If new commits are found, it fetches the updated code and re-applies the docker-compose.yaml.

Requirments

  1. Generate an API Token for your Hetzner project.
    This will allow terraform to deploy resources in your hetzner project.
    more info: https://docs.hetzner.com/cloud/api/getting-started/generating-api-token/
  2. (Optional) Create an Auth-Key in your Tailscale account
    This key will be used to connect the server to your Tailscale network.
    More information: Generating a Key
  3. (Optional) Create a new Infisical machine identity to access secrets from your Infisical project.
    More information: https://infisical.com/docs/documentation/platform/identities/universal-auth. For detailed instructions on setting up Infisical secrets, please refer to the "How to setup and inject secrets from infisical" section below in this document.
  4. (Optional) Create a GitHub Token
    This token is necessary if your application repository is private.

How to setup and inject secrets from infisical

Setup infisical

  1. Navigate to Admin > Access Control > Identities and create a new Identity. Give the Member role to this identity.
  2. Create a project and get the project ID. You will need to set it as infisical_project_id.
  3. In Access Control > Machine Identities of your project Assign the newly created identity as a Project Viewer.
  4. Click on Universal Auth, then click Add a client secret. Get the client secret and set it as infisical_client_secret
  5. Get the client ID and set it as infisical_client_id.
  6. If you are in the EU data center, export the following environment variable: INFISICAL_API_URL="https://eu.infisical.com".

The structure of the directories in infisical project should match the structure of directories in the apps directory.
Let's say you want to inject the secret DB_PASSWORD as environment variable for the app immich.

1.Under immich directory create the key DB_PASSWORD with the value you want to inject to the app image image

  1. Update docker-compose.yaml to pass the content of the .secrets file as environment variables.

image

Note: What will happened is when you run terraform apply infisical ig going to read all secrets under each infisical project and export it under each directory with same name to a file called .secrets For example if you have under apps three directories, immich, traefik and photoprism the module is going to generate for each directory a file called .secrets

image

Requirements

No requirements.

Providers

Name Version
hcloud n/a

Modules

No modules.

Resources

Name Type
hcloud_firewall.this resource
hcloud_server.this resource
hcloud_volume.this resource
hcloud_volume_attachment.this resource

Inputs

Name Description Type Default Required
custom_userdata Extra commands to be executed in cloud-init list(string)
[
"echo 'Default user-data execution'"
]
no
docker_compose_path The relative path in your repo where docker compose file is. string "examples/basic/apps" no
github_repo_url The URL of the applications repository. string "" no
github_token The GitHub token for accessing private repositories. string "" no
hcloud_network_id The network ID from your private network number n/a yes
image The image the server is created from. string "ubuntu-22.04" no
infisical_api_url The infisical api URL. This value will be exported to INFISICAL_API_URL if set string null no
infisical_client_id The infisical client id. string "" no
infisical_client_secret The infisical client secret. string "" no
infisical_project_id The infisical project ID. string "" no
ip_range The IP range of the network. string "10.10.0.0/24" no
name The name of your server string "server" no
private_key The private key which can be used to connect to the server. string "" no
public_access If false a firewall that block all public access will be attached to the server. bool false no
region The cloud region where resources will be deployed. string "nbg1" no
root_disk_size The size of the main disk in GB for the instance. number 80 no
server_ip The IP of the interface which will be attached to your server. string "10.10.0.2" no
server_type The server type this server should be created with. string "cax11" no
ssh_keys A list of SSH key names which will be imported while creating the server list(string) [] no
tailscale_auth_key The auth key for your tailscale network string "" no
tailscale_routes The routes which will be advertised in the tailscale network. string "10.10.0.2/32" no
timezone The timezone which the server will be configured. string "Europe/Amsterdam" no
volume_delete_protection If set to true is going to protect volume from deletion. bool false no
volume_size The size of the volume which will be attached to the server string "15" no

Outputs

Name Description
server_id n/a
server_ip n/a

About

Automates the creation of a server on Hetzner Cloud, and join it into a tailscale network. In addition it deploys the docker-compose files located in the specified 'apps' directory and optionally injects the secrets from infisical.

Resources

License

Stars

Watchers

Forks

Packages

No packages published