Feature Branch Subdomains: Every PR Gets Its Own URL

πŸ“– 2 minutes read

Staging environments are great until you have three developers all waiting to test on the same one. Feature branch subdomains solve this: every branch gets its own isolated URL like feature-auth-refactor.staging.example.com.

How It Works

The setup has three parts:

  1. Wildcard DNS β€” Point *.staging.example.com to your staging server
  2. Wildcard SSL β€” One certificate covers all subdomains
  3. Dynamic Nginx config β€” Route each subdomain to the right container

The DNS

Add a single wildcard A record:

*.staging.example.com  A  203.0.113.50

Every subdomain now resolves to your staging server. No DNS changes needed per branch.

The SSL Certificate

Use Let’s Encrypt with DNS validation for wildcard certs:

certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d "*.staging.example.com" \
  -d "staging.example.com"

The Nginx Config

Extract the subdomain and proxy to the matching container:

server {
    listen 443 ssl;
    server_name ~^(?<branch>.+)\.staging\.example\.com$;

    ssl_certificate     /etc/letsencrypt/live/staging.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/staging.example.com/privkey.pem;

    location / {
        resolver 127.0.0.11 valid=10s;
        proxy_pass http://$branch:80;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

The regex capture (?<branch>.+) extracts the subdomain. If your CI names Docker containers after the branch slug, Nginx routes directly to them.

The CI Pipeline

In your CI config, deploy each branch as a named container:

deploy_review:
  stage: deploy
  script:
    - docker compose -p "$CI_COMMIT_REF_SLUG" up -d
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: https://$CI_COMMIT_REF_SLUG.staging.example.com
    on_stop: stop_review

Why This Beats Shared Staging

With shared staging, you get merge conflicts, “don’t deploy, I’m testing” Slack messages, and broken environments that block everyone. With per-branch subdomains, each developer (and each PR reviewer) gets their own isolated environment. QA can test three features simultaneously. No coordination needed.

The wildcard DNS + wildcard SSL + dynamic Nginx combo means zero manual setup per branch. Push a branch, CI deploys it, URL works automatically.

Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *