Setting up Varnish on CentOS 7, Nginx and PHP-FPM with SSL - magento

I've not used Varnish before but I need to install it on our Magento site to help speed things up.
I've found lots of articles on how to set up Varnish on Centos 7, PHP-FPM etc but none that runs with CentOS7, Nginx, PHP-FPM AND SSL.
As I understand it, Varnish doesn't natievly work with SSL so you need to do some Nginx jiggery-pokery to get things working.
This is also a multi-store Magento site so that adds another layer of complication.
Does anybody have any information to help with this?

I will show you my own Nginx config files to make this works. This is Debian 9 not Centos 7, but Nginx should works in the same way.
If someone have a better configuration, or advices, i will listen carfully... I am a Magento dev not a system admin. I have a lot to learn about Nginx & Varnish.
Here, Varnish is listening port 6081.
I created a Varnish Proxy to redirect HTTPS requests to HTTP varnish. In /etc/nginx/sites-available/proxy.website.com :
## HTTPS termination & Varnish proxy
server {
server_name en.website.com fr.website.com es.website.com de.website.com;
listen 443 ssl http2;
access_log /var/www/log/varnish-proxy.log;
error_log /var/www/log/varnish-proxy.error.log;
include /etc/nginx/conf/ssl.conf;
keepalive_timeout 300s;
location / {
#BYPASS VARNISH
#proxy_pass http://127.0.0.1:611;
#VARNISH ENABLED
proxy_pass http://127.0.0.1:6081;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
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 X-Forwarded-Port 443;
proxy_set_header X-Secure on;
proxy_set_header X-Magento-Debug 1;
}
}
Then, my vhost in /etc/nginx/sites-available/website.com :
upstream fastcgi_backend { # USE YOUR OWN CONFIG HERE
# use tcp connection
# server 127.0.0.1:9000;
# or socket
server unix:/var/run/php7.1-fpm.sock;
}
map $http_host $MAGE_RUN_CODE_GLOBAL { # USE YOUR OWN CONFIG HERE
en.website.com en;
fr.website.com fr;
es.website.com es;
de.website.com de;
}
# Redirect to https
server {
server_name en.website.com fr.website.com es.website.com de.website.com;
listen 80;
location ~ /.well-known {
allow all;
}
return 301 https://$http_host$request_uri;
}
# Redirect to https
server {
server_name _;
listen 611;
set $MAGE_ROOT /var/www/magento;
set $MAGE_MODE developer;
set $MAGE_RUN_TYPE store;
set $MAGE_RUN_CODE $MAGE_RUN_CODE_GLOBAL;
set $HTTPS_FORWARD on;
set $FPM_USER www-data;
access_log /var/www/log/website.com.access.log;
error_log /var/www/log/website.com.error.log error;
include /var/www/magento/nginx.conf.sample;
}
Enable your vhosts
sudo ln -s /etc/nginx/sites-available/proxy.website.com /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/website.com /etc/nginx/sites-enabled/
Restart nginx. -t will test your configuration files, -s reload will reload Nginx config without interupting the service :
nginx -t && nginx -s reload
EDIT :
Edit Varnish startup config :
CentOS 6: /etc/sysconfig/varnish
CentOS 7: /etc/varnish/varnish.params
Debian/Ubuntu: /etc/default/varnish
...
## Alternative 2, Configuration with VCL
DAEMON_OPTS="-a :6081 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,1024m \
-p workspace_backend=256 \
-p http_resp_hdr_len=42000"
...
In Magento admin :
set Stores > Configuration > Advanced > System > Full Page Cache > Caching Application to Varnish Cache
Now clic on the new "Varnish Configuration" Filed
Set Access list and Backend host to localhost. I don't know what are the other options.
Save configuration changes
Clic Export VCL according to your Varnish's version
Upload the Magento VCL
Backup the default varnish VCL /etc/varnish/default.vcl to /etc/varnish/default.vcl.bkp
Put the magento VCL in a new /etc/varnish/default.vcl file.
Edit the first lines :
vcl 4.0; import std;
backend default {
.host = "127.0.0.1";
.port = "404";
}
backend mywebsite {
.host = "127.0.0.1";
.port = "611";
}
acl purge {
"localhost";
}
sub vcl_recv {
if (req.http.host ~ "website.com") {
set req.backend_hint = mywebsite;
} else {
set req.backend_hint = default;
}
...
Sometimes, you will have to handle special cases like disabling Varnish for some URLs.
Go to your /etc/varnish/default.vcl and edit this like you need. It's quite obscur the first time you see the VCL, but in the end it's not that hard to understand.
Or edit your varnish proxy that way :
## HTTPS termination & Varnish proxy
server {
...
location ^~ /sitemap {
#BYPASS VARNISH
proxy_pass http://127.0.0.1:611;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
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 X-Forwarded-Port 443;
proxy_set_header X-Secure on;
}
...
}

Related

Rewrite https-URL before encryption

I need to rewrite URLs like *.lang.domain.com to lang.domain.com and I successfully did it using nginx rewrite module. I have wildcard certificate *.domain.com and it can't secure 4 level domain like test.lang.domain.com
Main problem is when users type https://bla-bla.lang.domain.com in their browser they firstly get a notice about connection is not secure. Then they need to click advanced and proceed https://bla-bla.lang.domain.com (unsafe). After that they will be redirected to https://lang.domain.com.
So my question is whether it is possible to do redirect before https-connection has been established in nginx? Or can it be achieved on some upper-level?
server {
listen 80 default;
server_name www.domain.com domain.com *.domain.com;
if ($host ~* "^.+\.(.+\.domain\.com)$") {
set "$domain" "$1";
rewrite ^(.*)$ https://$domain$uri permanent;
}
return 301 https://$host$request_uri;
}
server {
listen 443 default;
server_name www.domain.com domain.com *.domain.com;
if ($host ~* "^.+\.(.+\.domain\.com)$") {
set "$domain" "$1";
rewrite ^(.*)$ https://$domain$uri permanent;
}
ssl on;
ssl_certificate /etc/ssl/domain.com/domain.com.ca-bundle;
ssl_certificate_key /etc/ssl/domain.com/domain.com.key;
include "conf.d/ssl_settings.default";
include "conf.d/redirect.ssl.default";
include "conf.d/logger_front.default";
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HTTPS on;
proxy_pass https://somestream;
}
}
Redirects happen after a secure connection is established. So no, you cannot have a redirect to handle your particular case.

