Skip to content

libops/cloud-compose

Repository files navigation

cloud-compose

Deploy Docker Compose projects to VMs. The repository root is a compatibility entrypoint for existing GCP callers. New callers should select exactly one Terraform entrypoint under providers/: providers/gcp, providers/do, or providers/linode. Each entrypoint loads only its target cloud provider. Existing Debian/Ubuntu hosts can consume the same runtime contract through the Ansible role or Salt formula.

Template defaults live in templates/apps.json and are shared by Terraform, Ansible, and Salt. The default deployment shape is one app per VM or host; pass runtime.compose.projects when several apps should share the same machine. Terraform template presets include an exact, reviewed sitectl core/plugin release set. Override individual selectors with runtime.sitectl.package_versions when intentionally testing or promoting a different compatible release set.

All presets use their coordinated sitectl v1.0.0 core/plugin release set. The ISLE preset selects the libops/isle v1.1.0 template; every other application preset remains on its v1.0.0 template contract. Keep each preset's complete template and package set together when promoting an override.

GCP deployments have two Terraform ownership layers. Apply modules/gcp-foundation once per service project from a small, long-lived state; it owns required APIs, the Cloud Run service identity, the reusable least-privilege power roles, and any Shared VPC attachment and service-agent grants. Per-application states consume the role names and bind their service accounts only to their own Compute Engine instance. They must not recreate or destroy the singleton foundation. The runtime contracts cover the state boundary, Shared VPC setup, and Cloud Run Direct VPC egress requirements.

Requirements

Name Version
terraform >= 1.3.0
cloudinit ~> 2.3
google ~> 7.0
time ~> 0.14

Providers

No providers.

Modules

Name Source Version
gcp ./modules/gcp n/a
managed_artifacts ./modules/managed-artifacts n/a

Resources

No resources.

Inputs

