8

I have recently deployed my Ruby on Rails application to a plain Ubuntu 16.04 DigitalOcean droplet with Nginx, passenger & Let's encrypt.

The rails app worked fine with just passenger and Nginx but after I installed Let's Encrypt, it points to the "Welcome to Nginx" page instead of my rails app.

I am able to make changes to see the "Welcome to Nginx!" page and see the results in the browser.

When I change the root location in my sites-enabled configs to my application path instead of /html I get a 403 Forbidden error.

This is where my application is: /var/www/myapp/code/

I don't know what gives... I keep getting "403 Forbidden nginx/1.14.0" when I try to change the root to my app's /public directory. I've even moved the /html folder into myapp directory and it loads the "Welcome to Nginx!" page there too. Is there something I need to do for it to process my index.html.erb files in my app's views, or, do I need to make a custom index.html without any ERB?

I do not have an index file in my /public directory. What do I need to do for nginx to point to my root_path defined in my rails app's routes?

The permissions are set to root rails for both the (working) "Welcome to Nginx!" index path and myapp/code/public path.

I would love some help, thank you!

My /etc/nginx/sites-enabled/default (without comments):

server {
    root /var/www/myapp/code/public;

    index index.html.erb 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;
    }

  listen [::]:443 ssl ipv6only=on; # managed by Certbot
  listen 443 ssl; # managed by Certbot
  ssl_certificate /etc/letsencrypt/live/transverseaudio.com/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/transverseaudio.com/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.transverseaudio.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = transverseaudio.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80 default_server;
        listen [::]:80 default_server;

        server_name _;
    return 404; # managed by Certbot

}

My /etc/nginx/sites-enabled/myapp.conf:

server {
  listen 80;
  server_name transverseaudio.com www.transverseaudio.com;

  # Tell Nginx and Passenger where your app's 'public' directory is
  root /var/www/myapp/code/public;

  # Turn on Passenger
  passenger_enabled on;
  passenger_ruby /usr/local/rvm/gems/ruby-2.5.1/wrappers/ruby;
}

I looked further into my Ruby + Rails config and verified the right versions where installed:

Rails -v = Rails 5.2.0

Ruby -v = ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]

