Configuring nginx to use www.domain.com instead of domain.com

Posted by scott on August 19, 2008

I had a client who had their local server setup under domain.com instead of properly under local.domain.com or something similar. It caused a bit of a headache (you could view their new site from outside their local office, but in their local office the old website was still showing.)

Their local server guy (thanks Will) helped me solve the issue. Their website needed to use only www.

Here’s his notes:

Company XYZ Mortuary has two separate DNS systems

1. The public-facing DNS server that you control

2. The internal DNS server for Company XYZ’s private network that we control

Since both of these servers are authoritative for the CompanyXYZ.com domain, both need to be updated when IP addresses of public servers change.

The other issue we had was the web site removing the www from the URL, which caused computers on Company XYZ’ private network to access an internal server. Windows domain controllers reserve the IP address for the domain name for themselves, and modifying this behavior breaks functionality such as DFS and Exchange. For this reason, Microsoft and other OS vendors recommend using a TLD that will never be used on the Internet, such as .local.

And here is the adjusted nginx config file to use www & point appropriately.

The key line(s) are:
server_name company-xyz.com;
rewrite ^/(.*) http://www.company-xyz.com/$1 permanent;

upstream domain4 {
        server 127.0.0.1:3400;
        }

server {
            listen   80;
            server_name company-xyz.com;
            rewrite ^/(.*) http://www.company-xyz.com/$1 permanent;
           }

server {
            listen   80;
            server_name www.company-xyz.com;

            access_log /home/username/public_html/railsapp/shared/log/access.log;
            error_log /home/username/public_html/railsapp/shared/log/error.log;

            root   /home/username/public_html/railsapp/current/public/;
            index  index.html;

            location / {
                          proxy_set_header  X-Real-IP  $remote_addr;
                          proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
                          proxy_set_header Host $http_host;
                          proxy_redirect false;

                          if (-f $request_filename/index.html) {
                                           rewrite (.*) $1/index.html break;
                          }

                          if (-f $request_filename.html) {
                                           rewrite (.*) $1.html break;
                          }

                          if (!-f $request_filename) {
                                           proxy_pass http://domain4;
                                           break;
                          }
            }

}

server {

            listen   443;
            ssl on;
            ssl_certificate     /etc/ssl/certs/company-xyz.com.crt;
            ssl_certificate_key   /etc/ssl/private/companyxyz.key;       

            server_name  company-xyz.com;
            rewrite ^/(.*) http://www.company-xyz.com/$1 permanent;

           }

server {

            listen   443;
            ssl on;
            ssl_certificate     /etc/ssl/certs/company-xyz.com.crt;
            ssl_certificate_key   /etc/ssl/private/companyxyz.key;

            server_name www.company-xyz.com;

            access_log /home/username/public_html/railsapp/shared/log/access.log;
            error_log /home/username/public_html/railsapp/shared/log/error.log;

            root   /home/username/public_html/railsapp/current/public/;
            index  index.html;

            location / {
                          proxy_set_header X_FORWARDED_PROTO https;

                          proxy_set_header  X-Real-IP  $remote_addr;
                          proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
                          proxy_set_header Host $http_host;
                          proxy_redirect false;

                          if (-f $request_filename/index.html) {
                                           rewrite (.*) $1/index.html break;
                          }

                          if (-f $request_filename.html) {
                                           rewrite (.*) $1.html break;
                          }

                          if (!-f $request_filename) {
                                           proxy_pass http://domain4;
                                           break;
                          }
            }

}

Scheduled Tasks with Cron in a Rails app

Posted by scott on August 19, 2008

One of my apps requires a daily task to run. It uses WWW::Mechanize (the gem) to log onto a website, insert a username and password, and save that information, come back to my app, and insert & save that into a form on my site.

I’m pretty impressed I was able to pull it off. It’s a great deal of detail to go into, but I used Recipe 75 in Advanced Rails Recipes and adjusted some of my old hpricot & mechanize scripts.

Best of all, it keeps me out of the crontab on the server. No hand editing. The capistrano cron rake task takes care of that.

UPDATED: Email validation/activation with rails, restful_authentication, and gmail smtp

Posted by scott on August 18, 2008

This is updated from my old post on the subject. It’s a process cheat sheet for me.

I’m not gonna explain it too much. Here’s the code.

