From 797a1404213173791a5f4126a77ad383ceb00064 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Mon, 4 Mar 2024 22:34:28 -0600 Subject: initial migration to test org-mode --- blog/nginx-reverse-proxy/index.org | 220 +++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 blog/nginx-reverse-proxy/index.org (limited to 'blog/nginx-reverse-proxy') diff --git a/blog/nginx-reverse-proxy/index.org b/blog/nginx-reverse-proxy/index.org new file mode 100644 index 0000000..6467f29 --- /dev/null +++ b/blog/nginx-reverse-proxy/index.org @@ -0,0 +1,220 @@ +#+title: Set-Up a Reverse Proxy with Nginx +#+date: 2022-04-02 +#+description: Learn how to set-up an Nginx reverse proxy from scratch. +#+filetags: :nginx: + +* What is a Reverse Proxy? +A reverse proxy is a server that is placed between local servers or +services and clients/users (e.g., the internet). The reverse proxy +intercepts all requests from clients at the network edge and uses its +configuration files to determine where each request should be sent. + +** A Brief Example +For example, let's say that I run three servers in my home: + +- Server_{01} (=example.com=) +- Server_{02} (=service01.example.com=) +- Server_{03} (=service02.example.com=) + +I also run a reverse proxy in my home that intercepts all public +traffic: + +- Reverse Proxy + +Assume that I have a domain name (=example.com=) that allows clients to +request websites or services from my home servers. + +In this case, the reverse proxy will intercept all traffic from +=example.com= that enters my network and determine if the client is +requesting valid data, based on my configuration. + +If the user is requesting =example.com= and my configuration files say +that Server_{01} holds that data, Nginx will send the user to +Server_{01}. If I were to change the configuration so that =example.com= +is routed to Server_{02}, that same user would be sent to Server_{02} +instead. + +#+begin_src txt +┌──────┐ ┌───────────┐ +│ User │─┐ ┌──► Server_01 │ +└──────┘ │ │ └───────────┘ + │ ┌──────────┐ ┌───────────────┐ │ ┌───────────┐ + ├────► Internet ├───► Reverse Proxy ├─────├──► Server_02 │ + │ └──────────┘ └───────────────┘ │ └───────────┘ +┌──────┐ │ │ ┌───────────┐ +│ User │─┘ └──► Server_03 │ +└──────┘ └───────────┘ +#+end_src + +* Reverse Proxy Options +There are a lot of options when it comes to reverse proxy servers, so +I'm just going to list a few of the options I've heard recommended over +the last few years: + +- [[https://nginx.com][Nginx]] +- [[https://caddyserver.com][Caddy]] +- [[https://traefik.io/][Traefik]] +- [[https://www.haproxy.org/][HAProxy]] +- [[https://ubuntu.com/server/docs/proxy-servers-squid][Squid]] + +In this post, we will be using Nginx as our reverse proxy, running on +Ubuntu Server 20.04.4 LTS. + +* Nginx Reverse Proxy Example +** Local Applications +You may be like me and have a lot of applications running on your local +network that you'd like to expose publicly with a domain. + +In my case, I have services running in multiple Docker containers within +a single server and want a way to visit those services from anywhere +with a URL. For example, on my local network, +[[https://dashy.to][Dashy]] runs through port 4000 (=localhost:4000=) +and [[https://github.com/louislam/uptime-kuma][Uptime Kuma]] runs +through port 3001 (=localhost:3001=). + +In order to expose these services to the public, I will need to do the +following: + +1. Set up DNS records for a domain or subdomain (one per service) to + point toward the IP address of the server. +2. Open up the server network's HTTP and HTTPS ports (80 & 443) so that + the reverse proxy can accept traffic and determine where to send it. +3. Install the reverse proxy software. +4. Configure the reverse proxy to recognize which service should get + traffic from any of the domains or subdomains. + +** Step 1: DNS Configuration +To start, update your DNS configuration so that you have an =A= record +for each domain or subdomain. + +The =A= records should point toward the public IP address of the server. +If you don't know the public IP address, log in to the server and run +the following command: + +#+begin_src sh +curl ifconfig.co +#+end_src + +In the DNS example below, =xxx.xxx.xxx.xxx= is the public IP address of +the server. + +#+begin_src config +example.com A xxx.xxx.xxx.xxx +uptime.example.com A xxx.xxx.xxx.xxx +dashy.example.com A xxx.xxx.xxx.xxx +www CNAME example.com +#+end_src + +Finally, ensure the DNS has propagated correctly with +[[https://dnschecker.org][DNS Checker]] by entering your domains or +subdomains in the search box and ensuring the results are showing the +correct IP address. + +** Step 2: Open Network Ports +This step will be different depending on which router you have in your +home. If you're not sure, try to visit +[[http://192.168.1.1][192.168.1.1]] in your browser. Login credentials +are usually written on a sticker somewhere on your modem/router. + +Once you're able to log in to your router, find the Port Forwarding +settings. You will need to forward ports =80= and =443= to whichever +machine is running the reverse proxy. + +In my case, the table below shows the port-forwarding rules I've +created. In this table, =xxx.xxx.xxx.xxx= is the local device IP of the +reverse proxy server, it will probably be an IP between =192.168.1.1= +and =192.168.1.255=. + +| NAME | FROM | PORT | DEST PORT/IP | ENABLED | +|-------+------+------+-----------------+---------| +| HTTP | ​** | 80 | xxx.xxx.xxx.xxx | TRUE | +| HTTPS | ​** | 443 | xxx.xxx.xxx.xxx | TRUE | + +Once configured, these rules will direct all web traffic to your reverse +proxy. + +** Step 3: Nginx Installation +To install Nginx, simply run the following command: + +#+begin_src sh +sudo apt install nginx +#+end_src + +If you have a firewall enabled, open up ports =80= and =443= on your +server so that Nginx can accept web traffic from the router. + +For example, if you want to use =ufw= for web traffic and SSH, run the +following commands: + +#+begin_src sh +sudo ufw allow 'Nginx Full' +sudo ufw allow SSH +sudo ufw enable +#+end_src + +** Step 4: Nginx Configuration +Now that we have domains pointing toward the server, the only step left +is to configure the reverse proxy to direct traffic from domains to +local services. + +To start, you'll need to create a configuration file for each domain in +=/etc/nginx/sites-available/=. They will look identical except for the +=server_name= variable and the =proxy_pass= port. + +Dashy: + +#+begin_src sh +nano /etc/nginx/sites-available/dashy.example.com +#+end_src + +#+begin_src config +server { + listen 80; + server_name dashy.example.com; + + location / { + proxy_pass http://localhost:4000; + } +} +#+end_src + +Uptime: + +#+begin_src sh +nano /etc/nginx/sites-available/uptime.example.com +#+end_src + +#+begin_src config +server { + listen 80; + server_name uptime.example.com; + + location / { + proxy_pass http://localhost:3001; + } +} +#+end_src + +Once the configuration files are created, you will need to enable them +with the =symlink= command: + +#+begin_src sh +sudo ln -s /etc/nginx/sites-available/dashy.example.com /etc/nginx/sites-enabled/ +#+end_src + +Voilà! Your local services should now be available through their URLs. + +* HTTPS with Certbot +If you've followed along, you'll notice that your services are only +available via HTTP (not HTTPS). + +If you want to enable HTTPS for your new domains, you will need to +generate SSL/TLS certificates for them. The easiest way to generate +certificates on Nginx is [[https://certbot.eff.org][Certbot]]: + +#+begin_src sh +sudo apt install snapd; sudo snap install core; sudo snap refresh core +sudo snap install --classic certbot +sudo ln -s /snap/bin/certbot /usr/bin/certbot +sudo certbot --nginx +#+end_src -- cgit v1.2.3-70-g09d2