Latest Ruby on Dreamhost

June 9th, 2016

  1. Install RVM, these instructions work: Install RVM on Dreamhost
    Do NOT skip steps, especially:
    rvm autolibs disable
  2. Install framework:
    gem install hanami
  3. Setup Domain
    1. "Do you want the www in your URL?", choose "Leave it alonge: Both..."
    2. "Run this domain uder the user", leave as your default user unless you know better.
    3. "Web directory",
      /home/username/sub.domain.tld
      . Where sub=your subdomain (if any), domain=your domain, tld=your top level domain (probably .com)
    4. Web directory should not have
      public
      if you use
      dispatch.fcgi
      below.
    5. PHP Mode: PHP 5.5 FastCGI (Other versions probably work, but experiment AFTER it is working.
    6. Go ahead and check "Automatically upgrade PHP" and "Extra Web Security?"
    7. DO NOT CHECK "Passenger (Ruby/NodeJS/Python apps only)"
    8. CloudFlare and Google Services can be added later once it's working.
  4. place .htaccess file in /home/username/sub.domain.tld/.htaccess
    <IfModule mod_fastcgi.c>
      AddHandler fastcgi-script .fcgi
    </IfModule>
    <IfModule mod_fcgid.c>
      AddHandler fcgid-script .fcgi
    </IfModule>
    
    Options +FollowSymLinks +ExecCGI 
    
    <Files *.fcgi>
      Header set Content-type "text/html"
    </Files>
    
    RewriteEngine On 
    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ dispatch.fcgi/$1 [QSA,L] 
     
    ErrorDocument 500 "Rack application failed to start properly!"
            
  5. place dispatch.fcgi in /home/username/sub.domain.tld/dispatch.fcgi (starts Hanami application)
    #!/home/username/.rvm/rubies/ruby-2.2.4/bin/ruby
    #      ^change^^            ^^change^^^
    # The above ruby MUST match the gems you try to load. GEM_HOME and GEM_PATH must match.
    VERSION="ruby-#{RUBY_VERSION}"
    # Must be gems for the ruby version specified on first line.
    ENV['GEM_HOME'] = File.expand_path("/home/blazerw/.rvm/gems/#{VERSION}")
    ENV['GEM_PATH'] = File.expand_path("/home/blazerw/.rvm/gems/#{VERSION}") + ":" + File.expand_path("/home/blazerw/.rvm/gems/#{VERSION}")
    # Basic environment
    ENV['RACK_ENV'] ||= 'production'
    ENV['HANAMI_ENV'] ||= 'production'
    ENV['RAILS_ENV'] ||= ENV['RACK_ENV']
    ENV['HOME'] ||= `echo ~`.strip
    
    # Setup logging, that helps a ton
    fastcgi_log = File.open("fastcgi.log", "a")
    STDOUT.reopen fastcgi_log
    STDERR.reopen fastcgi_log
    STDOUT.sync = true
    
    STDOUT.print "Application Startup:\n"
    STDOUT.print "RACK_ENV  : #{ENV['RACK_ENV']}\n"
    STDOUT.print "RAILS_ENV : #{ENV['RAILS_ENV']}\n"
    STDOUT.print "HANAMI_ENV: #{ENV['HANAMI_ENV']}\n"
    STDOUT.print "Rest of ENV\n"
    STDOUT.print "#{ENV.inspect}\n"
    
    require "fcgi"
    require File.join(File.dirname(__FILE__), 'config/environment.rb')
    
    # Good debugger, but only works once your ruby version matches your fcgi gem.
    #FCGI.each {|request|
    #  out = request.out
    #  out.print "Content-Type: text/plain\r\n"
    #  out.print "\r\n"
    #  out.print Time.now.to_s
    #  out.print "\r\n"
    #  out.print "ENV:\r\n#{ENV.inspect}"
    #  out.print "\r\n"
    #  out.print "#{RUBY_VERSION}p#{RUBY_PATCHLEVEL} #{RUBY_PLATFORM} #{RUBY_RELEASE_DATE}"
    #  out.print "\r\n"
    #  out.print "Main"
    #  request.finish
    #}
    
    # Class that translates FCGI requests for your ruby app.
    class Rack::PathInfoRewriter
      def initialize(app)
        @app = app
        STDOUT.print "app:#{@app.inspect}\n"
        # Following two lines can't be used when starting the Hanami::Controller
        STDOUT.print "app name:#{@app.name}\n"
        STDOUT.print "app config:#{@app.configuration.inspect}\n"
        @app
      end
      def call(env)
        env.delete('SCRIPT_NAME')
        #SCRIPT_NAME can't be nil if you want the Hanami::Container to be the app we start.
        #env['SCRIPT_NAME'] = ""
        parts = env['REQUEST_URI'].split('?')
        env['PATH_INFO'] = parts[0]
        env['QUERY_STRING'] = parts[1].to_s
        STDOUT.print "env:#{env.inspect}\n"
        STDOUT.print "input:#{env['rack.input'].inspect}\n"
        @app.call(env)
      end
    end
    wrappedApp = Rack::Builder.new do
      use Rack::ShowExceptions
      use Rack::PathInfoRewriter
      # Using Hanami::Container causes stack too deep on each request. Not sure why, didn't investigate.
      #run Hanami::Container.new
      # None of the examples had that last ".new", but only an instance of Web::Application has the ".call" method used in Rack::PathInfoRewriter above's last line.
      run Web::Application.new
    end
    Rack::Handler::FastCGI.run wrappedApp