2

I'm using nginx as web front-end and apache2 as web back-end. Apache runs several websites locally and nginx access them.

At the moment, different sub-domains are hosted, but I want to migrate them into a single one using http://my-single-domain.com/subdomain-alias thanks to nginx.

The root directory and the apache2 vhost port is different for each sub-domain (sounds obvious, doesn't it?).

I tried several configurations but I cannot get the resource being sent, i.e., the index html is sent but the resources are not found by the server (404 Not Found) despite the rule root being set.

I tried several solution such as:

location /alias1 {
  proxy_pass   http://127.0.0.1:9095/;
  include      /etc/nginx/proxy.conf;
}

or

location /alias1 {
  alias  /alias1/;
  proxy_pass   http://127.0.0.1:9095/;
  include      /etc/nginx/proxy.conf;
}

or even

location /alias1/ {
  rewrite ^/alias1(/.*)$ $1 break;
  proxy_pass http://127.0.0.1:9095/;
}

or again

location /alias1/ {
  rewrite ^/alias1(/.*)$ $1 break;
  proxy_pass   http://127.0.0.1:9095/;
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

What is wrong with this setup? How to set nginx to retrieves assets from a specific root directory when the age /alias1/page is requested ?


Asked first on webmasters.stackexchange.com

---### /etc/nginx/proxy.conf 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-Forwarded-Proto https; #client_max_body_size 10m; #client_body_buffer_size 128k; proxy_connect_timeout 90; #proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffers 32 4k;

/etc/nginx/nginx.conf

 user              www-data  www-data;

 worker_processes  2;

 pid        /var/run/nginx.pid;

 worker_rlimit_nofile 1024;

 events {
         worker_connections 512;
 }


 http {

         include /etc/nginx/mime.types;
         default_type application/octet-stream;
         sendfile "on";
         tcp_nopush "on";
         tcp_nodelay "on";
         keepalive_timeout "65";
         access_log "/var/log/nginx/access.log";
         error_log "/var/log/nginx/error.log";
         server_tokens off;
         types_hash_max_size 2048;

         include /etc/nginx/conf.d/*.conf;
         include /etc/nginx/sites-enabled/*/*;
 }

/etc/nginx/site-enable/single-domain.conf

server {
        listen      443;
        ssl on;
        ssl_certificate /etc/ssl/private/single-domain.com-with_chain.crt;
        ssl_certificate_key /etc/ssl/private/single-domain.com.key.pem;

        ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
        ssl_prefer_server_ciphers on;
        ssl_dhparam /etc/ssl/private/dhparams.pem;

        server_name www.single-domain.com;

        location / {
                proxy_pass   http://127.0.0.1:8090/;
                include      /etc/nginx/proxy.conf;
        }

        location /alias/ {
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_pass   http://127.0.0.1:8103/;
        proxy_set_header Host alias.single-domain.com;
        root /var/www/alias.single-domain.com;
        }

        location ~* \.(jpg|png|gif|jpeg|css|js|mp3|wav|swf|mov|doc|pdf|xls|ppt|docx|pptx|xlsx|otf|eot|svg|ttf|woff)$ {
                root /var/www/single-domain.com/public;
                proxy_buffering on;
                proxy_cache_valid 200 120m;
                expires 864000;
        }

        access_log /var/log/nginx/single-domain.com/www-access.log;
        error_log /var/log/nginx/single-domain.com/www-error.log;
}
  • It's really bad idea. You'll have to modify all your websites to look for static assets not in /img/logo.png but /alias1/img/logo.png. It could be sometimes nearly impossible. – Alexey Ten Mar 4 '16 at 14:09
  • Why you want get rid of subdomains? – Alexey Ten Mar 4 '16 at 14:10
  • The goal is not to get rid of the subdomains, but use the TLS of the single domain instead. The subdomains are just personal and private services that, IMO, do not need subdomains for that in the first place (just that it ease to separate them in the first place). Isn't it possible to request nginx to search assets into another root directory while removing the /alias/-part-path of the asset itself ?! – Auzias Mar 4 '16 at 14:14
  • Just get wildcard cert! Willl be valid for all sub domains. May cost you a little more but will save you a lot of time!! Changing away from sub domains will also have major SEO implications. Don't make such a major change if all your gaining is saving a few bucks on your SSL cert – Nath Mar 6 '16 at 18:58
  • As I said, it's personal and private services that are hosted. I do not need any valid cert while it's a plus. I'm well aware of this solution, that I do not seek (otherwise I would have asked where to buy a wild-card cert, not how to config nginx. Thanks for the comment though. – Auzias Mar 6 '16 at 19:44
2
+50

If apache is listening on port 9095 for domain sub1.example.com and on port 9096 for domain sub2.example.com, and you want nginx to pass http://www.example.com/alias1 to first, and http://www.example.com/alias2 to second apache virtualhost, you would do:

location /alias1/ {
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_pass   http://127.0.0.1:9095/;
        proxy_set_header Host sub1.example.com;
}

location /alias2/ {
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_pass   http://127.0.0.1:9096/;
        proxy_set_header Host sub2.example.com;
}

then for example original request to nginx at http://your-single-domain.example.com/alias1/foo/page1.html would be forwarded to apache as if it went to http://sub1.example.com:9095/foo/page1.html

And original request to nginx at http://your-single-domain.example.com/alias2/bar/baz/page2.html would be forwarded to apache as if it went to http://sub2.example.com:9096/bar/baz/page2.html

Update1 (proof of concept): with the nginx having only config file as above, we run netcat as nc -l -p 9095 (apache should not be listening on that port for this debug), and then open in browser http://www.single-domain.com/alias1/assets/style.css. We should see in netcat output the following:

GET /assets/style.css HTTP/1.1
Host: sub1.example.com
Connection: close
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.6.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1

If there was apache listening on port 9095 instead of our netcat, it would thus get HTTP/1.1 request for URL "http://sub1.example.com/assets/style.css" (which would be shown in /var/log/apache2/access_log or similar)

Note that rewrite ^/alias1(/.*)$ $1 break; isn't needed, as location /alias1/ will automatically strip that /alias1/ part of URL.

If you get different output when using your nginx config file, that means you have conflicting directives in nginx - I that case recommend starting with just the configuration in this answer, checking that it works, and then start adding old configuration blocks one by one until it breaks - and then you'll have conflicting block which needs to change.

Update2: since you posted your nginx config, it is obvious - you have location override that says all your .css files (along the bunch of other files) are to be served directly with nginx from /var/www/single-domain.com/public. Remove or edit it, and it will go through apache.

  • Thanks for your answer! I tried this conf but the assets are still fetched on http://www.single-domain.com/alias1/assets/style.css and not http://alias1.single-domain.com/assets/style.css. – Auzias Mar 10 '16 at 7:56
  • @Auzias are you sure you don't have some other directives in nginx configuration and that you've successfully restarted it? location /alias1 should always match http://www.single-domain.com/alias1/assets/style.css (if nginx is listening on www.single-domain.com, of course!) and thus should always get to apache via specified proxy. – Matija Nalis Mar 11 '16 at 2:09
  • That would explain the weird behavior. I'm positive that nginx restarted. Shouldn't a rewrite ^/alias1(/.*)$ $1 break; be added? – Auzias Mar 11 '16 at 9:29
  • @Auzias see the updated answer; rewrite isn't needed in this case (it would be needed only if you used "location /" instead of "location /alias1") – Matija Nalis Mar 12 '16 at 20:56
  • Hi again, you were actually right! The directive location ~* \.(jpg|...)${ root /var/www/path/to/single-domain sets nginx to fetch every ~*\.(jpg|png|css... in the directory of the single-domain. I guess I have to add a if within this location directive. Or is there a cleaner way to deal with that? – Auzias Mar 13 '16 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.