Multiple database.yml but one application - ruby-on-rails

The Setup
I have a Ruby on Rails application that I manage from a sysadmin perspective. This application in installed on a pool of load balanced application servers. These application servers a running Apache 2 and Passenger 3.0. The application files are stored in a ramdisk because IO on the application servers are ridiculously slow.
Database configuration
The backend database is stored on a pair of MySQL clusters (active/passive). Several clients use our application and each have a separate MySQL database.
Currently, we have X copies of the application (X being the number of clients). The difference between each copy is just the database.yml. Since we are using ramdisks, "disk" space is expensive and I'm thinking that there has to be a better way to solve this problem.
Potential solutions
Ideally, I would like to be able to specify the database.yml in the Apache virtualhost but that doesn't look possible with my current setup. The database.yml would be attached to the domain name accessed. If there is a way to do this, it would really be really fantastic.
Another approach would be to make a whole lot of symbolic links instead of storing copies of the application. I guess that doesn't sound too bad but I don't really like this solution.
How would you approach this problem and solve it ?
If you need more information, just ask and I'll be happy to answer. I'm not so sure whether this belongs to SF or SO but smells more SO to me.

As Mladen said, you can use RailsEnv. It's pretty much the ideal solution to your problem, it's intended to be used that way. Just don't forget to set different PassengerAppGroupName values for each env because Phusion Passenger normally uniquely identifies an application based on its path only. Also don't forget to make the config/initializers/[env name].rb file.

Perhaps you can use the same database.yml, but use different environments? You should be able to set different Rails environments using different RailsEnv parameter in your virtualhost setting.

Related

How to deploy my Rails app to a shared host

