Skip to content
This repository
Browse code

In production, unicorn should not listen on a TCP socket.

This change ensures that in production mode, Unicorn *only* listens
on a Unix domain socket. It includes the accompanying rewrite of the
nginx configuration and the various deploy/test tweaks to make this
work.

Fixes #256.
  • Loading branch information...
commit e305feae3e0635f5b984f08c4ee9e2f9969e4f62 1 parent 6dc666a
Caleb Spare authored
2  Vagrantfile
@@ -7,7 +7,7 @@ Vagrant::Config.run do |config|
7 7
 
8 8
   # Forward a port from the guest to the host, which allows for outside
9 9
   # computers to access the VM, whereas host only networking does not.
10  
-  config.vm.forward_port 8040, 8080
  10
+  config.vm.forward_port 80, 8080
11 11
 
12 12
   # More memory than the default, since we're running a lot of stuff (1GB)
13 13
   config.vm.customize ["modifyvm", :id, "--memory", 1024]
2  config/deploy_targets/common.rb
@@ -16,7 +16,6 @@ def self.common_options
16 16
     # Note that these options use the "deploy_to" and "hostname" vars, so those must have been defined prior
17 17
     # to calling this function (e.g. via set :deploy_to, "path").
18 18
     common_options = {
19  
-      barkeep_port: 8040,
20 19
       db_host: "localhost",
21 20
       db_port: 3306,
22 21
       db_name: "barkeep",
@@ -30,6 +29,7 @@ def self.common_options
30 29
       barkeep_hostname: hostname,
31 30
       repos_root: "#{deploy_to}/repos",
32 31
       unicorn_pid_file: "#{deploy_to}/unicorn.pid",
  32
+      unicorn_socket: "/tmp/barkeep-unicorn.sock",
33 33
       unicorn_workers: 4,
34 34
       resque_workers: 4,
35 35
       rack_env: "production"
48  config/system_setup_files/nginx_site.conf.erb
... ...
@@ -1,27 +1,45 @@
1 1
 # This file gets placed into /etc/nginx/sites-enabled/barkeep
2  
-# It's a standard nginx setup for receiving traffic on port 80 and then proxying it to some application
3  
-# server listening on a non-privileged port.
  2
+# Modified from Unicorn's sample nginx configuration.
  3
+
4 4
 # Render this file using ERB. It requires the params:
5  
-#   - path - the path that the app is being deployed to.
6 5
 #   - hostname
7  
-#   - port
  6
+#   - unicorn_socket - the filename of the socket on which the unicorn master listens
  7
+
  8
+upstream barkeep {
  9
+  # fail_timeout=0 means we always retry an upstream even if it failed
  10
+  # to return a good HTTP response (in case the Unicorn master nukes a
  11
+  # single worker for timing out).
  12
+
  13
+  # for UNIX domain socket setups:
  14
+  server unix:<%= unicorn_socket %> fail_timeout=0;
  15
+}
  16
+
  17
+# TODO(caleb): Use nginx's caching to serve Pinion's static assets.
8 18
 
9 19
 server {
10  
-  listen 80;
11  
-  root <%= current_path %>;
  20
+  listen 80 default deferred;
  21
+
  22
+  client_max_body_size 4G;
12 23
   server_name <%= hostname %> localhost;
13 24
 
14  
-  # Pass along the user's real IP.
15  
-  proxy_set_header X-Real-IP $remote_addr;
16  
-  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
17  
-  proxy_set_header Host $host;
  25
+  # ~2 seconds is often enough for most folks to parse HTML/CSS and
  26
+  # retrieve needed images/icons/frames, connections are cheap in
  27
+  # nginx so increasing this is generally safe...
  28
+  keepalive_timeout 5;
18 29
 
19 30
   location / {
20  
-    # Serve up static files directly.
21  
-    if (-f $request_filename) { break; }
  31
+    # an HTTP header important enough to have its own Wikipedia entry:
  32
+    #   http://en.wikipedia.org/wiki/X-Forwarded-For
  33
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  34
+
  35
+    # pass the Host: header from the client right along so redirects
  36
+    # can be set properly within the Rack application
  37
+    proxy_set_header Host $http_host;
22 38
 
23  
-    proxy_pass http://localhost:<%= port %>;
  39
+    # we don't want nginx trying to do something clever with
  40
+    # redirects, we set the Host: header above already.
  41
+    proxy_redirect off;
24 42
 
25  
-    error_page 500 502 503 504 /500.html;
  43
+    proxy_pass http://barkeep;
26 44
   }
27  
-}
  45
+}
6  config/tasks/deploy.rake
@@ -43,9 +43,8 @@ namespace :fezzik do
43 43
   task :evaluate_conf_file_templates do
44 44
     env_settings = Fezzik.environments[hostname]
45 45
     nginx_conf = Tilt::ERBTemplate.new("config/system_setup_files/nginx_site.conf.erb").render(Object.new,
46  
-        :port => env_settings[:barkeep_port],
47 46
         :hostname => hostname,
48  
-        :path => current_path)
  47
+        :unicorn_socket => env_settings[:unicorn_socket])
49 48
     File.open("/tmp/#{app}/staged/config/system_setup_files/nginx_site.conf", "w") { |f| f.write(nginx_conf) }
50 49
   end
51 50
 
@@ -158,11 +157,10 @@ namespace :fezzik do
158 157
 
159 158
   def server_is_up?
160 159
     begin
161  
-      port = Fezzik.environments[hostname][:barkeep_port]
162 160
       # We try and connect to Barkeep multiple times, because it can take awhile to come up after we start it.
163 161
       # We can remove this once we figure out how to make Barkeep start up faster.
164 162
       try_n_times(n = 4, timeout = 3) do
165  
-        run "curl --silent --show-error --max-time 20 localhost:#{port}/ > /dev/null"
  163
+        run "curl --silent --show-error --max-time 20 localhost:80/ > /dev/null"
166 164
       end
167 165
     rescue StandardError => error
168 166
       puts "#{error}\nBarkeep is not responding. It may have had trouble starting."
8  config/unicorn.barkeep.conf
@@ -4,10 +4,14 @@
4 4
 require "./environment.rb"
5 5
 
6 6
 port = ENV["BARKEEP_PORT"] || 8040
7  
-listen port, :tcp_nodelay => true
8 7
 worker_processes (ENV["UNICORN_WORKERS"] || 1).to_i
  8
+socket_path = ENV["UNICORN_SOCKET"]
9 9
 
10  
-listen "/tmp/barkeep-unicorn.sock", :backlog => 64
  10
+if ENV["RACK_ENV"] == "production"
  11
+  listen socket_path, :backlog => 64
  12
+else
  13
+  listen port, :tcp_nodelay => true
  14
+end
11 15
 
12 16
 timeout 30
13 17
 
5  test/integration/barkeep_server_integration_test.rb
@@ -2,7 +2,10 @@
2 2
 require "pathological"
3 3
 require "test/integration_test_helper"
4 4
 
5  
-SERVER = "http://localhost:8040"
  5
+require "environment.rb"
  6
+
  7
+PORT = (defined?(RACK_ENV) && RACK_ENV == "production") ? 80 : 8040
  8
+SERVER = "http://localhost:#{PORT}"
6 9
 
7 10
 class BarkeepServerIntegrationTest < Scope::TestCase
8 11
   include HttpTestHelper

0 notes on commit e305fea

Please sign in to comment.
Something went wrong with that request. Please try again.