Nginx how to redirect http to https? - nginx

I'm kind of new in aws services and nginx configuration.
I'm using nginx and my EB instance is a single instance with load balancer at classic mode in front of it.
I have this config file in system:
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 8080;
if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
set $year $1;
set $month $2;
set $day $3;
set $hour $4;
}
access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;
access_log /var/log/nginx/access.log main;
location / {
proxy_pass http://nodejs;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
the machine is behind load-balancer of aws elastic beanstack and EC2 that already configer to make a redirect from 80 to 443 according to aws docs
https://aws.amazon.com/premiumsupport/knowledge-center/elb-redirect-http-to-https-using-alb/
the problem here is that the redirect from http to https is not working, and i am unable to access my website when i come from http to https.
weird scenario when i visited my website http://something.com and then make refresh its make the redirect to https://something.com as i want to but not immediately.
any suggestion how to solve this problem?
*both http and https access work fine but i want that all my clients that access from http redirect them to https.

I did this solution and its work
node.js side
app.use(function(req, res, next) {
if (
(!req.secure) && (req.get('X-Forwarded-Proto') !== 'https') &&
!req.get('Host').includes('localhost')
) {
res.redirect('https://' + req.get('Host') + req.url);
}
else next();
});

Related

What is wrong with my FastAPI Reverse Proxy?

I have a web application which is setup in the following way: the frontend is being served by nginx. The backend is handled by FastAPI. I setup a rule in nginx to proxy all requests with url /api to the backend directly. Now, I also proxy to Grafana. The way I did this was to build a reverse proxy within my FastAPI server. So in nginx, I have a rule to proxy all requests with url /grafana to FastAPI. FastAPI then does some user authentication before proxying to the grafana server. The exception is that any Grafana websocket connection gets proxied directly from nginx to the grafana server.
Here's my nginx conf file
server {
server_name example.com www.example.com;
root /var/www/web-app/html;
index index.html index.htm index.nginx-debian.html;
location / {
try_files $uri $uri/ =404;
}
location /api {
proxy_pass http://localhost:5000;
}
# grafana reverse proxy
location /grafana {
proxy_set_header Origin http://localhost:3000;
# proxy_set_header Origin https://example.com;
proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin $http_origin;
proxy_pass http://localhost:5000;
}
location /grafana/api/live {
rewrite ^/(.*) /$1 break;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $http_host;
proxy_pass http://localhost:3030;
}
listen 443 ssl http2; # managed by Certbot
ssl_certificate /etc/letsencrypt/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/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
}
server {
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
Here's my FastAPI proxy
async def _reverse_proxy(request: Request):
url = httpx.URL(path=request.url.path,
query=request.url.query.encode("utf-8"))
new_header = MutableHeaders(request.headers)
if "grafana_session" not in request.cookies:
if "authorization" not in request.headers:
return RedirectResponse("/")
jwt_token = request.headers["authorization"].replace('Bearer ', '')
# user authentication stuff...
current_user = get_current_user_from_token(token=jwt_token, db=some_session)
org = get_org_by_id(current_user.org_id, some_session)
if org is None:
raise HTTPException(
status_code=404,
detail="Organization not found",
)
del new_header['authorization']
new_header['X-WEBAUTH-USER'] = current_user.username
new_header['X-Grafana-Org-Id'] = f"{org.grafana_org_id}"
if "authorization" in new_header:
del new_header['authorization']
rp_req = client.build_request(request.method, url,
headers=new_header.raw,
content=await request.body())
rp_resp = await client.send(rp_req, stream=True)
return StreamingResponse(
rp_resp.aiter_raw(),
status_code=rp_resp.status_code,
headers=rp_resp.headers,
background=BackgroundTask(rp_resp.aclose),
)
app = FastAPI(title=settings.PROJECT_NAME, version=settings.PROJECT_VERSION)
origins = ["http://localhost:3000", "https://example.com"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(api_router, prefix=settings.API_V1_STR)
app.add_route("/grafana/{path:path}", _reverse_proxy, ["GET", "POST", "DELETE"])
If I run this locally on localhost:3000 (with some modifications to nginx to be listening on 3000 instead of 443 ssl), everything works perfectly. If I try in production at example.com, I have to include this hacky bit proxy_set_header Origin http://localhost:3000; to change the origin in a request to my FastAPI proxy to make it work. Why is this happening?
NOTE: I've checked the grafana server logs to make sure that it wasn't the issue. None of the requests make it past the FastAPI server, it is the one returning error 403, origin not allowed.

How to set up nginx as reverse proxy to wordpress site hosted on apache2 with pretty permalinks?

With the following settings I am able to access the wordpress site which is hosted at localhost:8080 but the problem occurs when I enable the wordpress URL structure as post name instead of regular query string from permalinks settings.
#nginx server settings
server {
listen 80;
listen [::]:80;
server_name blog.mysite.com;
#use https always
return 307 https://$server_name$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
error_log /etc/nginx/logs/blog.mysite.com.log;
ssl on;
ssl_certificate /etc/letsencrypt/live/blog.mysite.com/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/blog.mysite.com/privkey.pem;
proxy_set_header X-SSL-CLIENT-CERT $ssl_client_cert;
server_name blog.mysite.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
also I have added the following snippet to wp-config.php
//wp-config.php modifications
if($_SERVER['HTTP_X-FORARDED-FOR'] == 'https') {
$_SERVER['HTTPS'] = 'on'
}
if(isset($_SERVER['HTTP_X_FORARDED_HOST']) {
$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORARDED_HOST']
}
I just want to use nginx as reverse proxy as I am planning to host nodejs apps on the same server, also I never used php fast cgi with nginx so any solution with my existing environment is preferable.
Thank you.

Unable to push docker images to artifactory

I set up artifactory as a docker registry and am trying to push an image to it
docker push nginxLoadBalancer.mycompany.com/repo_name:image_name
This fails with the following error
The push refers to a repository [ nginxLoadBalancer.mycompany.com/repo_name] (len: 1)
unable to ping registry endpoint https://nginxLoadBalancer.mycompany.com/v0/
v2 ping attempt failed with error: Get https://nginxLoadBalancer.mycompany.com/v2/: Bad Request
v1 ping attempt failed with error: Get https://nginxLoadBalancer.mycompany.com/v1/_ping: Bad Request
This is my nginx conf
upstream artifactory_lb {
server mNginxLb.mycompany.com:8081;
server mNginxLb.mycompany.com backup;
}
log_format upstreamlog '[$time_local] $remote_addr - $remote_user - $server_name to: $upstream_addr: $request upstream_response_time $upstream_response_time msec $msec request_time $request_time';
server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/my-certs/myCert.pem;
ssl_certificate_key /etc/nginx/ssl/my-certs/myserver.key;
client_max_body_size 2048M;
location / {
proxy_set_header Host $host:$server_port;
proxy_pass http://artifactory_lb;
proxy_read_timeout 90;
}
access_log /var/log/nginx/access.log upstreamlog;
location /basic_status {
stub_status on;
allow all;
}
}
# Server configuration
server {
listen 2222 ssl;
server_name mNginxLb.mycompany.com;
if ($http_x_forwarded_proto = '') {
set $http_x_forwarded_proto $scheme;
}
rewrite ^/(v1|v2)/(.*) /api/docker/my_local_repo_key/$1/$2;
client_max_body_size 0;
chunked_transfer_encoding on;
location / {
proxy_read_timeout 900;
proxy_pass_header Server;
proxy_cookie_path ~*^/.* /;
proxy_pass http://artifactory_lb;
proxy_set_header X-Artifactory-Override-Base-Url $http_x_forwarded_proto://$host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
There are no errors in the nginx error log. What might be wrong?
I verfied that the SSL verification works fine with the set up. Do I need to set up authentication before I push images?
I also verified artifactory server is listening on port 2222
Update,
I added the following to the nginx configuration
location /v1 {
proxy_pass http://myNginxLb.company.com:8080/artifactory/api/docker/docker-local/v1;
}
With this it now gives a 405 - Not allowed error when trying to push to the repository
I fixed this by removing the location /v1 configuration and also changing proxy pass to point to the upstream servers

How to redirect to specific upstream servers based on request URL in Nginx?

I'm using Nginx as a load balancer for my 5 app servers.
I'd like to redirect to specific servers based on the request URL, for instance:
acme.com/category/* => Server #1
acme.com/admin/* => Server #2
api.acme.com => Server #3
Fallback for any other URL => Server #4, #5
My config looks like:
upstream backend {
least_conn;
server 10.128.1.1;
server 10.128.1.2;
server 10.128.1.3;
server 10.128.1.4;
server 10.128.1.5;
}
server {
listen 80;
server_name _;
location / {
proxy_set_header Host $host;
proxy_pass http://backend;
}
}
I have no idea how to do this, since I'm not very familiar with Nginx - any one has some clues?
Read the documentation, eveything is well explained in it. There's particularly a beginner's guide explaining basics. You would end up with :
upstream backend {
least_conn;
server 10.128.1.4;
server 10.128.1.5;
}
server {
server_name _;
location / {
proxy_set_header Host $host;
proxy_pass http://backend;
}
}
server {
server_name acme.com;
location /admin/ {
proxy_set_header Host $host;
proxy_pass http://10.128.1.2;
}
location /category/ {
proxy_set_header Host $host;
proxy_pass http://10.128.1.1;
}
location / {
proxy_set_header Host $host;
proxy_pass http://backend;
}
}
server {
server_name api.acme.com;
location / {
proxy_set_header Host $host;
proxy_pass http://10.128.1.3;
}
}
You will also need to rewrite the URL otherwise /whatever/ will get forwarded to the backend server
location /admin/ {
rewrite ^/admin^/ /$1 break;
proxy_pass http://10.128.1.2;
}

Nginx wildcard proxy, pass subdomain to the server (upstream proxy)

I would like to be able to pass subdomain.domain.com to .domain.com apache server, with subdomain info too.
I would like to make a nginx cache for domain, acting like wildcard, but passing subdomain to the destination (there is apache witch wildcard too). Up to now, I pass the info via proxy_set_header Host $host; but I would like to have request with subdomain at the apache server.
upstream domain.com {
server 172.1.1.1:80 weight=50 fail_timeout=30s;
}
server {
server_name *.domain.com;
location / {
proxy_pass http://domain.com;
#proxy_pass $request;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
location ~* ^.+. (jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|swf)$ {
proxy_pass http://topmanagergame.com;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache my-cache;
proxy_cache_valid 200 302 30m;
proxy_cache_valid 404 1m;
}
access_log /var/log/nginx/domain.com.log main;
error_log off;
}
Do you think I can use proxy_pass with upstream ?
Nginx (*wildcard_domain.com) --(cache)--> Apache (*wildcard_domain.com)
Nginx (anything.domain.com) --(cache)--> Apache (anything.domain.com)
upstream somestring {
server domain2.com:80 weight=50 fail_timeout=30s;
}
server {
listen 80;
server_name *.domain.com;
server_name ~^(?<subdomain>.+)\.domain\.com$;
location / {
proxy_pass http://somestring;
proxy_set_header Host $subdomain.domain2.com;
}
}
So I was trying to find the answer to this problem and kept finding this post. But I think dmytrivv answer is out of date. In our scenario, we have both wildcard domains (e.g. *.mydomain.com) and custom domains (e.g. fullycustomdomain.com). But you can solve both by using proxy_set_header Host $host; and having default at the end of your listen.
upstream qaweb {
# Servers in the web farm
server ip-notreal-name.ec2.internal:80;
}
server {
listen 443 ssl default;
ssl_certificate certs/mydomain.com.crt;
ssl_certificate_key certs/mydomain.com.key;
# Support for wildcard domains
server_name admin.mydomain.com *.mydomain.com "";
location / {
# Turn off access logging so we don't fill the hardrive
access_log off;
proxy_pass http://qaweb;
proxy_set_header Host $host;
# So that the correct IP shows up in the log once libapache2-mod-rpaf is installed
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Note, we are also using it as a TLS termination proxy.
You can also find more examples on how to use proxy_pass here https://www.liaohuqiu.net/posts/nginx-proxy-pass/

Resources