I'm using Digital Ocean droplet for rails application. I've managed to deploy first application with success, but now facing with problems trying to deploy the second one. I am using unicorn as app server and nginx as web server. OS is Ubuntu 14.04
I've read lots of threads on stackexchange sites, also on blogs etc. but none of them fits my position. Problem is, I think, on app and system folder/file/configuration structures. Which I am very cautious to change anything on system configuration files.
In most examples on web, everyone is talking about unicorn.rb inside
rails_root/config/ however I don't have any. Instead I have unicorn.conf with same content inside /etc.
There is also a socket file which listens for first app, and I tried two create the second for my second app - but it failed.
I know, I have to create another unicorn configuration for second app, and also have to do something which should be resulted with the creation of a socket for second.
But the lack of knowledge and understanding about system administration drives me to trouble.
Can anyone guide me about this problem?
I can provide more files if needed.
nginx configuration file for first app (path /etc/sites-available/first_app).
upstream app_server {
server unix:/var/run/unicorn.sock fail_timeout=0;
}
server {
listen 80;
root /home/rails/myfirstapp/public;
server_name www.myfirstapp.com;
index index.htm index.html index.php index.asp index.aspx index.cgi index.pl index.jsp;
location / {
try_files $uri/index.html $uri.html $uri #app;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mp3|flv|mpeg|avi)$ {
try_files $uri #app;
}
location #app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}
server {
listen 80;
server_name www.myfirstapp.com;
return 301 $scheme://myfirstapp.com$request_uri;
}
second app (/etc/sites-available/second_app)
upstream app_server_2 {
server unix:/var/run/unicorn.app_two.sock fail_timeout=0;
}
server {
listen 80;
root /home/rails/secondapp/public;
server_name secondapp.com;
index index.htm index.html index.php index.asp index.aspx index.cgi index.pl index.jsp;
location / {
try_files $uri/index.html $uri.html $uri #app;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mp3|flv|mpeg|avi)$ {
try_files $uri #app;
}
location #app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server_2;
}
}
server {
listen 80;
server_name secondapp.com www.secondapp.com;
return 301 $scheme://secondapp.com$request_uri;
}
(/etc/unicorn.conf)
listen "unix:/var/run/unicorn.sock"
worker_processes 4
user "rails"
working_directory "/home/rails/myfirstapp"
pid "/var/run/unicorn.pid"
stderr_path "/var/log/unicorn/unicorn.log"
stdout_path "/var/log/unicorn/unicorn.log"
This has probably gone unanswered because you should just use 2 independent droplets as opposed to trying to make this work (which will be a bit of a nightmare for those unfamiliar with server and deployment stuff). Rails has lots of ways to interconnect 2 apps across the interwebs.
If you need to share the database you could even just setup a third droplet (although not needed) and host the centralised DB from there and have both apps connected to it. That also sets you up for mucho scalability.
Unless, of course, I misunderstood what you are trying to do.
If you are using 2 droplets and grammar is our fickle mistress, hook us up with some more details man.
Related
one nginx server is exposed to the internet and redirects the traffic.
A second nginx server is only available internally and listens to port 6880 (bookstack (a wiki) is hosted via docker).
In the local network, everything is unencrypted, while to the outside only https via port 443 is available.
The application (bookstack) works fine in the local network (http).
When accessing the application from the outside via https, the page is displayed, but all links are http instead of https. (For example, http://.../logo.png is in the login page's source code, but https://.../logo.png would be correct.)
Where and how do i switch to https?
First server sites-enabled/bookstack (already contains the redirect to https):
server {
listen 80;
server_name bookstack.example.org;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name bookstack.example.org;
ssl_certificate /etc/letsencrypt/live/<...>/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/<...>/privkey.pem;
location / {
try_files index index.html $uri $uri/index.html $uri.html #bookstack;
}
location #bookstack {
proxy_redirect off;
proxy_set_header X-FORWARDED_PROTO https;
proxy_set_header Host bookstack.example.org;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://<internal ip>:6880;
}
}
Second server sites-enabled/bookstack:
server {
listen 80;
listen [::]:80;
server_name bookstack.example.org;
index index.html index.htm index.nginx-debian.html index.php;
location / {
proxy_pass http://<local docker container ip>:6880;
proxy_redirect off;
}
}
The docker container also deploys its own nginx config, but i didn't touch that one yet.
I solved the problem. Above nginx settings should work. The issue was with the docker container still using the wrong APP_URL. Running the artisan update script (bookstackapp.com/docs/admin/commands) did not suffice, but reinstalling the docker container did it.
I'm trying to understand the best way to redirect all traffic for https://app.company.com/ to https://app.company.com/app
app.company.com is a rails 4.2 server which uses nginx to serve static assets and unicorn to handle the rails requests.
Should this redirect happen in nginx or rails?
Back story:
A few years ago I supported some rails apps that were installed on the intranet using URL Prefixing, like:
https://company.com/app1/
https://company.com/app2/
https://company.com/app3/
company.com ran an nginx server which routed traffic to each app server based on the url prefix.
Each app server runs nginx to serve static assets and unicorn as the rails server.
Recently a decision was made to hand management of the company.com server over to the parent company. As a result, a decision was made to route to each rails server by DNS using subdomains in place of nginx rules.
For now apps will be accessed using:
https://app1.company.com/app1/
https://app2.company.com/app2/
https://app3.company.com/app3/
Individual app servers are largely unchanged. They still run nginx and unicorn.
My main issue is understanding the best way to push traffic for the root to the url prefix
https://app1.company.com/ --> https://app1.company.com/app1/
The root route without the url prefix never reached the rails servers before.
UPDATE
Here is my nginx config file with original enhancement proposed by Vashed's answer.
I'm now curious if there is a refinement to this which would allow my config file to be independent of the server name like it was before.
upstream unicorn {
server unix:/tmp/unicorn.app1.sock fail_timeout=0;
}
server {
listen 80 deferred;
# ADDED THIS LOCATION BLOCK PER VASFED'S ANSWER
location = / {
rewrite ^ https://app1.company.com/app1;
}
location /app1/assets {
alias /var/www/application/current/public/app1/assets;
}
# Serve file uploads from nginx
location /app1/system {
alias /var/www/application/current/public/app1/system;
}
try_files $uri $uri/ #unicorn;
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}
client_max_body_size 1G;
keepalive_timeout 10;
}
You can issue a redirect using nginx:
server{
server_name app1.company.com;
listen 443 ssl;
# other setup
location = / {
rewrite ^ https://app1.company.com/app1/;
}
location / {
# as before
}
}
My rails app runs perfectly fine in production using nginx and unicorn except for one thing:
Requesting /articles.rss and /articles.json leads to a 404 with an error in the nginx logs that the requested file doesn't exist. Requesting e.g. /articles?format=rss works. So it looks like the .rss leads nginx to think this is a static file rather than dynamically generated content. In development (using the builtin server of rails) this works fine.
I use the h5bp config files for nginx, here's my site configuration (domain name replaced):
# www to non-www redirect -- duplicate content is BAD:
# https://github.com/h5bp/html5-boilerplate/blob/5370479476dceae7cc3ea105946536d6bc0ee468/.htaccess#L362
# Choose between www and non-www, listen on the *wrong* one and redirect to
# the right one -- http://wiki.nginx.org/Pitfalls#Server_Name
upstream app {
server unix:/var/www/rails-cms/shared/tmp/sockets/rails-cms.unicorn.sock fail_timeout=0;
}
server {
# don't forget to tell on which port this server listens
listen [::]:80;
listen 80;
# listen on the www host
server_name www.<my domain>;
# and redirect to the non-www host (declared below)
return 301 $scheme://<my domain>$request_uri;
}
server {
# listen [::]:80 accept_filter=httpready; # for FreeBSD
# listen 80 accept_filter=httpready; # for FreeBSD
# listen [::]:80 deferred; # for Linux
# listen 80 deferred; # for Linux
listen [::]:80;
listen 80;
# The host name to respond to
server_name <my domain>;
# Path for static files
root /var/www/rails-cms/current/public;
try_files $uri/index.html $uri #app;
location #app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
}
#Specify a charset
charset utf-8;
# Custom 404 page
error_page 404 /404.html;
# Include the basic h5bp config set
include h5bp/basic.conf;
}
This occurs because you include h5bp/basic.conf file which in turn includes h5bp/location/expires.conf file. Take a look at the latter file's contents:
# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
expires -1;
access_log logs/static.log;
}
# Feed
location ~* \.(?:rss|atom)$ {
expires 1h;
add_header Cache-Control "public";
}
See? the first location intercepts .json requests, and the second one - .rss requests, so your app never catches these requests.
If you want your app to handle these requests, you should either refuse h5bp at all, or just comment out abovementioned locations.
In both cases your app should send cache headers itself, if you want it of course.
Edit:
But since your json and rss contents are dynamically generated, I would not recommend using cache headers.
I am using Ubuntu.
Here is the tutorial
Nginx config I am using:
upstream my_app {
server unix:///home/uname/railsproject/my_app.sock;
}
server {
listen 88; #(I used exact 88 when I am testing now)
server_name localhost; # I used exact localhost when I am testing this
root /home/uname/railsproject/public; # I assume your app is located at that location
location / {
proxy_pass http://my_app; # match the name of upstream directive which is defined above
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~* ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
expires 1y;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
}
Puma command
RAILS_ENV=production puma -e production -b unix:///home/uname/railsproject/my_app.sock -p 8000
In the address bar, I am typing
http://localhost/
and then website opening but static assets not working. Of course, I ran
RAILS_ENV=production rake assets:precompile
and assets are available in public/assets folder
I also tried placing m.txt file in assets directory and accessing
http://localhost/assets/m.txt
but didn't work. I also tried this command:
sudo chown -R www-data:www-data public/
but this didn't help.
I'm posting for future readers.
I encounter this error when I change my hosting provider. My standard nginx conf for assets stop working, I have to change it for:
location ~ ^assets/
{
gzip_static on;
expires max;
add_header Cache-Control public;
}
Removing the / before /assets did the trick, don't know why.
ps: location is in the server block
I had a similar problem. I got an answer from the very helpful #nginx channel on irc. They said it was "idiomatic nginx" and that the other form, though more popular, was discouraged:
server {
server_name server.com;
# path for static files
root /home/production/server.com/current/public;
location / {
try_files $uri #proxy;
# if url path access by directory name is wanted:
#try_files $uri $uri/ #proxy;
}
location #proxy {
proxy_pass http://localhost:9292;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
/hattip: vandemar
I've been following Ryan B's VPS deployment railscast:
http://railscasts.com/episodes/335-deploying-to-a-vps
nginx.conf file he suggest using doesn't work with subdomains. This is what he shows:
upstream unicorn {
server unix:/tmp/unicorn.blog.sock fail_timeout=0;
}
server {
listen 80 default deferred;
# server_name example.com;
root /home/deployer/apps/<app name>/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #unicorn;
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
Does anyone know how to set things up to support subdomains?
You can uncomment line:
# server_name example.com;
replace example.com with your domain and add:
server_name example.com *.example.com;
or
server_name example.com blog.example.com;
Now all requests to domain and subdomains will go to the rails
It turns out (at least with linode.com), that handeling wildcard subdomains is pretty straight forward. You just need to add a * host to the A record.
Also, in nginix, what I did was replaced:
# server_name example.com;
with:
server_name localhost;
I'm not sure that's even needed.
My actual issue had nothing to do with either the host or nginx. My situation was that I was using a random hashed URL as a security token during registration (so a user can't hijack an existing subdomain), but the type of hash I was using had issues so I needed to modify it.
I wasn't seeing any errors, I was just being redirected back to the signup page -- as is the correct behavior when the hashed URL has problems / doesn't match.
Anyway, once I fixed that, the whole subdomain thing was a non-issue.
Hope this helps anyone else who uses hashed URLs, subdomains, and is generally new to deployment.
Cheers.