0
votes

I have been trying for a long time to set up a reverse proxy with nginx that works with both nodejs over ssl on port 3000 and apache over ssl on port 443. I have tried so many things that my conf files probably have tons of errors. My most recent attempt had this as the /etc/apache2/sites-enabled/000-default.conf:

<VirtualHost *:443>
        # The ServerName directive sets the request scheme, hostname and port t$
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin [email protected]
        DocumentRoot /var/www/html/public
        SSLEngine on
        SSLCertificateFile /var/www/certs/test_com.crt
        SSLCertificateKeyFile /var/www/certs/test_com.key

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

And my nginx configuration looks like this:

server {
listen 80;

access_log /var/log/nginx/secure.log;
error_log /var/log/nginx/secure.error.log;    


server_name test.com;

ssl on;
ssl_certificate /var/www/certs/test_com.crt;
ssl_certificate_key /var/www/certs/test_com.key;



location / {
    proxy_pass https://127.0.0.1:3000;
}

location /public {
    proxy_pass https://127.0.0.1:443;
    root /var/www/html/public; //this is where I keep all the html files
}
}

When I run netstat -tulpn I get:

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -               
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               
tcp6       0      0 :::22                   :::*                    LISTEN      -               
tcp6       0      0 :::3000                 :::*                    LISTEN      -               
udp        0      0 0.0.0.0:68              0.0.0.0:* 

This is my first time setting up a server like this so I would really appreciate it if someone could explain how reverse proxies are supposed to work with a nodejs server that uses webpages from an apache instance over ssl.

I'm not sure how this works, but if I had to guess logically, I would want an nginx instance listening on port 80 that redirects all http traffic to https traffic. I would want apache configured on port 443 so I would be able to browse to my css stylesheet https://test.com/assets/css/stylesheet.css and be able to use that as a path in my node server.

I found this in my searches but was unable to correctly implement it:https://www.digitalocean.com/community/questions/how-to-setup-ssl-for-nginx-and-apache

I know I'm not explaining it very well, but I hope someone is able to understand what I need and help me out. Thanks!

1

1 Answers

0
votes

Yes this sounds confusing. It is very common to have static assets served directly from nginx, then reverse proxy all other requests to some backend (node on 3000). I am very confused by the need for Apache. If you really need Apache this is how you can do it.

First, you said you want nginx to listen on port 80 and just redirect all http traffic to https, configure your nginx like this.

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
}

Thats it for nginx. Now for Apache, you need mod_proxy, it will listen on 443 and handle TLS termination, then proxy requests to node listening on 3000

<VirtualHost *:*>
  # your config here...

  ProxyPreserveHost On 
  ProxyPass / http://localhost:3000/
  ProxyPassReverse / http://localhost:3000/ 
</VirtualHost> 

https://httpd.apache.org/docs/2.4/mod/mod_proxy.html

I'm not sure why you want to do it this way, if you can, I'd suggest only using nginx to listen on 80, redirect to 443, handle TLS termination, serve static assets, and reverse proxy to your backend. It's much simpler to set up.

example

untested nginx config

# replace 'domain.com' with your domain name
# http server, redirects to https
server {
  listen 80;
  listen [::]:80;
  server_name example.com;
  return 301 https://example.com$request_uri;
}

# https server
server {
  listen 443 ssl;
  listen [::]:443 ssl;
  server_name example.com;

  ssl on;

  # replace this with your cert+key path
  ssl_certificate /etc/ssl/private/YOUR_CERT.crt;
  ssl_certificate_key /etc/ssl/private/YOUR_SERVER_KEY.key;

  ssl_session_timeout 1d;
  ssl_session_cache shared:SSL:20m;
  ssl_session_tickets off;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers on;

  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:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';

  ssl_stapling on;
  ssl_stapling_verify on;

  # replace 'node-app' with your app name
  access_log /var/log/nginx/node-app.access.log;
  error_log /var/log/nginx/node-app.error.log;

  location / {
    # the path to your static assets
    root /var/www/your-app/public;

    try_files $uri $uri/ @nodebackend;
  }

  # all requests to locations not found in static path
  # will be forwarded to the node server
  location @nodebackend {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_pass http://localhost:3000;
    proxy_redirect off;
  }
}