nginx rewrite mystery - duplicating hostname and losing https - nginx

I am replacing lighttpd with nginx on my development server. I got it working with PHP and SSL, but I'm stumped by what should be a simple rewrite. I need to rewrite URLs from
http[s]://dev.foo.com/signup/123456
to
http[s]://dev.foo.com/signup/index.php?attcode=123456
The rule I am using is:
rewrite ^/signup/([0-9]+)$ /signup/index.php?attycode=$1 last;
I have tried numerous variations on this, moved it around, put it inside a location block. What happens is the URL is rewritten to:
http://dev.foo.com/dev.foo.com/signup/123456
The hostname is inserted, and it seems to always lose https and go to http.
My nginx.com server section is below. I have read and re-read the nginx docs (as they are) and searched the nginx mailing list, but nothing I've tried has solved this problem.
Ubuntu 8.0.4 LTS in case that matters.
Thanks.
server {
listen 80;
listen 443 default ssl;
server_name dev.foo.com dev.bar.com localhost;
root /var/www/foo;
index index.php index.html;
# ssl cert stuff omitted
charset utf-8;
access_log /var/log/www/dev.access.log main;
location ~ /\. {
deny all;
}
location ~* ^.+\.(inc|tpl|sql|ini|bak|sh|cgi)$ {
deny all;
}
location ~* ^/(scripts|tmp|sql)/ {
deny all;
}
rewrite ^/robots.txt$ /robots_nocrawl.txt break;
rewrite ^/signup/([0-9]+)$ /signup/index.php?attycode=$1 last;
location / {
try_files $uri $uri/ /error_404.php;
}
location ~ \.php$ {
fastcgi_pass localhost:51115;
fastcgi_index index.php;
fastcgi_intercept_errors on;
include fastcgi_params;
fastcgi_param SERVER_NAME $http_host;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
error_page 404 /error_404.php;
}

Don't put HTTP and HTTPS in the same server block. Separate them into two almost-identical server blocks, one for HTTP and one for HTTPS. Otherwise you will confuse all kinds of Nginx internals.

Related

Nginx Problem with Joomla Backend (Cloudflare Error 520)

Hey everyone!
I'm having a really hard time figuring this out, when i run my website with apache, everything works as intended, however i recently switched to nginx, when i run my website on nginx and access the joomla backend i get an Error 520 from Cloudflare, i can't find out the difference in the two webservers, but it seems related to SSL, running without SSL works fine.
I'm out of luck i did a lot of testing and still the same issue.
Something that Cloudflare cannot understand is happening when using Nginx.
This is my Nginx Config
server {
listen 443 ssl http2;
listen 80;
server_name websitename.com www.websitename.com;
root /var/www/html;
ssl_certificate websitename.com.crt;
ssl_certificate_key websitename.com.key;
index index.php index.html index.htm default.html default.htm;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~* /(images|cache|media|logs|tmp)/.*\.(php|pl|py|jsp|asp|sh|cgi)$ {
return 403;
error_page 403 /403_error.html;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi.conf;
}
location ~* \.(ico|pdf|flv)$ {
expires 1y;
}
location ~* \.(js|css|png|jpg|jpeg|gif|swf|xml|txt)$ {
expires 14d;
}
}
Finally i solved it.
Finally i found out that somehow the Cloudflare Railgun isn't behaving right with Nginx
I went to Cloudflare and navigated to "Speed->Optimizations" I disabled the Railgun
and i no longer have 520 Errors.
Hope this helps anyone with the same issue, been 3 days stuck on this.

Nginx location rules not applying

I want to run both WordPress and YOURLS on one domain which is configured by a NGINX server block (not the default site). Since both need to handle URLs differently, they need different try_files directives. WordPress sits on the root of the domain (domain.tld), while YOURLS is being installed to the /g/ directory. Despite the two location rules, I get 404s on any links generated by YOURLS (e.g. domain.tld/g/linkname, all are redirects to external URLs), though I can access the admin backend.
As far as I read, declaring to location rules (one for /g/, and one for /) should suffice in order to let NGINX handle the direct and the /g/ URLS differently - is there something in wrong in my thinking?
The try_files rules are correct and do work well on other single-application server block (WordPress as well as YOURLS on installs on separate server blocks).
The server block definition config looks like this:
server {
listen [::]:80;
listen 80;
server_name domain.tld www.domain.tld;
return 301 https://domain.tld$request_uri;
}
server {
listen [::]:443 ssl;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.tld/privkey.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
root /var/www/html/domain.tld;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html index.php;
server_name domain.tld www.domain.tld;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;
}
location /g/ {
try_files $uri $uri/ /yourls-loader.php$is_args$args;
expires 14d;
add_header Cache-Control 'public';
}
location / {
try_files $uri $uri/ /index.php?$args;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
location ~ /\.ht {
deny all;
}
}
The problem with the location /g/ try_files directive is that the path to the YOURLS loader isn't correct. If the URL handler (yourls-loader.php) lies within the /g directory, the path to it has to be changed to include the /g directory:
try_files $uri $uri/ /g/yourls-loader.php$is_args$args;
The location rule does not imply that each path is handled from that location as well, but rather from the root path given above.

Hosts file and nginx redirect from http to https on development server

I am developing a website, and I just installed ssl on the production website (I have never done this before). When I load the development website the page redirects to https and breaks because https isn't installed on the development site.
Development url: http://local.ezel.io
Production url: https://ezel.io
The Nginx (production):
server{
listen 80;
server_name ezel.io;
root /var/www/ezel.io/public;
location ~ /.well-known {
allow all;
}
rewrite ^ https://$server_name$request_uri? permanent;
}
The Nginx (development):
server {
listen 80;
server_name local.ezel.io;
root /home/ryan/Documents/www/ezel.io/public;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.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;
}
}
On my development machine, I also have the following in my hosts file:
127.0.0.1 local.ezel.io
What would be causing me to go from http://local.ezel.io to https://local.ezel.io?
I think the problem is that you enabled https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security once and now your browser insists on trying HTTPS.
Try this: http://classically.me/blogs/how-clear-hsts-settings-major-browsers
Also, try pinging local.ezel.io to ensure it's really your localhost and not actually ezel.io.

