using nginx to proxy different domains to different ports

I’ve got a secret devops weapon in the works. At a very simple level, part of it involves running multiple web applications on a single IP, but without having control of the webserver. Well, full disclosure, the applications include built-in tomcat instances and automatically install themselves on separate ports, and figuring out how to hack giant pre-built applications and modify tomcat was obviously not the quick option.

So I decided to do a proof of concept. What I needed was to be able to route requests at the domain level, all ingressing on port 80 (443 and SSL/HTTPS is the next step I suppose), and route them to a local port, all within the webserver (the machine is on Google Cloud, sans loadbalancer, and AFAIK there is no option in the console to handle this at the TCP/IP level).

A quick google turned up two obvious proxy solutions: Apache with mod_proxy, or nginx.

I’m an nginx fan, and haven’t had the opportunity to use it much recently, so I chose to do the PoC with nginx and proxy_pass directives, on a local Ubuntu VM.

The preconditions I wanted to set up were pretty straightforward – I needed two web apps, running on different, non-standard http ports, that were both visible in browser if you added the port number.

– site1 on port 81, accessible in browser via http://proxytest.local:81
– site2 on port 82, accessible in browser via http://proxytest.local:82

Then end result I wanted to create was also easily defined – two sites, running on the same ip, but different domains, with each domain transparently forwarded to the right application on its non-standard local port:

– http://site1.local forwards to local port 81
– http://site2.local forwards to local port 82

Setting up the preconditions

Install nginx, if needed – if you’re running apache or another process that owns port 80, be sure to stop it first

service apache2 stop
apt-get install nginx

create web files for both site1 and site2

mkdir /var/www/proxy_test;
mkdir /var/www/proxy_test/site1;
mkdir /var/www/proxy_test/site2;
nano mkdir /var/www/proxy_test/site1/index.html;
add whatever text to make site1 identifiable
nano mkdir /var/www/proxy_test/site2/index.html;
add some text to make it apparent this is site2

edit /etc/hosts to make the test domains resolve to localhost

127.0.0.1 proxytest.local site1.local site2.local

create nginx config files for site1 and 2, in /etc/nginx/sites-available

root@ubuntu:/etc/nginx/sites-available# cat ./site1
server {
listen 81;
listen [::]:81;

server_name site1.local;

root /var/www/proxy_test/site1;
index index.html;

# location / {
# try_files $uri $uri/ =404;
# }
}

root@ubuntu:/etc/nginx/sites-available# cat ./site2
server {
listen 82;
listen [::]:82;

server_name site2.local;

root /var/www/proxy_test/site2;
index index.html;

# location / {
# try_files $uri $uri/ =404;
# }
}

… and symlink them to /etc/nginx/sites-enabled to enable the sites

cd /etc/nginx/sites-enabled ; ln -s ../sites-available/site1 ; ln -s ../sites-available/site2

root@ubuntu:/etc/nginx/sites-enabled# ll
total 8
drwxr-xr-x 2 root root 4096 Jul 27 07:56 ./
drwxr-xr-x 8 root root 4096 Jul 27 07:28 ../
lrwxrwxrwx 1 root root 34 Jul 27 07:28 default -> /etc/nginx/sites-available/default
lrwxrwxrwx 1 root root 24 Jul 27 07:56 site1 -> ../sites-available/site1
lrwxrwxrwx 1 root root 24 Jul 27 07:56 site2 -> ../sites-available/site2

restart nginx to apply changes

service nginx restart

verify you can see all the sites in browser, using their port numbers

default nginx page on port 80
2018-07-27_10h08_47

site 1
2018-07-27_10h09_01

site 2
2018-07-27_10h09_11

Setting up the Proxy

So preconditions were set up. Now I needed to figure out how to implement nginx as a proxy to let users access each site by domain, sans port number.

Turns out it was a lot easier than I thought it would be. Just create the proxy config at /etc/nginx/sites-available/proxy_test

root@ubuntu:/etc/nginx/sites-enabled# cat ./proxy_test
server {
listen 80;
server_name site1.local;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:81;
}
}
server {
listen 80;
server_name site2.local;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:82;
}
}

… symlink it into /etc/nginx/sites-enabled like you did with the site1 and site2 config files above, restart nginx, and viola! Now each site is accessible on external port 80, by domian name.

Site 1

2018-07-27_11h38_32

Site 2

2018-07-27_11h38_42

 

I love you nginx <3

Martinez-bros-concrete.com – completed WordPress project

My work life isn’t all Magento. Sometimes between contracts, I do other stuff.

I just did the logo, site design, and WordPress build for martinez-bros-concrete.com – http://martinez-bros-concrete.com, a concrete and landscaping company based in Denton, TX. Took about a week.

My design skills aren’t 1337, but they’re usually good enough to get something professional put together. And honestly, the North Texas concrete business is not exactly the most competitive sector when it comes to web design.