<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ravindra Thakur</title>
    <description>The latest articles on DEV Community by Ravindra Thakur (@myshourya).</description>
    <link>https://dev.to/myshourya</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4191022%2Fea09d295-d322-4d58-86f1-0019e4caf693.png</url>
      <title>DEV Community: Ravindra Thakur</title>
      <link>https://dev.to/myshourya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/myshourya"/>
    <language>en</language>
    <item>
      <title>Putting a Load Balancer in Front of a Boomi Molecule on AWS</title>
      <dc:creator>Ravindra Thakur</dc:creator>
      <pubDate>Mon, 26 Oct 2026 06:11:40 +0000</pubDate>
      <link>https://dev.to/myshourya/putting-a-load-balancer-in-front-of-a-boomi-molecule-on-aws-1h54</link>
      <guid>https://dev.to/myshourya/putting-a-load-balancer-in-front-of-a-boomi-molecule-on-aws-1h54</guid>
      <description>&lt;p&gt;In an earlier &lt;a href="https://dev.to/myshourya/installing-a-boomi-molecule-on-aws-ec2-part-2-unicast-clustering-and-the-web-server-3aio"&gt;post&lt;/a&gt; I got a two-node Boomi Molecule running on EC2, with shared storage on EFS and both nodes showing Online in Runtime Management. This post is the next step. The Molecule was up, but clients still had to pick one node's address, and if that node went down, their calls failed even though the other node was fine.&lt;/p&gt;

&lt;p&gt;The fix is an Application Load Balancer (ALB). It gives clients one stable address, sends each request to a healthy node, and keeps checking both nodes so a stopped one drops out of rotation on its own.&lt;/p&gt;

&lt;p&gt;I chose an ALB and not a Network Load Balancer because all the traffic here is HTTP. An NLB is for other protocols or very high throughput, and this didn't need either.&lt;/p&gt;

&lt;p&gt;This setup was a personal proof of concept on a Boomi training environment, built to learn how Molecules work.&lt;/p&gt;

&lt;p&gt;Account IDs, IPs, hostnames, and resource IDs are replaced with placeholders. Replace each one with the value from your own AWS and Boomi consoles as you go. The table below shows where each value comes from. The example values only show the format. They are not real.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Placeholder&lt;/th&gt;
&lt;th&gt;Where to find it&lt;/th&gt;
&lt;th&gt;Example format&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;VPC_ID&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VPC console, or the EC2 console under Network&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vpc-xxxxxxxxxxxxxxxxx&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;NODE_1_PRIVATE_IP&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;NODE_2_PRIVATE_IP&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;EC2 console, each instance, Private IPv4 address&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;10.0.x.x&lt;/code&gt; or &lt;code&gt;172.31.x.x&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;NODE_SG_ID&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;EC2 console, Security Groups, the group your nodes use&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sg-xxxxxxxxxxxxxxxxx&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;ALB_SG_NAME&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The name you give the ALB security group&lt;/td&gt;
&lt;td&gt;&lt;code&gt;demo-alb-sg&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;ALB_DNS_NAME&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;EC2 console, Load Balancers, DNS name on the Details tab&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;name&amp;gt;-xxxxxxxxx.&amp;lt;region&amp;gt;.elb.amazonaws.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;ENVIRONMENT_NAME&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Boomi platform, Manage, Runtime Management&lt;/td&gt;
&lt;td&gt;Your test environment name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;NODE_1_NAME&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The name you gave the first EC2 instance&lt;/td&gt;
&lt;td&gt;&lt;code&gt;node-1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;YOUR_PUBLIC_IP&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;curl -s https://checkip.amazonaws.com&lt;/code&gt; on the machine you test from&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;x.x.x.x&lt;/code&gt; (add &lt;code&gt;/32&lt;/code&gt; for the security group rule)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Keep these private:&lt;/strong&gt; installer tokens, your &lt;code&gt;.pem&lt;/code&gt; key file, AWS access keys, account IDs, and your public IP if you don't want it visible. Don't paste them into a forum post, a chat, or a screenshot. If a token is ever exposed, generate a new one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need before starting
&lt;/h2&gt;

&lt;p&gt;The Molecule has to be finished. Both nodes should show Online in Cluster Status, one should be the head node, and there should be no Cluster Issues tab. Both nodes should be in one security group, and that group should already allow node-to-node traffic and NFS from itself. You also need SSH access to both nodes.&lt;/p&gt;

&lt;p&gt;Two decisions to make first. The Shared Web Server in this setup uses plain HTTP with Authentication Type set to None, which is only acceptable if nobody else can reach it. So I restricted the ALB's security group to my own public IP and never opened it to the internet. The second is cost, which I cover later, because the ALB charge keeps running even when the EC2 instances are stopped.&lt;/p&gt;

