devops/quadlets/modules/postgres/tenant
Thomas Rijpstra a114a5002e
feat(quadlets): add new service modules for the mars ship
Add quadlet modules for affine, airsonic-advanced, beets, deeptutor,
documentdb, forgejo, gonic, mopidy, navidrome, opensign, plane, postgres
(with tenant sub-module), qdrant, rabbitmq (with tenant sub-module),
tmail-web, and zot, all built on the quadlet-app/network patterns.
2026-06-25 09:54:44 +02:00
..
README.md feat(quadlets): add new service modules for the mars ship 2026-06-25 09:54:44 +02:00
main.tf feat(quadlets): add new service modules for the mars ship 2026-06-25 09:54:44 +02:00
outputs.tf feat(quadlets): add new service modules for the mars ship 2026-06-25 09:54:44 +02:00
variables.tf feat(quadlets): add new service modules for the mars ship 2026-06-25 09:54:44 +02:00

README.md

PostgreSQL Tenant Module

This module creates a PostgreSQL database and user (tenant) on a VPS-hosted PostgreSQL instance using SSH tunneling for secure access.

Features

  • Creates SSH tunnel to VPS-hosted PostgreSQL
  • Creates isolated database and user for tenant
  • Generates secure random password
  • Outputs connection details for application use
  • Supports explicit dependencies via wait_on

Requirements

  • SSH access to VPS with key-based authentication
  • PostgreSQL admin credentials
  • terraform-ssh-tunnel module (automatically downloaded)
  • cyrilgdn/postgresql provider (automatically configured)

Usage

Basic Example

module "app_tenant" {
  source = "./quadlets/modules/postgres/tenant"

  tenant_name     = "myapp"
  admin_username  = "postgres"
  admin_password  = var.postgres_admin_password
  server_ip       = "203.0.113.10"
  ssh_user        = "fourlights"
  
  # Wait for PostgreSQL service to be ready
  wait_on = module.postgres.installed
}

# Use the connection details
output "app_db_connection" {
  value = {
    host     = module.app_tenant.host
    port     = module.app_tenant.port
    database = module.app_tenant.database
    username = module.app_tenant.username
    password = module.app_tenant.password
  }
  sensitive = true
}

With Custom Port

module "custom_tenant" {
  source = "./quadlets/modules/postgres/tenant"

  tenant_name     = "custom_app"
  admin_username  = "postgres"
  admin_password  = var.postgres_admin_password
  server_ip       = "203.0.113.10"
  target_port     = 5433  # Custom PostgreSQL port
  
  wait_on = module.postgres.installed
}

Multiple Tenants

module "tenant_1" {
  source = "./quadlets/modules/postgres/tenant"

  tenant_name     = "app1"
  admin_username  = "postgres"
  admin_password  = var.postgres_admin_password
  server_ip       = var.vps_ip
  
  wait_on = module.postgres.installed
}

module "tenant_2" {
  source = "./quadlets/modules/postgres/tenant"

  tenant_name     = "app2"
  admin_username  = "postgres"
  admin_password  = var.postgres_admin_password
  server_ip       = var.vps_ip
  
  wait_on = module.postgres.installed
}

Inputs

Name Description Type Default Required
tenant_name Name of the tenant (used for database name and username) string - yes
admin_username PostgreSQL admin username string "postgres" no
admin_password PostgreSQL admin password string - yes
server_ip VPS server IP address string - yes
ssh_user SSH user for connecting to VPS string "fourlights" no
ssh_private_key_path Path to SSH private key string "~/.ssh/id_rsa" no
target_port PostgreSQL port on VPS number 5432 no
wait_on Resources to wait on before creating tenant any null no

Outputs

Name Description Sensitive
host PostgreSQL connection host (via SSH tunnel) no
port PostgreSQL connection port (via SSH tunnel) no
database Database name no
username Database username no
password Database password yes
connection_string Full PostgreSQL connection string yes
installed Installation complete flag no

How It Works

  1. SSH Tunnel: The module uses terraform-ssh-tunnel to create a secure SSH tunnel from your local machine to the VPS PostgreSQL instance
  2. Provider Configuration: The PostgreSQL provider is configured to connect through the tunnel
  3. Resource Creation: Creates a PostgreSQL role (user) and database with appropriate permissions
  4. Password Generation: Generates a cryptographically secure random password
  5. Outputs: Provides connection details for your application to use

Notes

  • The SSH tunnel is created dynamically when Terraform needs to connect
  • Ensure your SSH agent is running and has the appropriate key loaded
  • The database and user will have the same name as tenant_name
  • The user is granted full privileges on their database
  • Password is stored in Terraform state (sensitive)