eleven / messenger Public

Clone
git clone https://amadan.net/eleven/messenger

Plain git — no account needed to clone.

Download

Download this file

1# πŸ€– The Dublin (ie) node β€” a Graviton box that reads the dev-mesh bucket via an
2# INSTANCE ROLE (no AWS keys on the box, the clean path). Ubuntu 26.04 arm64 to
3# mirror prod's OS; arm64 pairs with the amd64 Helsinki node to prove the mesh
4# works cross-arch (the release feed builds both every publish).
5
6data "aws_ami" "ubuntu_2604_arm" {
7 most_recent = true
8 owners = ["099720109477"] # Canonical
9
10 filter {
11 name = "name"
12 values = ["ubuntu/images/hvm-ssd*/ubuntu-*-26.04-arm64-server-*"]
13 }
14 filter {
15 name = "architecture"
16 values = ["arm64"]
17 }
18}
19
20resource "aws_key_pair" "ie_node" {
21 key_name = "eleven-dev-mesh-ie"
22 public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILReNBCz+nwYvJ7x/RfgW/kbvSFe3pzPhOBM1SOqbjSg eleven-dev-box"
23}
24
25# One /32 per operator. Add yourself via PR + `ops dev apply` (an in-place
26# security-group update β€” no instance touch); removing an entry revokes that
27# operator, so only ever prune with their say-so. Keep literal IPs out of the
28# description text β€” doctor/ops extract every a.b.c.d/nn inside this block.
29variable "ssh_ingress_cidr" {
30 description = "Operator IPs allowed to SSH (a /32 each)"
31 type = list(string)
32 default = ["136.206.228.80/32", "109.255.91.23/32", "51.155.205.89/32", "109.255.206.133/32"] # paul (two networks), james, docs-t1
33}
34
35resource "aws_security_group" "ie_node" {
36 name = "eleven-dev-mesh-ie"
37 description = "dev-mesh Dublin node: ssh from the operator, web open"
38
39 ingress {
40 description = "ssh (operators only)"
41 from_port = 22
42 to_port = 22
43 protocol = "tcp"
44 cidr_blocks = var.ssh_ingress_cidr
45 }
46 ingress {
47 description = "http (autocert HTTP-01 + serving)"
48 from_port = 80
49 to_port = 80
50 protocol = "tcp"
51 cidr_blocks = ["0.0.0.0/0"]
52 }
53 ingress {
54 description = "https"
55 from_port = 443
56 to_port = 443
57 protocol = "tcp"
58 cidr_blocks = ["0.0.0.0/0"]
59 }
60 egress {
61 from_port = 0
62 to_port = 0
63 protocol = "-1"
64 cidr_blocks = ["0.0.0.0/0"]
65 }
66}
67
68resource "aws_iam_role" "ie_node" {
69 name = "eleven-dev-mesh-ie"
70 assume_role_policy = jsonencode({
71 Version = "2012-10-17"
72 Statement = [{
73 Action = "sts:AssumeRole"
74 Effect = "Allow"
75 Principal = { Service = "ec2.amazonaws.com" }
76 }]
77 })
78}
79
80resource "aws_iam_role_policy" "ie_node" {
81 name = "eleven-dev-mesh-bucket"
82 role = aws_iam_role.ie_node.id
83 policy = data.aws_iam_policy_document.mesh_rw.json # shared with the fi user (storage.tf)
84}
85
86resource "aws_iam_instance_profile" "ie_node" {
87 name = "eleven-dev-mesh-ie"
88 role = aws_iam_role.ie_node.name
89}
90
91resource "aws_instance" "ie_node" {
92 ami = data.aws_ami.ubuntu_2604_arm.id
93 instance_type = "t4g.small" # 2 vCPU / 2 GB β€” the sizing floor for a node that runs a sidecar
94 key_name = aws_key_pair.ie_node.key_name
95 vpc_security_group_ids = [aws_security_group.ie_node.id]
96 iam_instance_profile = aws_iam_instance_profile.ie_node.name
97
98 # IMDSv2 required: an SSRF on the box can't read the role credentials with a
99 # bare GET. Hop limit 1 (nothing runs in containers here).
100 metadata_options {
101 http_endpoint = "enabled"
102 http_tokens = "required"
103 }
104
105 root_block_device {
106 volume_size = 20
107 volume_type = "gp3"
108 encrypted = true
109 }
110
111 # A newer Canonical AMI must never replace this box via a routine apply β€”
112 # that destroys /data (it did, 2026-07-23). Deliberate rebuilds still work:
113 # `ops dev rebuild` uses -replace, which overrides ignore_changes.
114 lifecycle {
115 ignore_changes = [ami]
116 }
117
118 tags = { Name = "eleven-dev-mesh-ie" }
119}
120
121# A stable address the DNS wildcard points at, so a stop/start (or a -replace of
122# the box) doesn't move the record.
123resource "aws_eip" "ie_node" {
124 instance = aws_instance.ie_node.id
125 domain = "vpc"
126 tags = { Name = "eleven-dev-mesh-ie" }
127}
128