> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/installation/rpm/cloud/aws.md).

# AWS

Provision EC2 instances, storage, networking and a load balancer for an OpenIAM RPM deployment — single node or three nodes.

## What this covers, and how long it takes

<table><thead><tr><th width="146.79998779296875"></th><th></th></tr></thead><tbody><tr><td><strong>You get</strong></td><td>EC2 instances provisioned and networked for an OpenIAM RPM build, and a load balancer in front of a three-node cluster</td></tr><tr><td><strong>Time</strong></td><td>60–90 minutes to provision, before the installation itself</td></tr><tr><td><strong>Hosts</strong></td><td>One instance, or three</td></tr><tr><td><strong>Downtime</strong></td><td>None — nothing is installed here</td></tr><tr><td><strong>Reversible</strong></td><td>Yes</td></tr></tbody></table>

## Before you start

* An AWS account, a VPC, and permission to create EC2 instances, security groups, an RDS instance and a load balancer.
* The build path for your shape: [*RPM, single node*](/installation/rpm/rpm-single-node.md) or [*RPM, three nodes*](/installation/rpm/rpm-ha.md).
* [*Managed databases*](/installation/rpm/cloud/managed-databases.md), if you are using RDS — the parameter group has to be right **before** you install.

***

## Set these first

{% code overflow="wrap" %}

```bash
export OPENIAM_URL=<the address users will type>
export NODES="<node-1> <node-2> <node-3>"   # three-node deployments only
export AWS_REGION=<your region>
```

{% endcode %}

***

## Provision it

### 1. Choose an instance type

Size against [*System requirements*](/installation/system-requirements.md): 8 vCPU, and 48 GB of memory for non-production or 62 GB for production.

<table><thead><tr><th width="159.40000915527344">Shape</th><th width="243.5999755859375">Instance</th><th>Why</th></tr></thead><tbody><tr><td>Single node, non-production</td><td><code>r5.2xlarge</code></td><td>8 vCPU, 64 GiB nominal — the host reports about 62 GB once firmware and kernel reserves are taken</td></tr><tr><td>Single node, production</td><td><code>r5.4xlarge</code>, or <code>r5.2xlarge</code> with no margin</td><td>64 GiB nominal sits exactly on the production figure. Size up unless the deployment is small and known</td></tr><tr><td>Three nodes</td><td>3 × the size you chose</td><td>Identical instances. Every node runs the full platform</td></tr></tbody></table>

**Memory-optimised rather than general-purpose.** OpenIAM runs its services as separate JVMs, so the platform is memory-hungry before it is CPU-hungry; the `m5`/`m6i` families at 8 vCPU top out at 32 GB, which is below the requirement.

### 2. Choose an image

**Enterprise Linux 9 is the tested image.** Red Hat Enterprise Linux 9, Rocky Linux 9 and AlmaLinux 9 are all standard choices, and the official Marketplace images work without modification. Enterprise Linux 10 is supported by the platform.

Confirm the image after launch:

{% code overflow="wrap" %}

```bash
grep PLATFORM_ID /etc/os-release
```

{% endcode %}

**Expected:** `platform:el9` or `platform:el10`.

### 3. Size the root volume

**The free-space check reads `/`**, so the root volume is what matters — not an attached data volume.

<table><thead><tr><th width="246.80001831054688">Environment</th><th>Root volume</th></tr></thead><tbody><tr><td>Non-production</td><td><strong>100 GB</strong> — 80 GB free after the image</td></tr><tr><td>Production</td><td><strong>250 GB</strong> — 200 GB free after the image</td></tr></tbody></table>

`gp2` is what the reference build uses; `gp3` is a reasonable substitute. To keep OpenIAM's data on a separate volume, attach one and follow [*Install on a separate partition*](/installation/rpm/rpm-single-node/separate-partition.md) — but size the root volume to the table above regardless, because that is what the check reads.

### 4. Place the instances

**Single node:** one private subnet, with the load balancer or your own routing providing the entry point.

**Three nodes:** the reference build places all three instances in **one subnet**. The three hosts share a filesystem exported from the first node and cluster over the ports in [*Ports*](/installation/rpm/rpm-ha/ports.md), both of which are sensitive to the latency between them.

Spreading the three across availability zones changes those characteristics and is an architecture decision rather than an installation one — the [Solution Architecture and Design Guide](/solution-architecture/deployment/availability-and-recovery.md) covers it.

### 5. Configure security groups

Two groups: one for the instances, one for the load balancer.

**Instance security group**

