Report abuse

build nginx

1
2
3
cd nginx-source
./configure --prefix=/home/ch/nginx --with-http_ssl_module --with-http_sub_module
make install

/etc/puppet/rack/config.ru

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ch@squigley:/etc/puppet/rack % cat config.ru
# a config.ru, for use with every rack-compatible webserver.
# SSL needs to be handled outside this, though.

# if puppet is not in your RUBYLIB:
$:.push('/home/ch/puppet/lib')

$0 = "puppetmasterd"
#require 'puppet'

# if you want debugging:
ARGV << "--debug"

ARGV << "--rack"
require 'puppet/application/puppetmasterd'
# we're usually running inside a Rack::Builder.new {} block,
# therefore we need to call run *here*.

run Rack::Lint.new(Puppet::Application[:puppetmasterd].run)

puppet.conf

1
2
3
4
5
6
7
8
ch@squigley:/etc/puppet % cat puppet.conf
[puppetmasterd]
  ssl_client_header = HTTP_X_SSL_SUBJECT
    bindaddress = 'squigley.namespace.at'
    storeconfigs = true
    dbadapter = sqlite3
    dblocation = /var/puppet/storeconfigs.sqlite
    manifestdir = /etc/puppet/foo

nginx.conf

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
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream unicorn_backend {
     server unix:/tmp/my_app.sock fail_timeout=0;
    }
    ssl                     on;
    ssl_certificate         /etc/puppet/ssl/certs/squigley.namespace.at.pem;
    ssl_certificate_key     /etc/puppet/ssl/private_keys/squigley.namespace.at.pem;
    ssl_client_certificate  /etc/puppet/ssl/ca_crt.pem;
    ssl_ciphers             SSLv2:-LOW:-EXPORT:RC4+RSA;
    ssl_session_cache       shared:SSL:8m;
    ssl_session_timeout     5m;
    server {
        listen                  8140;
        ssl_verify_client       on;
        root                    /var/empty;
        access_log              /tmp/access-8140.log;

        location / {
            proxy_pass          http://unicorn_backend;
            proxy_redirect      off;
            proxy_set_header    Host             $host;
            proxy_set_header    X-Real-IP        $remote_addr;
            proxy_set_header    X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_set_header    X-Client-Verify  SUCCESS;
            proxy_set_header    X-SSL-Subject    $ssl_client_s_dn;
            proxy_set_header    X-SSL-Issuer     $ssl_client_i_dn;
            proxy_read_timeout  65;
        }
    }
}

unicorn config

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
  worker_processes 1
  working_directory "/etc/puppet/rack"
  listen '/tmp/my_app.sock', :backlog => 10
  timeout 10
  pid "/tmp/my_app.pid"

  # combine REE with "preload_app true" for memory savings
  # http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
  preload_app true
  GC.respond_to?(:copy_on_write_friendly=) and
  GC.copy_on_write_friendly = true

  before_fork do |server, worker|
    # the following allows a new master process to incrementally
    # phase out the old master process with SIGTTOU to avoid a
    # thundering herd (especially in the "preload_app false" case)
    # when doing a transparent upgrade.  The last worker spawned
    # will then kill off the old master process with a SIGQUIT.
    old_pid = "#{server.config[:pid]}.oldbin"
    if old_pid != server.pid
      begin
        sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
        Process.kill(sig, File.read(old_pid).to_i)
      rescue Errno::ENOENT, Errno::ESRCH
      end
    end

    # optionally throttle the master from forking too quickly by sleeping
    sleep 1
  end

  after_fork do |server, worker|

    uid, gid = Process.euid, Process.egid
    user, group = 'puppet', 'puppet'
    target_uid = Etc.getpwnam(user).uid
    target_gid = Etc.getgrnam(group).gid
    worker.tmp.chown(target_uid, target_gid)
    if uid != target_uid || gid != target_gid
        Process.initgroups(user, target_gid)
        Process::GID.change_privilege(target_gid)
        Process::UID.change_privilege(target_uid)
    end

    # per-process listener ports for debugging/admin/migrations
    addr = "127.0.0.1:#{9293 + worker.nr}"
    server.listen(addr, :tries => 1, :delay => 5, :tcp_nopush => true)
    sleep 3
  end

puppet patch to disable setuid() for rack apps

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
ch@squigley:~/puppet (git)-[0.25.x] % git diff -a
diff --git a/lib/puppet/application/puppetmasterd.rb b/lib/puppet/application/puppetmasterd.rb
index 9b0bf30..1a8de9b 100644
--- a/lib/puppet/application/puppetmasterd.rb
+++ b/lib/puppet/application/puppetmasterd.rb
@@ -98,17 +98,17 @@ Puppet::Application.new(:puppetmasterd) do
             Puppet::SSL::Host.ca_location = :only
         end

-        if Process.uid == 0
-            begin
-                Puppet::Util.chuser
-            rescue => detail
-                puts detail.backtrace if Puppet[:trace]
-                $stderr.puts "Could not change user to %s: %s" % [Puppet[:user], detail]
-                exit(39)
+        unless options[:rack]
+            if Process.uid == 0
+                begin
+                    Puppet::Util.chuser
+                rescue => detail
+                    puts detail.backtrace if Puppet[:trace]
+                    $stderr.puts "Could not change user to %s: %s" % [Puppet[:user], detail]
+                    exit(39)
+                end
             end
-        end

-        unless options[:rack]
             @daemon.server = Puppet::Network::Server.new(:xmlrpc_handlers => xmlrpc_handlers)
             @daemon.daemonize if Puppet[:daemonize]
         else

start unicorn

1
cd /etc/puppet/rack; sudo /var/lib/gems/1.8/bin/unicorn -c /home/ch/unicorn.config