1.15.8 — Stable outbound IPs for provider allowlists
Editorial identity incomplete
2026-08-20
Providers that require IP allowlisting need a fixed set of addresses, and a fleet whose nodes take whatever public IP AWS hands them cannot supply one. This release adds a Stable outbound IPs control to the Admin fleet screen: one confirmed action gives every registered node a permanent Elastic IP, verifies the association against AWS before reporting success, and shows the canonical list to hand vendors. The policy is durable, so a node added later gets its address before it serves traffic. Disabling is deliberate and recoverable — it detaches but keeps the reservations, so an accidental click cannot discard addresses a vendor has already allowlisted. Installs with no load balancer, which this control does not manage, now get a read-only list of the addresses their nodes already hold instead of an empty panel. Also: deploys no longer risk installing a stale framework version from a cached PyPI catalog, and three admin-portal fixes.
Added
- Stable outbound IPs — an Admin fleet control that gives every registered application node a permanent Elastic IP, so third-party providers can allowlist a fixed set of addresses. The panel shows the canonical address list to give vendors.
enable_stable_ipsanddisable_stable_ipsactions onPOST /api/aws/capacity/apply, behind the same gate as the rest of capacity: a literal superuser withmanage_aws, an interactive session, fresh authentication, and a typed confirmation.AWS_STABLE_OUTBOUND_IPS, a protected system setting holding the policy. It is durable, soadd_nodeattaches a stable address to a new node before registering it behind the balancer.- An
egressblock on the capacity report: the vendor allowlist, reserved addresses, how many enabling would allocate, and per-nodepublic_ipandstable_ip. - A read-only
egress.fallback_attachedlist for installs with no load balancer, so a single-node estate still shows the address to give providers instead of an empty panel. stable_node_ipsin provisioning (env-file key and--stable-node-ips), which keeps per-node Elastic IPs when a load balancer is also built.- Elastic IP primitives on the EC2 helper:
address_map,allocate_address,associate_address,disassociate_address,tag_resources.
Changed
- Fleet-wide capacity actions now ignore a caller-supplied
resource; the typedconfirm_resourceecho is always the action word. A custom caller that sent its own resource foradd_nodeand echoed that value must now echoadd_node. add_nodegains anaddressingphase when the policy is on. It fails closed: a node that cannot get its stable address is left running and unregistered rather than serving from an address no provider has allowlisted.- Admin tab titles read
<page> - <installation>instead of a static "MOJO Admin", so several open tabs are tellable apart. - The GitHub workflow file and the reveal-once deploy secret render as read-only code blocks instead of bare form textareas.
Fixed
- Deploys and first-boot installs refresh the django-mojo catalog entry before installing. pip 26.2 began honoring PyPI's Simple API cache lifetime, so a framework version published moments earlier could be missing from a cached catalog response even though its wheel was already live — a deploy would then install the previous version and report success. Older pip releases, which always revalidate, are unaffected and skip the unsupported option.
- Admin portal list rows navigate when clicked anywhere on the row, not only from the small link at the far right.
Upgrade notes
- The stable-outbound control needs four more IAM actions:
ec2:DescribeAddresses,ec2:AllocateAddress,ec2:AssociateAddress,ec2:DisassociateAddress. Without them the section reports the denial and offers no controls rather than showing an empty address list. - Enabling adds no monthly cost while the addresses stay attached — an Elastic IP replaces the identical charge for the node's auto-assigned IPv4. The cost appears on disable, where each kept reservation bills alongside the node's new auto-assigned address.
- Disabling leaves each node without a public address for up to several minutes, and indefinitely if its network interface was not created with auto-assign. Outbound provider calls fail during that window.
- Ownership tags are not scoped by project or environment: two django-mojo installations sharing one AWS account and region can consume each other's reserved addresses. Run one installation per account and region, or do not rely on reserve-and-re-enable across them.
- The catalog-refresh fix ships in this release, so the deploy that installs 1.15.8 still runs the old behavior; the protection applies from the next deploy onward.