3

I have read every post, tutorial and comment on forums out there an for the life of me still cannot get Nginx proxy to work properly once SSL is turned withing Nginx server block.

Apache is fully set up with virtual host for both regular and ssl access. Apache is listening on port 8081 with ports.conf is as follows:

NameVirtualHost *:8081
Listen 8081

<IfModule ssl_module>
        Listen 443
</IfModule>

<IfModule mod_gnutls.c>
        Listen 443
</IfModule>

My SSL apache vhost is as follows:

With nginx turned on and ssl settings commented out as in the following configuration (see below) everything works fine as I am able to access both SSL and non SSL versions of site correctly.

    server {
        listen 80;
  #      listen 443 ssl;
        server_name foobar.net;

   # ssl on;
   #     ssl_certificate /etc/letsencrypt/live/foobar.net/fullchain.pem;
   #     ssl_certificate_key /etc/letsencrypt/live/foobar.net/privkey.pem;

        location / {
            proxy_pass http://104.236.224.53:8081;
            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 $scheme;
        }
    }

When I modify above file and turn on SSL by un-commenting options in server block there appears to be a conflict between Nginx and Apache on port 443?

Updated and un-commented server blocks looks like so:

    server {
        listen 80;
        listen 443 ssl;
        server_name foobar.net;

    ssl on;
        ssl_certificate /etc/letsencrypt/live/foobar.net/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/foobar.net/privkey.pem;

        location / {
            proxy_pass http://104.236.224.53:8081;
            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 $scheme;
        }
    }

Trying to start nginx return following error:

 nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Mon 2017-02-20 18:35:20 EST; 16s ago
  Process: 14505 ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid (code=exited, status=0/SUCCESS
  Process: 14475 ExecReload=/usr/sbin/nginx -g daemon on; master_process on; -s reload (code=exited, status=0/SUCCESS)
  Process: 14671 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=1/FAILURE)
  Process: 14652 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 14328 (code=exited, status=0/SUCCESS)

Feb 20 18:35:18 foo.foobar.net nginx[14671]: nginx: [emerg] listen() to 0.0.0.0:443, backlog 511 failed (98: Address already in use)
Feb 20 18:35:18 foo.foobar.net nginx[14671]: nginx: [emerg] listen() to 0.0.0.0:443, backlog 511 failed (98: Address already in use)
Feb 20 18:35:19 foo.foobar.net nginx[14671]: nginx: [emerg] listen() to 0.0.0.0:443, backlog 511 failed (98: Address already in use)
Feb 20 18:35:19 foo.foobar.net nginx[14671]: nginx: [emerg] listen() to 0.0.0.0:443, backlog 511 failed (98: Address already in use)
Feb 20 18:35:20 foo.foobar.net nginx[14671]: nginx: [emerg] listen() to 0.0.0.0:443, backlog 511 failed (98: Address already in use)
Feb 20 18:35:20 foo.foobar.net nginx[14671]: nginx: [emerg] still could not bind()
Feb 20 18:35:20 foo.foobar.net systemd[1]: nginx.service: Control process exited, code=exited status=1
Feb 20 18:35:20 foo.foobar.net systemd[1]: Failed to start A high performance web server and a reverse proxy server.
Feb 20 18:35:20 foo.foobar.net systemd[1]: nginx.service: Unit entered failed state.
Feb 20 18:35:20 foo.foobar.net systemd[1]: nginx.service: Failed with result 'exit-code'.

What am I missing here with my implementation to get SSL to get passed on properly to Apache from Nginx?


Edit 1: To address @Tim's good point I'll edit my main intent in having Nginx handling all requests.

  • My original intention was to install Discourse, which itself is in a Docker container, on the same machine where Apache was already being used as my main server.
  • Because Discourse needs access to port 80 to run properly, it is recommended to setup nginx in front as a reverse proxy to handle all incoming requests so that it passes them accordingly.
  • I want to use apache on the back to handle all dynamic content and let nginx handle static bits. And so it is my understanding that in order to do so a virtual hos needs to be established on apache for each instance: both http and https requests. Maybe I'm wrong here on this point?

I followed configurations suggested by DigitalOcean: fast forward to their optional step 9.

Logically at this point, just as I have HTTP host on apache listening on port 8081 for requests being passed on from nginx, I assumed I could do the same and also have HTTPS host on apache listen to port 8081 and gracefully pass headers over to Apache to handle the rest. This implementation did not work fully as I was plagued with error 400: the plain http request was sent to https port

I took it a step further and assumed that again maybe since both of Apache HTTP and HTTPS are listening to port 8081 on back that if I assigned assigned apache HTTP to port 8081 and HTTPS to port 1443 everything would work seamlessly. Again it does not work fully as when I try to access my worpress blog via HTTPS with this implementation I get error

Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.

At this point I'm literally fresh out of ideas even though it seems many have gotten digital ocean suggested implementation to work properly. :-/

Robert
  • 31
  • 1
  • 5

3 Answers3

2

You've told both Apache and Nginx to listen on port 443, I assume on the same machine. Only one application can listen on a port.

Perhaps you could edit your question to tell us why you want to use both Nginx and Apache - you can do most things with either of them. You might get more useful advice that way.

Tim
  • 30,383
  • 6
  • 47
  • 77
0

Looks like I finally got implementation thanks to all the feedback I received from you. Thanx @AlexeyTen and @Tim

  • First I disabled https vhost on apache for domain foobar.net sudo a2dissite foobar.net.cong

  • I edited apache ports.conf file to only listen to port 8081 and removed listening on port 443:

NameVirtualHost *:8081

Listen 8081
  • Finally I edited nginx server block to listen to port 443 and made sure to comment out ssl on. Not doing so did not work.
> server {
>     listen 80;
>     listen 443 ssl;
>     server_name foobar.net;
> 
>   # ssl on;
>     ssl_certificate /etc/letsencrypt/live/foobar.net/fullchain.pem;
>     ssl_certificate_key /etc/letsencrypt/live/foobar.net/privkey.pem;
> 
>     location / {
>         proxy_pass http://104.236.224.53:8081;
>         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 $scheme;
>     } }

This implementation appears to work fine and handover php handling to Apache seamlessly.

Robert
  • 31
  • 1
  • 5
  • So basically you did what I said, you just needed a bit more detail on how to do it :-) – Tim Feb 21 '17 at 19:21
0

@Robert, your solution worked but did not load SSL certificates in browser.

My solution is as below:

Change default port for apache from 80 to 8080

Change default SSL port for apache from 443 to 444

Below is my ngnix config:

server 
{

listen 80;

    server_name servername.com;

location / {

        proxy_pass http://127.0.0.1:8080;
        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 $scheme;
        expires off;
    }
}


server {

    listen 443 ssl http2;
    server_name servername.com;
    ssl on;
    ssl_certificate /etc/nginx/ssl/keyname.crt;
    ssl_certificate_key /etc/nginx/ssl/private/keyname.key;

location / {

        proxy_pass https://127.0.0.1:444;
        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 $scheme;
        expires off;
    }
}

Note:

  1. proxy_pass needs to be changed to https in case of SSL.
  2. This works fine when nginx is serving as reverse proxy for apache.
  3. Requires apache vhost to be modified to include 444 instead of 443 for SSL config.
  4. Configure ports.conf in apache to 444 for SSL
Rouven B.
  • 103
  • 4
yogi
  • 1
  • 1