&lt;p&gt;Here is what the setup looked like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Region / VPC&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;us-east-1&lt;/code&gt; / &lt;code&gt;&amp;lt;VPC_ID&amp;gt;&lt;/code&gt; (default VPC)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node 1&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;NODE_1_NAME&amp;gt;&lt;/code&gt;, private IP &lt;code&gt;&amp;lt;NODE_1_PRIVATE_IP&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node 2&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;NODE_2_NAME&amp;gt;&lt;/code&gt;, private IP &lt;code&gt;&amp;lt;NODE_2_PRIVATE_IP&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node Availability Zone&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;us-east-1b&lt;/code&gt; (both nodes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node security group&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;NODE_SG_ID&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Molecule environment&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;ENVIRONMENT_NAME&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Public IPs change every time you stop and start an instance, so I don't write them down. I copy them from the EC2 console before each SSH session. Private IPs stay the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: Check the Shared Web Server
&lt;/h2&gt;

&lt;p&gt;Open Runtime Management, go to the Molecule, and open Shared Web Server. Make sure the breadcrumb says the Molecule and not a single Atom, because that's an easy thing to get wrong.&lt;/p&gt;

&lt;p&gt;The settings that matter here are API Type set to &lt;strong&gt;Advanced&lt;/strong&gt;, port &lt;strong&gt;9090&lt;/strong&gt;, SSL unchecked, and Authentication Type set to &lt;strong&gt;None&lt;/strong&gt;. The Base URL column only shows one hostname, which will be node 1's internal name. Every node listens on 9090, and the load balancer talks to each node by its private IP. That internal hostname only resolves inside AWS, so don't try to use it from your laptop.&lt;/p&gt;

&lt;p&gt;API Type is a runtime-wide setting, and it decides how a deployed listener process turns into a URL. On Basic or Intermediate, a listener deploys with a fixed URL under &lt;code&gt;/ws/simple/&lt;/code&gt;. On Advanced, listeners are published through an API Service Component, which builds a URL tree under &lt;code&gt;/ws/rest/&lt;/code&gt;. This is the detail that caught me out in the first attempt. A listener process deployed by itself on an Advanced runtime deploys with no error, but the &lt;code&gt;/ws/simple/&lt;/code&gt; path doesn't route, and every request returns a 404. The process has to be wrapped in an API Service Component, and both must be deployed. That's why Part 2 exists.&lt;/p&gt;

&lt;p&gt;A port change only takes effect after a restart. Save first, then restart, then wait about 90 seconds before testing. On a cluster, restart one node at a time: stop node 2, restart node 1, wait until it's green and stable for a minute, then start node 2 again.&lt;/p&gt;

&lt;p&gt;Once the nodes are back, check each one directly on the node itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-tlnp&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;9090
curl &lt;span class="nt"&gt;-i&lt;/span&gt; http://localhost:9090/_admin/status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You want a LISTEN line for java on 9090, and a &lt;code&gt;200 OK&lt;/code&gt; with &lt;code&gt;Content-Length: 0&lt;/code&gt;. The empty body is correct. &lt;code&gt;/_admin/status&lt;/code&gt; is the health probe the load balancer will call every 15 seconds, and it only needs to return 200.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;curl -i&lt;/code&gt; when you test a probe. The first time I ran it without &lt;code&gt;-i&lt;/code&gt;, I got no output and assumed it had failed. The status code was 200 the whole time, and that's the only thing the ALB looks at.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Build a test API
&lt;/h2&gt;

&lt;p&gt;The load balancer needs something to send traffic to. I built a small test API that echoes the request and reports which node handled it. That way I could see the load balancer alternating between nodes without writing any extra scripts.&lt;/p&gt;

&lt;p&gt;The listener process is called &lt;code&gt;Molecule_GetLoadTest_Listener&lt;/code&gt;, and it has four steps. The first is a Web Services Server listener with an EXECUTE operation, object name &lt;code&gt;GetLoadTest&lt;/code&gt;, single-document input and output, and &lt;code&gt;text/plain&lt;/code&gt; as the response content type. The second is a Set Properties step that copies three values from Execution Property into dynamic document properties: Node Id, Atom Name, and Execution Id. The third is a Message step with the text &lt;code&gt;Echo: {1} | Handled by node: {2} | Molecule: {3} | Execution: {4}&lt;/code&gt;. The fourth is Return Documents set to none. For a listener, I turned on "Allow simultaneous executions" and kept the workload at general.&lt;/p&gt;

&lt;p&gt;Node Id is useful because the Molecule fills it in on clusters. It's the node's private IP with the dots turned into underscores, so you'll see something like &lt;code&gt;172_31_32_71&lt;/code&gt; in the reply. That's the value that makes the load balancing visible.&lt;/p&gt;

&lt;p&gt;Next, create an API Service Component. Give it any name, set the Base URL path to &lt;code&gt;v1&lt;/code&gt;, and add a REST route that points at the listener process with the HTTP method set to POST. The effective URL is built from the base path and the object name, so the path comes out as &lt;code&gt;/ws/rest/v1/GetLoadTest&lt;/code&gt;. The REST tab on the deployed API shows the final path, so check it there rather than trusting my arithmetic. API Management has to be enabled on your Boomi account for this component type to show up.&lt;/p&gt;

&lt;p&gt;Deploy both pieces to the Molecule's environment, and make sure you deploy them separately. If you deploy only the API component, the deployment reports success and the routes get registered, but nothing is listening behind them, so requests still fail. If you change the process later, you have to redeploy it as well. Wait about 15 seconds after the last deployment before you test.&lt;/p&gt;

&lt;p&gt;To confirm the API is loaded on a node, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://&amp;lt;NODE_1_PRIVATE_IP&amp;gt;:9090/ws/rest/v1/openapi.json
curl http://&amp;lt;NODE_2_PRIVATE_IP&amp;gt;:9090/ws/rest/v1/openapi.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 3: Test each node before adding the load balancer
&lt;/h2&gt;

&lt;p&gt;I always test the nodes directly before I put a load balancer in front of them. If something is broken, it's much easier to find it now.&lt;/p&gt;

&lt;p&gt;I SSH'd into node 2 with its public IP. First, a quick note on the key file. SSH refused to use it with a message about permissions being too open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WARNING: UNPROTECTED PRIVATE KEY FILE!
Permissions 0644 for '&amp;lt;KEY_FILE&amp;gt;.pem' are too open.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The message makes it sound like a login problem, but it's just the file permissions. Run &lt;code&gt;chmod 400&lt;/code&gt; on the key, then run the same SSH command again.&lt;/p&gt;

&lt;p&gt;From node 2, I ran both tests. Node 2 can reach node 1's private IP, so one session covers both nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: text/plain"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'hello'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  http://&amp;lt;NODE_1_PRIVATE_IP&amp;gt;:9090/ws/rest/v1/GetLoadTest
curl &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: text/plain"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'hello'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  http://&amp;lt;NODE_2_PRIVATE_IP&amp;gt;:9090/ws/rest/v1/GetLoadTest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each reply should be a &lt;code&gt;200 OK&lt;/code&gt; with an echo that names the node that answered. The reply has no trailing newline, so the second response gets glued onto the end of the first in the terminal. That's cosmetic.&lt;/p&gt;

&lt;p&gt;Don't run these from your laptop. The private IPs only exist inside the AWS network, so from a laptop the connection gets reset. It's the same mistake as trying to SSH with a private IP.&lt;/p&gt;

&lt;p&gt;If you get a 404 here, check that both the listener and the API Service Component are deployed to the Molecule's environment. If the connection is refused, the port isn't open, so go back to Part 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 4: Set up the security groups
&lt;/h2&gt;

&lt;p&gt;There are two firewalls to set up. One belongs to the load balancer, and one rule on the nodes lets the load balancer in.&lt;/p&gt;

&lt;p&gt;For the ALB's own security group, I went to EC2, then Security Groups, then Create security group. I named it &lt;code&gt;&amp;lt;ALB_SG_NAME&amp;gt;&lt;/code&gt;, set the description, and picked the same default VPC as the nodes. For inbound, I added one rule: HTTP on port 80, with the source set to My IP. Starting with My IP is safer than "allow everyone," since the web server has no authentication yet. I left the default outbound rule alone. Removing it stops the ALB from sending traffic to the nodes.&lt;/p&gt;

&lt;p&gt;One gotcha with My IP: it stores your address as a /32 at the moment you choose it. If your public IP changes, for example when you switch networks or turn a VPN on or off, requests will just time out. Edit the rule and pick My IP again.&lt;/p&gt;

&lt;p&gt;Then the node side. Open the node security group, click Edit inbound rules, and add a Custom TCP rule on port 9090. For the source, don't type the group name in the Description column, because that column is just a free-text label. Use the Source search box and pick the ALB security group. It shows up as a blue tag with its &lt;code&gt;sg-&lt;/code&gt; ID. Keep the rule from My IP that you use for direct testing.&lt;/p&gt;

&lt;p&gt;This rule is the one people forget. The ALB sends traffic and health checks to the nodes on 9090 from inside the VPC, and without this rule those are dropped. Nothing in the console tells you clearly what's wrong. Both targets just stay unhealthy, and requests through the ALB return 503.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 5: Create the target group
&lt;/h2&gt;

&lt;p&gt;The target group is the list of nodes the ALB can use, plus the health check that decides who's currently in rotation. In EC2, go to Target Groups and create one.&lt;/p&gt;

&lt;p&gt;For the basics, set the target type to Instances, the protocol and port to HTTP and 9090, the protocol version to HTTP1, and the VPC to the default VPC so it matches the nodes.&lt;/p&gt;

&lt;p&gt;For the health check, use HTTP with the path &lt;code&gt;/_admin/status&lt;/code&gt;, the traffic port, and a success code of 200. Set the healthy threshold to 5, the unhealthy threshold to 2, the timeout to 5 seconds, and the interval to 15 seconds. With those numbers, a node that stops answering gets removed after about 30 seconds (two checks at 15 seconds each), and a node that comes back has to pass five checks in a row before it's trusted again, which takes around 75 seconds.&lt;/p&gt;

&lt;p&gt;On the register step, select both nodes, check that the port shows 9090, and click &lt;strong&gt;Include as pending below&lt;/strong&gt;. That button is easy to skip. Until you click it, the selection is only a shopping basket, and the group gets created with no targets at all. The review page should list both instances. Note their Availability Zone, because you'll need it when you create the load balancer. Both nodes were in &lt;code&gt;us-east-1b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The targets will say Unused until a load balancer points at this group. That's normal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 6: Create the load balancer
&lt;/h2&gt;

&lt;p&gt;In EC2, go to Load Balancers, choose Create load balancer, and pick Application Load Balancer.&lt;/p&gt;

&lt;p&gt;Name it, make it internet-facing (it's still limited to your IP by the security group), pick IPv4, and choose the default VPC. For Availability Zones, select at least two, and make sure one of them is the zone your nodes are in. An ALB only sends traffic to targets in the zones it's enabled in. If the nodes are in &lt;code&gt;us-east-1b&lt;/code&gt; and you leave that zone out, the targets show as unused or unhealthy and nothing reaches them.&lt;/p&gt;

&lt;p&gt;For security groups, remove the default one the wizard pre-selects and choose the ALB group. The default group has no rule for your IP on port 80, so the ALB would be created and then be unreachable. For the listener, use HTTP on port 80 forwarding to your target group. I didn't add HTTPS, since there's no certificate in this setup.&lt;/p&gt;

&lt;p&gt;On the review page I got a yellow warning that said the load balancer's reachability might be impacted, because the security groups didn't have the required inbound and outbound rules. I checked both tabs in the security group, and the rules were there. The warning had been calculated before I saved the rules, so it was out of date. I refreshed the security group selector and it cleared. If it doesn't clear for you, create the ALB anyway, since you can always edit the security group later without rebuilding the ALB. The warning is only harmless if you've actually checked the rules, though. If the inbound rule is missing, or it's on the wrong port, or the outbound rule was deleted, the same warning is real. Spend 30 seconds checking before you dismiss it.&lt;/p&gt;

&lt;p&gt;Click Create. It goes into Provisioning and becomes Active after a few minutes. The DNS name on the Details tab is the address clients will use. Use it as &lt;code&gt;http://&amp;lt;ALB_DNS_NAME&amp;gt;/&lt;/code&gt; with no port, since the listener is on 80. AWS generates that name, and it changes every time you delete and recreate the load balancer.&lt;/p&gt;

&lt;p&gt;I left the default attributes alone. Two of them are worth knowing about. Cross-zone load balancing is on, so requests spread across both nodes even though only one zone has nodes. Deletion protection is off, so you can delete the ALB from the console when you want to pause it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 7: Check that it works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Wait for both targets to turn healthy
&lt;/h3&gt;

&lt;p&gt;In Target Groups, open the target group and look at the Targets tab. Both nodes start as Initial, then should become Healthy in about two minutes. Use the refresh icon rather than reloading the whole page.&lt;/p&gt;

&lt;p&gt;If a node stays unhealthy, the status text in its row tells you why. In my experience the usual causes are these. The security group rule from Part 4 is missing or has the wrong source. The node's own probe is failing, which you can check with &lt;code&gt;curl -i http://localhost:9090/_admin/status&lt;/code&gt; on that node. Or the Molecule isn't running on that node, which you can check with &lt;code&gt;./atom status&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test through the load balancer from inside AWS
&lt;/h3&gt;

&lt;p&gt;This test shows the ALB works without any help from a laptop or corporate network. My first attempt timed out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl: (28) Failed to connect to &amp;lt;ALB_DNS_NAME&amp;gt;:80 after 134836 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a long time to wait. I had added a temporary rule to the ALB group with the source set to the node group, reasoning that node 2 was "in that group." It doesn't work that way. An internet-facing ALB's DNS name resolves to public IPs, so the node calls it over its public address, and a security group source only matches traffic from private addresses. The ALB saw a stranger on port 80 and dropped the packets silently. That's why it looked like a timeout.&lt;/p&gt;

&lt;p&gt;The fix is to allow the node's public IP. You can find it by asking the node itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://checkip.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't use the public IP from the EC2 console, because it may have changed since you last looked. Then add a new rule with HTTP on port 80, a Custom source, and that address with &lt;code&gt;/32&lt;/code&gt;. Trying to edit the old rule and switch its source to an IP won't work. The console refuses, because a rule's source type can't be changed once it exists. Delete the old rule and add a new one.&lt;/p&gt;

&lt;p&gt;Always add &lt;code&gt;--max-time 10&lt;/code&gt; to your curl commands while you're testing. Without it, a blocked request can hang for more than two minutes. With it, a firewall problem fails in 10 seconds, which is much easier to live with.&lt;/p&gt;

&lt;p&gt;Once the rule was right, the same commands worked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;--max-time&lt;/span&gt; 10 http://&amp;lt;ALB_DNS_NAME&amp;gt;/_admin/status

&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in &lt;/span&gt;1 2 3 4 5 6&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--max-time&lt;/span&gt; 10 &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: text/plain"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'hello'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    http://&amp;lt;ALB_DNS_NAME&amp;gt;/ws/rest/v1/GetLoadTest
  &lt;span class="nb"&gt;echo
&lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The status call returned 200. The six requests were answered by both nodes, and the split wasn't strictly alternating. The ALB picks a healthy target for each request, so that's normal. When you're done testing, delete the temporary rule for your node's public IP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test from your laptop
&lt;/h3&gt;

&lt;p&gt;From my Mac, the same request failed with a reset, not a timeout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl: (56) Recv failure: Connection reset by peer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A timeout would mean the security group is blocking you. A reset means something answered and then cut the connection. Running &lt;code&gt;curl -v&lt;/code&gt; and &lt;code&gt;nslookup&lt;/code&gt; showed that the hostname resolved to a carrier-grade NAT address, not an AWS address, so security software on my laptop was intercepting the request. The ALB itself was fine, since it had worked from inside AWS. Once I turned the client off for the test, the laptop requests worked.&lt;/p&gt;

&lt;p&gt;If you hit this, don't just leave the protection off. Ask your IT or security team to allow the ALB hostname. Also remember that the security group needs your current public IP, and if your VPN changes it, the symptom goes back to a timeout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Confirm the work is actually shared
&lt;/h3&gt;

&lt;p&gt;The replies already show which node handled each request, but the best check is in the platform. Open Process Reporting, find the listener process, and look at the executions. Each request through the ALB makes one execution, and the execution details should show both node IDs. That's the final proof that the cluster is splitting the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd still do before using this for real
&lt;/h2&gt;

&lt;p&gt;I haven't tested failover yet. The plan is to stop node 2 and then send the six-request loop again. Every reply should come from node 1 after about 30 seconds. Then I'd start node 2 back up and confirm it returns to the pool after about 75 seconds. This is the test that actually matters, because the whole point is that clients keep working when a node disappears. I'll update this post once I've run it.&lt;/p&gt;

&lt;p&gt;Authentication is the other thing. Right now the Shared Web Server has no authentication, so anyone who can reach the ALB can call the API. Before anyone else uses this, switch the authentication type on the port row (Basic is a reasonable start), do a rolling restart, and confirm the health check still returns 200. Without a 200 from &lt;code&gt;/_admin/status&lt;/code&gt;, the nodes will stay unhealthy.&lt;/p&gt;

&lt;p&gt;HTTPS needs a certificate from AWS Certificate Manager for a name you own. You'd add a 443 listener and open 443 in the ALB's security group. Until then, the listener has to stay on 80.&lt;/p&gt;

&lt;p&gt;Keep the ALB security group narrow. My IP is fine for testing, but don't open it to &lt;code&gt;0.0.0.0/0&lt;/code&gt; while authentication is off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost, and how to pause
&lt;/h2&gt;

&lt;p&gt;This is the part that surprised me most. An ALB is billed by the hour for as long as it exists, plus a usage charge, and you can't stop or pause it. Stopping the EC2 instances does nothing to the ALB charge. The target group and security groups are free, so the cheap way to pause is to delete only the ALB and recreate it later with the same settings.&lt;/p&gt;

&lt;p&gt;To pause, delete the ALB from its Actions menu, and keep the target group and both security groups. Then stop the Molecule on each node, starting with the member node and finishing with the head node. Run &lt;code&gt;./atom stop&lt;/code&gt; and then &lt;code&gt;./atom status&lt;/code&gt; to confirm it's really down. After that, stop both EC2 instances in the console.&lt;/p&gt;

&lt;p&gt;To resume, start both instances. Their public IPs will have changed, but the private IPs won't. Check EFS is still mounted (&lt;code&gt;df -h /mnt/boomi&lt;/code&gt;, and run &lt;code&gt;sudo mount -a&lt;/code&gt; if it isn't). Start node 1, wait for it to go green and stay stable for a minute, then start node 2. Confirm both nodes show Online in Cluster Status. Then create a new ALB with the same settings, but pick the existing target group and security group instead of making new ones. The DNS name will be different this time, so copy the new one, wait for both targets to turn healthy, and run the tests again.&lt;/p&gt;

&lt;p&gt;When the experiment is over, delete in this order: the ALB, then the target group, then any leftover security group rules, then the ALB security group, which can't be deleted while the ALB is still using it. After that, follow the teardown steps for the nodes, EFS, and the Molecule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistakes I made, or nearly made
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Private key permissions:&lt;/strong&gt; SSH refused the key because the file was readable by other users. Run &lt;code&gt;chmod 400&lt;/code&gt; once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using an old public IP:&lt;/strong&gt; Public IPs change when you stop and start instances, so always copy the current one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not restarting after changing the port:&lt;/strong&gt; Nothing listens on 9090 until you restart. Save, restart, wait 90 seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing a probe without &lt;code&gt;-i&lt;/code&gt;:&lt;/strong&gt; An empty output looks like a failure, but a 200 with no body is correct.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building only the listener on an Advanced runtime:&lt;/strong&gt; Every URL returns 404. Wrap it in an API Service Component and deploy both.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploying only the API component:&lt;/strong&gt; The deployment says it worked, but requests still fail. Deploy the process too.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing from your laptop with private IPs:&lt;/strong&gt; The connection gets reset. Test from a node.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leaving the default security group on the ALB:&lt;/strong&gt; The ALB exists but nothing can reach it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not allowing the ALB into the node group on 9090:&lt;/strong&gt; Both targets stay unhealthy, and the ALB returns 503.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typing the group name in the Description column:&lt;/strong&gt; The rule saves but does nothing. The group goes in the Source search box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skipping "Include as pending below" in the target group:&lt;/strong&gt; The group gets created with no targets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registering the wrong port:&lt;/strong&gt; The group has to be on 9090, not 80.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leaving out the nodes' Availability Zone:&lt;/strong&gt; Targets stay unused or unhealthy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring the reachability warning:&lt;/strong&gt; Check the inbound and outbound rules before you dismiss it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allowing a security group source for an internet-facing ALB:&lt;/strong&gt; The ALB sees traffic from a public address and drops it. Allow the node's public IP as a &lt;code&gt;/32&lt;/code&gt; instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trying to edit a group-source rule into an IP rule:&lt;/strong&gt; Delete it and add a new one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running curl without &lt;code&gt;--max-time&lt;/code&gt;:&lt;/strong&gt; A blocked request hangs for minutes. Always set it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assuming an ALB can be paused:&lt;/strong&gt; It keeps billing. Delete it and recreate it when you need it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick reference
&lt;/h2&gt;

&lt;p&gt;On your laptop, &lt;code&gt;chmod 400 &amp;lt;key&amp;gt;.pem&lt;/code&gt; fixes the key permission problem, and &lt;code&gt;ssh -i &amp;lt;key&amp;gt;.pem ec2-user@&amp;lt;PUBLIC_IP&amp;gt;&lt;/code&gt; opens a session on a node. &lt;code&gt;curl -i http://&amp;lt;ALB_DNS_NAME&amp;gt;/_admin/status&lt;/code&gt; checks the probe through the ALB, and &lt;code&gt;curl -v --max-time 15&lt;/code&gt; shows exactly which IP you connected to. &lt;code&gt;nslookup &amp;lt;ALB_DNS_NAME&amp;gt;&lt;/code&gt; tells you which address the name resolved to.&lt;/p&gt;

&lt;p&gt;On a node, &lt;code&gt;curl -i http://localhost:9090/_admin/status&lt;/code&gt; checks the local probe, &lt;code&gt;curl -s https://checkip.amazonaws.com&lt;/code&gt; prints the node's public IP, and &lt;code&gt;sudo ss -tlnp | grep 9090&lt;/code&gt; shows whether java is listening. From &lt;code&gt;/mnt/boomi/Molecule_&amp;lt;name&amp;gt;/bin&lt;/code&gt;, &lt;code&gt;./atom start&lt;/code&gt;, &lt;code&gt;./atom stop&lt;/code&gt;, &lt;code&gt;./atom restart&lt;/code&gt;, and &lt;code&gt;./atom status&lt;/code&gt; control the node.&lt;/p&gt;

&lt;p&gt;In the console, Target Groups shows health for each node and the reason when one fails, Load Balancers shows the DNS name and listener state, and Security Groups holds the ALB group and the node's 9090 rule.&lt;/p&gt;

&lt;p&gt;When something breaks, a 404 usually means the process or API component isn't deployed to this environment, or the URL path is wrong. A 502 or 503 from the ALB means no healthy target, so check the target group status text. A timeout means a firewall dropped the packets. A reset means something in between cut the connection, which is often security software on the laptop. The container logs for each node are under the Molecule's &lt;code&gt;logs&lt;/code&gt; folder, and searching them for &lt;code&gt;sharedServer&lt;/code&gt;, &lt;code&gt;jetty&lt;/code&gt;, or &lt;code&gt;ws/rest&lt;/code&gt; will find most startup problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Once I had both targets healthy and the ALB handing requests to both nodes, the setup finally felt like a cluster and not just two machines. The mistakes above were the real time sink. Most of them come down to the same few things: security group sources, public versus private addresses, and skipping a step that doesn't give you any error message. If you hit something different, I'd like to hear about it.&lt;/p&gt;

</description>
      <category>loadbalancer</category>
      <category>boomi</category>
      <category>infrastructure</category>
      <category>aws</category>
    </item>
    <item>
      <title>Installing a Boomi Molecule on AWS EC2, Part 2: Unicast Clustering and the Web Server</title>
      <dc:creator>Ravindra Thakur</dc:creator>
      <pubDate>Wed, 21 Oct 2026 14:49:40 +0000</pubDate>
      <link>https://dev.to/myshourya/installing-a-boomi-molecule-on-aws-ec2-part-2-unicast-clustering-and-the-web-server-3aio</link>
      <guid>https://dev.to/myshourya/installing-a-boomi-molecule-on-aws-ec2-part-2-unicast-clustering-and-the-web-server-3aio</guid>
      <description>&lt;p&gt;This is part 2 of a two-part series. If you haven't done it yet, read &lt;a href="https://builder.aws.com/content/3Kn4E0kiILmRFN51Zj95Rke1ydG/installing-a-boomi-molecule-on-aws-ec2-part-1-infrastructure-and-installer" rel="noopener noreferrer"&gt;Part 1&lt;/a&gt; first. Part 1 covers building the EFS and EC2 infrastructure and running the Molecule installer. This part picks up once both nodes are installed and mounted on the same shared folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 5: Switch the cluster to unicast
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why this step exists
&lt;/h3&gt;

&lt;p&gt;When a Molecule node starts, it needs to find the other nodes. Boomi's default is multicast. The node sends a "who's out there?" message to a special group address and port, and any other node on the same network replies. That works on an office LAN. AWS doesn't carry multicast traffic, though. The message goes nowhere, each node decides it's alone, and each one declares itself the head of its own one-node cluster.&lt;/p&gt;

&lt;p&gt;Unicast replaces the broadcast with an explicit list: these are the nodes in this cluster, at these addresses, listening on TCP port 7800. Two settings control it:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting in the platform&lt;/th&gt;
&lt;th&gt;Property name in the config file&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cluster Network Transport Type (older name: Cluster Communication Method)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;com.boomi.container.cluster.type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;UNICAST&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Initial Hosts for Unicast&lt;/td&gt;
&lt;td&gt;&lt;code&gt;com.boomi.container.cluster.initialHosts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;NODE_1_PRIVATE_IP&amp;gt;[7800],&amp;lt;NODE_2_PRIVATE_IP&amp;gt;[7800]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The list uses the private IPs, each followed by &lt;code&gt;[7800]&lt;/code&gt;, separated by commas with no spaces. It doesn't have to include every node, just enough that at least one is always running. I listed both for simplicity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set it in the platform, not in the file
&lt;/h3&gt;

&lt;p&gt;The reliable way is through the platform UI, and it needs the Molecule to be online first. That creates a small chicken-and-egg sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start node 1 only. Wait until it shows green in Runtime Management. On its own it will run in multicast mode, which is fine for now because nothing else is trying to join.&lt;/li&gt;
&lt;li&gt;In Runtime Management, click the Molecule, then open Properties and the Advanced tab.&lt;/li&gt;
&lt;li&gt;The Advanced tab has a long alphabetical dropdown. Scroll to the C section, select Cluster Network Transport Type, and set it to UNICAST.&lt;/li&gt;
&lt;li&gt;Open the dropdown again, scroll to the I section, select Initial Hosts for Unicast, and enter the list of private IPs.&lt;/li&gt;
&lt;li&gt;Save. The platform pushes the values to the runtime and writes them to the config file on EFS.&lt;/li&gt;
&lt;li&gt;Restart node 1 with &lt;code&gt;./atom restart&lt;/code&gt;. The cluster layer only switches transport after a restart.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Common mistake: editing the config file by hand while the Molecule is offline.&lt;/strong&gt; That's exactly what I tried first, adding the two lines to &lt;code&gt;container.properties&lt;/code&gt; with &lt;code&gt;echo&lt;/code&gt;. The lines were there when I checked. But when node 1 started, it registered with the platform, the platform pushed its own copy of the properties (which didn't have my lines), and my edits were overwritten. The node came up in multicast mode. The platform is the source of truth for runtime properties, so set them in the UI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common mistake: looking for the old property name.&lt;/strong&gt; Older guides call this setting "Cluster Communication Method." In current versions it's listed as Cluster Network Transport Type. The dropdown is alphabetical, so scroll rather than searching.&lt;/p&gt;

