I am using nginx in a standard reverse proxy scenario, to pass all requests to /auth to another host, however I'm trying to use non-standard ports.
My end goal is to have the X-Forwarded-Port header set to the port that the request comes in on.
Here is my location block in nginx.conf:
location /auth/ { proxy_pass http://otherhost:8090; 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; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port <VAR>; }
This nginx is running in a docker container, that is configured to forward requests from 8085 into 80 in the container, such that the nginx process is listening on 80:
0.0.0.0:8085->80/tcp
When I hit the URL:
I am correctly redirected to http://otherhost:8090, but the X-Forwarded-Port header is missing or wrong.
Where I have <VAR> in the original block, I have tried the following:
$server_port - This is the port nginx is listening on (80), not the
request port.
$pass_port - Seems to be null in my setup, so nginx drops the
header.
$http_port - This is a random port per request.
$remote_port - This is a random port per request.
I can change my config at deploy time to hardcode to the known port of incoming requests, but ideally I would be able to change the front port without any change to the nginx config.
I've scoured the nginx variable list but can't find anything like $request_port. Is there any way for me to achieve my intent?
The only workaround I've found is to use a map rule to get the port from the http_host variable e.g.
map $http_host $port {
default 80;
"~^[^\:]+:(?<p>\d+)$" $p;
}
This is a just rough idea to write Nginx conf, but I am sure this can help you in redirection
server {
listen 80;
server_name host.docker.internal;
# By default land on localhost:80 to root so in root we copied UI build to the ngnix html dir.
# have a look to docker-compose uiapp service.
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
# after location add filter, from which every endpoint starts with or comes in endpoint
# so that ngnix can capture the URL and reroute it.
# like /backend/getUserInfo/<UserId>
# In above example /backend is that filter which will be captured by Ngnix and reroute the flow.
location /backend {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_pass http://<ContainerName>:<PortNumber>;
# In our case Container name is as we setup in docker-compose `beservice` and port 8080
proxy_pass http://beservice:8080;
}
}
For more details you can have a look at this project
Inside from container you cannot access the outer config. And nginx doesn't support using environment variables inside most configuration blocks.
But if you use poco you can define your ports, paths, etc in a simple env file. These definition used by docker-compose configuration or env variable too. For example
yourconfig.env
PROJECT_HOME=..
MAGIC_DOCKER_PORT=8085
poco.yml file (main config to your project, define plans)
version: '3.0'
maintainer: "youremail@yourdomain.com"
environment:
include: docker/conf/yourconfig.env
plan:
live:
description: "your plan to run live"
docker-compose-file:
- docker/dc-proxy.yml
- docker/dc-other-service.yml
# you can define other plans to run local/dev env
and in docker/dc-proxy.yml compose file (relevant part):
version: '3'
services:
proxy:
image: nginx:alpine
env_file: conf/yourconfig.env
ports:
- ${MAGIC_DOCKER_PORT}:80
command: /bin/sh -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
and at last your config template relevant part from /etc/nginx/conf.d/mysite.template
listen ${MAGIC_DOCKER_PORT};
...
location /auth/ {
...
proxy_set_header X-Forwarded-Port ${MAGIC_DOCKER_PORT};
...
}
I use the following folder structure to organize files. It is not mandatory, but easy to use for me because my every project structure are same.
/
docker <- all of docker related files here
conf <- env files, service configs, etc
scripts <- shell scripts which used by containers
dc-*.yml <- separate all services into single compose files
poco.yml <- main config, "start here" point
project-related-files <- separated by each service
Define a key-value pair in .env file. This is used by poco for create docker-compose files, and it used to create environment variable in nginx container. After that use envsubst to fill out nginx config template, and at last starts nginx service