I am setting up a cdn using cloudfront. My origin for my cloudfront distribution is my aws load balancer (ELB). When I make a request to cloudfront instead of getting the cloudfront url (cdn.mysite.com/images/image.jpg) it is being redirected to https://www.alio.com/images/image.jpg. I figured out why it is doing this due to my nginx.conf:
server {
root /var/www/html/alio/public;
index index.php;
server_tokens off;
server_name www.alio.com;
location / {
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$request_uri? permanent;
}
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
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;
}
}
The rewrite ^ https://$host$request_uri? permanent; changes the url (when i delete the rewrite i get the cdn url). I have this rewrite to ensure that all requests to my site are https. If there a way to do instead of a rewrite a 301 redirect or not do this rewrite if I detect it's cloudfront making the call to the ELB?
Have you configured CloudFront to whitelist host headers?
For each behaviour > Forward Headers > Select 'Whitelist' > Select 'Host' from the list and hit Add.
This setting ensures that the host header (cdn.mysite.com) is included in requests back to the origin (so make sure you've added cdn.mysite.com to your server_name directive).
It might also be worth considering using the HTTP Strict Transport Security header if you only want your site accessed over TLS. Adding the following to your config should do it:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
I see these types of constructs a lot. They're Apachisms that you should learn to do differently.
Http and https are protocols and as such should be handled at the level where the protocol is handled, not where the document location is handled, unless they a are location specific, which in your case they are not.
This also allows to keep things clean and not inadvertently configure something on the http level that circumvents the always https logic.
So always https is simple:
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 ... ;
....
}
Should not make it more complicated :-)
Related
I don't have much experience with regex, and less in an Nginx context, so this one is a difficult one for me.
What I want is that when I'm on a especific page (not subfolder) the server takes images from a different root.
My current configuration to handle images in all the pages of my website right now is this one.
location ~* \.(png|jpg|jpeg|gif) {
root /usr/share/nginx/nginxTestPHP/media;
}
And I'd like that when I'm in the page example.com/My-Profile the server handles the images from /usr/share/nginx/nginxTestPHP/media/uploads, my idea is something like this, if it makes any sense.
location ~* /My-Profile/*\.(png|jpg|jpeg|gif) {
root /usr/share/nginx/nginxTestPHP/media/uploads;
}
Obviously this one doesn't work otherwise I wouldn't be here asking this, so for the regex pros out there, what would be the solution for this one ?
Also how would I apply this in 2 different pages in the same regex, something like (My-Profile|Configuration) is my idea.
My Nginx configuration
server {
listen 81;
listen [::]:81;
server_name IP;
client_max_body_size 4M;
charset UTF-8;
include /etc/nginx/mime.types;
error_log /var/log/nginx/error_log warn;
access_log /var/log/nginx/access_log main;
rewrite ^(/.*)\.html(\?.*)?$ $1$2 permanent;
rewrite ^/(.*)/$ /$1 permanent;
root /usr/share/nginx/nginxTestPHP/PHP;
index index.html index.htm Inicio.php Index.php;
location / {
try_files $uri/index.html $uri.html $uri/ #extensionless-php;
}
location #extensionless-php {
rewrite ^(.*)$ $1.php last;
}
# pass the PHP scripts to FastCGI
location ~ \.php$ {
try_files $uri =404;
fastcgi_intercept_errors on;
fastcgi_pass app:9000;
fastcgi_index Inicio.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include fastcgi_params;
}
location ^~ /vendor/ {
deny all;
return 403;
}
# deny access to .htaccess files
location ~ /\.ht {
deny all;
}
location ^~ /en/ {
try_files $uri/.php $uri.php $uri/ #rewrite;
fastcgi_intercept_errors on;
fastcgi_pass app:9000;
fastcgi_index Index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include fastcgi_params;
}
location ^~ /Blog/ {
try_files $uri/.php $uri.php $uri/ #rewrite;
fastcgi_intercept_errors on;
fastcgi_pass app:9000;
fastcgi_index Index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include fastcgi_params;
}
location #rewrite {
rewrite ^/(en|Blog)(/.*\.(png|jpg|svg|ico))$ $2 last;
return 404;
}
location ~ \.css {
root /usr/share/nginx/nginxTestPHP/CSS;
default_type text/css;
add_header Content-Type text/css;
}
location ~ \.js {
root /usr/share/nginx/nginxTestPHP/JavaScript;
default_type text/javascript;
add_header Content-Type application/x-javascript;
}
location ~ \.txt {
root /usr/share/nginx/nginxTestPHP/PHP;
}
location ~* ^/Mi-Perfil/([^/]+\.(png|jpg|jpeg|gif))$ {
alias /usr/share/nginx/nginxTestPHP/media/uploads/$1;
}
location ~* \.(png|jpg|svg|ico|jpeg|gif) {
root /usr/share/nginx/nginxTestPHP/media;
}
error_page 405 =200 $uri;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/nginxTestPHP/PHP;
try_files $uri /Inicio.php;
}
}
Your regex is broken, it is a dot (.) in PCRE patterns that acts as a wildcard, not an asterisk one. If you want to match any non-zero number of characters except a / one, you can use [^/]+ regex pattern:
location ~* /My-Profile/[^/]+\.(png|jpg|jpeg|gif)$ { ... }
or to ensure that an URI started exactly with /My-Profile/ add a ^ anchor (matches start of the string):
location ~* ^/My-Profile/[^/]+\.(png|jpg|jpeg|gif)$ { ... }
Check the difference between root and alias nginx directives. With your configuration nginx will search the files inside the /usr/share/nginx/nginxTestPHP/media/uploads/My-Profile folder. Use an alias directive instead:
location ~* ^/My-Profile/[^/]+\.(png|jpg|jpeg|gif)$ {
alias /usr/share/nginx/nginxTestPHP/media/uploads;
}
Update
I think I made a serious mistake. Since this is a regex matching location an alias directive argument should contain full path to image file with filename:
location ~* ^/My-Profile/([^/]+\.(png|jpg|jpeg|gif))$ {
alias /usr/share/nginx/nginxTestPHP/media/uploads/$1;
}
Little experience with Nginx here but the regex part looks relatively simple to fix - try using:
location ~* /My-Profile/.+\.(png|jpg|jpeg|gif)$ {
root /usr/share/nginx/nginxTestPHP/media/uploads;
}
Note the .+ after My-Profile/ and the end-of-string anchor ($) - I'm assuming you want to only match images, not a URI like stackoverflow.com/test.png/somepage.
From the little research I did, you may also want to look into nginx maps, especially if you're looking to do this for multiple profile pages all following the same URI pattern.
※ I'm using example.com as example
I'm developing an app with ELB and EC2.
The structure is as followed.
When an user access to /manage/*, ELB will transfer to wordpress hosted instance.
Here is the ELB setting.
About ELB it works, but after transfered to wordpress side, CSS and JS files' response show 404.
When I access to /magazine/* URL, loading animation of wordpress theme starts to work but get stuck because of not loaded css and js.
I'm guessing it's because of nginx configuration but can't solve it.
This is the content of configuration file. I just add /etc/nginx/conf.d/vhosts.conf and write some settings. I don't touch other files.
# vhosts.conf
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443;
server_name example.com;
root /var/www/html;
location /magazine {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
}
below /var/www/html, project's structure is as followed.
/wp-content
/wp-admin
/wp-include
index.php
wp-config.php
for other information,
I installed php-fpm.
SSL certification is set up with ACM and Route53
Additional Info
Both siteurl and home in DB table wp_options are set to https://example.com/magazine.
Result
made /var/www/html/magazine directory and move all files into it.
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443;
server_name example.com;
location ~* /(wp-config|xmlrpc)\.php {
deny all;
}
location #magazine {
rewrite ^/magazine(.*) /magazine/index.php?$args;
}
location ^~ /magazine {
root /var/www/html;
index index.php index.html index.htm;
try_files $uri $uri/ #magazine;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
}
}
Since you are not serving wordpress from the root of your url, you must tell wordpress to load the assets from the subdirectory. How you can do this, is described in a wordpress support article. [1]
Did you check whether the WP_HOME and WP_SITEURL variables are set correctly?
Could you edit your question and include the URL your browser tries to load for the css and js files since it is not fully visible in the screenshot?
Edit:
Thanks to the additional information we know that wordpress constructs the path as expected. So, now I share your opinion that nginx is causing the issue.
I looked around and noticed two possible issues with the nginx configuration:
The root statement should probably be inside the location block. I do not know if this is really necessary, but many people do it. [2]
The location block does a prefix match and includes the prefix magazine into the $uri variable as stated in a serverfault thread. [3]
You could strip away the prefix by using a regex as follows:
location ~ ^/magazine(.*) {
root /var/www/html;
try_files $1 $1/ /index.php?$args;
}
Note: I do not know if the directory redirect $1 and default redirect to /index.php?$args make sense for serving js/css assets. You should probably remove them if they are not necessary.
References
[1] https://wordpress.org/support/article/changing-the-site-url/#changing-the-site-url
[2] https://serverfault.com/a/258540/531099
[3] https://serverfault.com/a/455853/531099
I'm using nginx to serve my SPA front end and my django back end (a REST api).
My django backend runs at http://127.0.0.1:8000 with gunicorn.
The IP of my server is http://X.X.X.X/
I want to serve my front end from http://X.X.X.X/ and my backend from http://X.X.X.X/api/.
So far, my nginx configuration file for my front end looks like this.
server {
listen 80;
server_name 0.0.0.0;
client_max_body_size 4G;
access_log /var/log/nginx/frontend/access.log;
error_log /var/log/nginx/frontend/error.log;
location /api/ {
proxy_pass http://goa:8000/api/;
proxy_redirect http://goa:8000/api/ http://$host/api/;
proxy_set_header SCRIPT_NAME /api;
}
location / {
alias /var/www/html/goa/;
try_files $uri $uri/ /index.html;
proxy_redirect off;
}
}
I tried to follow this post.
The problem now is that the django routing always route to /api/ but my routes don't know about this prefix. So if I go to /api/admin/ django will be handling the request but won't find /api/admin/ because it only knows about /admin/.
I know I could rewrite my routes in Django itself but I'd like to keep everything related to route redirection in nginx configuration.
I'm trying to change my website over from the default /year/month/day/post_title permalinks, to a simple /post_title/ link, however, when changing it, all of my older links are broken. I've read a site on how to do it on Apache with .htaccess, but need some help on figuring out how to make it work with nginx's location instead of mod_rewrite.
This is the site that details how to do it on Apache http://www.rickbeckman.org/how-to-update-your-wordpress-permalinks-without-causing-link-rot/
And I tried using this htaccess to nginx converter http://winginx.com/htaccess however, the regex is probably causing a problem and I get this error when starting nginx
[emerg]: unknown directive "4}/[0-9]" in /usr/local/nginx/sites-enabled/website.com:19
And this is my configuration file
server {
listen 80;
server_name website.com;
rewrite ^/(.*) http://www.website.com/$1 permanent;
}
server {
listen 80;
server_name www.website.com;
error_log /home/user/public_html/website.com/log/error.log;
client_max_body_size 10M;
client_body_buffer_size 128k;
location / {
root /home/user/public_html/website.com/public/;
index index.php index.html;
try_files $uri $uri/ /index.php;
}
location ~ ^/[0-9]{4}/[0-9]{2}/[0-9]{2}/([a-z0-9\-/]+) {
rewrite ^(.*)$ http://website.com/$1 permanent;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$
{
fastcgi_read_timeout 120;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include /usr/local/nginx/conf/fastcgi_params;
fastcgi_param SCRIPT_FILENAME /home/user/public_html/website.com/public/$fastcgi_script_name;
}
}
Would anyone know how to fix it? Thanks.
the fix is easy:
location ~ ^/[0-9]{4}/[0-9]{2}/[0-9]{2}/([a-z0-9\-/]+) {
rewrite ^(.*)$ http://website.com/$1 permanent;
}
the problem with the above is that the rewrite resets the backreferences so the $1 now matches the entire url from your rewrite match, not the $1 from the location match.
the following should work:
location ~ ^/[0-9]{4}/[0-9]{2}/[0-9]{2}/([a-z0-9\-/]+) {
set $post_title $1;
rewrite ^(.*)$ http://website.com/$post_title permanent;
}
(alternatively match the regex in the rewrite rule again)
Fixed it by adding quotes around the regex.
rewrite "^/[0-9]{4}/[0-9]{2}/[0-9]{2}/([a-z0-9\-/]+)" http://www.website.com/$1;
First of all, I have tried to search for similar questions, but the solutions to those questions were specific lines of code, that I couldn't customise to fit my needs.
I have a Codeigniter installation, and I'm trying to migrate from Apache to nginx. However, in Apache the .htaccess was pretty simple: it would take a whitelist, and rewrite everything else to index.php.
RewriteEngine on
RewriteCond $1 !^(index\.php|css|images|core|uploads|js|robots\.txt|favicon\.ico)
RewriteRule ^(.*)$ /index.php/$1 [L]
However in nginx, I have tried out the if and try_files directives, as well as messing around with locations, to no avail. I'm still new to how nginx reads the server config, and the tutorials online were somewhat confusing to follow through.
Additionally, the index.php will not be in the web root, but in a subdirectory server.
Because of this, I also need to make sure even URI requests beginning with /server do not go to the directory, but to index.php
This is my nginx virtual host configuration so far:
server {
listen 80;
server_name example.com;
root /home/example/public_html;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
index index.htm index.html index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/example.sock;
include fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~* ^.*(/|\..*) {
try_files $uri $uri/ /server/index.php;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Which helps to redirect requests to index.php, but doesn't have a whitelist. I would appreciate it if anyone could generate a working example with a brief explanation of what each part does.
I would use the $uri variable and if in a location block to achieve this.
location / {
if ( $uri !~ ^/(index\.php|css|images|core|uploads|js|robots\.txt|favicon\.ico) ) {
rewrite ^ /server/index.php last;
}
}
Also, as for the pathinfo security problems, (discussion) it's a good practice to add
try_files $uri =403;
fastcgi_split_path_info ^(.+.php)(.*)$;
to the location ~ \.php$ block.