I just wanted to let everyone know that I tried the method Rob Shultz suggested, and it works. &nbsp;In case it helps someone in the future, I&#39;ll sum up the problem and solution here.<div><br></div><div>My setup and requirements were as follows:<div>
<ul><li>custom CMS implemented with Rails</li><li>single app instance serves many websites</li><li>each website uses http and https</li><li>each website has an SSL certificate for its own domain, so each needs its own dedicated IP</li>
<li>hosting company policy limits me to five IP addresses per slice</li><li>each site has its own static file directory</li><li>CMS makes heavy use of caching (each site has its own cache directory)</li></ul></div><div>The problem was that in order to realize decent economies of scale, I needed to be able to host far more than five websites on my slice. &nbsp;In addition, for reasons of cost and convenience, I only wanted to maintain a single instance of the Rails app rather than running a copy of it on multiple servers. &nbsp;The IP address limit of five per slice was a killer.</div>
<div><br></div><div>The solution to the problem was to set up nginx on multiple front-end slices which would each proxy requests to nginx on a single back-end slice, which would itself then proxy those requests to the Rails app. &nbsp;I got this set up, and it worked great, except for one thing. &nbsp;Because the requests to the back-end nginx are always received from the front-end nginx over http (even when the client request to the front-end nginx is over https), the Rails app was unable to tell whether the client&#39;s original request was over http or https. &nbsp;(I couldn&#39;t simply proxy from the front-end nginx directly to the back-end Rails app due to the app&#39;s caching requirements.)</div>
<div><br></div><div>Per Rob&#39;s suggestion, I configured two server directives per site on the back-end nginx -- one for http and one for https. &nbsp;However, since the back-end nginx wouldn&#39;t be talking to clients directly, it does not need to listen on ports 80 or 443. &nbsp;Instead, it can listen on arbitrary port numbers as long as the front-end nginx instances know what those port numbers are. &nbsp;As such, the two server directives for the website <a href="http://one.com">one.com</a> on the back-end nginx can listen on ports 4000 (for http) and 4001 (for https). &nbsp;The server directives for <a href="http://one.com">one.com</a> on the front-end nginx will proxy requests for <a href="http://one.com">http://one.com</a> (port 80) to the back-end nginx on port 4000, and it will proxy requests for <a href="https://one.com">https://one.com</a> (port 443) to the back-end nginx on port 4001.</div>
<div><br></div><div>The significance of listening on multiple ports is that the back-end nginx can tell the Rails app that requests to port 4000 server were originally made over http and that requests to port 4001 were originally made over https. &nbsp;I&#39;ll attempt to illustrate here (this won&#39;t look right without a fixed-width font).</div>
<div><br></div><div><div><span class="Apple-style-span" style="font-family: &#39;courier new&#39;, monospace;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; front-end &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;back-end</span></div><div><span class="Apple-style-span" style="font-family: &#39;courier new&#39;, monospace;"><a href="http://one.com">one.com</a> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +----------+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+-----------+</span></div>
<div><span class="Apple-style-span" style="font-family: &#39;courier new&#39;, monospace;">request ---http---&gt; | port 80 &nbsp;| ---port:4000---&gt; | port 4000 | ---proto:http---&gt; &nbsp;+-----------+</span></div><div><span class="Apple-style-span" style="font-family: &#39;courier new&#39;, monospace;">&nbsp;&nbsp; &nbsp; &nbsp; \ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| Rails app |</span></div>
<div><span class="Apple-style-span" style="font-family: &#39;courier new&#39;, monospace;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;\--https--&gt; | port 443 | ---port:4001---&gt; | port 4001 | ---proto:https--&gt; &nbsp;+-----------+</span></div><div><span class="Apple-style-span" style="font-family: &#39;courier new&#39;, monospace;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+----------+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+-----------+</span></div>
</div><div><br></div><div>Only one front-end slice is shown, and it is shown only for one site, but this should give you an idea of how this can be expanded. &nbsp;The front-end slice can (in my case) be expanded to host five sites, and more slices can be added as needed.</div>
<div><br></div><div>Of course, to ensure the back-end server isn&#39;t tricked, it&#39;s necessary to make sure the server is set up to listen on ports 4000 and 4001 only from the front-end servers.</div><div><br></div><div>
If anyone else runs into a similar IP limitation or has some other need to proxy http and https traffic through two instances of nginx, I hope this helps you out.</div><div><br></div><div>Nick</div><div><br></div><div><br>
</div><div><br><div class="gmail_quote">On Thu, Oct 30, 2008 at 4:05 PM, Nick Pearson <span dir="ltr">&lt;<a href="mailto:nick.pearson@gmail.com">nick.pearson@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Yes, and that&#39;s my plan exactly.&nbsp; The only reason I need to listen on two separate ports for each site is that each site caches its content independently, which means that nginx has to be able to look for the cached content and server that up without ever touching Rails.&nbsp; So, for two sites to be able to each have a cached index.html file (as well as static image files), I have to have a site-specific path in each server directive.<br>

