dokku/dokku-redirect

https redirection not handled

Closed this issue · 19 comments

I have two domains configured for my app: domain.com and www.domain.com, and both are TLS-enabled.

The redirection I have set is domain.com -> www.domain.com.

The readme states:

This plugin only redirects one domain to another and does not handle complete URLs. If both domains are managed by dokku and are TLS enabled, then nginx configuration for https redirects will be handled automatically.

So I should experience:

  1. http://domain.com -> https://www.domain.com
  2. http://www.domain.com -> https://www.domain.com
  3. https://domain.com -> https://www.domain.com

The first and second cases are ok, but the third redirection is not done. In other words, I can see my page at both end-URL https://domain.com and https://www.domain.com.

Here is the resulting nginx.conf:

server {
  listen      [::]:80;
  listen      80;
  server_name www.domain.com;
  access_log  /var/log/nginx/www-access.log;
  error_log   /var/log/nginx/www-error.log;
  return 301 https://$host:443$request_uri;
}

server {
  listen      [::]:443 ssl spdy;
  listen      443 ssl spdy;
  server_name www.domain.com;
  access_log  /var/log/nginx/www-access.log;
  error_log   /var/log/nginx/www-error.log;
ssl_certificate     /home/dokku/www/tls/server.crt;
ssl_certificate_key /home/dokku/www/tls/server.key;

  keepalive_timeout   70;
  add_header          Alternate-Protocol  443:npn-spdy/2;
  location    / {

    gzip on;
    gzip_min_length  1100;
    gzip_buffers  4 32k;
    gzip_types    text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml  application/rss+xml font/truetype application/x-font-ttf font/opentype application/vnd.ms-fontobject image/svg+xml;
    gzip_vary on;
    gzip_comp_level  6;

    proxy_pass  http://www;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection upgrade;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header X-Request-Start $msec;
  }
  include /home/dokku/www/nginx.conf.d/*.conf;
}
server {
  listen      [::]:80;
  listen      80;
  server_name domain.com;
  access_log  /var/log/nginx/www-access.log;
  error_log   /var/log/nginx/www-error.log;
  return 301 https://$host:443$request_uri;
}

server {
  listen      [::]:443 ssl spdy;
  listen      443 ssl spdy;
  server_name domain.com;
  access_log  /var/log/nginx/www-access.log;
  error_log   /var/log/nginx/www-error.log;
ssl_certificate     /home/dokku/www/tls/server.crt;
ssl_certificate_key /home/dokku/www/tls/server.key;

  keepalive_timeout   70;
  add_header          Alternate-Protocol  443:npn-spdy/2;
  location    / {

    gzip on;
    gzip_min_length  1100;
    gzip_buffers  4 32k;
    gzip_types    text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml  application/rss+xml font/truetype application/x-font-ttf font/opentype application/vnd.ms-fontobject image/svg+xml;
    gzip_vary on;
    gzip_comp_level  6;

    proxy_pass  http://www;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection upgrade;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header X-Request-Start $msec;
  }
  include /home/dokku/www/nginx.conf.d/*.conf;
}
upstream www { 
  server 172.17.0.3:5000;
}
server {
  listen      [::]:80;
  listen      80;
  server_name domain.com;
  return 301 $scheme://www.domain.com$request_uri;
}
server {
  listen      [::]:443 ssl spdy;
  listen      443 ssl spdy;
  server_name domain.com;
ssl_certificate     /home/dokku/www/tls/server.crt;
ssl_certificate_key /home/dokku/www/tls/server.key;

  keepalive_timeout   70;
  add_header          Alternate-Protocol  443:npn-spdy/2;

  return 301 $scheme://www.domain.com$request_uri;
}

Here is what happens happens for the 3 cases:

  1. http://domain.com -301--> http://www.domain.com -301--> https://www.domain.com
  2. http://www.domain.com -301--> https://www.domain.com
  3. https://domain.com
Flink commented

Hmmm both domain.com and www.domain.com are listed when you do a dokku domains your_app right?
The README may not be clear enough about this but you should only have the target domain managed via dokku domains and the others (redirects) should only appears in dokku redirect.

So I think if you just remove domain.com with dokku domains:remove and have a redirect set correctly (dokku redirect:set domain.com www.domain.com) then all should work as expected. Just tell me :)

Yes, both are listed.

Well, that's what I did first, but then I have added SSL to my website and I am using a plugin that requests a Let's Encrypt cert for the domains listed on dokku domains, so I had to add domain.com back. (seems like you have a plugin that does the same thing ("You can request a certificate for multiple domains, just be aware that your app should be linked to those domains since Let’s Encrypt will request a challenge for each one of them.")).

So, I am trapped! But there is one thing I don't get: why is the http redirect working, but not the https one? Do you understand what I mean?

Flink commented

Yes my plugin is still under development and I have yet to handle certificate renewal. But you should not have to let all the domains in dokku domains once you have your certificate.

For the redirect not working on the https link it might just be some precedence rule or something like that.

The http redirect rule takes precedence over the previous one, so the https one should too.

Anyway, I'll test!

I am interested in setting up the exact same thing as OP but in reverse (www.domain.com -> domain.com, always https). @marvinroger have you had any luck getting this to work as you wanted since December?

@josegonzalez the issue we are currently commenting on is part of the repo you just linked to.

I'm asking @marvinroger, creator of this issue, if he's had any success with his case.

Shit lol I thought this was the core dokku repo. My bad :(

😉

It look like domain.com -> www.domain.com is working for us using this plugin!

I was able to make it work, but I don't remember how. Let me check my server, within a couple of hours.

@ngoldman forget what I just said: I was not able to make the https redirect work so as a workaround I handled the redirection in my application's code.

@parherman does it work for you with SSL enabled?

@marvinroger Yes, and this is generated in app/nginx.conf:

server {
  listen      [::]:443 ssl spdy;
  listen      443 ssl spdy;
  server_name domain.com;
ssl_certificate     /home/dokku/app/tls/server.crt;
ssl_certificate_key /home/dokku/app/tls/server.key;

  keepalive_timeout   70;
  add_header          Alternate-Protocol  443:npn-spdy/2;

  return 301 $scheme://www.domain.com$request_uri;
}

I have another app where the SSL redirect is not generated, but it turns out that I actually do not have a certificate for domain2.com, only www.domain2.com

My certificate is valid for both domain.com and www.domain.com, so this is not the issue here...

Alright, it works now. @ngoldman, you said you had the exact same setup as me in reverse. So I guess:

  • You want www.domain.com -> domain.com
  • You use Let's Encrypt for the domain and the subdomain, so you need to have www and the root domain into dokku domains

As @Flink said:

you should not have to let all the domains in dokku domains once you have your certificate

The problem I mentioned in the first post is indeed happening when the origin domain is both configured as a domain and as a redirect. To solve this:

  1. Configure your app to use domain.com only
  2. Configure your redirect from www.domain.com -> domain.com
  3. When you want to renew your certificate, just add www.domain.com to the domains of your app, renew your certificate, and remove it. So your crontab will look like:
@monthly dokku domains:add myapp www.domain.com; dokku letsencrypt myapp; dokku domains:remove myapp www.domain.com

So in our case, the problem is not with the redirect plugin, but with the Let's Encrypt plugin. It would be cool if the Let's Encrypt plugin could also request a certificate for the redirect domains. It was talked about in dokku/dokku-letsencrypt#21 but unfortunately it won't be done. So you will have to use the workaround I've described above.

@ngoldman if you agree, and if it works for you, I guess I can close this issue?

@marvinroger makes sense to me, thanks so much for taking the time to explain!

You welcome! Closing the issue, as this is not related to dokku-redirect.