I've just switched from Apache to nginx and it still takes some getting used to (and a lot of learning).
I'm running a Pagekit website which has this configuration: https://gist.github.com/DarrylDias/be8955970f4b37fdd682
server {
listen 80;
listen [::]:80;
# SSL configuration
listen 443 ssl;
listen [::]:443 ssl;
ssl on;
ssl_certificate /etc/ssl/private/mydomain.com.crt;
ssl_certificate_key /etc/ssl/private/mydomain.com.private.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_client_certificate /etc/ssl/private/cloudflare.origin-pull-ca.pem;
ssl_verify_client on;
server_name mydomain.com www.mydomain.com;
root /home/vhosts/domains/mydomain.com/public/;
index index.php;
# Leverage browser caching of media files for 30 days
location ~* \.(?:ico|css|js|gif|jpe?g|png|ttf|woff)\$ {
access_log off;
expires 30d;
add_header Pragma public;
add_header Cache-Control "public, mustrevalidate, proxy-revalidate";
}
location / {
try_files $uri $uri/ /index.php?$args;
}
# Deny access to sensitive folders
location ~* /(app|packages|storage|tmp)/.*$ {
return 403;
}
# Deny access to files with the following extensions
location ~* \.(db|json|lock|dist|md)$ {
return 403;
}
# Deny access to following files
location ~ /(config.php|pagekit|composer.lock|composer.json|LICENSE|\.htaccess) {
return 403;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php7-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param HTTP_MOD_REWRITE On;
}
}
Unforunately, many (including me) have the issue that files with extensions such as js|css|jpg|<etc> are getting a 403 response because they're located inside either the app or packages directory.
I've attempted multiple regexes to try and give the location for these files a higher priority in nginx, but they seemed to have no effect.
How should this config file be changed in order to allow these kind of files, but still return a 403 on all other files inside those directories?
EDIT: the file URL's look like https://example.com/app/js/something.min.js?v=1921 perhaps it doesn't work because of the ?v=1921 ?
According to nginx's document:
nginx checks locations given by regular expression in the order listed in the configuration file
So first you need to move your last location to the top.
Then the regular expression that tries to match static files is also incorrect. The dollar sign "$" should match the end of path but it was escaped by a prior backslash "\" (so it actually matches a character "$"). Remove the backslash will fix your issue:
location ~* \.(?:ico|css|js|gif|jpe?g|png|ttf|woff)$ {
...
}
Related
I am using an Ubuntu 18.04.5 LTS webserver that is configured with nginx. The server is running and I can access any file on my mainpage example.com. Now I want to install matomo on the server. However, I can only manage to access the installation via my root url www.example.com. Whenever I try to move the Matomo-access to a subpage e.g. example.com/matomo/ my sever sends a 404 instead. I think I have made a mistake in creating a configuration setup for calling subpages, but I cannot figure out what went wrong. I am new to nginx and have spent the last 2 days testing for a solution. Any help would be highly appreciated. Please find my server.conf, as well as the matomo.conf below.
My server config-file is as follows:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
set $base /var/www/example.com;
root $base/public;
# SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# security
include nginxconfig.io/security.conf;
# logging
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log warn;
# index.php
index index.php;
# index.php fallback
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# handle .php
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
include nginxconfig.io/php_fastcgi.conf;
}
}
My matomo.conf:
server {
listen 443 ssl http2;
server_name www.example.com/subpage example.com/subpage;
access_log /var/log/nginx/matomo.access.log;
error_log /var/log/nginx/matomo.error.log;
## SSL
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
add_header Referrer-Policy origin always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
root /var/www/example.com/subpage/matomo/; # path to matomo instance
index index.php;
## only allow accessing the following php files
location ~ ^/(index|matomo|piwik|js/index|plugins/HeatmapSessionRecording/configs)\.php {
include snippets/fastcgi-php.conf;
fastcgi_param HTTP_PROXY "";
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
## deny access to all other .php files
location ~* ^.+\.php$ {
deny all;
return 403;
}
## serve all other files normally
location / {
#try_files $uri $uri/ =404;
}
## disable all access to the following directories
location ~ ^/(config|tmp|core|lang) {
deny all;
return 403; # replace with 404 to not show these directories exist
}
location ~ /\.ht {
deny all;
return 403;
}
location ~ js/container_.*_preview\.js$ {
expires off;
add_header Cache-Control 'private, no-cache, no-store';
}
location ~ \.(gif|ico|jpg|png|svg|js|css|htm|html|mp3|mp4|wav|ogg|avi|ttf|eot|woff|woff2|json)$ {
allow all;
## Cache images,CSS,JS and webfonts for an hour
## Increasing the duration may improve the load-time, but may cause old files to show after an Matomo upgrade
expires 1h;
add_header Pragma public;
add_header Cache-Control "public";
}
location ~ ^/(libs|vendor|plugins|misc/user|node_modules) {
deny all;
return 403;
}
## properly display textfiles in root directory
location ~/(.*\.md|LEGALNOTICE|LICENSE) {
default_type text/plain;
}
}
# vim: filetype=nginx
Thanks for the quick reply.
After further looking for solutions I have now done both: I created a subdomain and launched matomo under a subpage by adding the following code to the subdomain.config.
location /matomo {
root /var/www/subdomain.example.com/matomo;
}
I found this to be a great tutorial on creating subdomains.
Hi there!
I'am trying to configure Nginx for 2 yii projects, frontend for users and admin for admins with only one domain (no sub domain). I need to configure it in a way such that mydomain.com should refer to frontend and mydomain.com/admin to admin. The problem is I'am being able to configure only one of them at a time, meaning I can use frontend or admin not both of them.
What I have tried
front.conf
server {
listen 80;
server_name api.maim.experiments.uz;
return 301 https://$server_name$request_uri;
}
server {
charset utf-8;
client_max_body_size 128M;
listen 443 ssl;
ssl_certificate_key privkey.pem;
ssl_certificate fullchain.pem;
ssl_protocols TLSv1.2;
set $host_path "/home/itschool/inha_dev/frontend";
server_name api.maim.experiments.uz;
root $host_path/web;
set $yii_bootstrap "index.php";
access_log /var/log/nginx/itschool-access.log;
error_log /var/log/nginx/itschool-error.log;
location / {
index index.html $yii_bootstrap;
try_files $uri $uri/ /index.php;
}
location ~ ^/(protected|framework|themes/\w+/views) {
deny all;
}
location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
try_files $uri =404;
}
location ~ \.php$ {
set $fsn /index.php;
if (-f $document_root$fastcgi_script_name){
set $fsn $fastcgi_script_name;
}
fastcgi_pass 127.0.0.1:9002;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fsn;
}
location ~ /\.(ht|svn|git) {
deny all;
}
location ~* /\. {
deny all;
access_log off;
log_not_found off;
}
}
back.conf
server {
listen 80;
server_name api.maim.experiments.uz;
return 301 https://$server_name$request_uri;
}
server {
charset utf-8;
client_max_body_size 128M;
listen 443 ssl;
ssl_certificate_key privkey.pem;
ssl_certificate fullchain.pem;
ssl_protocols TLSv1.2;
set $host_path "/home/itschool/inha_dev/backend";
server_name api.maim.experiments.uz;
root $host_path/web;
set $yii_bootstrap "index.php";
access_log /var/log/nginx/itschool-access.log;
error_log /var/log/nginx/itschool-error.log;
location ^~ /admin {
alias /home/itschool/inha_dev/backend/web;
if (!-e $request_filename) { rewrite ^ /admin/index.php last; }
location ~ \.php$ {
if (!-f $request_filename) { return 404; }
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass 127.0.0.1:9002;
}
}
location ~ /\.(ht|svn|git) {
deny all;
}
location ~* /\. {
deny all;
access_log off;
log_not_found off;
}
}
I found some questions with answers but they didn't work for me, please help.
I have recently use similar configuration to support web application / mobile application and admin panel on single domain
I hope this could help you out. Below is the configuration
server {
listen 80;
set $root /var/www/html/application;
#here we go
#if backend not found in url then set root url
if ($uri !~ "^(.*)/(backend)(.*)") {
set $root /var/www/html/application/frontend/web;
}
# when request is coming from mobile then display mobile site
# you don't need this one, I just written in order to explain the mobile application navigation.
if ($http_user_agent ~* "android|blackberry|googlebot-mobile|iemobile|ipad|iphone|ipod|opera mobile|palmos|webos") {
set $root /var/www/html/application/mobile/web;
}
root $root;
index index.php index.html index.htm index.nginx-debian.html;
server_name your_domain;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}
location / {
index index.html index.php;
if (!-e $request_filename){
rewrite ^/(.*) /index.php?r=$1 last;
}
}
location ~ /\.ht {
deny all;
}
}
Also have a look in official document of Yii2 to setup yii2-app-advanced on single domain (Apache, Nginx).
CLICK HERE
One more thing that you need to know is if you want to change backend/web to admin then you also have to made some changes in Yii2 application.
One domain will lead all requests to one IP (server). Nginx will use the first server block matching server_name https://nginx.org/en/docs/http/request_processing.html so you need to put all configuration on one file and use location to separate them.
You can move location ^~ /admin at the beginning of the front.conf locations and play with roots;
Or you can create a proxying config file that will contain just a little.
Something like that
location /admin {
proxy_pass http://localhost:8001;
}
location / {
proxy_pass http://localhost:8002;
}
Using the latter one you should change front & back configs to listen to other ports. Also, an SSL certificate was given for a domain, not URL. So you can use it only in the proxying config.
If you follow some of the key instructions from option 1 of Yii2 Single Domain Apache and Nginx you should be able to accomplish what you want.
Per the referenced link, Option 1:
Assuming Linux OS
cd /path/to/project/frontend/web
ln -s ../../backend/web backend
and set your nginx file
server {
charset utf-8;
client_max_body_size 128M;
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name api.maim.experiments.uz;
root /home/itschool/inha_dev/frontend/web;
index index.php;
access_log /var/log/nginx/itschool-access.log;
error_log /var/log/nginx/itschool-error.log;
location / {
# Redirect everything that isn't a real file to index.php
try_files $uri $uri/ /index.php$is_args$args;
}
# uncomment to avoid processing of calls to non-existing static files by Yii
#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
# try_files $uri =404;
#}
#error_page 404 /404.html;
# deny accessing php files for the /assets directory
location ~ ^/assets/.*\.php$ {
deny all;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
try_files $uri =404;
}
location ~* /\. {
deny all;
}
}
Not: See below link for the Option-2, if the above does not work:
Yii2 Single Domain Apache and Nginx
So I'm trying to setup 5 websites, all on the same domain just with diffrent subdomain, etc www. and cdn.
but www. works fine as it should
tho cdn. does not, It got the same files I just copyed them over, all permissions are the same for the folders.
I have each sub domain in their own files etc wwwmydomaincom and cdnmydomaincom and the config is the same, only diffrence is server_name. the file that works got www.mydomain.com the rest got somesubdomain.mydomain.com and they throw 404.
I use Nginx on ubuntu server 16.04.1.
Added
location / {
try_files $uri.html;
}
and the sub domains displays the html pages fine (now their config isent like the one that works)
But.. every asset, css, js, images or other things get 404 so it's a pure html page.
The config under is the exact same config as www.mydomain.com but changed to fit cdn.mydomain.com
server {
listen 80;
server_name cdn.domain.com;
location /.well-known/acme-challenge {
default_type "text/plain";
root /storage/webserver/certbot;
}
#Forces all other requests to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name cdn.domain.com;
ssl_certificate /etc/letsencrypt/live/cdn.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cdn.domain.com/privkey.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA512:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:ECDH+AESGCM:ECDH+AES256:DH+AESGCM:DH+AES256:RSA+AESGCM:!aNULL:!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
ssl_session_cache shared:TLS:2m;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
# Set HSTS to 365 days
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains';
root /storage/webserver/cdn.domain.com;
index index.html index.php;
location #rewrite {
rewrite ^ $uri.php last;
try_files $uri =404;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+?\.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
include fastcgi.conf;
try_files $uri =404;
}
rewrite ^(/.*)\.html(\?.*)?$ $1$2 permanent;
#rewrite ^/(.*)/$ /$1 permanent;
error_page 404 /404.php;
error_page 500 503 502 504 /error/40x.php;
location =/error/40x.html {
internal;
}
}
Ahem, this is why I want to learn this kind of stuff.
You obviosly need to make it look for the files.
so if anyone enters this litte situation, Don't forget to make it look in the root folder.
location / {
try_files $uri $uri/ $uri.html #rewrite;
}
I have ubuntu 14 on AWS ngnix is point to a website. I have tried everything but it does not serve up the static images. when I try to cache them. I have tired every combo of this but every time I go there are no files.
location ~* \.(css|js|jpeg|jpg|gif|png|ico|xml)$ {
access_log off;
expires 30d;
}
When I go to the directory there is no files in the root path. Any ideas?
Here is an official block usage https://www.nginx.com/resources/wiki/start/topics/examples/server_blocks/#
server {
# Replace this port with the right one for your requirements
listen 80 default_server; #could also be 1.2.3.4:80
# Multiple hostnames separated by spaces. Replace these as well.
server_name star.yourdomain.com *.yourdomain.com; # Alternately: _
root /PATH/TO/WEBROOT;
error_page 404 errors/404.html;
access_log logs/star.yourdomain.com.access.log;
index index.php index.html index.htm;
# static file 404's aren't logged and expires header is set to maximum age
location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires max;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_intercept_errors on;
# By all means use a different server for the fcgi processes if you need to
fastcgi_pass 127.0.0.1:YOURFCGIPORTHERE;
}
location ~ /\.ht {
deny all;
}
My company is running a webserver with nginx. The configuration is set so that every request on a certain server block are forcefully rewritten to https, using a location block. This is the full configuration for a specific domain:
# HTTP server
server {
listen 80;
server_name www.mydomain.it mydomain.it admin.mydomain.it;
rewrite ^(.*) https://$host$1 permanent;
}
# HTTPS server
server {
listen 443;
server_name www.mydomain.it mydomain.it admin.mydomain.it;
root /usr/share/nginx/html/mydomain_server;
ssl on;
ssl_certificate /etc/certs/mydomain-bundle.crt;
ssl_certificate_key /etc/certs/mydomain.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/mydomain.ssl.access.log main;
error_log /var/log/nginx/mydomain.ssl.error.log error;
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404-mydomain.html;
error_page 500 502 503 504 /50x.html;
location ~ \.php$ {
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
try_files $uri =404;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
This domain serves several implementations of the same software to different customers, and works like this:
Customer John: www.domain.com/John
Customer Ada: www.domain.com/Ada
etc...
Obviously, as you can see, all accesses to such URLS are redirected to HTTPS.
Now, there is a particular need for a single customer not this to happen.
I've been reading the official doc here about locations, which tells I can't non-match a particular expression (as stated here too), and I can't find a way to have it work.
I've tried to add another location block matching the customer path before the default one, like this:
server {
listen 80;
server_name www.mydomain.it mydomain.it admin.mydomain.it;
root /usr/share/nginx/html/mydomain_server;
location ^~ /Mole/ {
try_files $uri $uri/ =404;
}
location / {
rewrite ^(.*) https://$host$1 permanent;
try_files $uri $uri/ =404;
}
}
which is not working, as Mole is still being redirected to HTTPS. I've tried using "~", "=" and even simply "location /Mole/", without success. Not a browser cache problem as I've tried already flushing it. What am I missing?
You could try using the map directive to identify customers who prefer to use http:
map $uri $use_https {
default 1;
~^/Mole/ 0; # add other exceptions as needed
}
server {
listen 80;
server_name www.mydomain.it mydomain.it admin.mydomain.it;
root /usr/share/nginx/html/mydomain_server;
location / {
if ($use_https) { # consider using 302 for testing
return 301 https://$host$request_uri;
}
try_files $uri $uri/ =404;
}
}