nginx-apache-wordpress: setup apache/wordpress under subdirectory and behind nginx

I had developed a Rails app and was happy with it, but I was asked to setup Wordpress under subdirectory /wp. After some unhappy hours of trying to make nginx-to-apache proxying work, I gave up copying code from shitty guides and wrote some very short and clear config:
location #wp {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://127.0.0.1:8080;
}
location ~ ^/wp(/|$) {
root /home/apache/www;
rewrite ^/wp/?$ / break;
rewrite ^/wp/(.*) /$1 break;
try_files $uri #wp;
}
It solved most of problems I've had experienced, but it won't work for an obvious reason:
Wordpress generates <real_ip>:8080/<url> links and that is not just ugly (I can live with it), but links don't work since Apache listens on localhost only.
How can I tell Apache or Wordpress (or what header should I proxy with Nginx) to make links look like <real_ip>/wp/<url>? Or is my setup faulty by design? I would appreciate any solution or hint, thanks!
Below is my configuration for nginx, which runs a Rails app at the main root, and a WordPress blog under a subdirectory. Perhaps try this?
server {
listen <ip-address>:80;
server_name domain.com;
rewrite ^(.*)$ $scheme://www.domain.com$request_uri? permanent;
break;
}
server {
listen <ip-address>:80;
server_name www.domain.com;
root /www/domain.com/public_html/current/public;
access_log /www/domain.com/logs/access.log;
error_log /www/domain.com/logs/error.log;
location ^~ /blog {
root /www/domain.com/blog/public_html;
index index.php index.html index.htm;
try_files $uri $uri/ /blog/index.php?$args;
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
if ($uri !~ "^/images/") {
fastcgi_pass unix:/var/run/php-fastcgi/php-fastcgi.socket;
}
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /www/domain.com/blog/public_html$fastcgi_script_name;
}
}

Nginx forward www and non-www requests to one directory?

I have a MediaTemple server from which I serve many websites. I use nginx and have the follow config file. I am correctly forwarding all non-www traffic (ie, http://example.com) to the appropriate directory. However, all the www traffic is returning 404 because my config file is looking for /directory-structure/www.sitename.com instead of /directory-structure/sitename.com
How can I have both www and non-www requests go to one directory? Thanks.
server {
listen 80;
server_name _;
root /var/www/vhosts/$host/httpdocs/;
error_page 404 /;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
#fastcgi_pass php;
fastcgi_pass 127.0.0.1:9000;
}
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
expires max;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
# this prevents hidden files (beginning with a period) from being served
location ~ /\. { access_log off; log_not_found off; deny all; }
}
Starting with version 0.7.40 Nginx accepts regular expressions in server_name and captures. Thus it's possible to extract a domain name (without www) and use this variable in root directive:
server_name ~^(?:www\.)?(.+)$ ;
root /var/www/vhosts/$1/httpdocs;
Starting with 0.8.25 it is possible to use named captures:
server_name ~^(?:www\.)?(?P<domain>.+)$ ;
root /var/www/vhosts/$domain/httpdocs;
Another syntax to define named captures is (?<domain>.+) (PCRE version 7.0 and later). More on PCRE versions here
Try this and add the following in the above server config:
if ($host = "www.example.com") {
rewrite (.*) http://example.org$1;
}
What happens here, we are instructin nginx to serve the pages as http://example.com even though the browser URL reads http://www.example.com - I hope this works.
UPDATE
Try this for a generic version:
if ($host ~* "www.(.*)") {
rewrite ^ http://$1$request_uri?;
}
Given the potential issues with if as linked to in RakeshS's answer's comments, as well as the fact that RakashS's answer didn't work for me anyway, here's a solution that should be safer and worked for me with Nginx 1.0.14.
Add an additional server entry for each one of your server sections that does a rewrite:
server {
server_name www.yourwebsite.com;
rewrite ^ $scheme://yourwebsite.com$request_uri permanent;
}

Resources