undo
Go Beyond the Code
arrow_forward_ios

Stop buying domains: Unify your GitHub portfolio with NGINX reverse proxy

Federico Mahfoud
Software Engineer & Solver
April 16, 2026
To learn more about this topic, click here.

If you have been building things for a while, you probably have several GitHub Pages sites spread across different repositories. A personal landing page at username.github.io/portfolio, a resume at username.github.io/resume, maybe a blog at username.github.io/blog. Each one is a separate site with its own repository and its own URL.

This works fine until you want to present yourself professionally. Sending someone to username.github.io/resume is functional, but it does not look as clean as yourdomain.com/resume. The instinct is to buy multiple domains or subdomains and point each one at the corresponding repository. That gets expensive and hard to manage quickly.

There is a better way. With a single VPS and NGINX, you can unify all of your GitHub Pages sites under one domain without touching your repositories at all. This article walks through the full setup: configuring NGINX as a reverse proxy, routing multiple paths to separate GitHub Pages sites, and hardening the server.

How it works

NGINX will sit in front of all your GitHub Pages sites and act as a reverse proxy. When a request comes in for yourdomain.com/resume, NGINX intercepts it, fetches the content from username.github.io/resume, and returns it to the visitor. From the outside, everything looks like it lives at your domain. GitHub Pages still does the actual hosting.

The key directive that makes this possible is proxy_pass. It tells NGINX where to forward incoming requests. Combined with proxy_set_header, you can pass the correct Host header to GitHub so it knows which page to serve.


Prerequisites

Setting up NGINX

Connect to your VPS via SSH, switch to root, and install NGINX:



            


Create a new configuration file in /etc/nginx/sites-available/ named after your domain:



            


Then enable it by creating a symlink in sites-enabled:



            


Paste the following configuration in the configuration file, replacing yourdomain.com and username with your own values:



            


What each directive does


Location block ordering

NGINX matches location blocks from most specific to least specific. The / block is a catch-all and should always go last. More specific paths like /resume and /blog take priority and get matched first.


Testing and applying the configuration

Before reloading NGINX, verify the configuration has no syntax errors:



            


If the output says syntax is ok and test is successful, apply the new configuration:



            


NGINX does not need a full restart — reload applies changes gracefully without dropping active connections.


Pointing your domain to the VPS

Create an A record in your DNS provider pointing your domain to your VPS's public IP. DNS propagation may take a few minutes to a few hours.


Hardening your setup

SSH security

Once you have your VPS running, you should lock down SSH access:

See: How to Set Up SSH Keys on Debian 11


Using Cloudflare as a proxy layer

Routing your domain through Cloudflare adds DDoS protection, hides your VPS's real IP address, and gives you free analytics. Point your domain's nameservers to Cloudflare, then configure the DNS records there with the proxy enabled (the orange cloud icon).

Block non-Cloudflare traffic

With Cloudflare in front, your VPS only needs to accept connections from Cloudflare's IP ranges. You can configure iptables or ufw to drop all traffic on ports 80 and 443 that does not originate from a Cloudflare IP. Cloudflare publishes its current IP ranges at cloudflare.com/ips.

See: Allow CloudFlare only

Restore visitor real IP

To see real visitor IPs in your NGINX logs instead of Cloudflare's IPs, you need to restore the original IP using the ngx_http_realip_module.

See: ergin/nginx-cloudflare-real-ip


The result

You now have a single NGINX instance serving as a unified front door for all your GitHub Pages sites. Adding a new site is as simple as adding a new location block to your configuration, running nginx -t, and then nginx -s reload. No new domains to buy, no new DNS zones to manage.

The cost is one small VPS, which you probably have some use for anyway. The benefit is a clean, professional URL structure for everything you build.

Federico Mahfoud
Software Engineer & Solver

Start Your Digital Journey Now!

Which capabilities are you interested in?
You may select more than one.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.