Multiple websites with one IP: settings with proxy server and proxy cache (flask, uwsgi, nginx) - caching

I want to allow my nginx server to server multiple subdomains.
Each site is served by a flask + uwsgi, listening to own ports.
All sites have many endpoints with same name, and responses are cached in different zones: I want to serve the correct cache (or correct site) from the proxy server.
I read https://askubuntu.com/questions/766352/multiple-websites-on-nginx-one-ip : in my configuration I keep having domain2 redirected to domain1.
I cannot find proper configuration for listening to uwsgi and have the proxy server serve the correct site.
How to properly set the ports and proxy_cache on the proxy_server to allow nginx serve two flask sites from a single server?
Below is my set current setup:
configuration domain_1
server {
server_name www.domain1.com;
return 301 $scheme://domain1.com$request_uri;
}
server {
listen 8000 default_server;
server_name domain1.com;
root /var/www/example_site_1;
# common locations for all sites
location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/example_site_1/domain1.sock;
}
# API
location /api {
include uwsgi_params;
uwsgi_param UWSGI_SCRIPT wsgi;
uwsgi_pass unix:/var/www/example_site_1/domain1.sock;
}
}
# Set cache directory for site
proxy_cache_path /tmp/nginx/domain1 levels=1:2 keys_zone=my_zone_domain_1:10m max_size=50m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";
# Virtualhost/server configuration
server {
listen 80 default_server;
server_name domain1;
root /var/www/domain1;
## how to serve proxy_cache if locations of domain_1 and domain_2 are the same ?
location / {
proxy_cache my_zone_domain_1;
add_header X-Proxy-Cache $upstream_cache_status;
include proxy_params;
proxy_pass http://domain1.com:8000;
}
location /api {
add_header X-Proxy-Cache $upstream_cache_status;
proxy_cache my_zone_domain_1;
proxy_pass http://domain1.com:8000/api;
}
}
configuration domain_2
server {
server_name www.domain2.com;
return 301 $scheme://domain2.com$request_uri;
}
server {
listen 3000;
server_name domain2.com;
root /var/www/example_site_2;
# common locations for all sites
location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/example_site_2/domain2.sock;
}
# API
location /api {
include uwsgi_params;
uwsgi_param UWSGI_SCRIPT wsgi;
uwsgi_pass unix:/var/www/example_site_2/domain2.sock;
}
}
# Set cache directory for site
proxy_cache_path /tmp/nginx/domain2 levels=1:2 keys_zone=my_zone_domain_2:10m max_size=50m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";
# Virtualhost/server configuration
server {
# I tried listening on other ports than 80, but kept having redirects on domain_1
listen 80;
server_name domain2;
root /var/www/domain2;
## how to serve proxy_cache if locations of domain_1 and domain_2 are the same ?
location / {
proxy_cache my_zone_domain_2;
add_header X-Proxy-Cache $upstream_cache_status;
include proxy_params;
proxy_pass http://domain2.com:3000;
}
location /api {
add_header X-Proxy-Cache $upstream_cache_status;
proxy_cache my_zone_domain_2;
proxy_pass http://domain2.com:3000/api;
}
}

Your domain_2 configuration uses proxy_pass http://domain2.com:8000 but there is only domain_1 server listens on the port 8000 so it gets to serve requests directed to domain_2.
I also recommend you to rethink usage of proxy_pass in your configuration, it isn't really necessary.

I found the culprit was Uwsgi : it was loaded from usr/bin folder, and not from virtual environment folder of my app.
Maybe virtualenv folder was corrupted: when I tried to re-install uwsgi (pip install uwsgi), it kept saying requirements satisfied until I noticed that which uwsgi was not loaded from virtualenv.
I had to remove and reinstall virtualenv folder with uwsgi and python modules.
Now applications were running (answer to the question), but proxy_server configuration has to be further adjusted in my case.
The following may be useful for people making use of url_for() directives in flask: url_for() directive routes to an absolute path, which may conflict with the nginx proxy.
Example: nginx proxy server listens on domains2.com on port 80, proxy_pass /path location to http://domain2.com:3000; if flask is redirecting a route to /path (with url_for()), the resulting url will be http://domain2.com:3000/path (because it follows the port specified in absolute path) instead of http://domain2.com/path (the url of the proxy).
Add proxy_set_header Host $http_host; to /path location to allow nginx proxy follow the correct redirect of your flask application.