Rundeck reverse proxy behind Nginx

I have configured reverse proxy for Rundeck behind Nginx. Below is the Rundeck.conf which is placed in the path /etc/nginx/sites-enabled
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_session_cache shared:SSL:1m;
ssl_prefer_server_ciphers on;
## server configuration
server {
listen 443 ssl;
listen 80 ;
server_name ~(?<repo>.+)\.pilot1 pilot1;
if ($http_x_forwarded_proto = '') {
set $http_x_forwarded_proto $scheme;
}
## Application specific logs
## access_log /var/log/nginx/pilot1.ci1.peapod.com-access.log timing;
## error_log /var/log/nginx/pilot1.ci1.peapod.com-error.log;
# rewrite ^/$ /rundeck/menu/home redirect;
rewrite ^/rundeck/?(/rundeck)?$ /rundeck/menu/home redirect;
chunked_transfer_encoding on;
client_max_body_size 0;
location ^~ /rundeck/ {
proxy_pass http://localhost:4440;
proxy_read_timeout 900;
}
}
Reverse proxy works fine when I browse and login to Rundeck.But when I click log out the redirection to the login page exposes the port:4440
as below
LOGIN----> pilot1/rundeck redirects to pilot1/rundeck/menu/home (works fine)
Logout---> pilot1:4440/rundeck/user/loggedout
I do not want the port to be exposed. How do i fix this issue?
Here is what I had to do:
In NGINX config under an appropriate 'server' section set up a location:
location /rundeck/ {
proxy_pass http://localhost:4440;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Rundeck config:
sed -i "/^grails.serverURL/c grails.serverURL = ${RUNDECK_URL}" /etc/rundeck/rundeck-config.properties
sed -i "/^framework.server.url/c framework.server.url = ${RUNDECK_URL}" /etc/rundeck/framework.properties
sed -i '/^RDECK_JVM="$RDECK_JVM/ s/"$/ -Dserver.web.context=\/rundeck"/' /etc/rundeck/profile
where RUNDECK_URL should point to you NGINX ip (dns name) so http://my-nginx.com/rundeck

Sinatra, Unicorn and Nginx - Proxy multiple Sinatra Apps

I have multiple Sinatra apps on unicorn + nginx and I want to proxy the second Sinatra app to be on a /app path.
root
root/app
Here is my nginx configuration file:
upstream root {
# Path to Unicorn SOCK file, as defined previously
server unix:/tmp/unicorn.root.com.sock fail_timeout=0;
}
upstream app {
# Path to Unicorn SOCK file, as defined previously
server unix:/tmp/unicorn.app.io.sock fail_timeout=0;
}
server {
listen 80;
# Set the server name, similar to Apache's settings
server_name root.com www.root.com;
# 301 redirect http://root.com$requesturi;
# Application root, as defined previously
root /var/www/root.com/public;
try_files $uri/index.html $uri #root;
location #root {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://root;
}
location /app {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://app;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
access_log off;
}
Using the configuration above I get a 404 from the app application.
How can I achieve that?

Flask sub.domain.com overrides session on domain.com

I have two seperate server one for domain.com and another for sub.domain.com, and I store sessions using flask-session and following configuration:
SERVER_NAME = 'domain.com'
SESSION_COOKIE_DOMAIN = ".domain.com"
# Flask-Session
SESSION_TYPE = 'redis'
SESSION_REDIS = Redis(host='192.168.10.10', port=6379, db=0)
further more I am using reverse proxy using nginx and:
proxy_set_header Host $host;
When I login on domain.com everything is ok but when I refresh sub.domain.com, user logs out on domain.com(sub.domain.com creates another session and overrides the one which is created by domain.com). Authentication is done by flask-login and it's on domain.com (sub.domain.com only should get them).
I don't know what's going wrong and I appreciate any help.
Update:
I tried to run flask without uwsgi and it works as it should, but when I uwsgi and nginx the problem persists. I think something is wrong with my uwsgi or nginx config.
# uwsgi.ini
[uwsgi]
master = true
enable-threads = true
process = 3
plugin = python
socket = /tmp/name.sock
base = /var/www/app
chdir = %(base)
wsgi-file = %(base)/manage.py
callable = app
# nginx.conf
server {
listen 8001;
location / {
include uwsgi_params;
uwsgi_pass unix:///tmp/name.sock;
}
}
By mistake I thought it has nothing to do with my reverse proxy or uwsgi. Actually it was problem with reverse proxy and I could solve my problem by adding following rules to nginx:
proxy_cookie_domain media.$host $host;
proxy_set_header Host $host;
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 false;

nginx - rewrite domain.com:port to sub.domain.com

How can i rewrite a domain with a port to a subdomain?
e.q.: domain.com:3000 to sub.domain.com ?
thanks for your help! :)
greetz
If you actually want to redirect (301 or 302) your web traffic
You create a server {} section listening on port 3000 and you just redirect it to another server {} section that is listening on port 80. In each server {} section set the listen property appropriately.
I guess you are trying to handle the redirection within à single server section and according to this page the listen directive applies to a server context
If you want to use nginx as a proxy
Then what you are looking for is the proxy_pass directive. Here is a sample configuration extracted from an config I have to use nginx as a proxy for my rails app (thin). Basically my app runs locally (but it would also work on a remote host) on port 3200 and the relevant nginx config part looks as follow:
upstream my-app-cluster
{
server localhost:3200;
}
server
{
listen 80;
server_name mydomain.com;
root /root/to/public/folder;
access_log /my/app/log/folder/myapp.log;
location / {
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;
if (-f $request_filename/index.html) {
rewrite (.*) $1/index.html break;
}
if (-f $request_filename.html) {
rewrite (.*) $1.html break;
}
if (!-f $request_filename) {
proxy_pass http://my-app-cluster;
break;
}
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
You could use Passenger in nginx to delivery the Ruby app - that's the method we are currently using.
http://www.modrails.com/

Resources