&lt;p&gt;Leave Cluster Network Bind Address unset. The node binds to its private IP automatically, and the log confirms that with a line about &lt;code&gt;jgroups.bind_addr&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check which mode a node is really in
&lt;/h3&gt;

&lt;p&gt;Don't rely on the settings page alone. Look at the ports the Java process has open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-tulnp&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ss&lt;/code&gt; lists sockets. &lt;code&gt;-t&lt;/code&gt; is TCP, &lt;code&gt;-u&lt;/code&gt; is UDP, &lt;code&gt;-l&lt;/code&gt; shows listening ports only, &lt;code&gt;-n&lt;/code&gt; shows port numbers instead of names, and &lt;code&gt;-p&lt;/code&gt; shows which process owns each one.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you see&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A UDP line for &lt;code&gt;228.10.10.10:45588&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Still in multicast mode. The unicast settings haven't taken effect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A TCP LISTEN line for &lt;code&gt;&amp;lt;private-ip&amp;gt;:7800&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Unicast. The node is listening for the other nodes on the cluster port&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This check is what finally showed me the real problem, which I describe in Part 6.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 6: Start the nodes and form the cluster
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Start node 1
&lt;/h3&gt;

&lt;p&gt;On node 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /mnt/boomi/Molecule_&amp;lt;YOUR_NAME&amp;gt;/bin
./atom start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;bin&lt;/code&gt; folder holds the control script. Despite the name, &lt;code&gt;atom&lt;/code&gt; is also the script for Molecules. Wait about a minute, then check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./atom status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It prints &lt;code&gt;atom is running.&lt;/code&gt; or &lt;code&gt;atom is not running.&lt;/code&gt; In Runtime Management, the Molecule should turn green.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start node 2
&lt;/h3&gt;

