Tutorial: Setting up a private subnet on AWS

Nils Ziehn
Mar 10, 2019 · 9 min read

For growing companies that offer services over the internet, there often comes the point where they need to distinguish between what services they offer to the public and what services to offer only internally.

Especially when you’re building a micro-service infrastructure, you want that most services can talk to each other, but not that the entire internet can talk to them. The most typical way of doing this, is to ask the user for some kind of authentication, e.g. a password. The first downsides that come with passwords is that you have to management (e.g. when employees are joining and leaving your company) and they don’t protect you from attacks like DDoS.

One solution that I would like to talk about here are private subnets:

Image for post
Image for post

You want some of your machines/services to be accessible from the public internet, e.g. your web servers, but want to shield other machines, e.g. databases form direct web access. Often it is helpful to allow services in the private subnet to “call-out”, but not to allow systems from the outside to “call in” (see the red vs green-dashed arrows in the depiction above).

Your account

Since this is a tutorial on setting up a private subnet on AWS, you should be logged into the AWS user interface. I will assume that you have broad access rights in your account (e.g. you’re an administrator) and will not go into detail which rights you will need.

If you are worried that you might break a running system that already is in your account you have 2 choices. Create a new account for this tutorial or pick a region where there are no production systems running (the latter is obviously much less work!)

Pick a region

In AWS there are many different regions and probably you have already decided for one. If not here are my 2 cents on this topic:

  1. You should pick a region that is close to your customers and therefore reduce latency

Creating new subnets

We will create 2 new subnets in this tutorial one public, one private. If you have a completely new AWS account, you could also just use the already existing subnet as the public subnet, but I will assume you create a new one.

In the AWS Web UI go to ServicesVPC (virtual private cloud)Subnets

  1. Click the blue Create Subnet button at the top of the page

Done! You now have 2 fresh subnets.

Creating a NAT

In order to allow services from your private subnet to talk to the internet, we need a Network Address Translation device. You could use an EC2 instance for this, but let’s use a preconfigured one from AWS:

In the AWS Web UI go to ServicesVPCNAT Gateways

  1. Click Create NAT Gateway

Routing your traffic

Now in the last step of the setup process, we need to route where the traffic is going. For this we need to go to: ServicesVPCRoute Tables

  1. You can reuse the existing one, but in order to reduce the risk of breaking a running application, let’s create a new one. Click Create Route Table .

Done! If you have a normal AWS account without making any changes in this section you’re done. To be save, let’s make sure that your public subnet also knows how to talk to the internet:

  1. In the overview screen on the Route Table page find the route table where the column Main is equal to Yes and select it.


You are now finished setting everything up — but since there can always be a problem, let’s make sure it works by testing it!

Starting a server in our private subnet

Let’s start a new EC2 machine in our private subnet, by going to: ServicesEC2Instances

  1. Click Launch Instance

We have now started a server in the private subnet — but we should not be able to connect to it via SSH directly, since the private subnet is… private.

In order to connect to it, we must launch another instance in the public subnet. Go through the same steps as launching the private machine, except for selecting the public subnet in step (4)!

Now you should have 2 instances running — 1 private and 1 public. The public one should also have a public ip and dns. This public server is typically called bastion and I will refer to it as such in the next steps.

To connect to your private machine, we first have to ssh into the bastion:


After typing the above 2 commands into your terminal, you should now be logged in on your private server. To validate that also the outgoing internet connection is working, just type ping into the terminal and should see output like this:

64 bytes from icmp_seq=34 ttl=108 time=12.6 ms
64 bytes from icmp_seq=35 ttl=108 time=12.6 ms
64 bytes from icmp_seq=36 ttl=108 time=12.6 ms
64 bytes from icmp_seq=37 ttl=108 time=12.5 ms
64 bytes from icmp_seq=38 ttl=108 time=12.5 ms
64 bytes from icmp_seq=39 ttl=108 time=12.5 ms

I hope it does! → if yes, we are done! 🎉🍾

otherwise I’m very sorry and please go back though the steps above to check what may have gone wrong.


  1. We created 2 subnets — a public and a private one

Next Steps

Obviously this is only the start of the journey, but where can you go from here?

  1. If you want to connect to these private subnets from your office wifi, please go through this explanation: AWS Docs
    I will probably also clarify this in another Post, but until then, you can use the link above.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store