I wanted to share a project I’ve been working on to get feedback and see if anyone is interested to also work on the project. My goal is to take the IT friction out of starting an OpenMRS instance. Thinking about the end user that is running a clinic and wants to get started with a EMR, may not want to have to learn about docker. For instance if someone wants to start a blog they either go to WordPress.com and start a free site vs going to WordPress.org to download the source code as a zip. My desire is to create a similar similar site for the hosting of OpenMRS instances (including multiple distributions/flavors). I was tempted to create a openmrs.com style site; but there are obvious trademark issues, so I started with hostedehr.org. End users are able to self enroll and provision subdomain sites so ckwc.hostedehr.org would be for my organization (Connecting Kids With Care) and as long as your name is not taken, users can create the subdomain and invite users to the OpenMRS instance.
Before you run off to visit hostedehr.org, yes there is a site there, and it somewhat works, but there is still work to be done before it’s ready to turn over to end users. I wanted to describe the architecture and get feedback.
First the site itself is written in node-js and is connected to a simple backend database (in mysql) to validate user’s e-mail addresses and keep track of who is the admin on which subdomain. Each OpenMRS instance is created as a separate database on a single “powerful” Amazon RDS server (but we can upgrade this to an even better server as more and more users host installations on the site). The OpenMRS instances also served on a on another single “powerful” Amazon server (Memory Optimized) as each instance needs at least 600 MB when it’s running. I started with the r5d.xlarge because it has 32 GB of memory and a 150 GB local drive that can be provisioned as a swap file to give it 182 GB of addressable memory. The application server itself is just running docker so each OpenMRS instance can actually run a different OpenMRS distribution / docker image. The application data for each OpenMRS instance is mapped to a directory to an NFS mount point on the docker server. It’s using Amazon Elastic File System (EFS) so it starts out with 8 petabytes (1024 TB) of storage space and will grow automatically. The docker server is then providing the security so that each instance can only have access to their files. With the data on the NFS drive we can actually destroy the docker server and rebuilt it from an automated script, so it doesn’t really become a “single point of failure”.
Now with all these servers running on docker they all can’t have port 8080, so we also have HAProxy running on the box to run as an internal proxy server to route the HTTP requests to the proper docker instance. It also provides us with a unique feature to be able to start and stop servers based on inactivity. The HAProxy is also running the SSL proxy to server the wildcard *.hostedehr.org SSL certificate, so clinics don’t have to worry about installing SSL and renewing certificates, etc. So the HAProxy queries the docker server to see which subdomains are running on which ports and makes the config file to route the subdomains to the proper docker server.
For all the servers that are not running, it routes the URL to a “special” node-js app we have running on the box. When that app get’s a URL request it then calls the docker API to start the appropriate instance (or create it on first run), then wait for server to startup. I’m not sure if we should increase the timeout on the original request to wait for the server to come up, or just return a loading page with an HTML refresh for the root url or the login, and return a 503 service unavailable for web service requests. In any case when the server comes up the HAProxy sees it and puts it back in config as a regular instance and the “special” node-js app is no longer proxing the requests.
Now the server is a specific size so there is a limit to the number of instances that can run on one box, HAProxy has a stats interface so we can tell when an instance hasn’t received any HTTP requests in some number of days, so we can then stop the instance in an automated fashion. All the data will still be saved to MySQL and the NFS mount, so as soon as a web request is made, the server will start itself back up (using the process described above). This allows us to only have the instances running that are actually in use, vs the 100s that may have been created at one point and not used. But we have all the data saved incase the end user decides to try keeping electronic records again.
Finally if there was ever a point where we upgraded the to the point of r5d.24xlarge which is 96 logical processors on 48 physical cores with 768 GB of memory, we could always create multiple docker servers and have the HAProxy operate over multiple hosts.
The code is still a work in progress, but I have each part functional to some degree and plan to fully open source it after it is functional.
So- does anyone see any obvious problems? Do we think this would be a useful service to have an option for people who would want OpenMRS as a more of SaaS solution than a pure software project. My non-profit (Connecting Kids With Care) is fine to cover the hosting costs for this project; and sign a patient confidentiality agreement for any organization that would need one.