&lt;p&gt;Node 2 never runs the installer, because the installation is already on the shared disk. It just starts the same script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /mnt/boomi/Molecule_&amp;lt;YOUR_NAME&amp;gt;/bin
./atom start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do this only after node 1 is green, the unicast settings from Part 5 are in place, and node 1 has been restarted with them. Then wait two minutes and open Runtime Management, then the Molecule, then Cluster Status.&lt;/p&gt;

&lt;h3&gt;
  
  
  What success looks like
&lt;/h3&gt;

&lt;p&gt;You should see two rows, both Online, with a star next to exactly one Node ID. That star marks the head node. There should be no Cluster Issues tab. Take a screenshot for your records.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem: MULTIPLE_HEAD_NODES
&lt;/h3&gt;

&lt;p&gt;This is the problem most people hit on their first AWS Molecule, and it's exactly what happened to me. The Cluster Issues tab showed a severe warning, &lt;code&gt;MULTIPLE_HEAD_NODES&lt;/code&gt;, with each node reporting a different head node.&lt;/p&gt;

&lt;p&gt;It means each node wrote a small "view snapshot" file into the &lt;code&gt;bin/views&lt;/code&gt; folder on the shared disk, recording who it thinks the cluster members are and who the head is. The platform compares those files. In my case each file said "I'm the head, and I'm the only member." So the two nodes weren't talking to each other at all. They were two separate one-node clusters sharing a disk. That's dangerous, because both will try to run the same scheduled work and write to the same execution folders.&lt;/p&gt;

&lt;p&gt;There are only three possible causes, so check them in this order, from cheapest to most involved:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The nodes are still in multicast mode, so discovery messages never arrive. This was my actual cause.&lt;/li&gt;
&lt;li&gt;The network between the nodes is blocked, either because one instance is in the wrong security group or the self-referencing rule is missing.&lt;/li&gt;
&lt;li&gt;The nodes started too close together, or node 2 started before node 1 finished forming the cluster, and stale snapshot files kept the wrong state alive.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Start with a clean stop.&lt;/strong&gt; Stop node 2, then node 1, so nothing changes while you investigate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /mnt/boomi/Molecule_&amp;lt;YOUR_NAME&amp;gt;/bin
./atom stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check that the settings reached the runtime.&lt;/strong&gt; The config file is on the shared disk, so either node will show the same thing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; cluster /mnt/boomi/Molecule_&amp;lt;YOUR_NAME&amp;gt;/conf/container.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You want to see &lt;code&gt;cluster.type=UNICAST&lt;/code&gt; and an &lt;code&gt;initialHosts&lt;/code&gt; line. If they're missing, go back to Part 5 and set them in the UI. In my case they were there, which was misleading, and the next check showed why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check the network in both directions.&lt;/strong&gt; From node 2, run &lt;code&gt;ping -c 3 &amp;lt;NODE_1_PRIVATE_IP&amp;gt;&lt;/code&gt;, and from node 1, run &lt;code&gt;ping -c 3 &amp;lt;NODE_2_PRIVATE_IP&amp;gt;&lt;/code&gt;. The &lt;code&gt;-c 3&lt;/code&gt; option sends three packets and stops. If you see 0% packet loss, the security group is letting the nodes reach each other. If you see 100% loss, one instance isn't in the shared security group. Fix it under EC2, then Instances, then Actions, then Security, then Change security groups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check what the running node is actually doing.&lt;/strong&gt; Start node 1 and wait a minute, then run &lt;code&gt;sudo ss -tulnp | grep java&lt;/code&gt;. In my case the output showed a UDP line for the multicast address and no TCP 7800 at all. So the node was still in multicast mode, even though the file said UNICAST. The platform sync had overwritten my hand edits, and setting the properties through the UI fixed it. Once I'd done that and restarted node 1, &lt;code&gt;ss&lt;/code&gt; showed a TCP LISTEN on port 7800, and node 2 joined.&lt;/p&gt;

&lt;p&gt;You can also test the cluster port directly from the other node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;nmap-ncat &lt;span class="nt"&gt;-y&lt;/span&gt;
nc &lt;span class="nt"&gt;-zv&lt;/span&gt; &amp;lt;NODE_1_PRIVATE_IP&amp;gt; 7800
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;nc -z&lt;/code&gt; opens a connection and closes it without sending data. &lt;code&gt;-v&lt;/code&gt; tells you what happened. A "connection refused" while &lt;code&gt;ss&lt;/code&gt; shows nothing on port 7800 means the service isn't listening, which is a configuration problem. A "connection refused" or timeout while &lt;code&gt;ss&lt;/code&gt; does show 7800 means a firewall problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finish with an ordered restart&lt;/strong&gt;, so no stale state survives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# on node 2, then node 1&lt;/span&gt;
./atom stop

&lt;span class="c"&gt;# once, from either node: clear the old snapshot files&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /mnt/boomi/Molecule_&amp;lt;YOUR_NAME&amp;gt;/bin/views/&lt;span class="k"&gt;*&lt;/span&gt;.dat

&lt;span class="c"&gt;# on node 1&lt;/span&gt;
./atom start
&lt;span class="c"&gt;# wait until green in Runtime Management, then wait one more full minute&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-tlnp&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;7800   &lt;span class="c"&gt;# must show java on 7800 before you continue&lt;/span&gt;

&lt;span class="c"&gt;# on node 2&lt;/span&gt;
./atom start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deleting the &lt;code&gt;.dat&lt;/code&gt; files is safe, because they're regenerated within a minute. Skipping the wait between node 1 and node 2 is what creates the race condition in cause 3.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem: NODE_JAVA_HOME_MISMATCH
&lt;/h3&gt;

&lt;p&gt;Right after the cluster formed, another warning appeared: &lt;code&gt;NODE_JAVA_HOME_MISMATCH&lt;/code&gt;, saying node 2 was out of sync with the current Java home.&lt;/p&gt;

&lt;p&gt;Read the bracket in the message first. It says node 2 is reporting that node 1 is the head. That's good news, because it means &lt;code&gt;MULTIPLE_HEAD_NODES&lt;/code&gt; is resolved.&lt;/p&gt;

&lt;p&gt;The remaining issue comes from the "store runtime assets locally" choice during installation. Each node keeps its own copy of the Java runtime. Node 1's copy was created by the installer, but node 2's was created when it first started and hadn't been marked current yet. Restarting node 2 refreshes it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# on node 2&lt;/span&gt;
./atom stop
./atom start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the warning comes back, force node 2 to rebuild its local copy from the shared installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./atom stop
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /home/ec2-user/boomi_local/&lt;span class="k"&gt;*&lt;/span&gt;
./atom start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This deletes only node 2's local cache. It never touches the shared installation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 7: Configure the Shared Web Server
&lt;/h2&gt;

&lt;p&gt;A Molecule doesn't listen on any inbound HTTP port until you configure one. Until you do, the API Management page warns that no listener ports are set, and &lt;code&gt;curl http://localhost:9090&lt;/code&gt; on a node says it can't connect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set the port in the platform
&lt;/h3&gt;

&lt;p&gt;In Runtime Management, open the Molecule, then Shared Web Server. Check that the breadcrumb at the top names the Molecule, not an individual Atom. Under Listening Port Configuration, add a row with port &lt;code&gt;9090&lt;/code&gt;, SSL unchecked, and Authentication Type set to &lt;code&gt;None&lt;/code&gt;. That's fine for testing only. Scroll to the bottom and save.&lt;/p&gt;

&lt;h3&gt;
  
  
  Restart the nodes
&lt;/h3&gt;

&lt;p&gt;A new listener port only opens at startup, so both nodes have to restart. In a cluster, restart one node at a time so the Molecule stays online:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# on node 2&lt;/span&gt;
./atom stop

&lt;span class="c"&gt;# on node 1&lt;/span&gt;
./atom restart
&lt;span class="c"&gt;# wait until green, plus one more minute&lt;/span&gt;

&lt;span class="c"&gt;# on node 2&lt;/span&gt;
./atom start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Molecule node takes longer to come up than an Atom, so be patient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify on each node
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-tlnp&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;9090
curl http://localhost:9090
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You want a LISTEN line owned by java on port 9090. The curl should return an HTML page reading &lt;code&gt;Error 404 NOT_FOUND&lt;/code&gt;. That 404 is the correct result. It proves the web server is running. There's just nothing deployed at the root path yet.&lt;/p&gt;

&lt;p&gt;A note on the Base URL column: it shows node 1's hostname, but every node opens the port, so requests to node 2's IP on 9090 work the same way. A load balancer in front of the nodes is what gives clients one address. You don't need it for testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem: the port didn't open after the restart
&lt;/h3&gt;

&lt;p&gt;On my first restart, &lt;code&gt;ss&lt;/code&gt; only showed port 7800 and a random port, and curl couldn't connect. The setting was in the config file, though.&lt;/p&gt;

&lt;p&gt;The container log explained why. The web server libraries loaded at one time, and about five minutes later the log printed the full property set, including &lt;code&gt;sharedServer.http.connector.0.port=9090&lt;/code&gt;. The property arrived after the restart, because I'd saved the change in the UI after restarting the node, not before. The runtime accepted the new value, but a listener port only binds at startup.&lt;/p&gt;

