Multi Tenant Rails app: Certbot SSL, Puma and nginx - ruby-on-rails

I'm trying to set up a multi tenant rails app. Nginx & Puma with Certbot. However, certbot will rewrite the nginx conf to hard link to the last domain the server_name list.
Then the other sites "example1.com, exmaple2.com, etc" will not have certs served. They will have certs generated but not hard linked in the conf file.
I've tried seperating each domain into their own conf file in the sites-enabled directory but I get an error about multiple upstreams.
So, what is the solution?

Related

SSL certificate on local Laradock Nginx project

I need your help to set my Laradock (with Docker) using Nginx and SSL "fake" certificate on my local machine.
I have no idea how to setup it. Could you please help me?
Thanks
To enable SSL with the current version of laradock (as of Nov 2019) with a self signed certificate you must enable it in the nginx settings. Inside the folder nginx/sites remove the comments below line 6 "# For https" :
# For https
listen 443 ssl default_server;
listen [::]:443 ssl default_server ipv6only=on;
ssl_certificate /etc/nginx/ssl/default.crt;
ssl_certificate_key /etc/nginx/ssl/default.key;
restart nginx : docker-compose restart nginx
and you're ready.
If google-chrome complains you can enable the flag at chrome://flags/#allow-insecure-localhost to allow even invalid certificates.
The solution given only allows for https://localhost, however you might need to generate your own when using custom domain pointing to localhost, e.g https://testing.dev
I've written a gist to this — https://gist.github.com/r0lodex/0fe03fc8d22241d79cba65107b30868b
Hopefully this will help those who are still searching.

How to deploy rails 5 on digitalocean 16.04 one click app

I make a droplet on digital ocean and select rails 16.04 one click app.
Then done all project changes after clone
like bundle install , database.yml changes , migrations , assets precompile. All done fine
Now I don't know where to replace demo_name with my project name in nginx and puma settings and how to restart puma also
Please help thanks
Install passenger gem and add lines in your nginx conf file:
server {
listen 80;
server_name 67.205.128.137;
# Tell Nginx and Passenger where your app's 'public' directory is
root /var/www/app_name/public;
# Turn on Passenger
passenger_enabled on;
passenger_ruby /root/.rvm/gems/ruby-2.2.2/wrappers/ruby;
}
Restart nginx by command:
sudo /etc/init.d/nginx restart

LetsEncrypt in a Docker (docker-compose) app container not working

I'm using docker-compose for a rails app to have an app and db container. In order to test some app functionality I need SSL...so I'm going with LetsEncrypt vs self-signed.
The app uses nginx, and the server is ubuntu 14.04 lts, with the phusion passenger docker image as a base image (lightweight debian)
Normally with LetsEncrypt, I run the usual ./certbot-auto certonly --webroot -w /path/to/app/public -d www.example.com
My server runs nginx (proxy passing the app to the container), so I've hopped into the container to run the certbot command without issue.
However, when I try to go to https://test-app.example.com it doesn't work. I can't figure out why.
Error on site (Chrome):
This site can’t be reached
The connection was reset.
Curl gives a bit better error:
curl: (35) Unknown SSL protocol error in connection to test-app.example.com
Server nginx app.conf
upstream test_app { server localhost:4200; }
server {
listen 80;
listen 443 default ssl;
server_name test-app.example.com;
# for SSL
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_dhparam /etc/ssl/dhparam.pem;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-RSA-blahblahblah-SHA';
location / {
proxy_set_header Host $http_host;
proxy_pass http://test_app;
}
}
Container's nginx app.conf
server {
server_name _;
root /home/app/test/public;
ssl_certificate /etc/letsencrypt/live/test-app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/test-app.example.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_dhparam /etc/ssl/dhparam.pem;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-RSA-blahblah-SHA';
passenger_enabled on;
passenger_user app;
passenger_ruby /usr/bin/ruby2.3;
passenger_app_env staging;
location /app_test/assets/ {
passenger_enabled off;
alias /home/app/test/public/assets/;
gzip_static on;
expires +7d;
add_header Cache-Control public;
break;
}
}
In my Dockerfile, I have:
# expose port
EXPOSE 80
EXPOSE 443
In my docker-compose.yml file I have:
test_app_app:
build: "."
env_file: config/test_app-application.env
links:
- test_app_db:postgres
environment:
app_url: https://test-app.example.com
ports:
- 4200:80
And with docker ps it shows up as:
Up About an hour 443/tcp, 0.0.0.0:4200->80/tcp
I am now suspecting it's because the server's nginx - the "front-facing" server - doesn't have the certs, but I can't run the LetsEncrypt command without an app location.
I tried running the manual LetsEncrypt command on the server, but because I presumably have port 80 exposed, I get this: socket.error: [Errno 98] Address already in use Did I miss something here?
What do I do?
Fun one.
I would tend to agree that it's likely due to not getting the certs.
First and foremost read my disclaimer at the end. I would try to use DNS authentication., IMHO it's a better method for something like Docker. A few ideas come to mind. Easiest that answers your question would be a docker entrypoint script that gets the certs first and then starts nginx:
#!/bin/bash
set -ea
#get cert
./certbot-auto certonly --webroot -w /path/to/app/public -d www.example.com
#start nginx
nginx
This is "okay" solution, IMHO, but is not really "automated" (which is part of the lets encrypt goals). It doesn't really address renewing the certificate down the road. If that's not a concern of yours, then there you go.
You could get really involved and create an entrypoint script that detects when the cert expires and then rerun the command to renew it and then reloads nginx.
A much more complicated (but also more scalable solution) would be to create a docker image that's sole purpose in life is to handle lets_encrypt certificates and renewals and then provide a way of distributing those certificates to other containers, eg: nfs (or shared docker volumes if you are really careful).
For anyone in the future reading this: this was written before compose hooks was an available feature, which would be by far the best way of handling something like this.
Please read this disclaimer:
Docker is not really the best solution for this, IMHO. Docker images should be static data. Because lets encrypt certificates expire after 3 months, that means your container should have a shelf-life of three months or less (or, like I said above, account for renewing). "Thats fine!" I hear you say. But that would also mean you are constantly getting a new certificate issued each time you start the container (with the entrypoint method). At the very least, that means that the previous certificate gets revoked every time. I don't know what the ramifications are for doing this with Lets Encrypt. They may only give you so many revokes before they think something fishy is going on.
What I tend to do most often is actually use configuration management and use nginx as the "front" on the host system. Or rely on some other mechanism to handle SSL termination. But that doesn't answer your question of how to get Lets Encrypt to work with docker. :-)
I hope that helps or points you in a better direction. :-)
I knew I was missing one small thing. As stated in the question, since the nginx on the server is the 'front-facing' nginx, with the container's nginx specifically for the app, the server's nginx needed to know about the SSL.
The answer was super simple. Copy the certs over! (Kudos to my client's ops lead)
I cat the fullchain.pem and privkey.pem in the docker container and created the associated files in /etc/ssl on the server.
On the server's /etc/nginx/sites-enabled/app.conf I added:
ssl_certificate /etc/ssl/test-app-fullchain.pem;
ssl_certificate_key /etc/ssl/test-app-privkey.pem;
Checked configuration and restarted nginx. Boom! Worked like a charm. :)