Related

ERR_SSL_UNRECOGNIZED_NAME_ALERT Nginx

I was using Laravel Forge and stopped using it due to a problem with my card. So I continued on my own with Digital Ocean.
I followed the below instructable to apply SSL to the site.
https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04-es
This procedure indicated some errors que posteriormente solucioné:
For example:
maquino#codigobyte:/etc/nginx/sites-enabled$ sudo nginx -t
nginx: [warn] conflicting server name "todocontenidoweb.com" on 0.0.0.0:80, ignored
nginx: [warn] conflicting server name "www.todocontenidoweb.com" on 0.0.0.0:80, ignored
nginx: [warn] conflicting server name "todocontenidoweb.com" on [::]:80, ignored
nginx: [warn] conflicting server name "www.todocontenidoweb.com" on [::]:80, ignored
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
The issue is that my site is down, I'm already on the third day and Digital Ocean support tells me that they don't see a problem in the configurations. But the site is down.
On the next page it shows me a problem with the secure connection.
https://www.ssllabs.com/ssltest/analyze.html?d=todocontenidoweb.com
At this moment there are several things that make me believe that I have a problem in the following configuration:
In /etc/nginx/sites-enabled$
I have 3 files and one of them is my site todocontenidoweb.com
In todocontenidoweb.com:
server {
listen 80;
listen [::]:80;
server_name todocontenidoweb;
server_tokens off;
root /home/forge/todocontenidoweb.com/public;
In the server_name line all web content; I understand that I should put todocontenidoweb.com www.todocontenidos web.com
But it doesn't allow me and it gives me an error in the certificate if I do this.
I would really appreciate it if someone could help me to solve this situation.
EDITION
File: /etc/nginx/sites-available/mydomain.com
# FORGE CONFIG (DO NOT REMOVE!)
#include forge-conf/todocontenidoweb.com/before/*;
server {
listen 443 ssl;
listen [::]:443 ssl;
include snippets/self-signed.conf;
include snippets/ssl-params.conf;
server_name todocontenidoweb.com www.todocontenidoweb.com;
server_tokens off;
root /home/forge/todocontenidoweb.com/public;
# FORGE SSL (DO NOT REMOVE!)
# ssl_certificate;
# ssl_certificate_key;
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY13>
# ssl_prefer_server_ciphers off;
# ssl_dhparam /etc/nginx/dhparams.pem;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
# FORGE CONFIG (DO NOT REMOVE!)
#include forge-conf/todocontenidoweb.com/server/*;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/todocontenidoweb.com-error.log error;
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
server {
listen 80;
listen [::]:80;
server_name todocontenidoweb.com www.todocontenidoweb.com;
return 302 https://$server_name$request_uri;
}
# FORGE CONFIG (DO NOT REMOVE!)
#include forge-conf/todocontenidoweb.com/after/*;
//Edit
As you can see below, the site is returning a 301 respose and redirecting to https site, but none of your nginx configs are running on port 443
//End of Edit
There seems to an issue with your nginx config. It seems like your config is only allowing port 80 and not 443. Browsers expect to get 443 as port (unless you otherwise specify) as ssl port. And it seems like you're using some redirect to redirect users from http to https, only problem is you're not running any https service on port 443.
I could be an issue with your nginx config. make sure that the server entry that has the ssl input, also running on port 443.
If you did install ssl with let's encrypt, you can try to generate certificate manually and then you can modify nginx config to run on port 443 as ssl
You can follow this guide from digitalocean , just replace the certificates path with lets-encrypt one
Edit 2 :
I don't think this part should be commented out
# FORGE SSL (DO NOT REMOVE!)
# ssl_certificate;
# ssl_certificate_key;
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY13>
# ssl_prefer_server_ciphers off;
# ssl_dhparam /etc/nginx/dhparams.pem;
As you're essentially not serving any ssl certificate through the 443 port.
Here is an example server from DigitalOcean. As you can see, they're serving a private and public key. Once you generate your certificate, you need to enter the path of those.
server {
listen 443 http2 ssl;
listen [::]:443 http2 ssl;
server_name your_server_ip;
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
}
End of Edit

Nginx Server Configuration: Hostname not resolving on Subdomain

thank you in advance for your support.
I set up an Ubuntu Server with Nginx as a Digitalocean Droplet and am using the server provisioning tool Laravel Forge, which works fine. I successfully installed the PHP Framework Laravel and deployed the code on the server. I ssh into the server and checked the files in the supposed directory. The code is successfully deployed.
Next I own a domain, and created an A record for the following subdomain: app.mywebsite.de, that points to that server. I followed the digitalocean instructions and I waited the required time. Using a DNS Lookup tool, I confirmed that the subdomain actually points to the server.
Screenshot of DNS Lookup
Yet, when I use the subdomain in my browser, the browser doesn't connect to the server. I get the following error message in the browser:
Screenshot of Browser when connecting to server
It seems like the subdomain is correctly pointed to the server, but the server isn't rightly configured. I tried to check the nginx configuration and under sites-avaialble I have the following configuration for the subdomain:
# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/app.mywebsite.de/before/*;
server {
listen 80;
listen [::]:80;
server_name app.mywebsite.de;
server_tokens off;
root /home/forge/app.mywebsite.de/public;
# FORGE SSL (DO NOT REMOVE!)
# ssl_certificate;
# ssl_certificate_key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS_AES_256_GCM_SHA384:TLS-AES-256-GCM-SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparams.pem;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/app.mywebsite.de/server/*;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/app.mywebsite.de-error.log error;
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
# FORGE CONFIG (DO NOT REMOVE!)
include forge-conf/app.mywebsite.de/after/*;
In forge-conf/app.website.de/before/*; is only one file redirect.conf with the following code:
server {
listen 80;
listen [::]:80;
server_name www.app.website.de;
if ($http_x_forwarded_proto = 'https') {
return 301 https://app.website.de$request_uri;
}
return 301 $scheme://app.website.de$request_uri;
}
There are no other sites on the server. So there is only the 000-catch-all file in the sites available directory of the nginx configuration folder.
Unfortunately I reached my limit of understanding here and I would love if somebody could point me into the right direction to find out, which part of nginx is not configured corectly.
P.S.
Some additional info:
Yes I restarted Nginx and the whole server multiple times.
Turns out, everything was configured correctly. I didn't change anything, except that I added some additional sites on the nginx server. Forge probably updated the server blocks, which resolved the problem.

laravel email verify not works in production because of ssl certificate

User must verify their email address so I use laravel email verification.
I configured the project on Ubuntu20.04 and with nginx. Verification link works when I use let's encrypt certificate.
I followed all the steps and configured cloudflare and I followed digitalocean tutorial for adding cloudflare ssl certificate.
This is the nginx configuration for domain
server {
listen 80;
listen [::]:80;
server_name ishtap.az www.ishtap.az;
return 302 https://$server_name$request_uri;
}
server {
# listen 80;
# ssl(created in cloudflare) configuration follwing digitalocean tutorial
# https://www.digitalocean.com/community/tutorials/how-to-host-a-website-using-cloudflare-and-nginx-on-ubuntu-20-04
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/key.pem;
ssl_client_certificate /etc/ssl/cloudflare.crt;
ssl_verify_client on;
server_name ishtap.az www.ishtap.az;
root /var/www/ishtap.az/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
# listen 443 ssl; # managed by Certbot
# ssl_certificate /etc/letsencrypt/live/ishtap.az/fullchain.pem; # managed by Certbot
# ssl_certificate_key /etc/letsencrypt/live/ishtap.az/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
}
So when I click email verification link I get error in the attached
image. If cloudflare paused it works no problem but at some route like
where you input sensitive data like password chrome not makes request
and throws "your connection to this site is not fully secured"
In this case, you will have to repair the certificate since the certificate chain is unable to see where is the exact location or the cert is unable to be decrypted. In other words, you can use this tool
To use this tool, you will have to use a Windows machine.
This tool is from DigiCert, you can open it and you can click on SSL, and you can select the cert and click on repair. Also, you can create a new CSR, and you can reissue the cert once again to be able to upload it one more time to your server.
Let me know if you have any other questions or concerns, and I would be more than happy to help you.
The email verification notification is sent in queue and I use supervisor in ubuntu. I find out that there is something wrong with laravel .env file
This is the steps:
fixed APP_URL in .env file to https version of domain
php artisan cache:clear
php artisan config:clear
sudo systemctl reload nginx
php artisan config:cache
supervisorctl restart all restarts all workers

#spinner{} element fails two worker when Nginx is the reverse proxy in front of Nitrogen

I have running my Nitrogen driven application directly however because i want to use Nginx load-balancing magic i found out that the progress notifier of Nitrogen, the Spinner is not showing at all. I followed the example as at Nitrogen configuration options - bottom of the page. The example code snippet at the link is shown below.
# My config for a site that I only want serving SSL content.
server {
listen 80;
server_name www.mysite.com, mysite.com;
access_log /var/log/nginx/mysite.com.access.log;
# rewrite all requests to be SSL
rewrite ^(.*) https://$host$1 permanent;
}
server {
listen 443;
server_name mysite.com www.mysite.com
access_log /var/log/nginx/mysite.ssl.access.log;
ssl on;
ssl_certificate ssl/mysite/mysite.com.crt;
ssl_certificate_key ssl/mysite/mysite.com.key;
ssl_client_certificate ssl/mysite/ca.crt;
location / {
# This installation is running on port 8021, as you can plainly see.
proxy_pass http://127.0.0.1:8000;
}
}
Without Nginx the spinner works fine. I am using Nitrogen over Yaws of release as stated in the RELEASE file [{release,"nitrogen","2.3.0-beta5","5.10.3",[...,...,...,...],permanent}]. I do not what I am not doing right.

nginx, Magento & Cloudfront

I have inherited a website that is running Magento & nginx. I know virtually nothing about nginx and know a fair amount about Magento. The site is configured to use the Amazon Cloudfront CDN however all of the images, js & css are returning a 301 redirect to the origin site. I have a development site running Apache with the same Magento, MySQL & Cloudfront setup that is functioning correctly with this setup so I am pretty sure it is a problem with the config file for nginx. There have been some rewrites written in to the file and my assumption is that when the request for an asset at skin.mydomain.com is made it is redirecting to www.mydomain.com instead of serving the file from the CDN. I have CNAME records setup for js.mydomain.com, skin.mydomain.com and cloud.mydomain.com that all point to the same Cloudfront CDN. Here is the portion of the nginx config file that would seem to be applicable:
server {
listen 80;
##127.0.0.1:8080
server_name mydomain.com;
rewrite / $scheme://www.$host$request_uri permanent; ## Forcibly prepend a www
}
server {
listen 80;
##127.0.0.1:8080 default
## SSL directives might go here
listen 443 default ssl;
ssl_certificate /etc/nginx/
ssl_certificate_key /etc/nginx/
server_name www.mydomain.com;
## *.mydomain.com; Domain is here twice so server_name_in_redirect will favour the www
root /var/www/magento;
location / {
index index.html index.php; ## Allow a static html file to be shown first
try_files $uri $uri/ #handler; ## If missing pass the URI to Magento's front handler
expires 30d;
if ($request_uri ~* "\.(ico|css|js|gif|jpe?g|png)$") {
access_log off;
expires max;
}
port_in_redirect off;
}
Any help would be appreciated as I have been working on this pretty much all day and would like to stop working on it at some point.
Thanks!
It appears the first server directive is forcing a rewrite of the www.
server {
. . .
rewrite / $scheme://www.$host$request_uri permanent; ## Forcibly prepend a www
. . .
}

Resources