Passing subdomains to a Node.js app running behind Nginx

I’m trying to implement wildcard subdomains in my Node.js app – for example, a user visiting will hit the app, in addition to

I currently have a Node app running on, as well as an additional WordPress site running at Nginx is acting as a reverse proxy for both of them (server block below). I’ve made changes locally for routing subdomains once they get to the Node app, and they seem to be working locally. But trying to access a subdomain on my Droplet just hangs. I’ve also previously tried setting up a Node app on a subdomain of the Droplet (ex. with similar lack of success – the page just hangs. (I don’t even get a 503 back.)

Something that I’ve noticed is that the server_name specified seems to be ignored; even without specifying one the routing still seems to happen normally.

Any help would be much appreciated!

# Point http requests to https
server {
    listen 80;

    return 301 https://$server_name$request_uri;

server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    include snippets/;
    include snippets/ssl-params.conf;

    root /var/www/html;
    index index.php index.html index.htm index.nginx-debian.html;

    server_name *;

    location / {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;

    location /blog {
        try_files $uri $uri/ /index.php$is_args$args;

    # For Lets Encrypt certbot
    location ~ /.well-known {
        allow all;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;

    location ~ /\.ht {
        deny all;

    location /favicon.ico { alias /var/www/html/example/favicon.ico; }
    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt { log_not_found off; access_log off; allow all; }
# These lines seem to mess with serving static files on the Node app. Might need some other configuration
#    location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
#        expires max;
#        log_not_found off;
#    }


Update: tried accessing the subdomain via another service provider and the page returns as not existing, rather than hanging.

Submit an answer
You can type!ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.


Okay, then it’s quite different. You cannot proxy_pass to a Wildcard (*), so you would pass to and then in Node, you would have to implement something, so you know which subdomain is doing the query (look at header Host).

I would recommend keeping Node.js only listening on the localhost and then have Nginx handle the connection between the visitor and Node with the reverse proxy. Then everything runs through Nginx and it’s the one controlling what goes in and out.

And you would then have to setup 3 different server-blocks in Nginx. One taking care of the http redirect of server_name One serving the https version of those. And finally one serving the Wildcard * on http-only.

This comment has been deleted

Hi @lahuang4

Have you created a DNS record - either A or CNAME for * ?

Do you have a Wildcard certificate, because it seems like you’re using Let’s Encrypt, which doesn’t support Wildcard, but requires that you generate a certificate for each domain.

And your current http-redirect, it’s only redirecting to domains, but you probably want to redirect all to https, so it should look like this:

server {
    listen 80;
    listen [::]:80;
    return 301 https://$server_name$request_uri;

And unless your Node.js is running https and publicly accessible, which means you’ve also setup a certificate in Node.js and it’s accessible directly without Nginx, then your proxy_pass should only look like this:

proxy_pass http://localhost:3000;