I want to achieve the following rewrite with nginx:
example.com -> example.io
*.example.com -> *.example.io
So anything that is related to example.com should be redirected to example.io, while preserving the subdomain if there is one.
You just need a simple server block to listen on example.com and redirect to example.io
http {
map $server_name $redirect_to {
default example.io;
"~*^(.*)\.example.com$" $1.example.io;
}
server {
listen 80;
listen 443 ssl;
server_name example.com *.example.com;
ssl_certificate ...;
ssl_certificate_key ....;
return 302 $scheme://$redirect_to$request_uri;
}
Related
I'm trying to connect to my backend api, usually anything that is /intApi/<*> gets sends over to different api.domain.com. but for some reason the request changes from post to get.
+
I'm using nginx to do
listen 80;
listen [::]:80;
server_name api.domain.com www.api.domain.com;
location / {
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 http2 ssl;
server_name api.domain.com www.api.domain.com;
ssl_certificate /etc/nginx/ssl/live/api.domain.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/live/api.domain.com/privkey.pem;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://backendDocker:3500/;
}
location ~ /.well-known/acme-challenge/ {
root /usr/share/nginx/web/api;
}
}
To push it further and nginx output is either OPTIONS or GET instead of POST.
What am I doing wrong here? I tried 301/302 redirects. Same issue :/
I am moving to a new domain and have set up 301 redirects on my ec2 instance.
Currently I have the following:
server {
listen 80;
server_name olddomain.co.uk;
return 301 $scheme://www.newdomain.com$request_uri;
}
this works fine for www.olddomain.co.uk and olddomain.co.uk. However it does not work for https://www.olddomain.co.uk
I am wondering how I can make it so the redirect also works with https://www...
Thanks
Your server isn't listening to https:// i.e. 443 port. Connection to https://www.olddomain.co.uk would simply be refused. Add proper ssl configurations to your nginx file and it should be fine.
server {
listen 80;
listen 443 ssl;
server_name olddomain.co.uk;
return 301 $scheme://www.newdomain.com$request_uri;
}
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
I have a website running with a Python/Django/uWSGI/Nginx setup. I also use Certbot to enable https on my site. My redirects from non-www to www (e.g. "example.com" to "www.example.com") result in a "Bad Request (400)" message even though I couldn't spot any deviations from the Nginx/Certbot documentation. Here is the relevant part of my sites-available Nginx code:
server {
listen 80;
server_name example.com www.example.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/myname/example;
}
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/activities.sock;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; #managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/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
if ($scheme != "https") {
return 301 https://$host$request_uri;
} # managed by Certbot
}
I found a similar StackOverflow answer (Nginx: redirect non-www to www on https) but none of the solutions worked for me. I have SSL certificates for both example.com and www.example.com. I also tried creating a separate 443 ssl server block for example.com based on the comments in that answer but it didn't work either. My sites-available and sites-enabled code is the same.
What am I doing wrong?
It seems that server_name when translated to the $host variable selects the first in the list of server_name. Let me know if that works. I can't quite test this currently.
Try swapping server_name to server_name www.example.com example.com; as well as changing return 301 https://$host$request_uri; to return 301 https://$server_name$request_uri;
server {
server_name www.example.com example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
# SSL CERT STUFF.
server_name example.com;
return 301 https://www.$server_name$request_uri;
}
server {
listen 443 ssl;
# SSL CERT STUFF.
server_name www.example.com;
# LOCATION STUFF
}
This is not an efficient configuration for Nginx request processing. It's messy, your if condition gets evaluated on every request and I don't see where your non www to www is even meant to happen.
I'd split http and https:
server {
listen 80 default_server;
return 301 https://www.example.com$request_uri;
}
Thats all non https traffic taken care of in a single redirect. Now for the https:
server {
listen 443 default_server ssl;
server_name www.example.com;
root # should be outside location blocks ideally
......
}
The default server directive means this server will handle any requests which do not have a matching server configuration. If you don't want that then add example.com after www.example.com, not before it. Any requests ending up here will display the first entry in the client browser bar.
Based on your comments you might need to add a separate block for the other domain to avoid an SSL certificate mismatch. Try this:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate .....;
ssl_certificate_key .....;
return https://www.example.com$request_uri;
}
Although the OP has accept one of the answers as the solution, I just want to point out that it may not be the best practice.
The correct way is to use $host instead of $server_name (as per Mitchell Walls' example) or hardcoded www.exmple.com (as per miknik's example). Both results an extra 443 server directive that is not necessary and messy.
server {
listen 80 default_server;
server_name www.example.com example.com;
root /var/www/html; # define your root directory here
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
# SSL CERT STUFF.
#server_name www.example.com; you don't need to specify again here
# LOCATION STUFF
}
There is a difference between $host and $server_name:
$host contains "in this order of precedence: host name from the request line, or host name from the 'Host' request header field, or the server name matching a request".
$server_name contains the server_name of the virtual host which processed the request, as it was defined in the nginx configuration. If a server contains multiple server_names, only the first one will be present in this variable.
I was able to create certifications under the path /etc/letsencrypt/{{mywebdomain}}/ and set under my server where the ssl_cert and ssl_cert_key absolute pathfile locations for my nginx server.
When I run the command sudo nginx -t I receive a successful configuration output and the nginx server is running in the reverse proxy for Django without any problems. But when I access the root of my website on my chrome browser, I'm receiving the "http://website.com" instead of "https://website.com".
Please point me in the right direction if anyone was able to correctly encrypt their domain content with gunicorn-django-nginx configuration.
My website snippet conf:
upstream app_server {
unix:/home/me/Documents/masterdomain/src/portfolio_revamp.sock;
}
server {
client_max_body_size 4M;
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
listen www.mysite.com:80;
server_name example.com www.example.com;
http://example.com;
ssl_certificate
/etc/letsencrypt/live/mysite.com/fullchain.pem;
ssl_certificate_key
/etc/letsencrypt/live/mysite.com/privkey.pem;
root /home/akeem/Documents/SpencerMaster/src;
index templates/home.html templates/main.html;
location / {
proxy_pass
http://unix:/home/me/Documents/masterdomain/src/portfolio_revamp.sock;
alias /home/me/Documents/master/templates/home.html;
}
location ~ /.well-known {
allow all;
}
location /static {
autoindex on;
alias /home/me/Documents/masterdomain/static;
}
location /media {
autoindex on;
alias /home/me/Documents/masterdomain/media;
}
}
I'm running a xenial ubuntu 16.04 server if that makes a difference.
I believe the issue is that you aren't redirecting to HTTPS - unless you specifically enter https://example.com, you'll be directed to the standard http://example.com.
I use this guide from DigitalOcean which recommends two server blocks. In your case it will look something like:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name mysite.com www.mysite.com;
return 301 https://$server_name$request_uri;
}
server {
client_max_body_size 4M;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
No server_name required here
... Everything else ...
}
I have the issue that i want to rewrite all subdomains except www to a specific folder.
The Problem is this is running inside a docker container with a external volume an dynamic hostname for different hosts. So i have to use $hostname.
As soon as you use $hostname it gots the same threatment as a regex rule. So creating one rule for www don't work becuase it got the same threatment for www.$hostname as for *.$hostname or an regex there.
i tried multiple things, extracting it directly in a variable from the server_name that did not work at all and i'm now at a condition regex with a negative lookahead that works fine on any regex tester but not in the ngnix
2016/02/16 12:28:14 [emerg] 1#0: invalid condition "(?!www.)(\w" in /etc/nginx/sites-enabled/default:10
Anyone got any ideas?
server {
listen 443 ssl;
listen 80;
server_name *.$hostname;
error_log /var/log/nginx/rewrite.log debug;
root /src/webapp/dist;
ssl_certificate /etc/nginx/ssl/server-cert.pem;
ssl_certificate_key /etc/nginx/ssl/server-key.pem;
if ($http_host ~ ((?:\w+(?:-\w+)*\.)*)((?!www\.)\w+(?:-\w+)*)(\.$hostname)) {
set $subdomain $1;
return 301 $scheme://www.$hostname/#/$subdomain/media/portfolio/1;
break;
}
}
Also tested below block, same result no redirect working at all, again it's located inside a docker container with a ngninx 1.4.6-1ubuntu3.4 :
server {
listen 80;
listen 443 ssl;
server_name www.$hostname;
root /src/webapp/dist;
ssl_certificate /etc/nginx/ssl/server-cert.pem;
ssl_certificate_key /etc/nginx/ssl/server-key.pem;
}
server {
listen 80;
listen 443 ssl;
server_name *.$hostname;
ssl_certificate /etc/nginx/ssl/server-cert.pem;
ssl_certificate_key /etc/nginx/ssl/server-key.pem;
return 301 $scheme://www.$hostname/#/media/portfolio/1;
}
You could handle it with two server blocks. The first server block will handle the www.$hostname and the second will work for all other cases.
Here is an example:
server {
listen 80;
listen 443 ssl;
server_name www.$hostname;
ssl_certificate /etc/nginx/ssl/server-cert.pem;
ssl_certificate_key /etc/nginx/ssl/server-key.pem;
# Do whatever you want here
}
server {
listen 80;
listen 443 ssl;
server_name *.$hostname;
ssl_certificate /etc/nginx/ssl/server-cert.pem;
ssl_certificate_key /etc/nginx/ssl/server-key.pem;
# Do whatever you want here
}
If you had been thinking about some conditional if statements - Forget it. It's a bad idea. Nginx has support for ifs but they are only there for very extreme cases and their use is highly discouraged as they don't work as in normal programming languages.
server {
listen 443 ssl;
listen 80;
server_name *.$hostname;
error_log /var/log/nginx/rewrite.log debug;
root /src/webapp/dist;
ssl_certificate /etc/nginx/ssl/server-cert.pem;
ssl_certificate_key /etc/nginx/ssl/server-key.pem;
if ($host ~* "((?:\w+(?:-\w+)*\.)*)((?!www\.)\w{3,}(?:-\w+)*)(\..*\.muc\.pom)") {
set $subdomain $2;
return 301 $scheme://www.$hostname/#/$subdomain/media/portfolio/1/about;
break;
}
}
Ngninx somehow is not be able to use a variable in the regex, so i have to get around a little bit with dns endings, for production use there should also better solution, but hte regex is matching and rewriting.
I know If's are bad, if anyone can come up with another solution for docker please feel free to share