I have a firewall that blocks pretty much anything except port 80. Because of this, I just spent two days trying to set up a reverse proxy on my new server at http://cadence.singles.
Really dumbed down, a reverse proxy handles all traffic on the same port (80) and directs it within its network, before serving the response as if it did all the work.
I needed this in order to let select subdomains point to applications on other ports (but on the same server) behind the firewall. Specifically, I wanted:
- http://ci.cadence.singles -> http://cadence.singles:7070 (Jenkins), and
- http://node.cadence.singles -> http://cadence.singles:3000 (Node.js).
- As an added bonus, I wanted to to keep the default configuration for port 80.
As a complete newbie to HTTP servers, I started out with apache2/httpd and spent hours trying to understand how the configuration worked. When I finally took the entire server down, I decided to migrate to nginx. Best choice ever.
Here’s what I did to do what I did.
First off, configuring a reverse proxy does not magically configure the subdomains to point to your server’s IP. This took me quite a lot of time to understand. I host my servers on Linode, so I headed over there and configured it through their DNS manager.
In fact, I set up a “catch-all” subdomain (*) to point to my server’s IP address, basically saying that “no matter what comes before “.cadence.singles”, I want it directed here”. I could (and should, probably) have configured each one individually, but I honestly couldn’t be arsed. My configuration ended up like this (the IP pointing to my server):
Note: The configuration probably takes some time (we’re talking minutes, maybe even hours) to take effect. Then there’s caching and all that. Also note that the blank hostname points to no subdomain, that is, just http://cadence.singles. I messed that up.
Second, I installed nginx on my server:
- sudo apt-get install nginx
Third, I started the server and made sure it worked as intended, even with subdomains:
- sudo service nginx start (or, if you’re old school: sudo /etc/init.d/nginx start)
- http://cadence.singles (port 80 is the default)
- http://randomsubdomain.cadence.singles
Both 2. and 3. showed me the same page telling me it worked, so this was where the configuration bit came in.
Fourth: In the nginx default configuration directory (/etc/nginx/conf.d), I created a file called servers.conf. This file configures each server I wanted a specific subdomain for. I needed root access all the way. By the way, I like vim.
- sudo vim /etc/nginx/conf.d/servers.conf
I started out with Jenkins (on port 7070). I declared a server named ci.cadence.singles, which listens on port 80:
server { listen 80; server_name ci.cadence.singles; }
Then, I told it what I wanted it to do inside the server block. The only thing to really note is the proxy_pass address. Everything else can easily be the same in any configuration. The final configuration (/etc/nginx/conf.d/servers.conf) ended up like this:
server { listen 80; server_name ci.cadence.singles; location / { proxy_pass http://localhost:7070; 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_connect_timeout 150; proxy_send_timeout 100; proxy_read_timeout 100; proxy_buffers 4 32k; client_max_body_size 8m; client_body_buffer_size 128k; } }
FIfth, I restarted nginx, and and it just worked.
- sudo service nginx restart
- http://ci.cadence.singles
Sixth, I added the Node.js server to servers.conf by declaring a second server. I’m lazy, so I really just copied the previous block and changed the server_name and proxy_pass lines. The final file (my running config) looks like this:
server { listen 80; server_name ci.cadence.singles; location / { proxy_pass http://localhost:7070; 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_connect_timeout 150; proxy_send_timeout 100; proxy_read_timeout 100; proxy_buffers 4 32k; client_max_body_size 8m; client_body_buffer_size 128k; } } server { listen 80; server_name node.cadence.singles; location / { proxy_pass http://localhost:3000; 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_connect_timeout 150; proxy_send_timeout 100; proxy_read_timeout 100; proxy_buffers 4 32k; client_max_body_size 8m; client_body_buffer_size 128k; } }
Then I restarted nginx again, and I was good to go.
- sudo service nginx restart
- http://ci.cadence.singles
- http://node.cadence.singles
PS: My configuration is likely to change, so I do not guarantee that these links actually work!
Thanks. This post was very helpful.
Spent about 4 hours looking for this. Thank you very much!.
Hello, I’m trying a similar setting for my jenkins server, but in my case the jenkins instance run with a prefix (http://domain.tld:9999/jenkins). And this setting doesn’t seems to work, what do you suggest?
Thank you.
Took me 4 years 🙂 Really appreciate your tip
Awesome! Share, I’ve been looking for this. Thank you so much.
Thank a lot dude
Happy it helped! 😀
Is some equivalent for Apache using .htaccess in a subdomain for instance?
Hi! You can definitely accomplish the same thing with Apache/httpd. I’ve just shared how I did it with nginx 🙂
Thanks, your way of explaining really helpful
I’m glad you found it useful!