SSL fails to redirect from www to non-www

The problem I am facing is I can reach my site with Staff Login but I can't reach the same site with https://www.tapme.dk/login_staff. In my DNS I have 3 A records all pointing to the same server IP

  • A record : *.tapme.dk
  • A record : tapme.dk
  • A record : www.tapme.dk

After having run the command sudo certbot --nginx my www.tapme.dk.conf is as below. When I
curl -L Staff Login

I get the expected output from my site

but when I curl -L https://www.tapme.dk/login_staff

I get this error

jianwu@localhost:~/review_fountain/reviewstream$ curl -L https://www.tapme.dk/login_staff
curl: (60) SSL: no alternative certificate subject name matches target host name 'www.tapme.dk'
More details here: curl - SSL CA Certificates

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.


Please fill out the fields below so we can help you better. Note: you must provide your domain name to get help. Domain names for issued certificates are all made public in Certificate Transparency logs (e.g. crt.sh | example.com), so withholding your domain name here does not increase secrecy, but only makes it harder for us to provide help.

My domain is: https://tapme.dk

I ran this command: sudo certbot --nginx

It produced this output:

my /etc/nginx/sites-available/www.tapme.dk.conf output the below file after running the sudo certbot --nginx command

server_tokens               off;
access_log                  /home/jianwu/review_fountain/reviewstream/reviewstream/nginx_access.log;
error_log                   /home/jianwu/review_fountain/reviewstream/reviewstream/nginx_error.log;

# This configuration will be changed to redirect to HTTPS later
server {
  server_name               .tapme.dk;
  location / {
    proxy_pass              http://localhost:8000;
    proxy_set_header        Host $host;
  }

  location /static {
        autoindex on;
        alias /home/jianwu/review_fountain/reviewstream/productionStatic;
  }

  location /media {
        autoindex on;
        alias /home/jianwu/review_fountain/reviewstream/media;
  }


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/www.tapme.dk/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/www.tapme.dk/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


}

server {
    if ($host = www.tapme.dk) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


  server_name               .tapme.dk;
    listen 80;
      return 404; # managed by Certbot
}

My web server is (include version): nginx/1.24.0 (Ubuntu)

The operating system my web server runs on is (include version): Ubuntu 22.04

My hosting provider, if applicable, is:

