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.
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
- Deploys an instance in your Hetzner project, accessible via a pre-configured SSH key.
- Clones your GitHub repository containing the
docker-compose
file(s). - Retrieves secrets from your Infisical project and saves them in a
.env
file for the rootdocker-compose
file. - Retrieves secrets from your Infisical project and saves them in a
.secrets
file for each subdirectory in your repository. - Executes the root
docker-compose.yaml
file. - 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
.
- 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/ - (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 - (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. - (Optional) Create a GitHub Token
This token is necessary if your application repository is private.
- Navigate to Admin > Access Control > Identities and create a new Identity. Give the
Member
role to this identity. - Create a project and get the
project ID
. You will need to set it asinfisical_project_id
. - In
Access Control
>Machine Identities
of your project Assign the newly created identity as a Project Viewer. - Click on Universal Auth, then click Add a
client secret
. Get the client secret and set it asinfisical_client_secret
- Get the client ID and set it as
infisical_client_id
. - 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
Update docker-compose.yaml
to pass the content of the.secrets
file as environment variables.
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
No requirements.
Name | Version |
---|---|
hcloud | n/a |
No modules.
Name | Type |
---|---|
hcloud_firewall.this | resource |
hcloud_server.this | resource |
hcloud_volume.this | resource |
hcloud_volume_attachment.this | resource |
Name | Description | Type | Default | Required |
---|---|---|---|---|
custom_userdata | Extra commands to be executed in cloud-init | list(string) |
[ |
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 |
Name | Description |
---|---|
server_id | n/a |
server_ip | n/a |