&lt;p&gt;The fix was another restart on each node, followed by a 90-second wait. The rule is: save first, restart second, then wait a full 90 seconds before you check.&lt;/p&gt;

&lt;p&gt;If the port still doesn't show up after a correctly ordered save and restart, try deploying a listener process to the Molecule and check again. On some versions the shared web server doesn't bind until at least one Web Services Server process is deployed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 8: Next steps
&lt;/h2&gt;

&lt;p&gt;With the cluster online and the web server listening, the Molecule is ready for real work. These are the next things I plan to do.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deploy a test listener.&lt;/strong&gt; A simple one is a Start step set to Web Services Server with a REST resource and POST, a Message step, and Return Documents. Deploy it to the Molecule's environment. Because the Molecule lives in a different account from my original Atom, I had to rebuild the process there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load-test each node separately.&lt;/strong&gt; Run Autocannon from inside a node, pointing it at each node's private IP one at a time. Then check Process Reporting. Executions should show both node IDs, which proves the cluster is actually sharing work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put a load balancer in front.&lt;/strong&gt; An Application Load Balancer with a target group containing both nodes on port 9090 gives you one stable URL and spreads requests across the nodes. That's the production shape of a Molecule. I cover this in the next post.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn on HTTPS and authentication&lt;/strong&gt; on the Shared Web Server before exposing anything beyond a test network.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Day-to-day operation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Stopping for the day
&lt;/h3&gt;

&lt;p&gt;Order matters in a cluster. Stop the member node first and the head node last, so the head doesn't spend time re-electing itself. On node 2, run &lt;code&gt;./atom stop&lt;/code&gt; and then &lt;code&gt;./atom status&lt;/code&gt; to confirm it's down. Then do the same on node 1.&lt;/p&gt;