I can login to a root shell on my machine (yes or no, or I don't know): yes

I'm using a control panel to manage my site (no, or provide the name and version of the control panel):

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you're using Certbot):

Your certificate is only valid for tapme.dk with no www.

What command did you run to get your certificate?

3 Likes

You actually do have a certificate for the www domain, looking at crt.sh | tapme.dk.

But you're not using it. When connecting to the www subdomain, the certificate for just tapme.dk is being send.

It might have something to do with:

Because I don't think nginx would recognise .tapme.dk as www.tapme.dk? You might want to add a * in front of it.

Nevermind.. My lack of nginx understanding didn't know:

A special wildcard name in the form “.example.org” can be used to match both the exact name “example.org” and the wildcard name “*.example.org”.

Maybe there's some other server_name elsewhere overruling this..

Also, please show the output of sudo certbot certificates.

1 Like

it's most likely certbot not understanding the nginx special wildcard and going automatic with tapme.dk instead of tapme.dk,*.tapme.dk which would need dns-01. :confused:

2 Likes

Sure. The nginx authenticator doesn't do the dns-01 challenge anyway.

But that doesn't explain why the www certificate seems to be configured in nginx, while nginx doesn't send that one. So either we're missing parts of the nginx configuration or something else is going on.

@JianDk next to the request I made earlier, please provide the entire output of sudo nginx -T. (With a CAPITAL T please.)

Also, as @9peppe also mentions, for a wildcard DNS and wildcard nginx configuration to actually work, you'd also need a wildcard certificate, which is not possible with the http-01 challenge provided by the nginx authenticator. You'd need to use the dns-01 challenge for that.

1 Like

Thanks for comments. Right now when I do ningx -T I get the below response. Should I make a change in my nginx config file followed by renew my SSL certificate?

sudo nginx -T
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

configuration file /etc/nginx/nginx.conf:

user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;

        ##
        # Gzip Settings
        ##

        gzip on;

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        ##
        # Virtual Host Configs
        ##

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


#mail {
#       # See sample authentication script at:
#       # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
#       # auth_http localhost/auth.php;
#       # pop3_capabilities "TOP" "USER";
#       # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
#       server {
#               listen     localhost:110;
#               protocol   pop3;
#               proxy      on;
#       }
#
#       server {
#               listen     localhost:143;
#               protocol   imap;
#               proxy      on;
#       }
#}

# configuration file /etc/nginx/mime.types:

types {
    text/html                                        html htm shtml;
    text/css                                         css;
    text/xml                                         xml;
    image/gif                                        gif;
    image/jpeg                                       jpeg jpg;
    application/javascript                           js;
    application/atom+xml                             atom;
    application/rss+xml                              rss;

    text/mathml                                      mml;
    text/plain                                       txt;
    text/vnd.sun.j2me.app-descriptor                 jad;
    text/vnd.wap.wml                                 wml;
    text/x-component                                 htc;

    image/avif                                       avif;
    image/png                                        png;
    image/svg+xml                                    svg svgz;
    image/tiff                                       tif tiff;
    image/vnd.wap.wbmp                               wbmp;
    image/webp                                       webp;
    image/x-icon                                     ico;
    image/x-jng                                      jng;
    image/x-ms-bmp                                   bmp;

    font/woff                                        woff;
    font/woff2                                       woff2;

    application/java-archive                         jar war ear;
    application/json                                 json;
    application/mac-binhex40                         hqx;
    application/msword                               doc;
    application/pdf                                  pdf;
    application/postscript                           ps eps ai;
    application/rtf                                  rtf;
    application/vnd.apple.mpegurl                    m3u8;
    application/vnd.google-earth.kml+xml             kml;
    application/vnd.google-earth.kmz                 kmz;
    application/vnd.ms-excel                         xls;
    application/vnd.ms-fontobject                    eot;
    application/vnd.ms-powerpoint                    ppt;
    application/vnd.oasis.opendocument.graphics      odg;
    application/vnd.oasis.opendocument.presentation  odp;
    application/vnd.oasis.opendocument.spreadsheet   ods;
    application/vnd.oasis.opendocument.text          odt;
    application/vnd.openxmlformats-officedocument.presentationml.presentation
                                                     pptx;
    application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
                                                     xlsx;
    application/vnd.openxmlformats-officedocument.wordprocessingml.document
                                                     docx;
    application/vnd.wap.wmlc                         wmlc;
    application/wasm                                 wasm;
    application/x-7z-compressed                      7z;
    application/x-cocoa                              cco;
    application/x-java-archive-diff                  jardiff;
    application/x-java-jnlp-file                     jnlp;
    application/x-makeself                           run;
    application/x-perl                               pl pm;
    application/x-pilot                              prc pdb;
    application/x-rar-compressed                     rar;
    application/x-redhat-package-manager             rpm;
    application/x-sea                                sea;
    application/x-shockwave-flash                    swf;
    application/x-stuffit                            sit;
    application/x-tcl                                tcl tk;
    application/x-x509-ca-cert                       der pem crt;
    application/x-xpinstall                          xpi;
    application/xhtml+xml                            xhtml;
    application/xspf+xml                             xspf;
    application/zip                                  zip;

    application/octet-stream                         bin exe dll;
    application/octet-stream                         deb;
    application/octet-stream                         dmg;
    application/octet-stream                         iso img;
    application/octet-stream                         msi msp msm;

    audio/midi                                       mid midi kar;
    audio/mpeg                                       mp3;
    audio/ogg                                        ogg;
    audio/x-m4a                                      m4a;
    audio/x-realaudio                                ra;

    video/3gpp                                       3gpp 3gp;
    video/mp2t                                       ts;
    video/mp4                                        mp4;
    video/mpeg                                       mpeg mpg;
    video/ogg                                        ogv;
    video/quicktime                                  mov;
    video/webm                                       webm;
    video/x-flv                                      flv;
    video/x-m4v                                      m4v;
    video/x-matroska                                 mkv;
    video/x-mng                                      mng;
    video/x-ms-asf                                   asx asf;
    video/x-ms-wmv                                   wmv;
    video/x-msvideo                                  avi;
}

# configuration file /etc/nginx/sites-enabled/default:
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}
}


# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#       listen 80;
#       listen [::]:80;
#
#       server_name example.com;
#
#       root /var/www/example.com;
#       index index.html;
#
#       location / {
#               try_files $uri $uri/ =404;
#       }
#}

# configuration file /etc/nginx/sites-enabled/www.tapme.dk.conf:
server_tokens               off;
access_log                  /home/jianwu/review_fountain/reviewstream/reviewstream/nginx_access.log;
error_log                   /home/jianwu/review_fountain/reviewstream/reviewstream/nginx_error.log;

# This configuration will be changed to redirect to HTTPS later
server {
    if ($host = www.tapme.dk) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


  listen  80;
  server_name www.tapme.dk;
  return  301 https://tapme.dk$request_uri;


}

server {
  server_name               .tapme.dk;
  location / {
    proxy_pass              http://localhost:8000;
    proxy_set_header        Host $host;
  }

  location /static {
        autoindex on;
        alias /home/jianwu/review_fountain/reviewstream/productionStatic;
  }

  location /media {
        autoindex on;
        alias /home/jianwu/review_fountain/reviewstream/media;
  }


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/www.tapme.dk/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/www.tapme.dk/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot



}

server {
    if ($host = www.tapme.dk) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


  server_name               .tapme.dk;
    listen 80;
      return 404; # managed by Certbot
}
# configuration file /etc/letsencrypt/options-ssl-nginx.conf:
# This file contains important security parameters. If you modify this file
# manually, Certbot will be unable to automatically provide future security
# updates. Instead, Certbot will print and log an error message with a path to
# the up-to-date file that you will need to refer to when manually updating
# this file. Contents are based on https://ssl-config.mozilla.org

ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";

