How to Customize Your Dreamhost Dedicated Server While Retaining a Managed Apache2 Configuration

6 minute read

I use Dreamhost to host all my non-major sites. A non-major site, at least in my definition, is a site that doesn't require its own deployment stack. Dreamhost is great for hackers (read: people who hack on code, not people who hack to steal/disrupt) because you get shell access even at its most basic plans.

I started with Dreamhost way back 2006 with a low-level shared hosting plan. I would host my blog on it, school projects and even my wedding website. Eventually, I was hosting many different Rails projects, API's and managing multiple small sites with varying configurations. I began to bottleneck, competing for system resources with other unknown sites on my shared machine.

In addition to resource bottlenecks, I wanted to fine-tune my ruby setup, my RVM setup, my Passenger setup and other various tweaks. Because all sites on my shared box use the same resources, including compiled system binaries, I decided that I needed something a bit more flexible. Luckily, Dreamhost has various plans including one that fit my needs perfectly: a Dedicated Server.

I upgraded a dedicated a few years ago and never looked back. This means I have an entire box to myself to do whatever I wanted to. Because I am the only customer on this dedicated server, I have the correct permissions to tweak anything on my box. I also am allowed root access, something very important to my personalized solutions described below.

When I first got root access, I immediately installed RVM and Passenger, upgraded my ruby and hooked up passenger with Apache. After successfully editing the Apache conf file, located at /dh/apache2/httpd-argon/etc/httpd.conf, everything worked like a charm using my new setup...

...Until the next time I purchased a domain name from Dreamhost. One of the major benefits of having a hosting provider like Dreamhost is that you get managed files. By purchasing a domain name from them, and adding a redirect in the webpanel, Dreamhost automatically sets the right entries in the Apache conf file. Furthermore, they don't edit the existing file, they generate it somewhere else on the fly, then overwrite the Apache conf file (amongst others). This meant that all the changes I made to the Apache conf file were lost whenever I made a change in the panel, or whenever Dreamhost decided to push out an up-to-date version.

It seemed that my options were

  1. Give up my Apache configuration customization
  2. Give up all automated panel management for all domains
Neither of these were appealing to me, so I set out to find a better way. Armed with sudo access, I went to work.

I realized that the Apache conf file pointed to a specific ruby and passenger install that Dreamhost had on the machine. At the time of this writing, those version were ruby 1.8 and passenger 2.X. Any changes I made to the conf file would be overwritten by these older versions on the next Dreamhost push, so I went at it on the file system side and setup symlinks for these older versions that pointed to my new versions.

# Move the old mod_passenger out of the way...
sudo mv /dh/apache2/template/lib/modules/mod_passenger.so /dh/apache2/template/lib/modules/mod_passenger.so.bak
# Softlink your customized version to the place Dreamhost expects it to be
ln -s /usr/local/rvm/gems/ruby-1.9.3-p385/gems/passenger-4.0.21/buildout/apache2/mod_passenger.so /dh/apache2/template/lib/modules/mod_passenger.so

# Move the old ruby out of the way...
mv /usr/bin/ruby1.8 /usr/bin/_ruby1.8
# Softlink your customized version to the place Dreamhost expects it to be
ln -s /usr/local/rvm/wrappers/ruby-1.9.3-p385/ruby /usr/bin/ruby1.8

# Move the old passenger directory out of the way...
mv /dh/passenger /dh/passenger.bak
# Softlink your customized version to the place Dreamhost expects it to be
ln -s /usr/local/rvm/gems/ruby-1.9.3-p385/gems/passenger-4.0.21 /dh/passenger

# Restart server to apply changes
/etc/init.d/httpd2 restart

Symlinking the passenger and ruby resources allowed me to enjoy the customized setup I wanted, while retaining the Dreamhost managed Apache configuration.

This worked great for several years until I recently upgraded to Passenger 4.x. Passenger has deprecated a feature that Dreamhost uses in their Apache conf file, RailsAutoDetect and RackAutoDetect. These features were valid in the old version of Passenger, the version that Dreamhost expected, so they were present in the auto-pushed Dreamhost conf file. This means that when Apache tried to start up a server and hook into Passenger, the server would fail to start and none of the Passenger sites listed in the Apache conf file would start up at all.

This wasn't a problem that could be solved with a symlink, and every Dreamhost conf file push would re-add the values. Not wanting to give up points 1 and 2 above, I setup a simple cronjob running every minute which monitors the Apache conf file, looked for those lines, and comments them out if they were not already commented out. The script looks like this:

#!/usr/bin/env ruby
# Fixes the problem with Passenger 4.0 deprecating RailsAutoDetect and RackAutoDetect
# This script checks for uncommented versions of these strings and comments them
file_name = "/dh/apache2/httpd-argon/etc/httpd.conf"
regex = /^([^#].*[Rails|Rack]AutoDetect.*[on|off].*)$/
text = File.read(file_name)
new_text = text.gsub(regex, '# \1 # COMMENTED OUT AUTOMATICALLY WITH THE /home/root/scripts/server_health.rb CRON SCRIPT')

if text != new_text
  File.open(file_name, "w") {|file| file.puts new_text}
  `/etc/init.d/httpd2 restart`
end

Now, if Dreamhost pushes out a new Apache conf file to my server, My non-major sites will only be down for about a minute until the cronjob detects the change, comments them out and restarts the server.

UPDATE 11/15/2013

It appears that changes to the webpanel employ some sort of customization check before pushing out and overwriting the httpd.conf file. After changes to the conf file were made by this cron script, Dreamhost would not automatically overwrite the file, thinking I wanted 100% manual control of the file. They end up writing the new conf file to /dh/apache2/httpd-argon/etc/httpd.conf.pusher, but not copying it over.

The solution is simply to add a check to the cron script to look for this file, copy it over first, then comment out the necessary lines. I could also use this as the trigger rather than a regex search, but in case they ever fix this 100% manual or 100% managed problem, I will leave it in. With the addition, the new script is:

#!/usr/bin/env ruby

require 'fileutils'

# Fixes the problem with httpd.conf.pusher files not overwriting httpd.conf if detected as edited
# Fixes the problem with Passenger 4.0 deprecating RailsAutoDetect and RackAutoDetect

# This script first checks for the presence of the .pusher file and copies it over if found,
# then checks for uncommented versions of the deprecated [Rack|Rails]AutoDetect strings and comments them out

file_name = "/dh/apache2/httpd-argon/etc/httpd.conf"

pusher_file_name = file_name + ".pusher"
if File.exist?(pusher_file_name)
  FileUtils.mv(pusher_file_name, file_name, { :force => true})
end

regex = /^([^#].*[Rails|Rack]AutoDetect.*[on|off].*)$/
text = File.read(file_name)
new_text = text.gsub(regex, '# \1 # COMMENTED OUT AUTOMATICALLY WITH THE /home/root/scripts/server_health.rb CRON SCRIPT')

if text != new_text
  File.open(file_name, "w") {|file| file.puts new_text}
  `/etc/init.d/httpd2 restart`
end

END UPDATE

Right now, Dreamhosts expects a 100% managed or a 100% manual httpd.conf file. Until Dreamhost lets you configure some of the panel-pushed variables for Dedicated Server customers, these tricks will allow you to get the best of both worlds. Enjoy!

Lastly, I run a small software company called Urban Apps. It pays the bills so I can take the time to write helpful posts like this one. If you found this page helpful at all, I would really appreciate it if you would check out my Apps on the iTunes App Store.

Was this page helpful for you? Buy me a slice of 🍕 to say thanks!

Comments