<table><thead><tr><th width="127.39999389648438">Rule</th><th width="352.4000244140625">Source</th><th>Ports</th></tr></thead><tbody><tr><td>Inbound</td><td>The load balancer's security group</td><td>80, 443</td></tr><tr><td>Inbound</td><td>The instance security group <strong>itself</strong></td><td>The inter-node ports in <a href="/installation/rpm/rpm-ha/ports.md"><em>Ports</em></a> — three-node only</td></tr><tr><td>Inbound</td><td>Your administration network or Session Manager</td><td>22</td></tr><tr><td>Outbound</td><td><code>0.0.0.0/0</code>, through a NAT gateway</td><td>443</td></tr></tbody></table>

**Referencing the group as its own source** is a convenient way to let the three nodes reach each other without naming addresses, and it survives an instance replacement. On a single-node deployment there are no inter-node rules at all.

The installation also opens these ports in each host's own firewall. The security group is the layer around that, and the one your security review will look at.

**Outbound HTTPS is needed during the build.** All three instances need access to your OS vendor's package repositories — the build installs packages on each of them. **Only the first instance needs `download.openiam.com`**: it retrieves the OpenIAM components once and distributes them to the other two. A single node can be built with no outbound access at all — see [*Obtain the software*](/installation/obtain-the-software.md).

### 6. Confirm hostname resolution

The three-node build addresses the hosts by name. EC2 private DNS names resolve inside the VPC and work as they are:

{% code overflow="wrap" %}

```bash
for h in $NODES; do getent hosts "$h"; done
```

{% endcode %}

**Expected:** all three resolve, on all three hosts. Whatever names you use, use the same form everywhere — the cluster configuration and the shared filesystem both key off them.

### 7. Confirm swap is off

Some cloud images enable swap. The installation requires it disabled:

{% code overflow="wrap" %}

```bash
swapon --show      # expect no output
swapoff -a
```

{% endcode %}

Remove any swap entry from `/etc/fstab` so it stays off across restarts.

### 8. Provision the database

Use RDS. [*Managed databases*](/installation/rpm/cloud/managed-databases.md) covers the supported engines, the parameter group settings that must be in place before you install, and how to answer the installation's prompts.

Open the engine's port from the instance security group to the RDS security group, and nothing else.

***

## The load balancer, for a three-node cluster

An **Application Load Balancer**, internet-facing or internal to suit your design, across two or more subnets.

<table><thead><tr><th width="283.6000061035156">Setting</th><th>Value</th></tr></thead><tbody><tr><td><strong>Listener</strong></td><td>443, with an ACM certificate. Add an 80 listener redirecting to 443</td></tr><tr><td><strong>Target group protocol and port</strong></td><td>HTTP, 80</td></tr><tr><td><strong>Targets</strong></td><td>All three instances</td></tr><tr><td><strong>Health check path</strong></td><td><code>/idp/login</code></td></tr><tr><td><strong>Health check port</strong></td><td>Traffic port</td></tr><tr><td><strong>Interval</strong></td><td>30 seconds</td></tr><tr><td><strong>Timeout</strong></td><td>5 seconds</td></tr><tr><td><strong>Healthy threshold</strong></td><td>5</td></tr><tr><td><strong>Unhealthy threshold</strong></td><td>2</td></tr><tr><td><strong>Stickiness</strong></td><td>Off</td></tr></tbody></table>

**A recovered node takes about 150 seconds to return to rotation** — five healthy checks at 30-second intervals. That is deliberate: a node that has just restarted should not take traffic until it is genuinely serving. Shorten the interval if you need faster recovery, and keep the threshold.

**Check `/idp/login`, not `/`.** It exercises the reverse proxy and a real application behind it, so a node whose platform has stopped is taken out of rotation even though its proxy is still answering.

**Session affinity is not required.** Session state is shared across the three nodes by the cache tier, so any node can serve any request — [*The clustered tiers*](/installation/rpm/rpm-ha/form-the-clusters.md). Leaving stickiness off is the simplest configuration. If you enable it, do not use a form that pins a client to a target that has failed its health check.

**Terminate TLS at the load balancer** with an ACM certificate, and forward to the instances on 80. Set `X-Forwarded-Proto` so the platform builds `https://` links — [*Configure the load balancer*](/installation/rpm/rpm-ha/load-balancer.md) has the full requirements, and [*Enable HTTPS*](/installation/rpm/rpm-single-node/enable-https.md) covers terminating on the hosts instead.

Use the load balancer's DNS name — or a friendlier alias in Route 53 — as the content provider's **Domain Pattern** in [*First sign-in*](/installation/rpm/rpm-single-node/first-sign-in.md).

***

## The entry point, for a single node

A three-node deployment reaches users through the load balancer above. **A single-node deployment needs the same four things decided, and none of them is created for you.**

### 1. Reachability

