146 lines
3.5 KiB
Markdown
146 lines
3.5 KiB
Markdown
# VM Service Template
|
|
|
|
This repository is a starter template for deploying one or more service VMs in Proxmox using Terraform, then configuring and launching applications with Ansible and Docker Compose.
|
|
|
|
It is designed to work with a shared Terraform module stored in a separate repository. This repo acts as the wrapper/root module and provides the service-specific inputs, deployment workflow, and app stack files.
|
|
|
|
## What this repo does
|
|
|
|
- Creates one or more Proxmox VMs from a reusable Terraform module.
|
|
- Uses cloud-init and QEMU guest agent in the template VM.
|
|
- Writes the VM IP address into Ansible inventory.
|
|
- Tags VMs with Terraform, Docker, service name, and IP metadata.
|
|
- Deploys an application stack with Ansible and Docker Compose.
|
|
|
|
## Repository layout
|
|
|
|
```text
|
|
terraform/ Terraform wrapper for the shared Proxmox module.
|
|
compose/ Docker Compose application files.
|
|
ansible/ Playbook and role used to configure and deploy the app.
|
|
.gitea/ Workflow files for apply and deploy.
|
|
```
|
|
|
|
## Requirements
|
|
|
|
- Terraform installed locally or in CI.
|
|
- Access to the Proxmox API.
|
|
- A shared Proxmox VM module in a separate repository.
|
|
- Ansible installed for application deployment.
|
|
- Docker and Docker Compose available on the target VM.
|
|
|
|
## How it works
|
|
|
|
1. Terraform reads the instance configuration from `terraform.tfvars`.
|
|
2. Terraform calls the shared Proxmox module to create the VM.
|
|
3. Terraform outputs the VM IP address and tags.
|
|
4. The workflow writes the IP into `ansible/inventory/hosts.ini`.
|
|
5. Ansible connects to the VM and deploys the Compose stack.
|
|
|
|
## Single instance
|
|
|
|
Use `instance_mode = "single"` and define one `instance` object.
|
|
|
|
Example:
|
|
|
|
```hcl
|
|
instance_mode = "single"
|
|
|
|
instance = {
|
|
service_name = "grafana"
|
|
vm_name = "grafana-01"
|
|
node_name = "pop"
|
|
app_port = 3000
|
|
app_image = "grafana/grafana:latest"
|
|
vm_tags = ["monitoring"]
|
|
}
|
|
```
|
|
|
|
## Multi instance
|
|
|
|
Use `instance_mode = "multi"` and define an `instances` map.
|
|
|
|
Example:
|
|
|
|
```hcl
|
|
instance_mode = "multi"
|
|
|
|
instances = {
|
|
grafana = {
|
|
service_name = "grafana"
|
|
vm_name = "grafana-01"
|
|
node_name = "pop"
|
|
app_port = 3000
|
|
app_image = "grafana/grafana:latest"
|
|
vm_tags = ["monitoring"]
|
|
}
|
|
|
|
caddy = {
|
|
service_name = "caddy"
|
|
vm_name = "caddy-01"
|
|
node_name = "pop"
|
|
app_port = 80
|
|
app_image = "caddy:latest"
|
|
vm_tags = ["proxy"]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Defaults
|
|
|
|
The template supports module defaults for items like:
|
|
|
|
- datastore
|
|
- BIOS
|
|
- machine type
|
|
- SSH key
|
|
- bridge
|
|
- CPU, RAM, and disk size
|
|
|
|
Override only what you need in the service repo.
|
|
|
|
## Running locally
|
|
|
|
```bash
|
|
cd terraform
|
|
cp single.tfvars.example terraform.tfvars
|
|
terraform init
|
|
terraform apply
|
|
```
|
|
|
|
After Terraform finishes, run:
|
|
|
|
```bash
|
|
cd ..
|
|
ansible-playbook -i ansible/inventory/hosts.ini ansible/playbooks/deploy.yml
|
|
```
|
|
|
|
## Workflow trigger
|
|
|
|
This template is intended to be run after the repository is created from it.
|
|
|
|
The usual flow is:
|
|
|
|
- create a new repo from this template,
|
|
- update the tfvars file,
|
|
- trigger the workflow manually with `workflow_dispatch`,
|
|
- or push the first commit to start deployment.
|
|
|
|
## Notes
|
|
|
|
- The shared Proxmox module should live in a separate repository.
|
|
- The service repo should contain the wrapper, not the internal Proxmox resource logic.
|
|
- VM IP tags are generated after Terraform apply.
|
|
- If the VM disk is resized manually in Proxmox, Terraform may see drift on the next run.
|
|
|
|
## Example use case
|
|
|
|
This template works well for service VMs such as:
|
|
|
|
- Grafana
|
|
- Caddy
|
|
- Jellyfin
|
|
- Code Server
|
|
- Monitoring or proxy VMs
|
|
|