capistrano deploy to multiple servers with different subdomain variable - deployment

I used this railscast as a basis
# nginx_unicorn.erb
upstream unicorn-<%= application %> {
server unix:/tmp/unicorn.<%= application %>.sock fail_timeout=0;
}
server {
listen <%= subdomain ? subdomain : application %>.example.com:443 ssl;
server_name <%= subdomain ? subdomain : application %>.example.com;
root <%= current_path %>/public;
ssl on;
ssl_certificate /opt/nginx/ssl/example.com.pem;
ssl_certificate_key /opt/nginx/ssl/example.com.key;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:-ADH:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP;
ssl_session_cache shared:SSL:10m;
try_files $uri/index.html $uri #unicorn;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
proxy_pass http://unicorn-<%= application %>;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
I set a variable to subdomain in the deploy.rb
# deploy.rb
...
role :web, "avps.example.com", "bvps.example.com", "cvps.example.com"
role :app, "avps.example.com", "bvps.example.com", "cvps.example.com"
role :db, "avps.example.com", "bvps.example.com", "cvps.example.com", :primary => true
set :subdomain, "atsp"
...
This works great when I only deploy to one server, but I would like to be able to base this off the current server it is deploying to, so if it were avps.example.com, it would:
set :subdomain, "atsp"
or if it were bvps.example.com, it would do:
set :subdomain, "btsp"
Is there an easy way to accomplish this?

I think what you are looking for is the Capistrano multi-stage deployment. You can find the wiki page here. All you would have to do is move the
set :subdomain, "atsp"
into a file (ie. config/deploy/atsp.rb) with the server information and then you can deploy to that server with
cap atsp deploy
Hope this helps.

Related

URL requested a HTTP redirect, but it could not be followed. - Facebook/Nginx issue

I have used Facebooks sharing debugger to highlight an issue on the website
URL requested a HTTP redirect, but it could not be followed.
https://developers.facebook.com/tools/debug/sharing/?q=https%3A%2F%2Fwww.badgerbookings.com
This is also stopping it accepting the url in the privacy policy when creating an app.
I have researched and made sure to add all OG meta tags. I also "reduced" down the redirects on my nginx to only support a http > https redirect which to me seems pretty standard.
It still produces the error on both the debugger and the Privacy Policy URL.
My Nginx config:
server_tokens off; #Enables or disables emitting nginx version on error pages and in the “Server” response header field
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name _;
return 301 https://www.badgerbookings.com$request_uri;
}
server {
server_name www.badgerbookings.com badgerbookings.com *.badgerbookings.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # allow websockets
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $remote_addr; # preserve client IP
proxy_set_header Host $http_host;
proxy_set_header X-Forward-Proto http;
proxy_set_header X-Nginx-Proxy true;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/badgerbookings.com-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/badgerbookings.com-0001/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
}
Go to Facebook Developer's policy page.
Scroll down to this bit:
Privacy Policy
a. Provide a publicly available and easily accessible privacy policy
that explains what data you are collecting and how you will use that
data.
Now run
curl https://badgerbookings.com/terms
Are you looking at an easily accessible privacy policy which is publicly available at that url?
You maybe having IPv6 issues which can be resolved as simple as adding a listen [::]:443 ssl directive in you SSL server block.
If that doesn't fix it, try redirecting with a matching if directive
if ($scheme != "https") {
return 301 https://www.badgerbookings.com$request_uri
}
This is best if you unite both server blocks in one, to avoid more code. Just delete the non-https one and insert port 80 listen directives on the other one as well, with that conditional redirect, this way your code will be even slimmer.

prevent redirecting to https and URI hacks nginx reverse proxy