&lt;p&gt;Then, in the AWS Console, go to EC2, then Instances, select both nodes, and choose Instance state, then Stop instance. Stopping ends the compute charge, which is almost all of the cost. EFS, the security group, and the key pair are left alone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resuming
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Start both instances in the console. Their public IPs will have changed, so copy the new ones for SSH. The private IPs are the same, so the unicast list still works.&lt;/li&gt;
&lt;li&gt;On each node, run &lt;code&gt;df -h /mnt/boomi&lt;/code&gt; to confirm EFS came back through &lt;code&gt;/etc/fstab&lt;/code&gt;. If it didn't, run &lt;code&gt;sudo mount -a&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;On node 1, run &lt;code&gt;./atom start&lt;/code&gt; and wait for green plus one minute.&lt;/li&gt;
&lt;li&gt;On node 2, run &lt;code&gt;./atom start&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check Cluster Status.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Pause versus tear down
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Stop instances&lt;/th&gt;
&lt;th&gt;Terminate instances and delete EFS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Compute charge&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage charge&lt;/td&gt;
&lt;td&gt;Root disks of stopped instances plus EFS, a few rupees per day&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Molecule preserved?&lt;/td&gt;
&lt;td&gt;Yes, exactly as you left it&lt;/td&gt;
&lt;td&gt;No, you'll need a full reinstall&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;When to choose it&lt;/td&gt;
&lt;td&gt;Pausing for days or weeks&lt;/td&gt;
&lt;td&gt;When the experiment is finished&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you terminate, also release any Elastic IPs, delete leftover EBS volumes and snapshots, and remove the Molecule from Runtime Management so it doesn't stay behind as an offline runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes, in the order they happen
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Before you start&lt;/td&gt;
&lt;td&gt;Not checking the Molecule licence count&lt;/td&gt;
&lt;td&gt;Installer fails at "Retrieving Container ID" and rolls back&lt;/td&gt;
&lt;td&gt;Check Licensing first, free a slot, or use another account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Before you start&lt;/td&gt;
&lt;td&gt;Downloading from the wrong Boomi account&lt;/td&gt;
&lt;td&gt;Molecule shows up in the wrong account, or the token is rejected&lt;/td&gt;
&lt;td&gt;Switch accounts, generate the token there, reuse the installer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security group&lt;/td&gt;
&lt;td&gt;Leaving the description blank&lt;/td&gt;
&lt;td&gt;The form won't submit&lt;/td&gt;
&lt;td&gt;Type any text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security group&lt;/td&gt;
&lt;td&gt;Adding self-referencing rules during creation&lt;/td&gt;
&lt;td&gt;"CIDR block, a security group ID or a prefix list has to be specified"&lt;/td&gt;
&lt;td&gt;Create with SSH and 9090 first, then add the two self-referencing rules by editing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security group&lt;/td&gt;
&lt;td&gt;Typing the group name in the Description column&lt;/td&gt;
&lt;td&gt;Rule saves but does nothing&lt;/td&gt;
&lt;td&gt;Put the group in the Source search box&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EFS&lt;/td&gt;
&lt;td&gt;Mounting before the targets are Available or before attaching the security group&lt;/td&gt;
&lt;td&gt;Mount hangs, then "Connection timed out"&lt;/td&gt;
&lt;td&gt;Wait for Available, then assign the group under Network, then Manage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EFS&lt;/td&gt;
&lt;td&gt;Missing &lt;code&gt;.efs&lt;/code&gt; in the DNS name, or stray backticks&lt;/td&gt;
&lt;td&gt;"Failed to resolve server"&lt;/td&gt;
&lt;td&gt;Copy the DNS name from the EFS console exactly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;Using the private IP from your laptop&lt;/td&gt;
&lt;td&gt;Connection reset by peer&lt;/td&gt;
&lt;td&gt;Use the public IP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;Your laptop's IP changed since the rule was created&lt;/td&gt;
&lt;td&gt;Operation timed out on port 22&lt;/td&gt;
&lt;td&gt;Edit the SSH rule's source to My IP again&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;Running &lt;code&gt;ssh&lt;/code&gt; or &lt;code&gt;scp&lt;/code&gt; while already on a server&lt;/td&gt;
&lt;td&gt;Key file not accessible, or cannot stat the local file&lt;/td&gt;
&lt;td&gt;Read the prompt, and run &lt;code&gt;ssh&lt;/code&gt; and &lt;code&gt;scp&lt;/code&gt; from your laptop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terminal tabs&lt;/td&gt;
&lt;td&gt;Losing track of which tab is which node&lt;/td&gt;
&lt;td&gt;Commands run on the wrong machine&lt;/td&gt;
&lt;td&gt;Quit the app, reconnect deliberately, and check each prompt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;scp&lt;/td&gt;
&lt;td&gt;Leaving off &lt;code&gt;:~/&lt;/code&gt; at the end of the destination&lt;/td&gt;
&lt;td&gt;Copy fails or goes to the wrong place&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;user@host:~/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Installer&lt;/td&gt;
&lt;td&gt;Typing an email or token at a &lt;code&gt;[1]&lt;/code&gt; or &lt;code&gt;[2]&lt;/code&gt; prompt&lt;/td&gt;
&lt;td&gt;The prompt repeats&lt;/td&gt;
&lt;td&gt;Type the digit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Installer&lt;/td&gt;
&lt;td&gt;Choosing option 1 when you meant a token&lt;/td&gt;
&lt;td&gt;Asked for a username and password&lt;/td&gt;
&lt;td&gt;Press Ctrl+C, run again, answer &lt;code&gt;2&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Installer&lt;/td&gt;
&lt;td&gt;Typing the environment name or ID instead of its number&lt;/td&gt;
&lt;td&gt;The list reprints&lt;/td&gt;
&lt;td&gt;Type the number in brackets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Installer&lt;/td&gt;
&lt;td&gt;Typing &lt;code&gt;y&lt;/code&gt; at a &lt;code&gt;[1]&lt;/code&gt; or &lt;code&gt;[2]&lt;/code&gt; prompt&lt;/td&gt;
&lt;td&gt;The prompt repeats&lt;/td&gt;
&lt;td&gt;Type &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;2&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Installer&lt;/td&gt;
&lt;td&gt;Pressing Enter on a required field with empty brackets&lt;/td&gt;
&lt;td&gt;"... is required," then loops back&lt;/td&gt;
&lt;td&gt;Type the value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Installer&lt;/td&gt;
&lt;td&gt;Accepting the default installation directory&lt;/td&gt;
&lt;td&gt;Node 2 has nothing to start&lt;/td&gt;
&lt;td&gt;Install under &lt;code&gt;/mnt/boomi&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Installer&lt;/td&gt;
&lt;td&gt;Node 2's &lt;code&gt;boomi_local&lt;/code&gt; folder not created&lt;/td&gt;
&lt;td&gt;Node 2 fails to start or reports a missing local directory&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;mkdir -p /home/ec2-user/boomi_local&lt;/code&gt; on every node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unicast&lt;/td&gt;
&lt;td&gt;Leaving multicast on&lt;/td&gt;
&lt;td&gt;MULTIPLE_HEAD_NODES, and the nodes never join&lt;/td&gt;
&lt;td&gt;Set Cluster Network Transport Type to UNICAST and set the initial hosts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unicast&lt;/td&gt;
&lt;td&gt;Editing &lt;code&gt;container.properties&lt;/code&gt; by hand&lt;/td&gt;
&lt;td&gt;The lines are there, but the node is still in multicast mode&lt;/td&gt;
&lt;td&gt;The platform overwrites the file on sync. Set the properties in the UI, then restart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unicast&lt;/td&gt;
&lt;td&gt;Searching for the old property name&lt;/td&gt;
&lt;td&gt;Can't find "Cluster Communication Method"&lt;/td&gt;
&lt;td&gt;It's now called Cluster Network Transport Type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unicast&lt;/td&gt;
&lt;td&gt;Using public IPs in the initial hosts list&lt;/td&gt;
&lt;td&gt;Nodes can't connect on 7800&lt;/td&gt;
&lt;td&gt;Use private IPs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Start-up&lt;/td&gt;
&lt;td&gt;Starting node 2 too soon after node 1&lt;/td&gt;
&lt;td&gt;MULTIPLE_HEAD_NODES from stale snapshots&lt;/td&gt;
&lt;td&gt;Wait for green plus a minute, delete &lt;code&gt;bin/views/*.dat&lt;/code&gt;, and restart in order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cluster&lt;/td&gt;
&lt;td&gt;NODE_JAVA_HOME_MISMATCH after joining&lt;/td&gt;
&lt;td&gt;Severe issue on node 2&lt;/td&gt;
&lt;td&gt;Restart node 2, and if needed clear its &lt;code&gt;boomi_local&lt;/code&gt; folder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web server&lt;/td&gt;
&lt;td&gt;Restarting before saving the port&lt;/td&gt;
&lt;td&gt;9090 never opens&lt;/td&gt;
&lt;td&gt;Save first, restart, then wait 90 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web server&lt;/td&gt;
&lt;td&gt;Treating the root-path 404 as a failure&lt;/td&gt;
&lt;td&gt;Confusion&lt;/td&gt;
&lt;td&gt;A 404 from &lt;code&gt;/&lt;/code&gt; means the web server is up&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Command reference
&lt;/h2&gt;

&lt;h3&gt;
  
  
  On your laptop
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chmod 400 ~/Downloads/&amp;lt;KEY_FILE&amp;gt;.pem&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Makes the key file readable only by you. SSH refuses keys with looser permissions. Run this once&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ssh -i ~/Downloads/&amp;lt;KEY_FILE&amp;gt;.pem ec2-user@&amp;lt;PUBLIC_IP&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opens a terminal on a node. &lt;code&gt;-i&lt;/code&gt; selects the key file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scp -i ~/Downloads/&amp;lt;KEY_FILE&amp;gt;.pem &amp;lt;local-file&amp;gt; ec2-user@&amp;lt;PUBLIC_IP&amp;gt;:~/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Copies a file from your laptop to the node's home folder&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  On the nodes: setup
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sudo yum update -y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Updates the operating system packages. &lt;code&gt;-y&lt;/code&gt; answers yes to prompts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sudo yum install java-17-amazon-corretto nfs-utils -y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Installs a system Java and the NFS client tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sudo mkdir -p /mnt/boomi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates the folder the shared disk attaches to. &lt;code&gt;-p&lt;/code&gt; creates parent folders and doesn't complain if the folder exists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sudo mount -t nfs4 -o nfsvers=4.1 &amp;lt;EFS_DNS_NAME&amp;gt;:/ /mnt/boomi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Attaches the root of the EFS file system to &lt;code&gt;/mnt/boomi&lt;/code&gt; using NFS 4.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;df -h /mnt/boomi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shows what's mounted at that path and how much space it has&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;`echo ":/ /mnt/boomi nfs4 nfsvers=4.1,_netdev 0 0" \&lt;/td&gt;
&lt;td&gt;sudo tee -a /etc/fstab`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sudo mount -a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mounts everything listed in &lt;code&gt;/etc/fstab&lt;/code&gt; that isn't already mounted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sudo chown ec2-user:ec2-user /mnt/boomi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Makes &lt;code&gt;ec2-user&lt;/code&gt; the owner of the shared folder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;touch &amp;lt;file&amp;gt;&lt;/code&gt;, &lt;code&gt;ls &amp;lt;dir&amp;gt;&lt;/code&gt;, &lt;code&gt;rm &amp;lt;file&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Create an empty file, list a folder, or delete a file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mkdir -p /home/ec2-user/boomi_local&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates the per-node local assets folder&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  On the nodes: installer
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chmod u+x molecule_install64.sh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gives the downloaded installer permission to run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;./molecule_install64.sh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Runs the installer. The &lt;code&gt;./&lt;/code&gt; is needed because the script isn't on the PATH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl+C&lt;/td&gt;
&lt;td&gt;Cancels a running command. It's safe to use before the installer's summary screen&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  On the nodes: Molecule control
&lt;/h3&gt;

&lt;p&gt;Run these from &lt;code&gt;/mnt/boomi/Molecule_&amp;lt;YOUR_NAME&amp;gt;/bin&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;./atom start&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Starts this node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;./atom stop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stops this node cleanly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;./atom restart&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stops, then starts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;./atom status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prints whether this node is running&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  On the nodes: diagnostics
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sudo ss -tlnp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lists TCP ports that are listening, and which process owns each&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;`sudo ss -tulnp \&lt;/td&gt;
&lt;td&gt;grep java`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ping -c 3 &amp;lt;private-ip&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sends three packets to the other node to test basic reachability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nc -zv &amp;lt;private-ip&amp;gt; 7800&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tests whether a TCP connection to the cluster port succeeds. Install it with &lt;code&gt;sudo yum install nmap-ncat -y&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -i cluster .../conf/container.properties&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shows the cluster settings the runtime currently holds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;grep -r 9090 .../conf/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Finds any file under &lt;code&gt;conf&lt;/code&gt; that mentions the port&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;`grep -i -E "pattern1\&lt;/td&gt;
&lt;td&gt;pattern2"  \&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{% raw %}&lt;code&gt;tail -50 &amp;lt;logfile&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Shows the last 50 lines of a file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rm -f .../bin/views/*.dat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deletes the cluster snapshot files. They regenerate on start. Use this to clear stale head-node state&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Appendix A: How to read installer prompts
&lt;/h2&gt;

&lt;p&gt;Every question the console installer asks follows one of three patterns. Once you recognize them, most of the installer mistakes go away.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;What to type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Options with characters in brackets&lt;/td&gt;
&lt;td&gt;User Name and Password [1, Enter], Token [2], or Yes [y, Enter], No [n]&lt;/td&gt;
&lt;td&gt;Exactly the character in the brackets. Nothing else is accepted. The option marked Enter is the default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A default value in brackets&lt;/td&gt;
&lt;td&gt;Choose an installation directory [/home/ec2-user/...]&lt;/td&gt;
&lt;td&gt;Enter to accept the default, or type a replacement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Empty brackets&lt;/td&gt;
&lt;td&gt;Token [] or Working Data Local Storage Directory (required) []&lt;/td&gt;
&lt;td&gt;There's no default. Type the value. Enter on its own gets rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If a prompt keeps repeating, you've given it something it doesn't recognize. Look at the brackets again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix B: Where the logs are
&lt;/h2&gt;

&lt;p&gt;All of these paths are under the shared installation, so you can read them from either node.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Contents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mnt/boomi/Molecule_&amp;lt;YOUR_NAME&amp;gt;/logs/YYYY_MM_DD.container.&amp;lt;node-id&amp;gt;.log&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;One container log per node per day. The node ID is the private IP with underscores, for example &lt;code&gt;&amp;lt;NODE_ID&amp;gt;&lt;/code&gt;. This is the first place to look for cluster and web server problems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mnt/boomi/Molecule_&amp;lt;YOUR_NAME&amp;gt;/conf/container.properties&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The runtime properties as last synced from the platform&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/mnt/boomi/Molecule_&amp;lt;YOUR_NAME&amp;gt;/bin/views/*.dat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cluster snapshot files, one per node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;/home/ec2-user/boomi_local/&lt;/code&gt; (on each node)&lt;/td&gt;
&lt;td&gt;Per-node local copies of the Java runtime, libraries, and working data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Useful search terms for the container log are &lt;code&gt;cluster&lt;/code&gt;, &lt;code&gt;unicast&lt;/code&gt;, &lt;code&gt;multicast&lt;/code&gt;, &lt;code&gt;MULTIPLE_HEAD_NODES&lt;/code&gt;, &lt;code&gt;jgroups.bind_addr&lt;/code&gt;, &lt;code&gt;sharedServer&lt;/code&gt;, &lt;code&gt;jetty&lt;/code&gt;, and &lt;code&gt;9090&lt;/code&gt;. Searching for &lt;code&gt;Container Properties for account&lt;/code&gt; shows the full property set at the moment the platform pushed it, with a timestamp you can compare to your restart time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Getting the cluster to form was the hardest part. Most of the problems came from one thing: the nodes couldn't see each other, and the cause wasn't obvious from the error messages. The fix was switching to unicast through the UI, checking the actual open ports rather than trusting the settings page, and restarting in the right order.&lt;/p&gt;

&lt;p&gt;In the next post I'll put an Application Load Balancer in front of these two nodes, so clients get one address and keep working when a node goes down.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>boomi</category>
      <category>ec2</category>
      <category>community</category>
    </item>
    <item>
      <title>Installing a Boomi Molecule on AWS EC2, Part 1: Infrastructure and Installer</title>
      <dc:creator>Ravindra Thakur</dc:creator>
      <pubDate>Sun, 18 Oct 2026 16:42:02 +0000</pubDate>
      <link>https://dev.to/myshourya/installing-a-boomi-molecule-on-aws-ec2-part-1-infrastructure-and-installer-5e1k</link>
      <guid>https://dev.to/myshourya/installing-a-boomi-molecule-on-aws-ec2-part-1-infrastructure-and-installer-5e1k</guid>
      <description>&lt;h2&gt;
  
  
  What this post covers
&lt;/h2&gt;

&lt;p&gt;This is part 1 of a two-part series. Part 1 covers the infrastructure and the installer. Part 2 covers switching the nodes to unicast, forming the cluster, and configuring the web server.&lt;/p&gt;

&lt;p&gt;I installed a Boomi Molecule on two EC2 instances in September 2026 and took it from empty AWS infrastructure to a working two-node cluster, with both nodes online in Atom Management. This is the first post in a short series. &lt;/p&gt;

&lt;p&gt;I've written this the way I actually did it, including the parts that went wrong. Most of the mistakes below are ones you're likely to make too, so I've pointed them out where they happened.&lt;/p&gt;

&lt;p&gt;This setup was a personal proof of concept on a Boomi training environment, built to learn how Molecules work.&lt;/p&gt;

&lt;p&gt;Every account-specific value has been replaced with a placeholder such as &lt;code&gt;&amp;lt;NODE_1_PRIVATE_IP&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;EFS_DNS_NAME&amp;gt;&lt;/code&gt;. Replace each one with the value from your own AWS and Boomi consoles as you go. The table below shows where each value comes from. The example values are only there to show the format. They are not real.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Placeholder&lt;/th&gt;
&lt;th&gt;Where to find it&lt;/th&gt;
&lt;th&gt;Example format&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;EFS_DNS_NAME&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;EFS console, your file system, DNS name box on the right&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fs-xxxxxxxxxxxxxxxxx.efs.&amp;lt;region&amp;gt;.amazonaws.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;NODE_1_PRIVATE_IP&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;NODE_2_PRIVATE_IP&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;EC2 console, each instance, Private IPv4 address&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;10.0.x.x&lt;/code&gt; or &lt;code&gt;172.31.x.x&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;NODE_1_PUBLIC_IP&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;EC2 console, each instance, Public IPv4 address (changes after stop and start)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;x.x.x.x&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;KEY_FILE&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;.pem&lt;/code&gt; file you downloaded when you created the key pair&lt;/td&gt;
&lt;td&gt;&lt;code&gt;my-key-name.pem&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;YOUR_NAME&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Any short label you choose for the Molecule installation folder&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Molecule_demo&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;YOUR_MOLECULE_NAME&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Any name you choose for the Molecule in Boomi&lt;/td&gt;
&lt;td&gt;&lt;code&gt;demo-molecule&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Keep these private:&lt;/strong&gt; installer tokens, your &lt;code&gt;.pem&lt;/code&gt; key file, your AWS access keys, account IDs, and the full contents of &lt;code&gt;container.properties&lt;/code&gt;. Don't paste them into a forum post, a chat, or a screenshot. If a token is ever exposed, generate a new one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Molecule is, and why AWS needs a different setup
&lt;/h2&gt;

&lt;p&gt;A Boomi Atom is a single-server runtime. A Molecule is the clustered version: two or more servers (called nodes) that share one installation folder on a network file system and show up in the Boomi platform as a single runtime. Work is spread across the nodes, and if one node goes down, the others keep going.&lt;/p&gt;

&lt;p&gt;That shared-folder idea is what makes installing a Molecule different from an Atom. You need four things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A shared disk&lt;/strong&gt; that every node can read and write. On AWS that's Amazon EFS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two or more servers.&lt;/strong&gt; One node is just an Atom with extra steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A network path between the nodes&lt;/strong&gt;, since they constantly talk to each other to agree on which node is the head node.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A way for the nodes to find each other.&lt;/strong&gt; Boomi's default method, multicast, doesn't work on AWS, so you have to switch to unicast. I explain why in Part 5.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The finished setup looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      Boomi AtomSphere platform (control plane)
                      ^
                      | outbound HTTPS from each node
        +-------------+-------------+
        |                           |
+-------+---------+       +---------+-------+
| EC2 node-1      | 7800  | EC2 node-2      |
| &amp;lt;NODE_1_PRIVATE_IP&amp;gt; &amp;lt;--&amp;gt; &amp;lt;NODE_2_PRIVATE_IP&amp;gt; |
| head node       |       | member node     |
+-------+---------+       +---------+-------+
        |  NFS 2049                 |
        +-------------+-------------+
                      |
              +-------+-------+
              |  Amazon EFS   |
              |  /mnt/boomi   |
              +---------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Before you start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Check your Molecule licence
&lt;/h3&gt;

&lt;p&gt;Molecule licences are counted per Boomi account, and the installer checks the count before it creates anything. In the platform, open the settings menu, go to Account Information and Setup, then Licensing, and check the Molecule line. You need at least one free.&lt;/p&gt;

&lt;p&gt;I learned this the hard way. My first attempt ran all the way through downloading the Java runtime and the Atom and Molecule files, and then failed at "Retrieving Container ID" with a message saying the account had already reached its Molecule limit. The installer rolled everything back cleanly, but I'd lost about an hour. The licences were tied up by older test Molecules still registered in the account. So check this first. If you're at the limit, remove any unused Molecules you own, or use an account that has spare capacity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make sure you're in the right account
&lt;/h3&gt;

&lt;p&gt;If your Boomi user can access more than one account, check which one is selected before you download anything. The installer file is the same for every account, but the token you paste in during installation ties the Molecule to a specific account. If you grab a token from the wrong account, just switch accounts, generate a fresh token there, and reuse the same installer file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create an environment
&lt;/h3&gt;

&lt;p&gt;A Molecule has to belong to a Boomi environment. In Manage, then Runtime Management, create one with the New button if you don't already have a suitable test or dev environment. Give it a clear name and set its classification to Test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understand the cost
&lt;/h3&gt;

&lt;p&gt;Nothing here is free tier. Two t3.medium instances cost roughly USD 0.08 per hour combined while they're running. EFS is billed by the amount of data you store, around USD 0.30 per GB-month, and a Molecule installation is only a few hundred megabytes, so the storage cost is small. The section on pausing and resuming covers how to avoid paying for compute you aren't using.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: Build the AWS infrastructure
&lt;/h2&gt;

&lt;p&gt;Everything in this part happens in the AWS Console in your browser. Nothing gets typed into a terminal yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the shared file system
&lt;/h3&gt;

&lt;p&gt;Search for EFS in the AWS Console and choose Create file system. Give it a name, pick your default VPC, and click Create.&lt;/p&gt;

&lt;p&gt;When the file system opens, you need two things from the top of the page. The first is the file system ID, which looks like &lt;code&gt;fs-0123456789abcdef0&lt;/code&gt;. The second is the DNS name, shown in a copyable box on the right. It looks like &lt;code&gt;fs-0123456789abcdef0.efs.us-east-1.amazonaws.com&lt;/code&gt;. Copy the DNS name exactly, because you'll paste it into a command later.&lt;/p&gt;

&lt;p&gt;Open the Network tab. There's one mount target per Availability Zone, and each one starts in the Creating state. Wait until every row says Available before you try to mount anything. If you don't, the mount command just hangs.&lt;/p&gt;

&lt;p&gt;You don't need the mount target IDs, the network interface IDs, or the individual IP addresses in that table. The DNS name works from any subnet and resolves to the right mount target automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the security group
&lt;/h3&gt;

&lt;p&gt;A security group is the firewall for your instances. I used one group for both nodes and the EFS mount targets, which keeps the rules simple.&lt;/p&gt;

&lt;p&gt;Go to EC2, then Security Groups, then Create security group. Give it a name. It can't be changed later, so pick something you'll recognize. Add a description, which can be anything as long as it isn't blank. The form won't submit without one, and the error message is easy to miss among the other red boxes. Pick the same default VPC as EFS.&lt;/p&gt;

&lt;p&gt;Add these inbound rules. Leave the outbound rules at their defaults. "Allow all outbound" is exactly what the nodes need, so they can reach the Boomi platform, download packages, and connect to EFS.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;My IP&lt;/td&gt;
&lt;td&gt;Terminal access from your machine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom TCP&lt;/td&gt;
&lt;td&gt;9090&lt;/td&gt;
&lt;td&gt;My IP&lt;/td&gt;
&lt;td&gt;Calling the web server from your machine (optional)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;All traffic&lt;/td&gt;
&lt;td&gt;All&lt;/td&gt;
&lt;td&gt;This security group&lt;/td&gt;
&lt;td&gt;Node-to-node cluster traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NFS&lt;/td&gt;
&lt;td&gt;2049&lt;/td&gt;
&lt;td&gt;This security group&lt;/td&gt;
&lt;td&gt;Nodes connecting to EFS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A security group describes traffic arriving at a machine, so node 1 talking to node 2 needs node 2 to accept it. Because both nodes are in the same group, one rule that says "allow traffic from members of this group" covers both directions. The EFS mount targets are in the same group, so the NFS rule lets both nodes reach them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common mistake: adding the self-referencing rules while you create the group.&lt;/strong&gt; The rules whose source is "this security group" can't be filled in until the group exists, so the form will complain that a CIDR block, security group ID, or prefix list is needed. Do it in two rounds. Create the group with just the SSH and 9090 rules. Then open it, choose Edit inbound rules, add the other two rows, and in each Source box type the group's name and pick it from the list. It shows up as a blue tag with its &lt;code&gt;sg-&lt;/code&gt; ID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common mistake: typing the group name into the Description column.&lt;/strong&gt; That column is a free-text label with no effect. The group reference has to go in the Source search box.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attach the security group to the EFS mount targets
&lt;/h3&gt;

&lt;p&gt;Back in EFS, open your file system, go to Network, and choose Manage. For every mount target, replace the default security group with the one you just made, then save. Without this, the servers will time out when they try to mount, because the default group doesn't allow NFS from them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Launch two EC2 instances
&lt;/h3&gt;

&lt;p&gt;Go to EC2, choose Launch Instance, and create the first node with these settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; &lt;code&gt;node-1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AMI:&lt;/strong&gt; Amazon Linux 2023. It's simple, well integrated with AWS, and uses yum and dnf.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instance type:&lt;/strong&gt; t3.medium (2 vCPU, 4 GB RAM). Boomi recommends at least 4 GB per node. A t3.small will run a demo but is marginal, and a t3.micro won't work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key pair:&lt;/strong&gt; a key pair you already have the &lt;code&gt;.pem&lt;/code&gt; file for. Use the same key for both nodes so SSH stays simple.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network settings:&lt;/strong&gt; select the existing security group you just built. Don't let the wizard create a new one, because the nodes have to be in your group.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subnet:&lt;/strong&gt; pick one and note which one. Both nodes need to be in the same subnet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Launch a second instance the same way and call it &lt;code&gt;node-2&lt;/code&gt;, putting it in the same subnet.&lt;/p&gt;

&lt;p&gt;When both show Running, open each one and write down two addresses. The public IPv4 address is what you use for SSH from your laptop. It changes every time you stop and start the instance. The private IPv4 address is what the nodes use to talk to each other in the cluster, and it doesn't change.&lt;/p&gt;

&lt;p&gt;If you don't want to copy the public IP every time, you can allocate an Elastic IP and attach it to each instance. It's free while attached to a running instance, but it costs a small amount per hour while the instance is stopped, so it's optional for a learning setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Connect to the nodes and mount the shared disk
&lt;/h2&gt;

&lt;p&gt;From here on you'll be working in two kinds of terminal, and mixing them up caused more errors for me than anything else. Check the prompt before you paste a command.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prompt looks like&lt;/th&gt;
&lt;th&gt;Where you are&lt;/th&gt;
&lt;th&gt;What goes here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yourname@your-laptop ~ %&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your laptop&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ssh&lt;/code&gt; to connect, &lt;code&gt;scp&lt;/code&gt; to copy files up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[ec2-user@ip-&amp;lt;NODE_PRIVATE_IP_DASHED&amp;gt; ~]$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Node 1&lt;/td&gt;
&lt;td&gt;Everything that runs on the server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[ec2-user@ip-&amp;lt;NODE_PRIVATE_IP_DASHED&amp;gt; ~]$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Node 2&lt;/td&gt;
&lt;td&gt;Everything that runs on the server&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The last few digits of the private IP tell you which node you're on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connect to both nodes
&lt;/h3&gt;

&lt;p&gt;Open two terminal tabs on your laptop, and in each one run &lt;code&gt;ssh&lt;/code&gt; with the public IP of one node. The &lt;code&gt;-i&lt;/code&gt; option names the key file you downloaded when you created the key pair. &lt;code&gt;ec2-user&lt;/code&gt; is the default login on Amazon Linux. The first time you connect to a new server, SSH will ask whether to trust its fingerprint. Type &lt;code&gt;yes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common mistake: using the private IP for SSH.&lt;/strong&gt; You'll get &lt;code&gt;Connection reset by peer&lt;/code&gt;. Private IPs only exist inside AWS, so your laptop can't reach them. Use the public IP for SSH and save the private IP for the cluster setup later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common mistake: SSH times out because your IP has changed.&lt;/strong&gt; The SSH rule is set to My IP, and that's a snapshot. If your laptop's public IP has changed since you created the rule, SSH will time out. Open the security group, edit the inbound rules, and set the SSH row's source to My IP again. AWS fills in your current address. Do the same for the 9090 row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common mistake: running &lt;code&gt;ssh&lt;/code&gt; from inside a server.&lt;/strong&gt; I had a tab still logged into a node from the day before. When I ran the &lt;code&gt;ssh&lt;/code&gt; command there, it failed with a "not accessible" warning, because the key file only exists on my laptop. Check the prompt. If it says &lt;code&gt;ec2-user@ip-...&lt;/code&gt;, you're already on a server. Press Ctrl+C, or type &lt;code&gt;exit&lt;/code&gt;, and run the command from your laptop.&lt;/p&gt;

&lt;p&gt;If things get muddled and you can't tell which tab is which node, quit the terminal app, reopen it, and connect to node 1 in the first tab and node 2 in the second. Then check each prompt. It takes thirty seconds and saves a lot of confusion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Java and the NFS client on both nodes
&lt;/h3&gt;

&lt;p&gt;On each node, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum update &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;java-17-amazon-corretto nfs-utils &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;yum update&lt;/code&gt; brings the operating system up to date. &lt;code&gt;java-17-amazon-corretto&lt;/code&gt; is Amazon's build of OpenJDK 17. The Boomi installer bundles its own Java runtime, but having a system Java around is useful for troubleshooting. &lt;code&gt;nfs-utils&lt;/code&gt; provides the NFS mount helper EFS needs. Without it, the mount fails with "unknown filesystem type."&lt;/p&gt;

&lt;h3&gt;
  
  
  Mount EFS on both nodes
&lt;/h3&gt;

&lt;p&gt;On each node, create a folder and mount the file system into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /mnt/boomi
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; nfs4 &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;nfsvers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4.1 &amp;lt;EFS_DNS_NAME&amp;gt;:/ /mnt/boomi
&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; /mnt/boomi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;mkdir -p&lt;/code&gt; creates the folder and doesn't complain if it already exists. The mount command attaches the root of the EFS file system to that folder over NFS 4.1, which is the version EFS supports. &lt;code&gt;df -h&lt;/code&gt; shows what's mounted. A successful mount shows a line ending in &lt;code&gt;/mnt/boomi&lt;/code&gt;, with a size of 8.0E. That's EFS reporting a huge nominal size, because it grows as you use it.&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;&amp;lt;EFS_DNS_NAME&amp;gt;&lt;/code&gt; with the DNS name from the EFS console, exactly as it appears there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common mistake: a mistyped EFS DNS name.&lt;/strong&gt; I got &lt;code&gt;Failed to resolve server ...: Name or service not known&lt;/code&gt; because the &lt;code&gt;.efs&lt;/code&gt; part was missing from the name, and I'd also copied backticks from a chat message along with the ID. The address has to be exactly &lt;code&gt;&amp;lt;file-system-id&amp;gt;.efs.&amp;lt;region&amp;gt;.amazonaws.com&lt;/code&gt;. Copy it from the console instead of typing it.&lt;/p&gt;

&lt;p&gt;If the mount hangs for a minute and then says &lt;code&gt;Connection timed out&lt;/code&gt;, one of two things is wrong. Either the mount targets aren't Available yet, or you haven't attached the security group to them.&lt;/p&gt;

&lt;p&gt;Next, make the mount permanent so it comes back after a reboot or a stop and start. Then give &lt;code&gt;ec2-user&lt;/code&gt; ownership of the shared folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;EFS_DNS_NAME&amp;gt;:/ /mnt/boomi nfs4 nfsvers=4.1,_netdev 0 0"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/fstab
&lt;span class="nb"&gt;sudo chown &lt;/span&gt;ec2-user:ec2-user /mnt/boomi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/etc/fstab&lt;/code&gt; is the list of file systems Linux mounts at boot. &lt;code&gt;tee -a&lt;/code&gt; appends the line with root permission. The &lt;code&gt;_netdev&lt;/code&gt; flag tells the boot process to wait for networking before trying this mount. The &lt;code&gt;chown&lt;/code&gt; makes the shared folder writable by the user that will run the installer and the Molecule.&lt;/p&gt;

&lt;p&gt;Using the same user on every node matters. Files written to EFS by node 1 have to be readable and writable by node 2. NFS identifies users by numeric ID, and &lt;code&gt;ec2-user&lt;/code&gt; has the same ID on every Amazon Linux instance, so using that one user everywhere avoids a whole class of permission problems.&lt;/p&gt;

&lt;p&gt;To prove both nodes see the same disk, run &lt;code&gt;touch /mnt/boomi/hello&lt;/code&gt; on node 1, then &lt;code&gt;ls /mnt/boomi&lt;/code&gt; on node 2. You should see &lt;code&gt;hello&lt;/code&gt;. Delete it afterwards with &lt;code&gt;rm /mnt/boomi/hello&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the local assets folder on node 2
&lt;/h3&gt;

&lt;p&gt;The installer will ask for a folder on each node's local disk, where per-node working files and the Java runtime are kept for speed. Node 1 creates it automatically during installation, but node 2 never runs the installer, so create it by hand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/ec2-user/boomi_local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The path is saved in the shared configuration, so it has to be identical on every node.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3: Get the installer and a token onto node 1
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Download the Molecule installer
&lt;/h3&gt;

&lt;p&gt;In the Boomi platform, check that you're in the right account, then go to Manage, then Atom Management, and click New. Choose Molecule, then Local, then Linux 64-bit, and download the file. It's called &lt;code&gt;molecule_install64.sh&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copy the installer to node 1
&lt;/h3&gt;

&lt;p&gt;Run this from your laptop, not from a server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp &lt;span class="nt"&gt;-i&lt;/span&gt; ~/Downloads/&amp;lt;KEY_FILE&amp;gt;.pem ~/Downloads/molecule_install64.sh ec2-user@&amp;lt;NODE_1_PUBLIC_IP&amp;gt;:~/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;scp&lt;/code&gt; copies a file over SSH. The first path is the local file. The second is &lt;code&gt;user@host:destination&lt;/code&gt;, and &lt;code&gt;:~/&lt;/code&gt; means your home folder on the server. A successful copy ends with a progress line at 100%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common mistake: running &lt;code&gt;scp&lt;/code&gt; on the server.&lt;/strong&gt; If you paste the command into the node's terminal, it can't find the file, because the file is on your laptop. Also make sure the destination has the trailing &lt;code&gt;:~/&lt;/code&gt;, or the copy won't go where you expect.&lt;/p&gt;

&lt;p&gt;Then, on node 1, confirm the file arrived and make it executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; ~/molecule_install64.sh
&lt;span class="nb"&gt;chmod &lt;/span&gt;u+x molecule_install64.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;chmod u+x&lt;/code&gt; gives the file's owner permission to run it. Downloaded scripts usually arrive without that permission.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate a token right before you install
&lt;/h3&gt;

&lt;p&gt;On the same Atom Management screen, under Security Options, click Generate Token. Tokens expire quickly, often within thirty minutes, so generate it just before you run the installer. Paste it only into the installer prompt, and never into a chat, a document, or a ticket.&lt;/p&gt;

&lt;p&gt;An installer token is a credential for your Boomi account. If one has ever been pasted somewhere it shouldn't be, generate a new one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 4: Run the Molecule installer
&lt;/h2&gt;

&lt;p&gt;On node 1 only, create the local folder and run the installer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/ec2-user/boomi_local
./molecule_install64.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script first looks for Java, downloads a runtime from the Boomi platform if it needs one (about 190 MB), and then starts the interactive installer in the terminal. You'll see some &lt;code&gt;WARNING: An illegal reflective access operation has occurred&lt;/code&gt; lines. Those are harmless notices about an older installer running on a newer Java. Don't interrupt the install because of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Answer the prompts
&lt;/h3&gt;

&lt;p&gt;Here's every prompt in order, with the answer I used. Replace the names with your own.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prompt&lt;/th&gt;
&lt;th&gt;Answer&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;This will install a Molecule on your computer. OK [o, Enter], Cancel [c]&lt;/td&gt;
&lt;td&gt;Enter&lt;/td&gt;
&lt;td&gt;Confirms you want to start&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User Name and Password [1, Enter], Token [2]&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use a token instead of typing your Boomi password on a server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token []&lt;/td&gt;
&lt;td&gt;Paste the token&lt;/td&gt;
&lt;td&gt;The credential from Part 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Molecule Name [ip-.ec2.internal]&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;YOUR_MOLECULE_NAME&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The default is the server's hostname, so give it something meaningful&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use Proxy Settings? Yes [y], No [n, Enter]&lt;/td&gt;
&lt;td&gt;&lt;code&gt;n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;An EC2 instance in a default VPC has direct internet access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choose an Environment, followed by a numbered list&lt;/td&gt;
&lt;td&gt;The number next to your environment&lt;/td&gt;
&lt;td&gt;Attach it to a test or dev environment, not production&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choose an installation directory&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/mnt/boomi/Molecule_&amp;lt;YOUR_NAME&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Must be on EFS.&lt;/strong&gt; If it's on the local disk, node 2 will have nothing to start&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Store runtime assets locally [1, Enter], use cluster shared storage [2]&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Keeps temp files, libraries, and the Java runtime on each node's local disk, which is faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Working Data Local Storage Directory (required) []&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/ec2-user/boomi_local&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The folder from earlier. Use the same path on every node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local Temp Directory [/tmp]&lt;/td&gt;
&lt;td&gt;Enter&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/tmp&lt;/code&gt; is local to each node, so this default is fine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Create symlinks? Yes [y, Enter], No [n]&lt;/td&gt;
&lt;td&gt;&lt;code&gt;y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Adds the &lt;code&gt;atom&lt;/code&gt; commands to your PATH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choose the location to create symlinks [/usr/local/bin]&lt;/td&gt;
&lt;td&gt;Enter&lt;/td&gt;
&lt;td&gt;Accept the default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Summary screen, [Enter]&lt;/td&gt;
&lt;td&gt;Enter&lt;/td&gt;
&lt;td&gt;Starts the actual installation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A successful run ends with messages about downloading the JRE, unpacking it, downloading the Atom and Molecule files, retrieving the container ID, and attaching the container to your environment. The last line says the Molecule has been installed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't start the Molecule yet.&lt;/strong&gt; Part 5 has to happen first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistakes I made at the prompts
&lt;/h3&gt;

&lt;p&gt;These all come from misreading how the console installer works. The rule is simple: the installer only accepts the answers shown in the brackets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typing an email address or token at the "1 or 2" prompt.&lt;/strong&gt; The installer asks for &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;2&lt;/code&gt;. I typed my email, then the email and token together. Each time, it just asked again. Type the digit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choosing option 1 when I meant to use a token.&lt;/strong&gt; Typing &lt;code&gt;1&lt;/code&gt; moved me into the username and password prompts, and there's no way back from there inside the installer. Press Ctrl+C, run the installer again, and answer &lt;code&gt;2&lt;/code&gt;. Nothing has been installed at that point, so it's safe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typing the environment name or ID instead of its number.&lt;/strong&gt; The environment list wants the number in brackets. The installer kept reprinting the list while I tried the name and then the GUID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typing &lt;code&gt;y&lt;/code&gt; or &lt;code&gt;yes&lt;/code&gt; at a &lt;code&gt;[1, Enter]&lt;/code&gt; or &lt;code&gt;[2]&lt;/code&gt; prompt.&lt;/strong&gt; The asset-storage question offers &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;2&lt;/code&gt;, not &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;n&lt;/code&gt;. Both &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;yes&lt;/code&gt; were rejected before I typed &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pressing Enter on a prompt with empty brackets.&lt;/strong&gt; The &lt;code&gt;Working Data Local Storage Directory (required) []&lt;/code&gt; prompt has no default. Pressing Enter gave me "is required" and sent me back to the previous question. Type the path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accepting the default installation directory.&lt;/strong&gt; The default is under &lt;code&gt;/home/ec2-user&lt;/code&gt;, on node 1's local disk. A Molecule installed there works on node 1 and is invisible to node 2. The installation directory has to be on the shared mount.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next up
&lt;/h2&gt;

&lt;p&gt;In Part 2 we make the two nodes find each other with unicast, deal with the cluster problems I ran into, and open the web server port. Part 2 is linked at the end of this post once it is live.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>boomi</category>
      <category>ec2</category>
      <category>efs</category>
    </item>
  </channel>
</rss>
