Files
ouranos/terraform/containers.tf
Robert Helewka 042df52bca Refactor user management in Ansible playbooks to standardize on keeper_user
- Updated user addition tasks across multiple playbooks (mcp_switchboard, mcpo, neo4j, neo4j_mcp, openwebui, postgresql, rabbitmq, searxng, smtp4dev) to replace references to ansible_user and remote_user with keeper_user.
- Modified PostgreSQL deployment to create directories and manage files under keeper_user's home.
- Enhanced documentation to clarify account taxonomy and usage of keeper_user in playbooks.
- Introduced new deployment for Agent S, including environment setup, desktop environment installation, XRDP configuration, and accessibility support.
- Added staging playbook for preparing release tarballs from local repositories.
- Created templates for XRDP configuration and environment activation scripts.
- Removed obsolete sunwait documentation.
2026-03-05 10:37:41 +00:00

286 lines
7.4 KiB
HCL

locals {
# Common cloud-init configuration
base_cloud_init = <<EOT
#cloud-config
package_update: true
packages:
- apt-utils
- openssh-server
users:
- name: ${var.keeper_user}
uid: ${var.keeper_uid}
homedir: /srv/${var.keeper_user}
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
groups: sudo
lock_passwd: true
EOT
# Uranian host definitions - Red Panda Approved
uranian_hosts = {
oberon = {
description = "Docker Host + MCP Switchboard - King of Fairies orchestrating containers and managing MCP infrastructure"
remote = "local"
role = "container_orchestration"
image = "noble"
config = {
"security.nesting" = true
"raw.lxc" = "lxc.apparmor.profile=unconfined"
}
devices = [{
name = "app_ports"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:25580-25599"
connect = "tcp:127.0.0.1:25580-25599"
}
}]
}
portia = {
description = "PostgreSQL Host - Intelligent database justice"
role = "database"
image = "noble"
config = {}
devices = []
}
ariel = {
description = "Neo4j Host - Ethereal graph connections"
role = "graph_database"
image = "noble"
config = {
"security.nesting" = true
"raw.lxc" = "lxc.apparmor.profile=unconfined"
}
devices = [{
name = "neo4j_ports"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:25554"
connect = "tcp:127.0.0.1:25554"
}
}]
}
miranda = {
description = "Dedicated Docker Host for MCP Servers - Curious bridge between worlds"
role = "mcp_docker_host"
image = "noble"
config = {
"security.nesting" = true
"raw.lxc" = "lxc.apparmor.profile=unconfined"
}
devices = [{
name = "mcp_containers"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:25530-25539"
connect = "tcp:127.0.0.1:25530-25539"
}
},
{
name = "mcpo_ports"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:25560-25569"
connect = "tcp:127.0.0.1:25560-25569"
}
}]
}
sycorax = {
description = "Arke LLM Proxy - Original magical language power"
role = "language_models"
image = "noble"
config = {
"security.nesting" = true
"raw.lxc" = "lxc.apparmor.profile=unconfined"
}
devices = [{
name = "arke_ports"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:25540-25544"
connect = "tcp:127.0.0.1:25540-25544"
}
}]
}
puck = {
description = "Python App Host - Shape-shifting trickster"
role = "application_runtime"
image = "questing"
config = {
"security.nesting" = true
"raw.lxc" = "lxc.apparmor.profile=unconfined"
}
devices = [{
name = "puck_ports"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:25570-25579"
connect = "tcp:127.0.0.1:25570-25579"
}
},
{
name = "puck_rdp"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:25520"
connect = "tcp:127.0.0.1:3389"
}
},
{
name = "gpu"
type = "gpu"
properties = {}
}
]
}
caliban = {
description = "Agent S MCP Server - Autonomous computer agent learning through environmental interaction"
role = "agent_automation"
image = "questing"
config = {
"security.nesting" = true
"raw.lxc" = "lxc.apparmor.profile=unconfined"
}
devices = [{
name = "caliban"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:25521"
connect = "tcp:127.0.0.1:3389"
}
},
{
name = "gpu"
type = "gpu"
properties = {}
}]
}
prospero = {
description = "Master magician observing events - PPLG observability stack with internal HAProxy"
role = "observability"
image = "noble"
config = {}
devices = [
{
name = "https_internal"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:25510"
connect = "tcp:127.0.0.1:443"
}
},
{
name = "http_redirect"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:25511"
connect = "tcp:127.0.0.1:80"
}
}
]
}
titania = {
description = "Proxy & SSO Services - Queen of the fairies managing access and authentication"
role = "proxy_sso"
image = "noble"
config = {
"security.nesting" = true
"raw.lxc" = "lxc.apparmor.profile=unconfined"
}
devices = [
{
name = "https_standard"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:443"
connect = "tcp:127.0.0.1:8443"
}
},
{
name = "http_redirect"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:80"
connect = "tcp:127.0.0.1:8080"
}
},
{
name = "gitea_ssh"
type = "proxy"
properties = {
listen = "tcp:0.0.0.0:22022"
connect = "tcp:127.0.0.1:22022"
}
}
]
}
rosalind = {
description = "Nextcloud Host - Witty and resourceful moon for cloud collaboration (PHP, Go, Node.js runtimes)"
role = "collaboration"
image = "noble"
config = {
"security.nesting" = true
"raw.lxc" = "lxc.apparmor.profile=unconfined"
}
devices = [{
name = "nextcloud_data"
type = "disk"
properties = {
source = "nextcloud-data"
pool = "default"
path = "/mnt/nextcloud"
}
}]
}
}
images = {
noble = incus_image.noble.fingerprint
plucky = incus_image.plucky.fingerprint
questing = incus_image.questing.fingerprint
}
}
resource "incus_instance" "uranian_hosts" {
for_each = local.uranian_hosts
name = each.key
project = var.project_name
profiles = [var.profile_name]
image = local.images[each.value.image]
ephemeral = false
dynamic "device" {
for_each = lookup(each.value, "devices", [])
content {
name = device.value.name
type = device.value.type
properties = device.value.properties
}
}
config = merge(
{
"user.access_Interface" = "eth0"
"cloud-init.user-data" = local.base_cloud_init
"user.Environment" = "sandbox"
"user.ManagedBy" = "terraform"
"user.Role" = each.value.role
},
each.value.config
)
file {
target_path = "/srv/${var.keeper_user}/.ssh/authorized_keys"
source_path = var.ssh_key_path
uid = var.keeper_uid
gid = var.keeper_uid
mode = 0750
create_directories = true
}
lifecycle {
ignore_changes = [config]
}
}