The instance sits in a private subnet, so decide how users reach it:

<table><thead><tr><th width="308.4000244140625">Option</th><th>When</th></tr></thead><tbody><tr><td><strong>An Application Load Balancer in front of the one instance</strong></td><td>The usual choice. Gives you an ACM certificate, a stable DNS name, and a path to three nodes later without changing the published address</td></tr><tr><td><strong>A public subnet with an Elastic IP</strong></td><td>Evaluation only. The instance is then directly exposed on 80 and 443</td></tr></tbody></table>

The load balancer settings above apply unchanged with a single target.

### 2. DNS

Create a record for the address users will type — an alias to the load balancer, or an A record to the Elastic IP. **This is the address that goes on the content provider during first sign-in**, so decide it before you get there; changing it later means editing the content provider.

### 3. TLS

<table><thead><tr><th width="271.6000061035156">Where TLS terminates</th><th>What to do</th></tr></thead><tbody><tr><td><strong>At the load balancer</strong>, with an ACM certificate</td><td>Forward to the instance on 80. Set <code>X-Forwarded-Proto</code> so the platform builds <code>https://</code> links</td></tr><tr><td><strong>On the instance</strong></td><td><a href="/installation/rpm/rpm-single-node/enable-https.md"><em>Enable HTTPS</em></a> — put your certificate on the host</td></tr></tbody></table>

**Complete HTTPS before first sign-in.** The first sign-in sets the administrator password; doing it over plain HTTP sends that password across the network in the clear. If you must sign in before a certificate is available, do it from the host itself over an SSH tunnel and change the password again afterwards.

### 4. The published URL

{% code overflow="wrap" %}

```
https://$OPENIAM_URL/webconsole
```

{% endcode %}

Confirm it answers before going further:

{% code overflow="wrap" %}

```bash
curl -s -o /dev/null -w '%{http_code}\n' https://$OPENIAM_URL/webconsole
```

{% endcode %}

**Expected: `200`, or a `30x` redirect to a sign-in page.** Then complete [*First sign-in*](/installation/rpm/rpm-single-node/first-sign-in.md) using that DNS name.

## Verify it

Before installing anything, on each instance:

{% code overflow="wrap" %}

```bash
grep PLATFORM_ID /etc/os-release
free -g | awk '/^Mem:/ {print $2" GB memory"}'
df -h / | awk 'NR==2 {print $4" free on /"}'
swapon --show
curl -s -o /dev/null -w '%{http_code}\n' -m 10 https://download.openiam.com
```

{% endcode %}

**Expected:** an EL9 or EL10 platform, memory and disk at or above the requirement, no swap, and an HTTP response from the download site — or no response if you are building air-gapped, which is expected.

For a three-node build, add the checks in [*Prepare the hosts*](/installation/rpm/rpm-ha/prepare-the-hosts.md).

## If it goes wrong

| What you see                                      | What it means                                                                                   | What to do                                                             |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| The installation stops on free space              | The root volume is too small — the check reads `/`, not an attached volume                      | Grow the root volume and extend the filesystem, then re-run            |
| The installation stops on memory                  | The instance family tops out below the requirement at this vCPU count                           | Move to a memory-optimised type                                        |
| The installation stops on swap                    | The image enabled it                                                                            | `swapoff -a` and remove the `/etc/fstab` entry                         |
| Nodes cannot reach each other                     | The security group does not reference itself                                                    | Add an inbound rule with the instance security group as its own source |
| The load balancer marks every target unhealthy    | The health check is on the wrong port or path, or 80 is not open from the load balancer's group | Confirm HTTP on 80 to `/idp/login`, and the inbound rule               |
| The download site is unreachable                  | No NAT gateway or route from a private subnet                                                   | Add the route, or use the air-gapped procedure                         |
| Package installation fails on the OS repositories | The instance cannot reach them                                                                  | The same route, or the air-gapped procedure                            |

## What this procedure does not cover

Provisioning automation, account structure, and network design beyond what the platform needs. Those are your organisation's, and the [Solution Architecture and Design Guide](/solution-architecture/deployment/network-design.md) covers the design decisions.

## Related

* [*Managed databases*](/installation/rpm/cloud/managed-databases.md) — RDS, before you install
* [*RPM, single node*](/installation/rpm/rpm-single-node.md) and [*RPM, three nodes*](/installation/rpm/rpm-ha.md)
* [*Ports*](/installation/rpm/rpm-ha/ports.md) — what the security groups have to allow
* [*Configure the load balancer*](/installation/rpm/rpm-ha/load-balancer.md)

*Applies to OpenIAM 2026.8.1.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/installation/rpm/cloud/aws.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