<br>For instance, consider the following:<br><br>&nbsp;&nbsp;&nbsp; server {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; listen&nbsp; 80;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; server_name&nbsp; <a href="http://site-a.com" target="_blank">site-a.com</a>&nbsp; *.<a href="http://site-a.com" target="_blank">site-a.com</a>;&nbsp; # needs to be site-specific<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; root&nbsp; /var/www/site-a;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; location / {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # serve static files<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (-f $document_root$uri.html) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rewrite (.*) $1.html break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # serve cached pages directly<br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (-f $document_root/../../../current/tmp/cache/content/site-a/$uri.html) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rewrite (.*) $document_root/../../../current/tmp/cache/content/site-a/$1.html break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br><br>

I realize I could set the root to &quot;/var/www&quot; (and drop the &quot;/site-a&quot;), then use the $host or $http_host variable in my static/cache paths, but my CMS supports *.domain.com-style vhosts, which can&#39;t be represented on the file system.&nbsp; If I drop the *.domain.com-style vhost support, then I could have paths like /var/www/<a href="http://site-a.com" target="_blank">site-a.com</a> with symlinks pointing to it (like /var/www/<a href="http://www.site-a.com" target="_blank">www.site-a.com</a> -&gt; /var/www/<a href="http://site-a.com" target="_blank">site-a.com</a>).<br>

<br>Even if I could figure out a good way to represent this on the file system, the CMS (and my nginx config for serving static and cached content) supports serving different files for a request to the same site based on the requested host.&nbsp; This is useful (and is actually being used) for a company with multiple locations that wants a site tailored to each location.&nbsp; For instance, when you request <a href="http://site-a.com" target="_blank">site-a.com</a>, you see the home page with the address and phone number for the company&#39;s primary location in the header.&nbsp; Requesting <a href="http://site-b.com" target="_blank">site-b.com</a> shows the exact same home page except that the header now has the address and phone number for the company&#39;s secondary location.&nbsp; Similarly, a slightly different logo image can be served for <a href="http://site-b.com" target="_blank">site-b.com</a>, even though both images are at /images/logo.gif.&nbsp; As such, simply symlinking /var/www/<a href="http://site-b.com" target="_blank">site-b.com</a> to point to /var/www/<a href="http://site-a.com" target="_blank">site-a.com</a> would break this functionality.<br>

<br>I still think the original solution will work -- I&#39;ll just have to have two server directives on the back-end nginx for each site (one for http, and one for https).&nbsp; This isn&#39;t a problem, as this is how it works now -- only now, the backend nginx uses server_name to choose the proper server directive whereas with the new solution it will use an internal IP and port number to do the same thing.<br>
<font color="#888888">
<br>Nick</font></blockquote></div></div></div>