EventStore on Azure and Ubuntu - it's a piece of cake! #2

In the previous post we installed and started an EventStore instance. To be honest it's possible to work with it from this point with no problem. However, there're things, which I'd like to focus on a bit more. 

EventStore structure and configuration

How EventStore is structured on Linux differs somehow when compared with the Windows version. Default directories for it can be found here and I strongly recommend to read so there's no confusion. Important thing is the configuration file stored in /etc/eventstore/ and being read-only. If you'd like to edit it(e.g. to change external IP used by ES), here's the easiest way to do it using vi:

kamz@Ubuntu-EventStore:/$ cd etc/eventstore
kamz@Ubuntu-EventStore:/etc/eventstore$ sudo vi eventstore.conf

To edit a file simple press i. Once you're done with your changes, press Escape and :wq to save them and exit. The reason we're using sudo here is to force changes on this locked file. More detailed instruction how to use vi can be found here.

Accessing ES locally

Well, we have EventStore configured and running. What if we'd like to access it via browser. Going to your_vm_ip:2113 is not working just out of the box. Honestly, there're two possible ways:

  • port tunneling
  • using RDP

Both are quite easy to get and configure.

Using port tunneling

For the purpose of port tunneling I'm using PuTTY. The instruction is pretty simple - tunnel target :2113 port to the local port of your choice. How to do it is described here and here. Once you're done, simply go to e.g. in your browser. It should connect to the VM and open EventStore screen.

Using RDP

If you don't want to allow external access to your EventStore instance you can use RDP and manage it from within your virtual machine. If you prefer this way, make sure you are familiar with this instruction how to connect from Windows to Ubuntu using xRDP. One additional thing is needed here - since a VM in Azure is defended by network security group, which denies whole traffic, we have to allow inbound access using RDP. Here's what you have to do:

  • Go to your resource group and find Network security group resource related to your VM
  • Go to Inbound security rules
  • Add a new security rule using port TCP 3389
  • Save a new configuration

Now go to your RDP client and pass public IP of your Ubuntu VM. You should be able to see xRDP screen. Just use credentials you're using to connect to the VM and that's all - you've accessed Ubuntu's desktop. Open a browser window and go to Now you can log in and manage EventStore as you wish.

In the next post we'll try to create and connect ES cluster using multiple Ubuntu machines.

Azure Functions proxy - overview

Azure Functions are great for building a bigger solution, which contains smaller services representing logical separation of different responsibilities. There's however a problem if you'd like to encapsulate logic what can be accessed and which HTTP methods are allowed. Additional problem arises if you're going to somehow avoid passing function keys to each application consuming or using your function. Fortunately Microsoft has just published a public preview of Azure Functions proxy - a very simple yet powerful concept, which allows you to overcome mentioned problems and make your functions to even more fun to work with.

Special thanks to @marekgrabarz for making me aware of this feature and encouraging to write some words about it.

Hide your functions

Actually to take advantage of this feature there's one requirement - a Function app. If you don't have one, quickly go to Azure Portal and create one!

Once you have your Function app created, simply click on it. You will see a Function app screen with a new feature added:

as you can see it's still in preview so it may be still a bit unstable, but it won't bother us in this moment. To be actually able to use proxies, you have to enable them. Go to the Function app settings and turn proxies on in the Proxies(preview) section. Now we can do some real work!

Create a simple function, for which we'll create a proxy. For the testing scenario I created a following function:

using System.Net;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
    return req.CreateResponse(HttpStatusCode.OK, "You called ProxiedFunction1!");

now with a function created, we can create a proxy for it. To do so, follow below steps:

  1. Click on the New proxy button
  2. Give it an unique name and template(I used proxy/function1)
  3. For Backend URL you have to use any URL you'd like to forward a request to(in my case it was my function Function URL with the key)
  4. Simply click a Create button

Now try to access your proxy by going to https://{your_function_app){template} - if you used the same function as me, you'll get "You called ProxiedFunction1!" as a response. You can create as many proxies as you want and connect them to the resource of your choice(it can be a function, a web app or other endpoint accessible with HTTP). Your possibilities are unlimited here.

Parameters and application settings

You can also create a proxy in more generic way simply using parameter in your route. Consider following example:

Whatever you pass as a {function} parameter, it will be routed to the ProxiedFunction1 function

Additionally you can reference application settings what can be helpful if you're searching for more flexibility. Let's create another proxy like this:

What is more, I added MY_SECRET key with a value of a5gYhj87Hgsta to the app settings. How when I try to access proxy, I can go to and get desired results. If a secret doesn't match, you'll get HTTP 404 instead.


Currently alternative to this kind of proxy is using Application Gateway or API Management. The advantage of this solution is its simplicity and cost related - since Azure Functions are free for the first 1M requests*, it's possible that in the beginning you will be running this solution for free.


Currently proxies for Azure Functions are limited in functionality by the preview version. Fortunately the team responsible for this component promised many enhancements implemented soon - can't wait to test them :)

* considering duplicated request when a proxy rewrites it, depending on how proxy is treated in pricing, it can be lowered to 0.5M free requests