cmc/cleberg.net

My personal web garden & blog.

clone: git clone https://gitbay.org/cmc/cleberg.net.git

main: content/blog/2022-04-02-nginx-reverse-proxy.org · raw

  1#+date:        [2022-04-02 Sat 00:00:00]
  2#+title:       Nginx Reverse Proxy Config
  3#+description: Setting up Nginx as a reverse proxy on Ubuntu.
  4#+slug:        nginx-reverse-proxy
  5#+filetags:    :linux:web:
  6
  7* What is a Reverse Proxy?
  8
  9A reverse proxy is a server that is placed between local servers or services and
 10clients/users (e.g., the internet). The reverse proxy intercepts all requests
 11from clients at the network edge and uses its configuration files to determine
 12where each request should be sent.
 13
 14** A Brief Example
 15
 16For example, let's say that I run three servers in my home:
 17
 18- Server01 (=example.com=)
 19- Server02 (=service01.example.com=)
 20- Server03 (=service02.example.com=)
 21
 22I also run a reverse proxy in my home that intercepts all public traffic:
 23
 24- Reverse Proxy
 25
 26Assume that I have a domain name (=example.com=) that allows clients to request
 27websites or services from my home servers.
 28
 29In this case, the reverse proxy will intercept all traffic from =example.com=
 30that enters my network and determine if the client is requesting valid data,
 31based on my configuration.
 32
 33If the user is requesting =example.com= and my configuration files say that
 34Server_{01} holds that data, Nginx will send the user to Server_{01}. If I were
 35to change the configuration so that =example.com= is routed to Server_{02}, that
 36same user would be sent to Server_{02} instead.
 37
 38#+begin_src txt
 39┌──────┐                                              ┌───────────┐
 40│ User │─┐                                         ┌──► Server_01 │
 41└──────┘ │                                         │  └───────────┘
 42         │    ┌──────────┐   ┌───────────────┐     │  ┌───────────┐
 43         ├────► Internet ├───► Reverse Proxy ├─────├──► Server_02 │
 44         │    └──────────┘   └───────────────┘     │  └───────────┘
 45┌──────┐ │                                         │  ┌───────────┐
 46│ User │─┘                                         └──► Server_03 │
 47└──────┘                                              └───────────┘
 48#+end_src
 49
 50* Reverse Proxy Options
 51
 52There are a lot of options when it comes to reverse proxy servers, so I'm just
 53going to list a few of the options I've heard recommended over the last few
 54years:
 55
 56- [[https://nginx.com][Nginx]]
 57- [[https://caddyserver.com][Caddy]]
 58- [[https://traefik.io/][Traefik]]
 59- [[https://www.haproxy.org/][HAProxy]]
 60- [[https://ubuntu.com/server/docs/proxy-servers-squid][Squid]]
 61
 62In this post, we will be using Nginx as our reverse proxy, running on Ubuntu
 63Server 20.04.4 LTS.
 64
 65* Nginx Reverse Proxy Example
 66
 67** Local Applications
 68
 69You may be like me and have a lot of applications running on your local network
 70that you'd like to expose publicly with a domain.
 71
 72In my case, I have services running in multiple Docker containers within a
 73single server and want a way to visit those services from anywhere with a URL.
 74For example, on my local network, [[https://dashy.to][Dashy]] runs through port 4000
 75(=localhost:4000=) and [[https://github.com/louislam/uptime-kuma][Uptime Kuma]] runs through port 3001 (=localhost:3001=).
 76
 77In order to expose these services to the public, I will need to do the
 78following:
 79
 801. Set up DNS (Domain Name System) records for a domain or subdomain (one per
 81   service) to point toward the internet protocol (IP) address of the server.
 822. Open up the server network's HTTP (Hypertext Transfer Protocol) and HTTPS
 83   (Hypertext Transfer Protocol Secure) ports (80 & 443) so that the reverse
 84   proxy can accept traffic and determine where to send it.
 853. Install the reverse proxy software.
 864. Configure the reverse proxy to recognize which service should get traffic
 87   from any of the domains or subdomains.
 88
 89** Step 1: DNS Configuration
 90
 91To start, update your DNS configuration so that you have an =A= record for each
 92domain or subdomain.
 93
 94The =A= records should point toward the public IP address of the server. If you
 95don't know the public IP address, log in to the server and run the following
 96command:
 97
 98#+begin_src sh
 99curl ifconfig.co
100#+end_src
101
102In the DNS example below, =xxx.xxx.xxx.xxx= is the public IP address of
103the server.
104
105#+begin_src conf
106example.com             A        xxx.xxx.xxx.xxx
107uptime.example.com      A        xxx.xxx.xxx.xxx
108dashy.example.com       A        xxx.xxx.xxx.xxx
109www                     CNAME    example.com
110#+end_src
111
112Finally, ensure the DNS has propagated correctly with [[https://dnschecker.org][DNS Checker]] by entering
113your domains or subdomains in the search box and ensuring the results are
114showing the correct IP address.
115
116** Step 2: Open Network Ports
117
118This step will be different depending on which router you have in your home. If
119you're not sure, try to visit [[http://192.168.1.1][192.168.1.1]] in your browser. Login credentials are
120usually written on a sticker somewhere on your modem/router.
121
122Once you're able to log in to your router, find the Port Forwarding settings.
123You will need to forward ports =80= and =443= to whichever machine is running
124the reverse proxy.
125
126In my case, the table below shows the port-forwarding rules I've created. In
127this table, =xxx.xxx.xxx.xxx= is the local device IP of the reverse proxy
128server, it will probably be an IP between =192.168.1.1= and =192.168.1.255=.
129
130| NAME  | FROM PORT | DEST PORT/IP    | ENABLED |
131|-------+-----------+-----------------+---------|
132| HTTP  | 80        | xxx.xxx.xxx.xxx | TRUE    |
133| HTTPS | 443       | xxx.xxx.xxx.xxx | TRUE    |
134
135Once configured, these rules will direct all web traffic to your reverse proxy.
136
137** Step 3: Nginx Installation
138
139To install Nginx, simply run the following command:
140
141#+begin_src sh
142sudo apt install nginx
143#+end_src
144
145If you have a firewall enabled, open up ports =80= and =443= on your server so
146that Nginx can accept web traffic from the router.
147
148For example, if you want to use =ufw= for web traffic and SSH, run the following
149commands:
150
151#+begin_src sh
152sudo ufw allow 'Nginx Full'
153sudo ufw allow SSH
154sudo ufw enable
155#+end_src
156
157** Step 4: Nginx Configuration
158
159Now that we have domains pointing toward the server, the only step left is to
160configure the reverse proxy to direct traffic from domains to local services.
161
162To start, you'll need to create a configuration file for each domain in
163=/etc/nginx/sites-available/=. They will look identical except for the
164=server_name= variable and the =proxy_pass= port.
165
166Dashy:
167
168#+begin_src sh
169nano /etc/nginx/sites-available/dashy.example.com
170#+end_src
171
172#+begin_src config
173server {
174    listen 80;
175    server_name dashy.example.com;
176
177    location / {
178        proxy_pass http://localhost:4000;
179    }
180}
181#+end_src
182
183Uptime:
184
185#+begin_src sh
186nano /etc/nginx/sites-available/uptime.example.com
187#+end_src
188
189#+begin_src config
190server {
191    listen 80;
192    server_name uptime.example.com;
193
194    location / {
195        proxy_pass http://localhost:3001;
196    }
197}
198#+end_src
199
200Once the configuration files are created, you will need to enable them with the
201=symlink= command:
202
203#+begin_src sh
204sudo ln -s /etc/nginx/sites-available/dashy.example.com /etc/nginx/sites-enabled/
205#+end_src
206
207Voilà! Your local services should now be available through their URLs (uniform
208resource locators).
209
210* HTTPS with Certbot
211
212If you've followed along, you'll notice that your services are only available
213via HTTP (not HTTPS).
214
215If you want to enable HTTPS for your new domains, you will need to generate TLS
216(Transport Layer Security) certificates for them. The easiest way to generate
217certificates on Nginx is [[https://certbot.eff.org][Certbot]]:
218
219#+begin_src sh
220sudo apt install snapd; sudo snap install core; sudo snap refresh core
221sudo snap install --classic certbot
222sudo ln -s /snap/bin/certbot /usr/bin/certbot
223sudo certbot --nginx
224#+end_src