Resources

Build the multi-tier application design

Published on: October 15, 2026

This page lists everything the multi-tier application design needs and how to configure each part. Build it with the tool you prefer: the Control Panel, the API, upctl or Terraform. Each step ends with a check that confirms the step worked.

Prerequisites

  • An SSH key pair. The same public key goes on all four servers.
  • The public IP address you connect from, or its range. Step 6 allows SSH to the admin host from this address only.
  • Free ranges: 172.16.1.0/24, 172.16.2.0/24 and 172.16.3.0/24 must not be in use in your account, including in other zones. To use other ranges, change them in steps 1 and 3. See Private ranges outside 10.0.0.0/8.

What the build creates

The build creates these resources. See Products used for what each one does in the design.

  • 1 SDN Router
  • 3 SDN Private Networks: front-net, restricted-net and admin-net
  • 1 NAT Gateway
  • 3 SDN Firewall rulesets: front, restricted and admin
  • 4 Cloud Servers: front-01, front-02, restricted-01 and admin-host
  • 1 Managed Load Balancer

These are the example's counts. To use a different number of servers, see Adapt the design and the notes in steps 4, 5 and 7.

The numbers on the diagram show which step creates each part.

Build map of the multi-tier application design: step 1 creates the router and the three networks, step 2 the NAT Gateway, steps 3 and 5 the SDN Firewall on each server, step 4 the servers, step 6 the Public & Utility Firewall on each server, and step 7 the load balancer.

1. Create the router and networks

Create one SDN Router and three SDN Private Networks attached to it. Set the DNS servers before you create any servers, so the first DHCP lease already carries them.

All three networks are attached to the router, with DHCP on, DNS servers 94.237.127.9 and 94.237.40.9, and route auto-population off.

NetworkRangeRoutes handed out
front-net172.16.1.0/24Default route
restricted-net172.16.2.0/24Default route
admin-net172.16.3.0/24No default route. Static routes to 172.16.1.0/24 and 172.16.2.0/24

Make sure:

  • The DHCP default route is off on admin-net. The admin host's default route goes through its public interface. See Admin host routes.
  • Route auto-population is off on admin-net. The Control Panel switches it on by default.
  • Both DNS servers are set on every network. Without them, the tier servers cannot resolve names. See DNS servers.

API: create router, create SDN network
upctl: create router, create SDN network
Terraform resources: router, network

Check: each network shows the router, both DNS servers and its default route setting, and admin-net lists the two static routes.

2. Create the NAT Gateway

Create a NAT Gateway with the NAT feature, attached to the router. It gives both tiers one shared path out to the internet. Any plan works for the design. The examples use essentials.

Make sure:

  • The gateway reaches the running state before you test outbound connections. This usually takes several minutes and can take longer.

API: create NAT Gateway
Terraform resources: gateway

Check: the gateway is running and has a public IP address, and the router has a static route of type service for 0.0.0.0/0. See NAT Gateway route.

3. Create the firewall rulesets

Create one SDN Firewall ruleset for each tier and one for the admin host. Every ruleset is stateful, and every rule accepts incoming IPv4 TCP traffic. Replies to allowed connections need no rules of their own. See Isolation comes from firewall rules.

RulesetPortFromPurpose
front22admin-netSSH from the admin host
restricted22admin-netSSH from the admin host
restricted5432front-netApplication traffic from the front tier
admin22admin-netSSH within admin-net only

The sources are the networks' ranges from step 1. Port 80 on the front ruleset, from the load balancer, is added in step 7, once its addresses are known.

Make sure:

  • Each ruleset is created with "stateful": true. The API returns a 400 error when the field is missing or set to false.
  • Each rule is enabled. Through the API, pass "enabled": true on every rule. A single POST to /firewall-ruleset/{uuid}/rule creates a rule disabled, while a bulk PUT to the same path creates it enabled.
  • Every ruleset has at least one rule before you attach it.

API: create ruleset, add rules
Terraform resources: ruleset

Check: read each ruleset back and compare every rule with the table above. Servers enforce exactly what is configured.

4. Create the servers

Create the three tier servers without a public IP address, and the admin host with one. Every server has a utility network interface, your SSH key and the same operating system. The examples use the PREMIUM-1xCPU-1GB plan and Ubuntu Server 24.04.

ServerPrivate networkPublic IP
front-01front-netNo
front-02front-netNo
restricted-01restricted-netNo
admin-hostadmin-netYes

Make sure:

  • The networks have their DNS servers set before you create the servers. See step 1.
  • You note each server's private address. Servers get their addresses by DHCP in the order they start, so front-01 and front-02 can end up with either of 172.16.1.2 and 172.16.1.3. Step 7 needs the front servers' addresses.

For a different number of front servers, create each one on front-net in the same way.

API: create server
upctl: create server
Terraform resources: server