I have been chipping away at this for the last couple of days but it has become quite frustrating. My web host is "JustHost" and I have a shared hosting service. I have found this translates directly to "strips you of all privileges," when it comes to trying to set up the deployment on the server.
I thought I had found some really good tutorials that might help me to get my environment set up (I tried to Follow Rob McLarty's blogs on How to setup a Production Server and How to Deploy a Rails App as best as I could). The problem that I found is that I couldn't/didn't need to install any of the things recommended, and when it came time to try to set things up I didn't have permission over the files that were recommended to modify or I didn't have permission to use the commands that were needed.
Naturally I can see why this would be important on a shared host. It would be silly if each individual on the host could restart an apache server willy nilly.
Regardless, I have found this to be the problem with most of the research into getting this deployment up and running. Simply put, most of the things that are recommended I don't have permission to access.
Does anyone know how to setup a deployment on an environment that is so restrictive? Even some resources, or a simple "you are thinking about this way too hard" to point me in the right direction would be really really helpful.
I highly recommend OpenShift as a platform for deploying your rails app on a shared environment. It gives you the option to start for free with a small amount of resources in the server and gives you the ability of starting up everything you need at first like relational or NoSQL databases, loadbalancers, cache, etc.
Heroku is a simple setup formula, For a shared host ROR Deployment Found a good reference : REFERENCE LINK this will help to deploy ROR App on a shared host.(some modules may not be allowed on a shared server environment. You may have to go for a VPS to meet all the requirements).

Rails turn feature on/off on the fly

I am a newbie to rails. I have used feature flags when i was in java world. I found that there are a few gems in rails (rollout and others) for doing it. But how to turn a feature on/off on the fly in rails.
In java we can use a mbean to turn features on the fly. Any idea or pointers on how to do this? I dont want to do a server restart on my machines once a code is deployed.
Unless you have a way of communicating to all your processes at once, which is non-standard, then you'd need some kind of centralized configuration system. Redis is a really fast key-value store which works well for this, but a database can also do the job if a few milliseconds per page load to figure out which features to enable isn't a big deal.
If you're only deploying on a single server, you could also use a static YAML or JSON configuration file that's read before each request is processed. The overhead of this is almost immeasurable.

Multiple redmine instances best practices

I'm studying the best way to have multiple redmine instances in the same server (basically I need a database for each redmine group).
Until now I have 2 options:
Deploy a redmine instance for each group
Deploy one redmine instance with multiple database
I really don't know what is the best practice in this situation, I've seen some people doing this in both ways.
I've tested the deployment of multiple redmines (3 instances) with nginx and passenger. It worked well but I think with a lot of instances it may not be feasible. Each app needs around 100mb of RAM, and with the increasing of requests it tends to allocate more processes to the app. This scenario seems bad if we had a lot of instances.
The option 2 seems reasonable, I think I can implement that with rails environments. But I think that there are some security problems related with sessions (I think a user of site A is allowed to make actions on site B after an authentication in A).
There are any good practice for this situation? What's the best practice to take in this situation?
Other requirement related with this is: we must be able to create or shut down a redmine instance without interrupt the others (e.g. we should avoid server restarts..).
Thanks for any advice and sorry for my english!
Edit:
My solution:
I used a redmine instance for each group. I used nginx+unicorn to manage each instance independently (because passenger didn't allow me to manage each instance independently).
The two options are not so different after all. The only difference is that in option 2, you only have one copy of the code on your disk.
In any case, you still need to run different worker processes for each instance, as Redmine (and generally most Rails apps) doesn't support database switching for each request and some data regarding a certain environment are cached in process.
Given that, there is not really much incentive to share even the codebase as it would require certain monkey patches and symlink-magic to allow the proper initialization for the intentional configuration differences (database and email configuration, paths to uploaded files, ...). The Debian package does that but it's (in my eyes) rather brittle and leads to a rather non-standard system.
But to stress again: even if you share the same code on the disk between instances, you can't share the running worker processes.
Running multiple instances from the same codebase is not officially supported by Redmine. However, Debian/Ubuntu packages seem to support such approach... See:
Multiple instances of redmine on Debian squeeze
So, generally:
If you use Debian/Ubuntu go with option #2
Otherwise go with #1
Rolling forward a couple of years, and you might now want to consider a third option of using docker containers for each of your redmine instances.
I've been using https://github.com/sameersbn/docker-redmine.git , and have been quite happy with it except that it doesn't yet support handling of incoming mail for creating and commenting on tickets.

Set up staging and production environmets and minimizing downtime on simple hosting

I have an ASP.NET MVC 3 application, WouldBeBetter.com, currently hosted on Windows Azure. I have an Introductory Special subscription package that was free for several months but was surprised at how expensive it has turned out to be (€150 p/m on average!) now that I have started paying for it. That is just way too much money for a site that is not going to generate money any time soon so I've decided to move to a regular hosting provider (DiscountASP.Net).
One of the things I'll truly miss though, is the separated Staging and Production environments Azure provides, along with the zero-downtime environment swap.
My question is, how could I go about "simulating" a staging environment while hosting on a traditional provider? And what is my best shot at minimizing downtime on new deployments?
Thanks.
UPDATE: I chose the answer I chose not because I consider it the best method, but because it is what makes the most sense for me at this point.
Before abandoning Windows Azure, there are several cost-saving things you can do to lower your monthly bill. For instance:
If you have both a Web role and a Worker role, merge the two. Take your background processing, queue processing, etc. and run them in your Web role (do your time-consuming startup in OnStart(), then just add a Run() override to call queue-processing, etc.
Consider the new Extra Small instance, which costs just under half of a Small instance
Delete your Staging deployment after you're confident your production code is running ok. Keep the cspkg handy though, in blob storage, so that you could always re-deploy it.
I use DiscountASP myself. It's pretty basic hosting for sure, a little behind the times. But I have found just creating a subdirectory and publishing my beta/test/whatever versions there works pretty well. It's not fancy or pretty, but does get the job done.
In order to do this you need to create the subdirectory first, then go into the control panel and tell DASP that directory is an application. Then you also have to consider that directory's web.config is going to be a combination of its own and the parent one. You also have to consider robots.txt for this subdirectory and protecting it in general from nosy people.
You could probably pull this off with subdomains too, depending on how your domain is set up.
Another option: appharbor? They have a free plan. If you can stay within the confines of their free plan, it might work well (I've never used them, currently interested in trying them though)
1) Get an automated deployment tool. There are plenty of free/open-source ones that million/billion dollar companies actually use for their production environments.
2) Get a second hosting package identical to the first. Use it as your staging, then just redeploy to production when staging passes.

Big things to do when deploying a rails app

In the question What little things do I need to do before deploying a rails application I am getting a lot of answers that are bigger than "little things". So this question is slighly different.
What reasonably major steps do I need to take before deploying a rails application. In this case, i mean things which are are going to take more than 5 mins, and so need to be scheduled. For small oneline config changes, please use the little things question.
Set up Capistrano to deploy You'll want to learn capistrano if you don't already know it, and use it to deploy your code in an automated way. This will involve setting up your shared directory and shared resources like database.yml.
Install C Based MySQL gem If you don't have all the required libs, this can take a little while, but less than 20 minutes.
Make sure you aren't vulnerable to common web application attacks Session fixation, session hijacking, cross-site scripting, SQL injection (probably you don't have to worry much about SQL injection). Be sure you use h() when outputting user-entered data in a view screen. Lots of good material online about this.
Choose a server architecture Nginx, Mongrel, FastCGI, CGI, Apache, Passenger: there is a lot to choose from. Think about how your app will be used and decide on the best architecture, then set it up.
Set up Exception Notifier or Exception Logger You will want your app to warn you when it breaks. Set one of these tools up to track production exceptions. Note: Exception notifier will warn you when routing errors occur (i.e. when people fat-finger URLs or script kiddies attack you): so think about what you want the framework to do when that happens and adjust accordingly.
Make sure all of your passwords are out of source control If you have database.yml, mail.yml (if you use yaml_mail_config) or other sensitive files in source control, get them out of there, replace them with database.yml.example, and put them in the shared/ folder on your server.
Ensure that your DB is locked down. A lot of people forget to secure MySQL when setting up their new production Rails box. Don't be like them.
Make sure all of the little web-files are in place If you are planning to be listed in Google, generate a sitemap.xml file. If you are planning to use an .htaccess file for something, make sure it's there. If you need a robots.txt file to prevent certain areas of your site from being indexed, make one. If you want a good looking 404 Page, make sure it's set up correctly. If you want a "Be Right Back" page to be present when you deploy, make sure that you have a Capistrano maintenance file specified and Nginx or Apache knows how and when to redirect to it.
Get your SSL Certs in place If you are going to use SSL, make sure you get certificates that are valid on your production domain, and set them up.
Use some process monitoring
Sometimes your processes (mongrels in many cases) will die or other bad things will happen to them. For example a memory leak could cause the memory consumption to increase indefinitely or a process could start using all your CPU.
monit and god are both good choices to save you from this fate. They can also be set to hit a url on your site to check for a 200 response code.
Set up server monitoring
Some suggestions in this space: fiveruns, newrelic, scout
These tools will record detailed metrics on your servers and are invaluable when something goes wrong and you need to see what actually happened. They also give you real time information on server load.
If you have a cluster this kind of reporting is even more critical.
Backup
Write a script to periodically backup your database and any other assets that your users can upload. S3 might be a good choice for this.
Choose a web server / load balancer
My preferred server is nginx, but the common pattern is to start with apache + mod_proxy_http.

Resources