Securing your CoreOS Container


· · · ·

f you are reading this, you probably know about CoreOS and what it does. And you may be looking for a way to improve the security of your CoreOS container.

There’s good news: You can. The beauty of CoreOS is that it is super lightweight and customizable. Anyone can use CoreOS to run what they want, without fluff.

In this post, I’ll demonstrate how to use the customizability of CoreOS to improve security.


Let’s imagine that we have an application that contains multiple microservices inside it, working in sync. The application heavily relies on the data that is being sent in and out to a third-party server which we cannot control.

Our target here is to create and execute a strategy that will allow us to stick to a tight security protocol, without any loose ends. It will follow just two broad checkpoints:

• Communicate only on ports that are absolutely necessary.
• Make all the microservices work in sync, without exposing them to the Internet.

We are going to achieve this strategy with three steps to run a secure CoreOS container in a production environment.

1. Secure iptables
2. Enforce etcd
3. Use reverse proxy app servers (like NGINX)

Before we jump in, please familiarize yourself with configuring the cloud-config file.

Secure Iptables

This is the first and crucial step towards securing your CoreOS containers. Here’s what we will do in this step:

• Reject all incoming traffic by default
• Listen and allow traffic on ports that are absolutely necessary
• Allow freely moving traffic to the outside world from the container

This way, we control what goes in and comes out of the containers using traditional Iptables. The following are the code snippets for these three steps. These go into your cloud-config YAML file.

Let’s start by blocking all the incoming traffic by default. This piece of code will go under the content: section of the write_files: block in your cloud-config YAML:

This enforces the container to drop all the incoming traffic by default, which is an extreme solution to a problem. In the next step, we will create a “whitelist” of ports that can listen to the outside world.

For our scenario, these are the ports that we need:

• Port 80 for allowing HTTP traffic for the end user
• Port 443 for allowing HTTPS traffic for the end user
• Port 3000 to allow incoming traffic from the third-party API servers
• Port 3001 to allow incoming traffic from the third-party API servers

Here’s the general syntax that allows this (assuming that everything is TCP traffic):

So in our case, this would be:

There’s a lot more you can do with your cloud-config YAML. Head over to the docs to find out!

Now that we have restricted incoming traffic, we need to shift our focus to the outgoing traffic from the container. Let’s now set the container to access any port it wants by adding this to our cloud-config file’s content: section:

Finally, don’t forget to verify if everything is proper by running:

With this, we’ve secured the traffic flow that goes in and out of the container!

Enforce etcd

If you are not fully aware of what etcd is, you can learn more about it here.

One of the first things to be noticed with etcd is the use of HTTP by default for transferring data. This is not a secure option, so we’re going to force etcd to make use of TLS/SSL to send and receive traffic in and out of the container.

Here are the steps we would take to achieve this:

1. Get a new discovery URL from

2. Add this to the cloud-config YAML:

This will route all traffic through TLS/SSL. But there’s more to this story. We now need to generate the SSL certificates and add them to our environment before we push this live.

Use the code block below, after you generate the SSL certificates for your container:


Use reverse proxy app servers

The final step in our strategy to secure our CoreOS container is making sure pods are securely tucked inside our container—without exposing any traffic to the outside world. This is going to be critical, since some pods need access to the Internet.

To make sure all the pods are communicating with each other without having to rely on an external source, we’re going to place an application server right in front of them. This way, whenever a pod wants to communicate, all traffic is routed through an app server (NGINX in our case). The app server handles which port to utilize for which traffic. So here, each namespace will have its own listening port with which it will be able to communicate to the appropriate pod.

To sum things up, here’s what we did:

1. Created an Iptable configuration in your cloud-config to control the traffic that flows in and out of the container

2. Enforced etcd to utilize TLS/SSL with your certificates to transfer data only via secure channel

3. Used a reverse proxy like NGINX or gogeta to route inter-pod communication traffic in real-time without having to restart a process

Do you think you can beat this Sweet post?

If so, you may have what it takes to become a Sweetcode contributor... Learn More.

Swaathi Kakarla is the co-founder and CTO at Skcript She enjoys talking and writing about code efficiency, performance and startups. In her free time she finds solace in yoga, bicycling and contributing to open source.


Click on a tab to select how you'd like to leave your comment

Leave a Comment

Your email address will not be published. Required fields are marked *