AWS Elastic Beanstalk Rails modify passenger config gzip

Hi I have an EBS app and trying to enable gzip on this. However when i test for gzip compression, I see that the home page itself is gzip enabled, however the api calls are not gzip enabled.
For example:
masterpiecesart.com - gzip on!
http://masterpiecesart.com/api/v2/countries.json - gzip off!
Do i have to add some additional config files in the .ebextensions folder to enable gzip on all calls?
If so, where should this config be added. In one suggested answer(Increasing client_max_body_size in Nginx conf on AWS Elastic Beanstalk), I see that the below /etc/nginx/.. folder is where the conf should be added.
files:
"/etc/nginx/conf.d/proxy.conf" :
mode: "000777"
owner: ec2-user
owner: ec2-user
content: |
client_max_body_size 20M;
gzip on;
However, when I ssh into my ebs ec2 instance, I see no nginx folder inside the /etc/ directory. The nginx server is running at /var/lib/passenger-standalone/3.0.17-x86_64-ruby1.9.3-linux-gcc4.6.2-1002/nginx-1.2.3/sbin/nginx and thr config seems to be from the /tmp/passenger-standalone.1661/config file.
In the config file which I should add to .ebextensions, where should I add the proxy.conf file if not at the "/etc/nginx/conf.d/proxy.conf" as specified in the above answer.
Any help would be great, thanks in advance!

Nginx and Passenger deploy issue

Currently I can only get the default nginx page to come up on my domain name. I am pretty sure the error is either in the /etc/hosts file or the enginx.config file.
my /etc/hosts file is
127.0.0.1 localhost.localdomain localhost
myip server.mydomain.com server
and nginx.config is:
server {
listen 80;
server_name server.mydomain.com;
root /whatever/pulic;
passenger_enabled on;
rails_env production;
I don't get any errors in the log. Incidentally I can run mongrel and on mydomain:3000 see the application there.
In your /etc/hosts, you have
123.45.67.78 server.domain.com servername
So in you nginx.conf you should have the line
server_name servername
as you defined in the third column of your /etc/host. Make sure you don't still have the default nginx server block in your nginx.conf file, too, otherwise it might be taking priority (based on it's relative position).
We just had this issue. The problem turned out to be that Nginx was using a different config file than we thought it was (possibly an issue with how it was compiled on the server?).
We discovered this by doing nginx -t, which lists the config file it's reading and tests the syntax. The one it said it was testing was not the one we expected.

Resources