From 7b5dc0692c520a5c657c0a41375bc5805607ecb1 Mon Sep 17 00:00:00 2001 From: frrist Date: Tue, 17 Mar 2026 15:41:40 -0700 Subject: [PATCH] feat: support deployments with postgres or minio --- .../deployment-types/multi-instance/main.tf | 14 ++- .../multi-instance/tofu.tfvars.template | 85 ++++++++++++++++++- .../multi-instance/variables.tf | 69 +++++++++++++++ .../deployment-types/single-instance/main.tf | 12 ++- .../single-instance/tofu.tfvars.template | 59 +++++++++++++ .../single-instance/variables.tf | 64 ++++++++++++++ .../files/docker-compose.yml.tpl | 42 +++++++++ .../piri-instance/files/piri.service.tpl | 21 ++++- .../full-node/modules/piri-instance/main.tf | 51 +++++++++-- .../piri-instance/scripts/user-data.sh.tpl | 52 ++++++++++++ .../modules/piri-instance/variables.tf | 64 ++++++++++++++ 11 files changed, 518 insertions(+), 15 deletions(-) create mode 100644 deploy/full-node/modules/piri-instance/files/docker-compose.yml.tpl diff --git a/deploy/full-node/deployment-types/multi-instance/main.tf b/deploy/full-node/deployment-types/multi-instance/main.tf index f30eef8d..11295ed6 100644 --- a/deploy/full-node/deployment-types/multi-instance/main.tf +++ b/deploy/full-node/deployment-types/multi-instance/main.tf @@ -30,7 +30,7 @@ data "aws_route53_zone" "primary" { module "piri_instances" { source = "../../modules/piri-instance" - + for_each = var.instances name = each.key @@ -46,7 +46,7 @@ module "piri_instances" { protect_volume = var.environment == "production" || var.environment == "prod" || var.environment == "forge-prod" domain_name = "${var.environment}.${each.value.subdomain}.${var.root_domain}" route53_zone_id = data.aws_route53_zone.primary.zone_id - + install_method = coalesce(lookup(each.value, "install_method", null), var.default_install_method) install_source = coalesce(lookup(each.value, "install_source", null), var.default_install_source) network = var.network @@ -57,6 +57,16 @@ module "piri_instances" { operator_email = each.value.operator_email use_letsencrypt_staging = var.environment != "production" && var.environment != "prod" && var.environment != "forge-prod" + # Backend configuration (instance can override defaults) + storage_backend = coalesce(lookup(each.value, "storage_backend", null), var.default_storage_backend) + database_backend = coalesce(lookup(each.value, "database_backend", null), var.default_database_backend) + minio_root_user = var.minio_root_user + minio_root_password = coalesce(lookup(each.value, "minio_root_password", null), var.minio_root_password) + minio_bucket_prefix = var.minio_bucket_prefix + postgres_user = var.postgres_user + postgres_password = coalesce(lookup(each.value, "postgres_password", null), var.postgres_password) + postgres_database = var.postgres_database + tags = { Owner = var.owner Team = var.team diff --git a/deploy/full-node/deployment-types/multi-instance/tofu.tfvars.template b/deploy/full-node/deployment-types/multi-instance/tofu.tfvars.template index ea6a5128..1e044508 100644 --- a/deploy/full-node/deployment-types/multi-instance/tofu.tfvars.template +++ b/deploy/full-node/deployment-types/multi-instance/tofu.tfvars.template @@ -148,6 +148,48 @@ network = "warm-staging" # Default: "v0.0.12" - uncomment to override # default_install_source = "v0.0.12" +# =========================================================================== +# STORAGE BACKEND CONFIGURATION (DEFAULTS) +# =========================================================================== +# By default, Piri uses filesystem storage and SQLite database. +# For native deployments, you can configure MinIO and/or PostgreSQL +# backends running on the same EC2 instance via Docker Compose. +# Each instance gets its own MinIO/PostgreSQL containers. + +# Default blob storage backend: "filesystem" (default) or "minio" +# Default: "filesystem" - uncomment to use MinIO +# default_storage_backend = "minio" + +# Default database backend: "sqlite" (default) or "postgres" +# Default: "sqlite" - uncomment to use PostgreSQL +# default_database_backend = "postgres" + +# MinIO configuration (required when storage_backend = "minio") +# ------------------------------------------- +# MinIO root user (shared across all instances) +# Default: "minioadmin" - uncomment to override +# minio_root_user = "minioadmin" + +# MinIO root password (required when using MinIO) +# minio_root_password = "your-secure-minio-password" + +# Prefix for MinIO buckets +# Default: "piri-" - uncomment to override +# minio_bucket_prefix = "piri-" + +# PostgreSQL configuration (required when database_backend = "postgres") +# ------------------------------------------- +# PostgreSQL user (shared across all instances) +# Default: "piri" - uncomment to override +# postgres_user = "piri" + +# PostgreSQL password (required when using PostgreSQL) +# postgres_password = "your-secure-postgres-password" + +# PostgreSQL database name +# Default: "piri" - uncomment to override +# postgres_database = "piri" + # =========================================================================== # INSTANCE DEFINITIONS # =========================================================================== @@ -163,6 +205,10 @@ network = "warm-staging" # - install_source: Override version/branch to install # - service_pem_content: Service private key (only if use_secrets_manager = false) # - wallet_hex_content: Wallet private key (only if use_secrets_manager = false) +# - storage_backend: Override default storage backend ("filesystem" or "minio") +# - database_backend: Override default database backend ("sqlite" or "postgres") +# - minio_root_password: Override MinIO password for this instance +# - postgres_password: Override PostgreSQL password for this instance instances = { # Example: Basic node using all defaults @@ -198,14 +244,49 @@ instances = { # node1 = { # subdomain = "node1" # operator_email = "operator1@example.com" -# +# # # When use_secrets_manager = false, these are REQUIRED: # service_pem_content = < /etc/piri/config.toml' ExecStart=/usr/local/bin/piri serve --config=/etc/piri/config.toml @@ -29,4 +46,4 @@ Restart=on-failure RestartSec=10 [Install] -WantedBy=multi-user.target \ No newline at end of file +WantedBy=multi-user.target diff --git a/deploy/full-node/modules/piri-instance/main.tf b/deploy/full-node/modules/piri-instance/main.tf index 1472754e..883ff878 100644 --- a/deploy/full-node/modules/piri-instance/main.tf +++ b/deploy/full-node/modules/piri-instance/main.tf @@ -3,15 +3,45 @@ locals { server_name = var.domain_name }) + # Determine if Docker is needed for native backends + needs_docker = var.storage_backend == "minio" || var.database_backend == "postgres" + systemd_service_content = templatefile("${path.module}/files/piri.service.tpl", { - network = var.network - lotus_endpoint = var.pdp_lotus_endpoint - operator_email = var.operator_email - public_url = "https://${var.domain_name}" + network = var.network + lotus_endpoint = var.pdp_lotus_endpoint + operator_email = var.operator_email + public_url = "https://${var.domain_name}" + needs_docker = local.needs_docker + storage_backend = var.storage_backend + database_backend = var.database_backend + # PostgreSQL CLI flags + postgres_url = "postgres://${var.postgres_user}:${var.postgres_password}@localhost:5432/${var.postgres_database}?sslmode=disable" + postgres_max_open_conns = 10 + postgres_max_idle_conns = 5 + postgres_conn_max_lifetime = "30m" + # S3/MinIO CLI flags + s3_endpoint = "localhost:9000" + s3_bucket_prefix = var.minio_bucket_prefix + s3_access_key_id = var.minio_root_user + s3_secret_access_key = var.minio_root_password }) - + install_from_release_script = file("${path.module}/scripts/install-from-release.sh") install_from_branch_script = file("${path.module}/scripts/install-from-branch.sh") + + # Docker Compose content + docker_compose = local.needs_docker ? templatefile( + "${path.module}/files/docker-compose.yml.tpl", + { + enable_postgres = var.database_backend == "postgres" + enable_minio = var.storage_backend == "minio" + postgres_user = var.postgres_user + postgres_password = var.postgres_password + postgres_database = var.postgres_database + minio_root_user = var.minio_root_user + minio_root_password = var.minio_root_password + } + ) : "" } data "aws_ami" "ubuntu" { @@ -55,6 +85,11 @@ resource "aws_instance" "piri" { install_from_release_script = local.install_from_release_script install_from_branch_script = local.install_from_branch_script use_letsencrypt_staging = var.use_letsencrypt_staging + # Backend configuration + storage_backend = var.storage_backend + database_backend = var.database_backend + needs_docker = local.needs_docker + docker_compose = local.docker_compose }) tags = merge( @@ -70,7 +105,7 @@ resource "aws_instance" "piri" { # Force replacement when user_data changes (includes install_source changes) create_before_destroy = true } - + # Force replacement when user_data changes user_data_replace_on_change = true @@ -95,7 +130,7 @@ resource "aws_ebs_volume" "piri_data" { ) lifecycle { - ignore_changes = [size] # Allow manual resizing outside of Terraform + ignore_changes = [size] # Allow manual resizing outside of Terraform } } @@ -118,7 +153,7 @@ resource "aws_ebs_volume" "piri_data_protected" { lifecycle { prevent_destroy = true - ignore_changes = [size] # Allow manual resizing outside of Terraform + ignore_changes = [size] # Allow manual resizing outside of Terraform } } diff --git a/deploy/full-node/modules/piri-instance/scripts/user-data.sh.tpl b/deploy/full-node/modules/piri-instance/scripts/user-data.sh.tpl index 6c94b98f..12245d71 100644 --- a/deploy/full-node/modules/piri-instance/scripts/user-data.sh.tpl +++ b/deploy/full-node/modules/piri-instance/scripts/user-data.sh.tpl @@ -15,6 +15,22 @@ echo "=== Updating system packages ===" apt-get update apt-get upgrade -y +%{ if needs_docker ~} +# ============================================================================= +# Install Docker for native backends +# ============================================================================= +echo "=== Installing Docker ===" +apt-get install -y ca-certificates curl gnupg +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +apt-get update +apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +systemctl enable docker +systemctl start docker +%{ endif ~} + # Create piri user echo "=== Creating piri user ===" useradd -m -s /bin/bash piri @@ -66,6 +82,42 @@ chown -R piri:piri /etc/piri chown -R piri:piri /data/piri chown -R piri:piri /tmp/piri +%{ if needs_docker ~} +# ============================================================================= +# Setup Docker Compose for backend services +# ============================================================================= +echo "=== Setting up backend services ===" + +# Create directories for container data +mkdir -p /data/postgres /data/minio + +# Deploy docker-compose.yml +cat > /etc/piri/docker-compose.yml <<'DOCKEREOF' +${docker_compose} +DOCKEREOF + +# Start containers +cd /etc/piri +docker compose up -d + +# Wait for services to be healthy +echo "=== Waiting for backend services ===" +%{ if database_backend == "postgres" ~} +echo "Waiting for PostgreSQL..." +until docker compose exec -T piri-postgres pg_isready -U piri -d piri 2>/dev/null; do + sleep 2 +done +echo "PostgreSQL is ready" +%{ endif ~} +%{ if storage_backend == "minio" ~} +echo "Waiting for MinIO..." +until curl -sf http://localhost:9000/minio/health/live >/dev/null 2>&1; do + sleep 2 +done +echo "MinIO is ready" +%{ endif ~} +%{ endif ~} + # Install nginx echo "=== Installing nginx ===" apt-get install -y nginx diff --git a/deploy/full-node/modules/piri-instance/variables.tf b/deploy/full-node/modules/piri-instance/variables.tf index 55881774..c05f35b7 100644 --- a/deploy/full-node/modules/piri-instance/variables.tf +++ b/deploy/full-node/modules/piri-instance/variables.tf @@ -128,4 +128,68 @@ variable "tags" { description = "Additional tags to apply to all resources" type = map(string) default = {} +} + +# ============================================================================= +# Storage Backend Configuration +# ============================================================================= + +variable "storage_backend" { + description = "Blob storage backend: 'filesystem' (default) or 'minio'" + type = string + default = "filesystem" + validation { + condition = contains(["filesystem", "minio"], var.storage_backend) + error_message = "storage_backend must be 'filesystem' or 'minio'" + } +} + +variable "database_backend" { + description = "Database backend: 'sqlite' (default) or 'postgres'" + type = string + default = "sqlite" + validation { + condition = contains(["sqlite", "postgres"], var.database_backend) + error_message = "database_backend must be 'sqlite' or 'postgres'" + } +} + +# MinIO configuration (when storage_backend = "minio") +variable "minio_root_user" { + description = "MinIO root user" + type = string + default = "minioadmin" +} + +variable "minio_root_password" { + description = "MinIO root password (required when storage_backend = 'minio')" + type = string + sensitive = true + default = "" +} + +variable "minio_bucket_prefix" { + description = "Prefix for MinIO buckets" + type = string + default = "piri-" +} + +# PostgreSQL configuration (when database_backend = "postgres") +variable "postgres_user" { + description = "PostgreSQL user" + type = string + default = "piri" +} + +variable "postgres_password" { + description = "PostgreSQL password (required when database_backend = 'postgres')" + type = string + sensitive = true + default = "" +} + +variable "postgres_database" { + description = "PostgreSQL database name" + type = string + default = "piri" } \ No newline at end of file