Check: each server is started and has the interfaces in the table, and the tier servers have no public interface.

5. Attach the rulesets

Attach each server's ruleset and switch on its private firewall. With the private firewall on, the default actions are drop for incoming traffic and accept for outgoing traffic.

ServerRuleset
front-01front
front-02front
restricted-01restricted
admin-hostadmin

Make sure:

  • The private firewall is on for every server. Without it, an attached ruleset filters nothing. Terraform attaches rulesets but cannot switch the private firewall on, so do that in the Control Panel or through the API.

For a different number of front servers, attach the front ruleset to each of them.

API: attach ruleset, switch on the private firewall
Terraform resources: ruleset attachment

Check: on each server, the ruleset's applied_version matches its version, for example with GET /1.3/server/{uuid}/firewall_ruleset_relationships/private. The rollout is asynchronous. The first rollout to a new server can take a few minutes.

6. Close the utility network and open SSH on the admin host

Switch on the Public & Utility Firewall on every server, so that no other server in your account can reach them over the utility network. Rules apply in order, and each server ends with a rule that drops all other incoming traffic. See Keep the utility network closed.

The tier servers, front-01, front-02 and restricted-01, each get two rules: an accept rule for all outgoing traffic, then a drop rule for all incoming traffic.

The admin host gets six:

PositionRulePurpose
1In, TCP 22 from your address, acceptSSH
2In, UDP from 94.237.127.9 port 53, acceptDNS replies
3In, UDP from 94.237.40.9 port 53, acceptDNS replies
4In, UDP from port 123 to ports 1024–65535, acceptNTP replies
5Out, all, acceptOutgoing traffic
6In, all, dropEverything else

All rules are IPv4. To allow a range for SSH instead of one address, use the range as the source.

Make sure:

  • The firewall is switched on for every server. Switching it on can fail while setting the rules succeeds, and a server with its firewall off accepts traffic on the utility network.
  • Every rule is in place. A failed request can leave a rule missing while the others succeed.
Note

The admin host accepts no incoming ICMP, so ping and traceroute from the admin host get no replies. To use them, add an accept rule for incoming ICMP above the final drop rule.

API: set firewall rules, switch on the firewall
upctl: add firewall rule, switch on the firewall
Terraform resources: firewall rules, server

Check: every server shows its firewall as on, with 2 rules on the tier servers and 6 on the admin host. The rules can take a minute or two to apply.

7. Create the load balancer

Create a Managed Load Balancer with a public frontend on port 80 and a backend that forwards to both front servers on front-net.

SettingValue
PlanAny. The examples use development.
NetworksA public IPv4 network, and front-net
FrontendPort 80, HTTP mode, on the public network
BackendStatic members on port 80: the private addresses of front-01 and front-02

For a different number of front servers, add one member for each.

API: create load balancer, read its addresses
Terraform resources: load balancer, frontend, backend, member

Check: the load balancer is running. This takes several minutes.

Allow the load balancer through the front ruleset

The load balancer's addresses on front-net are only known once it is running. It holds two: its private frontend address, marked "listen": true, and its node address, marked "listen": false. Your servers see requests and health checks from the node address. See Load balancer addresses.

Add one rule to the front ruleset for each address:

PortFromPurpose
80The node address, as /32Requests and health checks
80The frontend address, as /32The load balancer's private frontend

Make both changes in one request, then read the ruleset back. The new version reaches both front servers on its own within a minute or two. To roll it out at once, attach the ruleset to one of the front servers. See Change rules later.

Make sure:

  • The rules name the load balancer's addresses, not the whole of front-net. A front-net source would let any other server on front-net reach port 80.

API: add rules, attach ruleset
Terraform resources: ruleset, ruleset attachment

Check: both front servers report the ruleset's new version as applied. Once your application listens on port 80, the load balancer shows both members as up.

8. Deploy your application and verify

Install your application on the tier servers: the front tier serves port 80 and the restricted tier listens on port 5432. Until something listens on port 80, the load balancer's health checks mark the front servers as down.

Reach the tier servers through the admin host, as described in Reach the servers. For example:

ssh -J root@ADMIN_PUBLIC_IP [email protected]

Then run the tests in Verify it works.

Change rules later

A saved change to a ruleset reaches every server that uses it on its own, usually within a minute or two. To change rules safely:

  1. Make the whole change in one request. Each saved change goes live as soon as it rolls out, so changing related rules one at a time can leave the servers with a half-finished set for a while. Replacing the ruleset's rules in one request avoids that.
  2. Read the ruleset back and check every rule, because servers enforce exactly what is configured.
  3. Check that each server's applied_version matches the ruleset's version. To roll the change out at once instead of waiting, attach the ruleset to any one of its servers. One attach rolls the current version out to every server that uses the ruleset.
Contributed by: Samir Haliru

Can't find what you're looking for?

For more help you can contact our awesome 24/7 support team