Hello I am trying to setup a reverse proxy with nginx and docker container rails app, public static files are served correctly but can not access to my app. the nginx error log says:
2018/12/08 16:46:45 [error] 4093#4093: *350 could not find named location "#puma", client: xx.xxx.xxx.xx, server: my.app, request: "GET /en/users/sign_in HTTP/2.0",host: "my.app", referrer: "https://my.app/"
my nginx config is this:
upstream puma {
server 0.0.0.0:3000;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name my.app;
root /var/www/myapp/public;
# SSL
ssl_certificate /etc/letsencrypt/live/my.app/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my.app/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/my.app/fullchain.pem;
include snippets/letsencrypt.conf;
include snippets/ssl.conf;
# reverse proxy
location / {
proxy_pass http://puma; # => http://0.0.0.0:3000
proxy_set_header Host $http_host; # => $host
proxy_set_header X-Forwarded-Proto $scheme; # => "https"
proxy_set_header X-Forwarded-Host $host; # => 0.0.0.0
proxy_set_header X-Forwarded-Port $server_port; # => 3000
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
# index fallback
try_files $uri $uri/ /index.html;
}
# . files
location ~ /\. {
deny all;
}
# assets, media
location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?)$ {
expires 7d;
access_log off;
}
# svg, fonts
location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
add_header Access-Control-Allow-Origin "*";
expires 7d;
access_log off;
}
# gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
# error pages
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/myapp/public;
}
error_page 404 /404.html;
location = /404.html {
root /var/www/myapp/public;
}
}
# subdomains redirect
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name _ *.my.app;
# SSL
ssl_certificate /etc/letsencrypt/live/my.app/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my.app/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/my.app/chain.pem;
include snippets/letsencrypt.conf;
include snippets/ssl.conf;
return 301 https://my.app$request_uri;
}
# HTTP redirect
server {
listen 80;
listen [::]:80;
server_name _ .my.app my.app;
include snippets/letsencrypt.conf;
return 301 https://my.app$request_uri;
}
the rails container start thru docker-compose with this setup:
version: '3.2'
services:
web:
command: rails server -p '3000' -b '0.0.0.0' -e production
ports:
- '3000:3000'
I have tried also with unix socket to connect puma and nginx without success
Related
I have Nginx server with domain name example.com and it servers
location / => for web, running docker at port 8080
location /api => for API, running docker at port 8090
There is another backend service running in docker at port 9000, which wants to call the API https://example.com/api ... If I try it as localhost:8090 then no issue.
But using https://example.com/api via Nginx returns 301 Moved permanent error.
That is, calling from the same system to Nginx is not working.
Not sure what is wrong.
Please find the nginx conf:
map $sent_http_content_type $expires {
default off;
text/html epoch;
text/css max;
application/javascript max;
~image/ max;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
include /etc/nginx/conf.d/*.conf;
server {
listen [::]:443 ssl http2 ipv6only=on; # managed by Certbot
listen 443 ssl http2; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.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
index index.html index.htm index.nginx-debian.html;
server_name example.com;
location / {
proxy_pass http://localhost:8080/;
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;
}
location /api/v1/socketio/ {
proxy_pass http://lb_autosys_api/socket.io/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /api/v1/ {
proxy_pass http://localhost:8090/;
}
gzip on;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
gzip_min_length 1000;
gunzip on;
gzip_vary on;
expires $expires;
}
server {
if ($host = example.com) {
return 301 https://$host$request_uri;
}
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
return 301 https://$host$request_uri;
}
Fighting for months with this, another new career path blooming every week, it seems, I look down.
So, that said. Here's the closest I've come. I had it working several times, but it's so brittle as I'm more a developer than a devops (?) person.
I am running Ubuntu 20.04.
be puma -C config/puma.rb config.ru -e production \
--pidfile /run/puma.pid \
--control-url 'unix:///root/mysite/tmp/sockets/mysite-puma.sock' \
--control-token 'app' \
--state tmp/puma.state \
-b 'tcp://mysite.com'
I can run pumactl as so: bundle exec pumactl -T 'app' -C 'unix:///root/mysite/tmp/sockets/mysite-puma.sock' -S tmp/puma.state [pumactl switch]
My nginx config.
/etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip off;
gzip_vary off;
#gzip_proxied any;
#gzip_comp_level 6;
#gzip_buffers 16 8k;
#gzip_http_version 1.1;
#gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/mysite.com;
}
/etc/nginx/sites-enabled/mysite.com
# This configuration uses Puma. If using another rack server, substitute appropriate values throughout.
upstream puma {
server unix:///root/mysite/tmp/sockets/mysite.sock;
}
# We need to be listing for port 80 (HTTP traffic).
# The force_ssl option will redirect to port 443 (HTTPS)
server {
# Update this
server_name mysite.com www.mysite.com;
# Don't forget to update these, too.
# For help with setting this part up, see:
# http://localhost:4000/2018/09/18/deploying-ruby-on-rails-for-ubuntu-1804.html
root /root/mysite/public;
access_log /root/mysite/log/nginx.access.log;
error_log /root/mysite/log/nginx.error.log info;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #puma;
location #puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
}
# This is the configuration for port 443 (HTTPS)
server {
listen [::]:443 ssl ipv6only=on; # managed by Certbot
server_name mysite.com www.mysite.com;
ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.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
# Don't forget to update these, too.
# I like to update my log files to include 'ssl' in the name.
# If there's ever any need to consult the logs, it's handy to have HTTP and HTTPS traffic separated.
root /root/mysite/public;
access_log /root/mysite/log/nginx.ssl.access.log; # Updated file name
error_log /root/mysite/log/nginx.ssl.error.log info; # Updated file name
error_page 500 502 503 504 /500.html;
client_max_body_size 10M;
location ^~ /assets/ {
gzip_static off;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #puma;
location #puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# This is an important line to help fix some redirect issues.
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
}
# If you chose Certbot to redirect all traffic to HTTPS, this will be in your current config.
# Remove it or you'll run into redirection errors:
server {
if ($host = example.com) {
return 301 https://www.example.com$request_uri;
} # managed by Certbot
listen [::]:80 default_server deferred;
server_name example.com;
return 404; # managed by Certbot
}
First thing first, in your /etc/nginx/sites-enabled/mysite.com
First step
change
upstream puma {
server unix:///root/mysite/tmp/sockets/mysite.sock;
}
to
upstream puma {
server 0.0.0.0:9838; # port number in which your puma server starts
}
After changing your /etc/nginx/sites-enabled/mysite.com It should look like the following.
upstream puma {
server 0.0.0.0:9838;
}
server {
server_name mysite.com www.mysite.com;
client_max_body_size 200m;
gzip on;
gzip_comp_level 4;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain application/javascript application/json application/x-javascript text/xml text/css application/xml text/javascript;
root /root/mysite/public;
location / {
try_files $uri/index.html $uri #app;
}
location ~* ^/assets {
root /root/mysite/public;
expires 1y;
add_header Cache-Control public;
add_header Last-Modified "";
add_header ETag "";
break;
}
error_page 500 502 503 504 /500.html;
location #app {
proxy_pass http://puma;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_redirect off;
}
location ~ /.well-known {
allow all;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.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 = mysite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = www.mysite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name mysite.com www.mysite.com;
listen 80;
return 404; # managed by Certbot
}
Second step
Then run gem install foreman to install foreman library. To know more about foreman click here.
Third step
Create Procfile in your project root directory and paste the below content
web: RAILS_ENV=production bundle exec puma -e production -p 9838 -d -S ~/puma -C config/puma.rb
Final step
Run foreman start to start the puma server and there you go, you will be able to see your application running.
I have a computer trying to do:
docker login docker-repo.mydomain.com
docker-repo is handled by an nginx which has this config:
server {
listen 80;
server_name docker-repo.mydomain.com ;
# Redirect non-https traffic to https
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name docker-repo.mydomain.com;
ssl_certificate /etc/nginx/ssl/docker-repo.mydomain.com.crt;
ssl_certificate_key /etc/nginx/ssl/docker-repo.mydomain.key;
server_tokens off;
ssl_dhparam /etc/nginx/ssl/dhparams.pem;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:AES256-GCM-S$
gzip_proxied any;
gzip on;
gzip_min_length 1023;
gzip_types text/plain text/css text/js text/javascript text/xml application/json application/javascript application/x-javascript application/xml application/xml+rss;
proxy_send_timeout 610s;
proxy_read_timeout 610s;
proxy_max_temp_file_size 16384m;
proxy_redirect off;
proxy_buffers 32 4k;
send_timeout 610s;
client_max_body_size 0;
client_body_buffer_size 128k;
location / {
proxy_pass http://nexus.mydomain.com:8102;
proxy_set_header X-Custom-Referrer "https://docker-repo.mydomain.com:443";
proxy_set_header Host $http_host;
proxy_set_header Client-IP $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
And on nexus.mydomain.com i have sonatype nexus running a docker group with Http Proxy set to run on port 8102
Errors i'm getting:
$ docker login docker-repo.mydomain.com
Username: XXXX
Password:
Error response from daemon: Get https://docker-repo.mydomain.com/v2/: Service Unavailable
If i try to access the page https://docker-repo.mydomain.com from a browser I get the page: HTTP Error 400, Not a docker request
I i try to ping both docker-repo and nexus.mydomain.com it works fine.
Turns out that this was due to a proxy i was behind. Once i added the proxy config with the proper exclusions it worked fine.
I'm trying to follow this article:
https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04
with a fresh Amazon Linux EC2 instance. I'm using the out-of-the-box /etc/nginx/nginx.conf file, and added my config file to /etc/nginx/sites-default/default
Puma seems to be running fine:
/home/ec2-user/flviewer/shared/log/puma_error.log: [8006] *
Listening on
unix:///home/ec2user/flviewer/shared/sockets/tmp/puma.sock
But this shows up in /var/log/nginx/error.log:
2016/12/12 05:33:00 [error] 11018#0: *1 open()
"/usr/share/nginx/html/flviewer" failed (2: No such file or
directory), client: 173.73.119.219, server: localhost, request: "GET
/flviewer HTTP/1.1", host: "54.86.222.53"
Why the heck is it looking in '/usr/share/nginx/html/flviewer' when it should be looking at the socket i opened?
here is my config as dumped by 'nginx -T':
# configuration file /etc/nginx/sites-available/default:
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:/home/ec2-user/flviewer/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost;
root /home/ec2-user/flviewer/current/public;
try_files $uri/index.html $uri #app;
location #app {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_redirect off;
#proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_pass http://app;
#autoindex on;
}
location ~ ^/(assets|fonts|system)/|favicon.ico|robots.txt {
gzip_static on;
expires max;
add_header Cache-Control public;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
Nothing worked. I stripped /etc/nginx.conf down to just this, and am up and running. I had to throw away all of the boilerplate that was in nginx.conf. This works:
config file:
# Run nginx as a normal console program, not as a daemon
daemon off;
user ec2-user;
# Log errors to stdout
error_log /dev/stdout info;
events {} # Boilerplate
http {
# Print the access log to stdout
access_log /dev/stdout;
# Tell nginx that there's an external server called #app living at our socket
upstream app {
server unix:/home/ec2-user/flv/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
# Accept connections on localhost:2048
listen 80;
server_name localhost;
# Application root
root /home/ec2-user/flv/shared/public;
# If a path doesn't exist on disk, forward the request to #app
try_files $uri/index.html $uri #app;
# Set some configuration options on requests forwarded to #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;
}
location ~ ^/(assets|fonts|system)/|favicon.ico|robots.txt {
gzip_static on;
expires max;
add_header Cache-Control public;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
}
I think it has to do with using the default nginx config file. Try moving /etc/nginx/sites-available/default to /etc/nginx/sites-enabled/flviewer.
$ mv /etc/nginx/sites-available/default /etc/nginx/sites-enabled/flviewer
Then reload and restart nginx.
I want to configure NGINX with Rails 4 and run my application in production mode. The problem is I get 403 code - command: rails s -e production and in browser typing localhost. Naturally I established 755 privileges for the whole files in my application folder. There is my nginx.conf below:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
# include /etc/nginx/conf.d/*.conf;
# include /etc/nginx/sites-enabled/*;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
client_max_body_size 50M;
# fastcgi_buffers 8 16k;
# fastcgi_buffer_size 32k;
# fastcgi_connect_timeout 300;
# fastcgi_send_timeout 300;
# fastcgi_read_timeout 300;
upstream proxy-user {
server 127.0.0.1:2000;
}
upstream thin_cluster {
server unix:/tmp/thin.0.sock;
# server unix:/tmp/thin.1.sock;
# server unix:/tmp/thin.2.sock;
}
server {
listen 80;
server_name localhost;
# access_log /var/log/nginx-access.log;
root /home/user/Apps/myapp/public;
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mp3|flv|mpeg|avi)$ {
try_files $uri #app;
}
location /home/user/Apps/myapp/ {
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_redirect off;
proxy_pass http://proxy-user;
if (!-f $request_filename) {
proxy_pass http://proxy-user;
break;
}
}
}
server {
listen 443;
server_name _;
ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers HIGH:!ADH:!MD5;
access_log /var/log/nginx-access-ssl.log;
root /home/user/Apps/myapp/public;
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mp3|flv|mpeg|avi)$ {
try_files $uri #app;
}
location /home/user/Apps/myapp/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-FORWARDED_PROTO https;
proxy_set_header SSL_CLIENT_S_DN $ssl_client_s_dn;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://proxy-user;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
You kinda have few issues in your config, I'll write what I would have done and you tell me what ever questions you have, I'll assume that the server is on port 2000 because that's the upstream you used.
I'll also ignore the http block and only use the server and upstream blocks.
upstream rails {
server 127.0.0.1:2000;
}
server {
server_name domain.com; # or whichever
listen 80;
# ssl settings start
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# ssl settings end
root /home/user/Apps/myapp/public;
error_page 500 502 503 504 /50x.html;
access_log /var/log/nginx/domain-access.log;
error_log /var/log/nginx/domain-error.log;
location #pass_to_rails {
proxy_set_header X-Real-IP $remote_addr;
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://rails;
}
location / {
try_files $uri $uri/ #pass_to_rails;
}
}
You should place this inside sites-available and symlink to sites-enabled if you are on a debian/ubuntu distro, or use /etc/nginx/conf.d if you are on another distro, to keep things tidy and maintainable.
also make sure to uncomment one of those lines depending on what you want to use
# include /etc/nginx/conf.d/*.conf;
# include /etc/nginx/sites-enabled/*;