Name Description Type Default Required
name Deployment name. string n/a yes
cloud_provider Compatibility selector for the root GCP entrypoint. Use providers/do or providers/linode for other clouds. string "gcp" no
gcp Google Cloud infrastructure settings.
object({
project_id = optional(string, "")
project_number = optional(string, "")
region = optional(string, "us-east5")
zone = optional(string, "us-east5-b")

identity = optional(object({
vm_service_account_email = optional(string, "")
app_service_account_email = optional(string, "")
app_credentials_enabled = optional(bool, false)
}), {})

instance = optional(object({
machine_type = optional(string, "n4-standard-2")
os = optional(string, "cos-125-19216-220-185")
production = optional(bool, false)
}), {})

disks = optional(object({
type = optional(string, "hyperdisk-balanced")
docker_volumes_size_gb = optional(number, 50)
}), {})

network = optional(object({
create = optional(bool, true)
project_id = optional(string, "")
name = optional(string, "")
subnetwork = optional(string, "")
ip_cidr_range = optional(string, "10.42.0.0/24")
mtu = optional(number, 1460)
power_button_allowed_ips = optional(list(string), [])
power_button_ip_depth = optional(number)
ssh_ipv4 = optional(list(string), [])
ssh_ipv6 = optional(list(string), [])
}), {})

snapshots = optional(object({
enabled = optional(bool, false)
}), {})

overlay = optional(object({
source_instance = optional(string, "")
volume_names = optional(list(string), [])
}), {})

cloud_init = optional(object({
initcmd = optional(list(string), [])
runcmd = optional(list(string), [])
}), {})

artifact_registry = optional(object({
repository = optional(string, "")
location = optional(string, "us")
}), {})

power_management = optional(object({
enabled = optional(bool, false)
start_role = optional(string, "")
suspend_role = optional(string, "")
frontend = optional(object({
image = string
port = optional(number, 8080)
cpu = optional(string, "1000m")
memory = optional(string, "1Gi")
}), null)
}), {})

rollout = optional(object({
enabled = optional(bool, false)
release_url = optional(string, "")
release_sha256 = optional(string, "")
port = optional(number, 8081)
jwks_uri = optional(string, "")
jwt_audience = optional(string, "")
custom_claims = optional(string, "")
allowed_ipv4 = optional(list(string), ["10.0.0.0/8"])
}), {})
})
{} no
runtime Provider-neutral compose/runtime settings.
object({
rootfs = optional(string, "")
rootfs_archive_url = optional(string, "")
rootfs_archive_sha256 = optional(string, "")
users = optional(map(list(string)), {})

compose = optional(object({
primary = optional(string, "")
ingress_port = optional(number, 80)
ingress = optional(object({
letsencrypt = optional(bool, false)
bot_mitigation = optional(bool, false)
mode = optional(string, "")
domain = optional(string, "")
acme_email = optional(string, "")
trusted_ips = optional(list(string), [])
max_upload_size = optional(string, "")
upload_timeout = optional(string, "")
}), {})
repo = optional(string, "")
branch = optional(string, "")
projects = optional(map(object({
docker_compose_repo = string
docker_compose_branch = optional(string)
project_dir = optional(string)
compose_project_name = optional(string)
ingress_port = optional(number)
ingress = optional(object({
letsencrypt = optional(bool)
bot_mitigation = optional(bool)
mode = optional(string)
domain = optional(string)
acme_email = optional(string)
trusted_ips = optional(list(string))
max_upload_size = optional(string)
upload_timeout = optional(string)
}), {})
sitectl_context_name = optional(string)
sitectl_plugin = optional(string)
sitectl_environment = optional(string)
sitectl_packages = optional(list(string))
sitectl_verify_args = optional(list(string))
docker_compose_init = optional(list(string))
docker_compose_up = optional(list(string))
docker_compose_down = optional(list(string))
docker_compose_rollout = optional(list(string))
})), {})
init = optional(list(string))
up = optional(list(string))
down = optional(list(string))
rollout = optional(list(string))
}), {})

sitectl = optional(object({
packages = optional(list(string))
version = optional(string, "latest")
package_versions = optional(map(string), {})
context_name = optional(string, "")
plugin = optional(string, "core")
environment = optional(string, "production")
verify_args = optional(list(string), [])
}), {})

docker = optional(object({
# renovate: datasource=github-releases depName=docker-compose packageName=docker/compose versioning=semver
compose_version = optional(string, "v5.3.1")
# renovate: datasource=github-releases depName=docker-buildx packageName=docker/buildx versioning=semver
buildx_version = optional(string, "v0.35.0")
}), {})

managed_runtime = optional(object({
enabled = optional(bool, true)
internal_services_enabled = optional(bool, false)
internal_services_auto_update = optional(bool, false)
artifacts = optional(list(object({
name = string
url = string
sha256 = string
path = string
mode = optional(string, "0755")
owner = optional(string, "root")
group = optional(string, "root")
restart = optional(string, "")
})), [])
}), {})

vault = optional(object({
addr = optional(string, "")
namespace = optional(string, "")
role = optional(string, "")
agent_enabled = optional(bool, false)
auth_method = optional(string, "auto")
gcp_auth_mount_path = optional(string, "auth/gcp")
agent_token_path = optional(string, "/mnt/disks/data/vault/token")
agent_additional_config = optional(string, "")
agent_templates = optional(list(object({
destination = string
contents = string
perms = optional(string, "0640")
command = optional(string, "")
})), [])
}), {})

extra_env = optional(map(string), {})
})
{} no
template Optional compose template preset. Supported values are archivesspace, ojs, isle, drupal, wp, omeka-s, and omeka-classic. Explicit runtime settings override preset defaults. string "" no

Outputs

Name Description
appGsa The Google Service Account the app can use for app-scoped auth.
backend Backend service ID for attaching Cloud Run ingress to an external HTTPS load balancer.
cloud_provider Root entrypoint cloud provider (gcp).
compose_projects Normalized compose project manifest.
external_ip GCP VM public IPv4 address.
instance GCP VM instance details.
instance_id GCP VM instance ID.
internal_ip GCP VM private IPv4 address.
network Resolved GCP network and regional subnetwork.
primary_compose_project Normalized primary compose project.
rollout Optional rollout API endpoint details.
serviceGsa The Google Service Account internal services run as.
sitectl_package_versions Effective release selector for every installed sitectl package; values may be exact tags or latest.
template Selected compose template preset.
urls Cloud Run ingress URLs by region.
volumes GCP persistent application-data and Docker-volume details.