Jake
  • 1,086
  • 12
  • 38
  • 1
    It sounds like Nginx issue. can you please share more of the Nginx configuration, i.e. the server attribute configuration? – HatzavW Jul 14 '18 at 20:41
  • @HatzavWolff Thanks for asking for these, I updated my question with the config files. – Jake Jul 14 '18 at 22:13
  • 1
    @Jake Please, show your nginx config before you’ve installed Let’s Encrypt. There are settings in your `/etc/nginx/sites-enabled/default` for Certbot which is a part of Let’s Encrypt. So it will be great to see its version before Let’s Encrypt when site worked as needed. – Alexander Ushakov Jul 17 '18 at 05:12
  • @AlexanderUshakov Thanks for pointing this out, as I wasn't using version control, I remade the server with my website functioning without Let's Encrypt. Here is the [pastebin](https://paste.ubuntu.com/p/FP4J7Vdbw7/) w/o the comments in the file. – Jake Jul 17 '18 at 15:49

3 Answers3

2

you describe multiple different problems in your journey. let's tackle them in order they (should) have appeared.

default page

You have correctly identified that the server is serving your root at /var/www/html which is the default homepage. You could try symlinking /var/www/html to you app's public dir, if you don't want to give nginx read access to that directory. The actual issue is, that you are doing a name based hosting and your domain name is configured on the default site and not your myapp.conf. If you move the server_name listed in default to the server_name directive in myapp.conf it would be enough.

Also Passanger is should pick up the requests:

When Passenger handles a request, Nginx will first try and find a matching file in the public directory and if it finds one will serve it directly without passing the request to your app, since many web app frameworks use this directory for static files by default (e.g. Rails, Sinatra). From For a rack app, how do I make passenger-standalone serve the output of .erb files rather of sending the .erb file itself?

403 forbidden

After successfully changing the root of the virtual host, nginx might not be able to read the data there. This could be due to bad file permissions, i.e. the user running nginx cannot read the directory/file.

Also this happens if you don't have an index document and directory indexing is disabled. You can either create a index document or add some rewrite rule.

500

if you tail the logfiles of nginx, it should give you more details for the error message. 500 is a server side error, so nginx should at least give you a hint. I assume it's because of missing in your server section/file.

# Turn on Passenger
passenger_enabled on;
passenger_ruby /usr/local/rvm/gems/ruby-2.3.0/wrappers/ruby;

wrapping it up

ensure also that you have include /etc/nginx/passenger.conf; in your nginx.conf.

so wrapping it all up, I recommend removing the default to get it out of the way.

# redirect non https traffic for the correct domains
server {
    if ($host = www.transverseaudio.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = transverseaudio.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;
    return 404; # managed by Certbot

}

server {
  listen [::]:443 ssl ipv6only=on;
  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/transverseaudio.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/transverseaudio.com/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

  # server for these domains
  server_name transverseaudio.com www.transverseaudio.com;

  # first try to serve the erb version.
  index index.html;

  # Tell Nginx and Passenger where your app's 'public' directory is
  root /var/www/myapp/code/public;

  # Turn on Passenger
  passenger_enabled on;
  passenger_ruby /usr/local/rvm/gems/ruby-2.5.1/wrappers/ruby;
}
Jonathan
  • 752
  • 8
  • 18
  • I changed my `server_name` to `myapp.conf` instead of my domain name, I also changed my `root` to my apps public directory. I'm getting a 403 forbidden now. I may have misunderstood what you were suggesting I do. Would it be better if I just changed myapp directory to my domain name? Also, the log tail is just telling me `directory index of "/var/www/myapp/code/public/" is forbidden`. – Jake Jul 23 '18 at 16:19
  • And how could the permissions be wrong when the "Welcome to Nginx!" page is visible and the edits I've made are updating on the domain? The HTML directory has the same permissions as the public directory from what I see. – Jake Jul 23 '18 at 21:58
  • Do I need to explicitly have an index file in my public directory? – Jake Jul 23 '18 at 22:05
  • I've updated the answer. Please see if that helps you. – Jonathan Jul 24 '18 at 11:24
  • I changed my `server_name` in myapp.conf to the two domain names seen above and I now get: `nginx: [warn] conflicting server name "transverseaudio.com" on 0.0.0.0:80, ignored` for both the root domain and the www. subdomain. I've also moved my nginx index into the public directory, it works fine. I just don't know what I need to do to get my rails app index's to load instead of the "Welcome to Nginx!". – Jake Jul 24 '18 at 13:44
  • you have to remove them on the other file to get rid of the conflict – Jonathan Jul 24 '18 at 14:14
  • Okay, that solved the conflict, but I'm still not sure why my rails app is not being rendered. If the "Welcome to Nginx!" html doc is working in the public directory, why wouldn't my rails app? Do I need to move my root view `index.html.erb` into the public, or would nginx already know how to navigate through my rails view directories and its configured routes? – Jake Jul 24 '18 at 14:26
  • I've lost track of how your config looks like. Can you post the current config again? – Jonathan Jul 24 '18 at 14:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/176660/discussion-between-jake-and-jonathan). – Jake Jul 24 '18 at 14:46
  • It worked!!!! After creating a new droplet and investigating the production.log in my rails app I discovered an error in my code that only prevented my app from launching with Let's Encrypt. For some reason, it never warned me of this while in production with only Nginx and Passenger. I've got to thank you again! – Jake Jul 27 '18 at 20:43
  • I fixed mine by defining the root and index in the SSL server block – Olotin Temitope May 22 '20 at 23:30
0

Usually, you shouldn't have multiple server directives with same server_name when using Nginx. Just remove /etc/nginx/sites-enabled/default file. It's useless.

Upgrade your /etc/nginx/sites-enabled/myapp.conf to something like this:

server {

  listen 80;
  listen 443 ssl;

  server_name transverseaudio.com www.transverseaudio.com;

  ssl_certificate /etc/letsencrypt/live/transverseaudio.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/transverseaudio.com/privkey.pem;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

  # Tell Nginx and Passenger where your app's 'public' directory is
  root /var/www/myapp/code/public;

  # Turn on Passenger
  passenger_enabled on;
  passenger_ruby /usr/local/rvm/gems/ruby-2.3.0/wrappers/ruby;
}

Alternative is to move your myapp.conf content to the first server directive of /etc/nginx/sites-enabled/default and remove myapp.conf

Jake
  • 1,086
  • 12
  • 38
magazovski
  • 11
  • 2
  • Also u can add `include /etc/letsencrypt/options-ssl-nginx.conf;`, but i cant see, what is inside. – magazovski Jul 17 '18 at 16:54
  • This just got rid of `https://` functionality. It works, but only has the root domain (i.e. without `http/https`) and the `www.` subdomain simply points to "Welcome to Nginx" – Jake Jul 17 '18 at 17:18
  • Can you show output of `nginx -c /etc/nginx/nginx.conf -T` ? – magazovski Jul 17 '18 at 17:30
  • Sure, I put it all into this [Pastebin](https://paste.ubuntu.com/p/bvCpHjcwXR/). I waited some time, and now it's giving me a page stating: "500 Internal Server Error nginx/1.14.0" - The `http` and `https` are now working, just with those errors on both of them. – Jake Jul 17 '18 at 18:06
  • Do u have certificates inside this dir `/etc/letsencrypt/live/transverseaudio.com/` ? – magazovski Jul 17 '18 at 18:38
  • Yes, I have `cert.pem` `chain.pem` `fullchain.pem` `privkey.pem` `README` – Jake Jul 17 '18 at 18:39
0

In my case (with DigitalOcean, after installing CertBot) I just had to change in nginx/sites-enabled/default :

root var/www/html to correct path.

T.Todua
  • 53,146
  • 19
  • 236
  • 237