script/plugin install git://github.com/technoweenie/restful-authentication.git
script/generate authenticated user sessions --include-activation
1
2
3
#Add an observer to config/environment.rb
config.active_record.observers = :user_observer
#put it just before the very last 'end' on the page
1
2
3
4
5
#Add routes to these resources. In config/routes.rb, insert routes like:
    map.signup '/signup', :controller => 'users', :action => 'new'
    map.login  '/login',  :controller => 'sessions', :action => 'new'
    map.logout '/logout', :controller => 'sessions', :action => 'destroy'
    map.activate '/activate/:activation_code', :controller => 'users', :action => 'activate', :activation_code => nil
rake db:migrate
1
2
3
4
5
6
7
8
9
10
11
# create new file config/initializers/mail.rb
 
require "smtp_tls"
 
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:authentication => :plain,
:user_name => "you@gmail.com",
:password => 'yourpassword'}
1
2
3
4
# edit config/environments/production.rb & put these lines at the top
SITE_NAME = "Your Site"
SITE_URL = "www.yourdomain.com"
SITE_EMAIL = "admin@yourdomain.com"
1
2
3
4
# edit config/environments/development.rb & put these lines at the top
SITE_NAME = "ToolTime"
SITE_URL = "localhost:3000"
SITE_EMAIL = "scott@scottmotte.com"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Make app/models/user_mailer.rb look like the following:
class UserMailer < ActionMailer::Base
  def signup_notification(user)
    setup_email(user)
    @subject    += 'Please activate your new account'
 
    @body[:url]  = "http://#{SITE_URL}/activate/#{user.activation_code}"
 
  end
 
  def activation(user)
    setup_email(user)
    @subject    += 'Your account has been activated!'
    @body[:url]  = "http://#{SITE_URL}/"
  end
 
  protected
    def setup_email(user)
      @recipients  = "#{user.email}"
      @from        = "#{SITE_EMAIL}"
      @subject     = "#{SITE_NAME}"
      @sent_on     = Time.now
      @body[:user] = user
    end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# create file lib/smtp_tls.rb with following code in it
 
require "openssl"
require "net/smtp"
 
Net::SMTP.class_eval do
  private
  def do_start(helodomain, user, secret, authtype)
    raise IOError, 'SMTP session already started' if @started
    check_auth_args user, secret, authtype if user or secret
 
    sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
    @socket = Net::InternetMessageIO.new(sock)
    @socket.read_timeout = 60 #@read_timeout
 
    check_response(critical { recv_response() })
    do_helo(helodomain)
 
    if starttls
      raise 'openssl library not installed' unless defined?(OpenSSL)
      ssl = OpenSSL::SSL::SSLSocket.new(sock)
      ssl.sync_close = true
      ssl.connect
      @socket = Net::InternetMessageIO.new(ssl)
      @socket.read_timeout = 60 #@read_timeout
      do_helo(helodomain)
    end
 
    authenticate user, secret, authtype if user
    @started = true
  ensure
    unless @started
      # authentication failed, cancel connection.
      @socket.close if not @started and @socket and not @socket.closed?
      @socket = nil
    end
  end
 
  def do_helo(helodomain)
    begin
      if @esmtp
        ehlo helodomain
      else
        helo helodomain
      end
    rescue Net::ProtocolError
      if @esmtp
        @esmtp = false
        @error_occured = false
        retry
      end
      raise
    end
  end
 
  def starttls
    getok('STARTTLS') rescue return false
  return true
  end
 
  def quit
    begin
      getok('QUIT')
    rescue EOFError
    end
  end
end

Restart your server, visit http://yourapp.com/signup and give it a shot.

Once that works. Then put before_filter :login_required in your controllers where needed.

Autotest

Posted by scott on August 18, 2008

Getting started tutorial

How to check for all your rake tasks

Posted by scott on August 18, 2008

In terminal

rake -T

How to open files in terminal

Posted by scott on August 18, 2008

open -a Firefox doc/plugins/rspec-rails/index.html

My Terminal bash settings

Posted by scott on August 18, 2008

cd ~
mate .bashrc # or nano .bashrc
1
2
# then type in
export PS1='\[[~/\W]'

WP-Syntax 5

Posted by scott on August 17, 2008

I’ve installed WP-Syntax on my blog. It will help brighten up my lines of code.

