Setup Staging Environment with Nginx
Share your work with clients privately using a password-protected staging site—no code access, no public exposure.
What You'll Have at the End
- A private URL like
staging.yoursite.comwhere your client can preview the project - Password protection so random people can't access it
- A proper SSL certificate (the padlock icon) so it looks professional
- Your code stays completely private, they only see the running website
What You'll Need
- A cheap VPS (DigitalOcean, Hetzner, Hostinger or even your old laptop with public ip)
- A domain name you own
- Your project running on the server
- About 15 minutes
Step 1: Point Your Domain to the Server
First, you need to tell the internet that staging.yoursite.com should go to your VPS. Log into wherever you manage your domain (Cloudflare, Namecheap, GoDaddy, etc.) and add an A record:
| Type | Name | Value |
|---|---|---|
| A | staging | YOUR_VPS_IP |
Replace YOUR_VPS_IP with your server's IP address (something like 165.232.123.45).
DNS changes can take a few minutes to propagate. You can check if it's working
by running ping staging.yoursite.com in your terminal.
Step 2: Install Nginx on Your Server
SSH into your VPS and install Nginx. It's the software that will handle incoming requests and add the password protection:
sudo apt update
sudo apt install nginx -yStart it up and make sure it runs automatically if your server ever restarts:
sudo systemctl start nginx
sudo systemctl enable nginxQuick sanity check—make sure it's running:
sudo systemctl status nginxYou should see "active (running)" in green. If you visit your server's IP address in a browser, you'll see the default Nginx welcome page.
Step 3: Create the Login Credentials
This is the magic part—we're creating a username and password that your client will need to enter before seeing the site. Install the tool that creates password files:
sudo apt install apache2-utils -yNow create the password file. Replace client_name with something memorable (like your client's name or project name):
sudo htpasswd -c /etc/nginx/.htpasswd client_nameYou'll be asked to type a password twice. Pick something simple, you'll be sharing this with your client.
Step 4: Configure Nginx to Protect Your Site
Now we tell Nginx: "When someone visits staging.yoursite.com, ask for a password, then show them my app running on port 3000."
Create a new config file:
sudo nano /etc/nginx/sites-available/staging.yoursite.comPaste this configuration (update the domain and port if needed):
server {
listen 80;
server_name staging.yoursite.com;
location / {
# This is what triggers the password prompt
auth_basic "Client Preview - Enter credentials to continue";
auth_basic_user_file /etc/nginx/.htpasswd;
# Forward requests to your app
proxy_pass http://localhost:3000;
# Keep the original request info intact
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_set_header X-Forwarded-Proto $scheme;
# Support for WebSockets (needed for hot reload, real-time features)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}Save and exit.
What's happening here? When someone visits your staging URL, Nginx intercepts the request. It shows a password prompt first. Only after they enter the correct credentials does it forward them to your actual application.
Step 5: Activate the Configuration
Enable your new site by linking it to the sites-enabled folder:
sudo ln -s /etc/nginx/sites-available/staging.yoursite.com /etc/nginx/sites-enabled/Before reloading, always test your config for typos:
sudo nginx -tIf it says "syntax is ok", you're good. Apply the changes:
sudo systemctl reload nginxTest it! Open http://staging.yoursite.com in your browser. You should see a password prompt. Enter the credentials you created, and boom—your app appears.
If you see the default Nginx page instead of your app, make sure your application is actually running on port 3000 (or whatever port you configured).
Step 6: Add SSL (The Padlock Icon)
Right now it works, but your client will see a "Not Secure" warning in their browser. Not a great look. Let's fix that with a free SSL certificate from Let's Encrypt.
Install Certbot:
sudo apt install certbot python3-certbot-nginx -yGet your certificate (this is almost magical one command does everything):
sudo certbot --nginx -d staging.yoursite.comFollow the prompts. Certbot will automatically:
- Verify you own the domain
- Get a certificate
- Update your Nginx config to use HTTPS
- Redirect HTTP to HTTPS
That's it. Visit https://staging.yoursite.com and you'll see the padlock. Your client will never know the difference between this and a "real" production site.
Let's Encrypt certificates expire after 90 days, but Certbot automatically renews them. You don't have to think about it.
Send It to Your Client
You're done! Here's what you can send your client:
Hey! I've set up a preview site for your project. You can check out the progress anytime at:
URL: https://staging.yoursite.com
Username: client_name
Password: preview2024Feel free to click around and let me know if you have any feedback!
This is so much more professional than "hop on a call and I'll share my screen" or "check out this weird Vercel URL."