I have setted up a reverse proxy on my server with nginx inside docker, and since then all request are redirecting to https although i didn't set all locations to https redirection.
Basically what i want is to be able to serve both https and http with the reverse proxy.
In addition i want to be able to redirect to different URI dynamically, for example i want to set all routes of /bla2/foo/bar to be redirected to only what comes after /bla2
what i tried to get here is that whenever accessing to example.com/bla2/foo/bar it should redirect it to example.com/foo/bar without the bla2 section...
Is it possible on the same configuration file?
what can cause my server to redirect all request to https
This is my server nginx.conf
server {
listen 443;
ssl on;
ssl_certificate /etc/ssl/example.com.crt;
ssl_certificate_key /etc/ssl/example.com.key;
listen 80;
server_name example.com;
location /bla/bla {
proxy_pass http://example.com:3980/foo/bar1;
}
**location /bla2/**{
# proxy_pass http://example.com:3004;
return 301 http://example.com:3004$request_uri;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
}
location /app3 {
rewrite ^/app3(.*) /$1 break;
proxy_pass http://example.com:1236/app3;
}
}
I want to be able to get directly content of http://example.com:3004 if i put it in the browser without any redirection to https.
Only if i try access example.com/bla2 i want it to be required https instead of http, and to be redirected to different path.
You need to use regular expression and capture groups for this
location ~* /bla2/(.*) {
return 301 http://example.com:3004$1$is_args$args;
}
Another way of doing it would be just use rewrite
rewrite ^/bla2/(.*)$ http://example.com:3004/$1 redirect;
If you want to transparently proxy it to the example.com:3004 removing /bla2 then you should use
location /bla2/ {
proxy_pass http://example.com:3004/;
}
The trailing slash / in /bla2/ and http://example.com:3004/ is very important here

Nginx - All my domains and sub are redirected to the same web site

I just move my setup (personal web + different services) to a more powerful server.
I copy and paste some setup I made before like my nginx configuration for 3 web site I host (my personal + 2 services as subdomain).
I try to figure it out but something wrong happend.
Let say I have my own web site xxx.com. I manage to redirect every www request to non-www (it's not working now).
Plus now when I try to hit this web site I got a redirect to my subdomain yyy.xxx.com.
I give you my two server blocks :
Main web site :
server {
listen 80;
listen [::]:80;
server_name gfelot.xyz www.gfelot.xyz;
return 301 https://gfelot.xyz$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
include snippets/ssl-gfelot.xyz.conf;
include snippets/ssl-params.conf;
server_name gfelot.xyz;
access_log /var/log/nginx/gfelot.xyz.access.log;
error_log /var/log/nginx/gfelot.xyz.log;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~* \.css$ {
access_log off;
expires 1M;
add_header Pragma public;
add_header Cache-Control public;
add_header Vary Accept-Encoding;
}
}
Transmission service :
server {
listen 80;
listen [::]:80;
server_name dl.gfelot.xyz www.dl.gfelot.xyz;
return 301 https://dl.gfelot.xyz$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
include snippets/ssl-gfelot.xyz.conf;
include snippets/ssl-params.conf;
server_name dl.gfelot.xyz
access_log off;
error_log /var/log/nginx/dl.gfelot.xyz.log;
location / {
proxy_pass http://127.0.0.1:9091/web/;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass_header X-Transmission-Session-Id;
}
location /rpc {
proxy_pass http://127.0.0.1:9091/rpc;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass_header X-Transmission-Session-Id;
}
}
I dunno what's wrong with this configuration. And the weird thing is, it was working well before.
Looks like you've comma separated your the server_name directive. It should be space separated.
server_name gfelot.xyz, www.gfelot.xyz;

How do I make an nginx proxy stop redirecting to root?

I have a node app running as a proxy on nginx in a sub-directory. I'm having trouble with redirects that point to a different part of the app itself. They always redirect to the root instead of the proxy's sub-directory.
Example:
If my app proxy is at https://example.com/myApp/ and it redirects to /admin/ I want the page to redirect to https://example.com/myApp/admin/ not https://example.com/admin/.
Here is the relevant section of my config:
location /myApp {
rewrite /myApp(.*) $1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:3030;
proxy_redirect http://localhost:3030/ /myApp/;
}
I also tried setting proxy_redirect to (^|^http://localhost:3030)/ /myApp/;
Here is the full config file for this domain:
upstream php-handler {
#server 127.0.0.1:9000;
server unix:/var/run/php5-fpm.sock;
}
## HTTP
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
## HTTPS
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/www.example.com.crt;
ssl_certificate_key /etc/ssl/www.example.com.key;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
root /var/www/example.com/;
index index.html index.php;
client_max_body_size 500M;
fastcgi_buffers 64 4k;
gzip on;
# Website
location / {
try_files $uri $uri/ =404;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
# My App
location /myApp {
rewrite /myApp(.*) $1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:3030;
proxy_redirect http://localhost:3030/ /myApp/;
}
Alright, I figured it out on my own.
tl;dr:
This worked:
proxy_redirect ~(^http://localhost:3030|^)/(.*)$ /myApp/$2;
First option:
proxy_redirect / /myApp/;
I'm guessing this works because the app is redirecting to /admin/ not http://localhost:3030/admin/. This, however, does not provide the flexibility I'm looking for.
Second Option:
Use RegExp
So I made a couple mistakes originally when I tried using regex like this:
proxy_redirect (^|^http://localhost:3030)/ /myApp/;
First, if you're going to use regex you need to start it with ~ for case sensitive or ~* for case insensitive.
Secondly, when you use regex it apparently replaces the full path instead of just the matched portion. For instance if you were to set a proxy_redirect like this:
proxy_redirect ~/(a|b)/ /myApp/;
If you then redirect to /a/some-subdirectory/ the rewrite will result in /myApp/ not /myApp/some-subdirectory/. To make this work you need to capture the end of the path and insert that onto the end of the rewrite like this:
proxy_rewrite ~/(a|b)/(.*)$ /myApp/$2;
Note: I can't find any information on this behavior in the docs. I am just basing this on the results of my own trial and error.
So my final proxy_redirect looks like this:
proxy_redirect ~(^http://localhost:3030|^)/(.*)$ /myApp/$2;
From my point of view, you should try the listen directive in the server block define it as the default (source: http://nginx.org/en/docs/http/request_processing.html):
listen 80
default_server;
The following declaration is meant as an invalid server name (source: http://nginx.org/en/docs/http/server_names.html) (so it never intersect any of your valid domain) :
Server_name _;
To fix you problem, make sure you have a server block with listen (port) and server_name (virtual host) - this one will be triggered first as you go from 'more precise to less precise' when you do virtual host names matching in nginx:
Listen 80
Server_name your-domain-name.com;

Configure NGINX for web and mobile site redirection

We have defined two server objects, one for example.com and another for www.example.com. We want to automatically redirect user to the mobile website www.example.com/m if user is on mobile browser.
There are two different projects for mobile and web version of app deployed on tomcat and APIs are exposed via only the web version. The mobile project consumes the same web APIs so the root is common.
the configuration is :
server {
#listen 80 is default
listen 80;
listen 443 ssl;
ssl on;
ssl_certificate /path/to/certificates/www.example.com.chained.crt;
ssl_certificate_key /path/to/certificates/example.com.key;
location / {
if ($http_user_agent ~* "(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino") {
return 301 https://www.example.com/m;
}
return 301 https://www.example.com;
}
location /m {
}
server_name example.com;
}
server {
listen 80;
listen 443 ssl;
ssl on;
ssl_certificate /path/to/certificates/www.example.com.chained.crt;
ssl_certificate_key /path/to/certificates/example.com.key;
server_name www.example.com;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
root /usr/share/tomcat/webapps/ExampleApp;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:8080/;
}
}
This configuration works properly when :
example.com is entered from mobile
example.com or www.example.com from web
However it does not work when:
www.example.com is entered from mobile (it opens the web version instead of the mobile site).
How can we make it redirect to www.example.com/m when user enters www.example.com from mobile?
You can implement your if condition with a rewrite within the location / block. The rewrite loop is avoided by adding a location /m block. For example:
server {
...
server_name www.example.com;
...
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
if ($http_user_agent ~* ...) {
rewrite ^ /m$request_uri last;
}
proxy_pass http://localhost:8080;
}
location /m {
proxy_pass http://localhost:8080;
}
}
Notice that the trailing / on the proxy_pass is removed as an additional rewrite is not required.
Note also that the ssl on; directives should be removed from your config as they will enable SSL on all ports (even port 80). The listen 443 ssl; directive is sufficient to enable SSL on port 443 only.