It was an easy install and pretty easy to use. Intead, of just using the pre html tag, I know do something like this:

pre lang=”ruby” line=”1″
#put some ruby code
Categories.find(:all, :conditions => ['cool_field = ?', 'awesome'])
pre

1
2
#put some ruby code
Categories.find(:all, :conditions => ['cool_field = ?', 'awesome'])

or html

pre lang=”html4strict” line=”1″>

Title me

That car was bright blue.

pre

1
2
3
<!-- comment -->
<h1>Title me</h1>
<p>That car was bright blue.</p>

Slicehost, nginx, mysql, php, wordpress setup

Posted by scott on August 17, 2008

Detailed tutorial on nginx, mysql, php, wordpress setup. bonus: it includes setup instructions for the super cache plugin

Rails model validation without database using active_form

Posted by scott on August 17, 2008

Usually, when you create a model, you create a database, and then the model works with ActiveRecord. And it’s ActiveRecord (as far as I currently know) that lets you use validation techniques.

So how do we add validation techniques to something like a contact form on our Rails site that does not have a database?

Install the plugin active form

script/plugin install git://github.com/xgamerx/active_form.git

Then create a file in your app/models folder called email.rb. Paste in the following into that file. Line #1 is key

1
2
3
4
5
6
class Email < ActiveForm
  attr_accessor :name, :email_address, :message
  validates_presence_of :message
  validates_presence_of :email_address
  validates_presence_of :name 
end

Then create another file in app/models called contact_emailer.rb and paste in the following. This is what will let you send the email

(Wait: make sure you know how to setup email so it works. See my post on creating a contact form with gmail smtp and rails. In that post I called the following file Emailer.rb. You could do that as well, but Line #1 with ActionMailer::Base is key.)

1
2
3
4
5
6
7
8
9
10
11
class ContactMailer < ActionMailer::Base
 
  def contact_email(email)
      recipients  "site@email.com" 
      headers     "Reply-to" => "#{email.email_address}"
      from        email.name + " <" + email.email_address + ">"
      subject     "SiteName"
      body        :email => email
  end
 
end

Then in your views create a folder called contact_mailer & inside of that folder create a file called contact_email.html.erb
app
-views
–contact_mailer
—contact_email.html.erb

This will style the email so put something like the following. This essentially routes to the contact_email method in contact_mailer.rb

1
2
3
4
5
6
7
8
9
10
11
Name:
 
<%= @email.name %>
 
Email: 
 
<%= @email.email_address %>
 
Message:
 
<%= @email.message %>

Now you can create a controller and use the form. Here’s an example using a static based site. The key is line #14 (ContactMailer.deliver_contact_email(@email)). This uses the contact_email method we created, and rails knows that if you put deliver_ in front of it, then it will deliver it according to your email setup (which you shoud have done already here).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# static controler
class StaticController < ApplicationController
  def index
  end
 
  def overview
  end
 
  def faqs    
  end
 
  def contact
    if request.post?
      @email = Email.new(params[:email])
      if @email.valid?
        ContactMailer.deliver_contact_email(@email)
        flash[:notice] = "Your email was sent successfully. Thanks."
        # without the redirect the params[:email] gets filled back into the form making it look like the form did not get submitted
        redirect_to :action => 'contact'
      end
    end 
  end
 
  def signup    
  end
 
 
end

And here’s what the contact.html.erb looks like associated with that action.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
<h1>Contact Us</h1>
 
<p>Email us.</p>
 
<% form_tag( {:action => "contact"}, :id => 'contact') do %>
<%= error_messages_for('email') %>
<ul>
	<li>
		<label for="email_name">Your Name</label>
		<%= text_field "email", "name", :class => 'input-txt' %>
	</li>
	<li>
		<label for="email_company">Your Email Address</label>
		<%= text_field "email", "email_address", :class => 'input-txt' %>
	</li>
 
	<li>
		<label for="email_message">Message</label>
		<%= text_area "email", "message", :cols => 10 %>
	</li>
	<li class="actn">
		<!-- <a id="sendmessage" href="">Send Message</a> -->
		<input type="submit" value="Send Message" />
	</li>
<% end %>

Finally, make sure to restart your local server using script/server before testing. Otherwise, the plugin active_form won’t load the first time.