I'm not entirely sure, but maybe this part you left out earlier:

can mess up the virtualhost with the .tapme.dk server_name?

It shouldn't. One is for port 80 the other port 443.

@JianDk Would you also show this?

2 Likes

Yeah I also thought about that, but I didn't know what else it could be.. Except for manually messed up Certbot configurations :wink:

Also the default server_name _; could maybe be something?

There is definitely something else going wrong (probably not that) but knowing the certbot certificates would be helpful in any case.

Note this 404 shouldn't be happening so I was hoping to see all the info first

curl -i http://www.tapme.dk
HTTP/1.1 404 Not Found
Server: nginx
3 Likes

here is the output from certbot certificate

sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log


Found the following certs:
Certificate Name: tapme.dk
Serial Number: 40ab80239d77836aafc42f622a1830a1b75
Key Type: ECDSA
Domains: tapme.dk
Expiry Date: 2025-03-07 09:58:48+00:00 (VALID: 80 days)
Certificate Path: /etc/letsencrypt/live/tapme.dk/fullchain.pem
Private Key Path: /etc/letsencrypt/live/tapme.dk/privkey.pem


The nginx you showed us uses a path of .../live/www.tapme.dk/...

But, your certificate list does not have that certificate path.

Do you have multiple nginx systems? Because nginx will usually fail to start with an invalid certificate path.

1 Like

I solved it now but still I am a bit unsure what really went wrong. I did this:

step 1. I realized that my nginx conf file which is called www.tapme.dk.conf did not have the .conf ending. I realized this by doing a ls -la

step 2. I deleted the old www.tapme.dk file and created a new one. This time making sure that it ends with .conf

step 3. In the new nginx configuration file I started with

server_tokens               off;
access_log                  /home/jianwu/review_fountain/reviewstream/nginx_access.log;
error_log                   /home/jianwu/review_fountain/reviewstream/nginx_error.log;

# This configuration will be changed to redirect to HTTPS later
server {
  server_name               .tapme.dk;
  location / {
    proxy_pass              http://localhost:8000;
    proxy_set_header        Host $host;
    proxy_set_header    X-Forwarded-Proto $scheme;
  }

  location /static {
    autoindex on;
    alias /home/jianwu/review_fountain/reviewstream/productionStatic;
  }
}

I then checked to make sure that I can access the page both with Staff Login and http://tapme.dk/login_staff . That was positive.

step 4.
I then proceed by sudo certbot --nginx. When it asked me for domain, I tested first with tapme.dk. Things went smootly, BUT I can no longer access https://www.tapme.dk/login_staff and only access the page with Staff Login

step 5. Since the sudo certbot --nginx command wrote into my www.tapme.dk.conf I restored the file back to

server {
  server_name               .tapme.dk;
  location / {
    proxy_pass              http://localhost:8000;
    proxy_set_header        Host $host;
    proxy_set_header    X-Forwarded-Proto $scheme;
  }

  location /static {
    autoindex on;
    alias /home/jianwu/review_fountain/reviewstream/productionStatic;
  }
}

step 6. I rerun the sudo certbot --nginx. When I asked for domain I input www.tapme.dk . This solved the problem. The resulting www.tapme.dk.conf after running the command looks as below

server_tokens               off;
access_log                  /home/jianwu/review_fountain/reviewstream/nginx_access.log;
error_log                   /home/jianwu/review_fountain/reviewstream/nginx_error.log;

# This configuration will be changed to redirect to HTTPS later
server {
  server_name               .tapme.dk;
  location / {
    proxy_pass              http://localhost:8000;
    proxy_set_header        Host $host;
    proxy_set_header    X-Forwarded-Proto $scheme;
  }

  location /static {
    autoindex on;
    alias /home/jianwu/review_fountain/reviewstream/productionStatic;
  }



    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/www.tapme.dk/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/www.tapme.dk/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = www.tapme.dk) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


  server_name               .tapme.dk;
    listen 80;
    return 404; # managed by Certbot


}

now I can access using Staff Login and https://www.tapme.dk/login_staff

now doing

sudo certbot certificates

Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: tapme.dk
    Serial Number: 40ab80239d77836aafc42f622a1830a1b75
    Key Type: ECDSA
    Domains: tapme.dk
    Expiry Date: 2025-03-07 09:58:48+00:00 (VALID: 80 days)
    Certificate Path: /etc/letsencrypt/live/tapme.dk/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/tapme.dk/privkey.pem
  Certificate Name: www.tapme.dk
    Serial Number: 3d74f8cea15e3409a2eb613e5066e713ab8
    Key Type: ECDSA
    Domains: www.tapme.dk
    Expiry Date: 2025-03-16 16:22:30+00:00 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/www.tapme.dk/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/www.tapme.dk/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Two things:

  1. Now you're sending the www.tapme.dk certificate also for tapme.dk, which is incorrect;
  2. You could have combined the two certs into a single certificate for tapme.dk and www.tapme.dk.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.