Introduction
Many developers rely on managed hosting platforms to deploy their applications. While these platforms are easy to use, they can become expensive very quickly. A full-stack application often requires separate hosting for the frontend, backend and a database. As a result, the monthly cost can easily reach 25$ to 75$, even for small to medium projects.
However, this cost can be reduced significantly if you learn how to deploy your application on a VPS.
A VPS(Virtual Private Server) gives you full control over your server at a much lower cost. In many cases, you can run your entire application for less than 10$ a month.
The main reason developers avoid VPS is that it seems complex to set up and manage, but once you understand the process, it becomes much simpler than it looks.
In this tutorial, you will learn step by step:
- How to set up a VPS.
- How to secure your server.
- How to configure a firewall.
- How to install and configure Nginx.
- How to set up SSL using Let’s Encrypt.
- How to deploy a Next.js frontend and FastAPI backend.
Table of Contents
- Introduction
- Prerequisites
- Understanding the Deployment Architecture
- Setting Up the VPS
- Securing the VPS
- Installing Required Software
Prerequisites
Before starting this tutorial, make sure you are comfortable with the following: —
1. Basic Knowledge of Linux Commands
You should know how to:
- Navigate directories (
cd,ls) - Create and edit files (
nano) - Run basic terminal commands
This tutorial uses a Linux-based VPS, so all setup will be done through the terminal.
2. Basic understanding of Next.js and FastAPI
You should already have:
- A working Next.js project
- A working FastAPI backend
If you have not built them yet, check these beginner-friendly tutorials:
3. A VPS (Virtual Private Server)
You will need access to a VPS from providers like:
- DigitalOcean
- Hentzner
- AWS EC2
A basic VPS ($5–$10/month) is enough for this tutorial.
4. Domain Name (Recommended)
To enable SSL (HTTPS) you should have:
- A domain name (e,g.,
yourdomain.com)
You can still follow the tutorial without a domain but SSL setup requires one. If you want to buy a domain, you can buy from the following platforms.
- NameCheap
- GoDaddy
Just buy a cheaper one.
5. SSH Access to Your Server
You should know how to connect to your VPS using SSH.
ssh root@your_server_ip6. Basic Understanding of Networking
- What is a port (e.g., 3000, 8000)
- What is a server IP
- What is HTTP vs HTTPS
If all of the above is ready, we can start setting up the VPS.
Understanding the Deployment Architecture
Before deploying our application, it is important to understand how all parts of the system works together.
We are not just deploying code, we are setting up a complete system where multiple systems communicate with each other.
1. Components Involved
Our setup includes four main parts:
- Next.js as Frontend
- FastAPI as backend
- Nginx as Reverse Proxy
- VPS as a Server
2. Why We Need Nginx
If we run both apps directly such as:
- Next.js runs on port
3000 - FastAPI runs on port
8000
This is not clean and production ready as user have to visit:
http://your-ip:3000
http://your-ip:8000Nginx acts as a middle layer between users and your applications. It allows you to:
- Serve your app on a single domain
- Hide internal ports
- Route requests properly
Example:
User → Nginx → Next.js (port 3000)
→ FastAPI (port 8000)3. How Routing Works
We configure Nginx like this:
- Any request to
/goes to Next.js (Frontend) - Any request to
/api/goes to FastAPI (Backend)
So users only visit https://yourdomain.com. Everything works behind the scenes.
4. Role of SSL
SSL is added at the Nginx level.
User → HTTPS → Nginx → Your AppsBenefits of SSL:
- Secure connection (HTTPS)
- Data is encrypted
- Trusted by browsers
5. Final Architecture Overview
User (Browser)
↓
Nginx (HTTPS)
↓
┌───────────────┐
│ │
↓ ↓
Next.js FastAPI
(port 3000) (port 8000)Setting Up the VPS
In this section, we will prepare our vps so it becomes ready to host our applications.
We will:
- Connect to the server
- Update system package
- Prepare a stable environment
1. Connecting to Your VPS via SSH
Before connecting make sure you create a VPS using above mentioned VPS providers. Once your VPS is created, you will get an IP address.
To connect with your VPS, you will need a pc or laptop from where you can access your VPS.
Open the shell of your device and connect using ssh:
ssh root@your_server_ipReplace your_server_ip with your VPS IP.
If this is your first login, the system may ask you for confirmation. Type:
yes2. Updating the Server
Before installing anything, update your system packages:
apt update && apt upgrade -yThis update ensures that security patches are applied and the latest software versions are installed.
3. Installing Basic Utilities
Install some basic tools the we will need later:
apt install curl git nano unzip -y4. Creating a Safe Working Environment
Instead of working directly as root, it is recommended to create a new user:
adduser user_name_hereReplace user_name_here with the actual user name.
Now give the user sudo permissions:
usermod -aG sudo user_name_hereNow switch to this user:
su - deployThis command would ask you to enter a password for the user. Make sure to choose a strong password.
Note: In later sections we will run commands starting with sudo which requires the user password to execute. Enter this password every time you are asked as these commands require root access.
Securing the VPS
A fresh VPS is not secure by default. Before deploying any application, we must protect the server from unauthorized access.
In this section, we will perform the following steps:
- Setup the firewall
- Secure SSH access
- Disable root login (Recommended)
1. Setting Up Firewall (UFW)
A firewall controls which ports are allowed to access your server. Let’s install and enable UFW.
sudo apt install ufw -y2. Allow Required Ports
We need to allow only essential services:
sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443Let’s understand what we allowed in our VPS.
- OpenSSH – allows SSH connection
- 80 – HTTP traffic
- 443 – HTTPS traffic
Now turn on the firewall:
sudo ufw enableAfter the firewall is turned on we can check the status of the firewall:
sudo ufw status3. Why Firewall is Important
Without a firewall anyone can try to access open ports which means your server is exposed to attacks. With firewall only allowed traffic is accepted. Everything else is blocked.
4. Disable Root Login (Recommended)
Root user has full control in the VPS. If it is hacked, everything is lost. We will create a safer setup. Let’s open the SSH configuration file.
sudo nano /etc/ssh/sshd_configFind this line PermitRootLogin yes. Change it to PermitRootLogin no.
This will ensure no one can login as a root user directly. Press CTRL + S to save the file and CTRL + X to exit the file.
5. Restart SSH Service
To apply the changes, restart the SSH service using the following command:
sudo systemctl restart sshNow that our VPS is secured, we can proceed to install required softwares.
Installing Required Software
In this section, we will install all the software needed to run our application:
- Node.js for Next.js
- Python and pip for FastAPI
- Nginx for reverse proxy
1. Installing Node.js
Next.js requires Node.js to run. To install Node.js we need to install NodeSource first:
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -Now install the Node.js:
sudo apt install nodejs -yVerify the installation using the following command.
node -v
npm -v2. Install Python and Pip
Most VPS already have Python installed. You can check the installation using the following command:
python3 --versionIf Python is installed, you will see a version like Python 3.x.x. If Python is not installed, install it using the following command:
sudo apt update
sudo apt install python3 -yNow install pip and venv.
sudo apt install python3-pip python3-venv -y3. Install Nginx
Nginx will act as a reverse proxy and handle incoming requests.
sudo apt install nginx -yNow start the nginx.
sudo systemctl start nginxEnable Nginx on boot, so you don’t have to restart nginx everytime the VPS reboot.
sudo systemctl enable nginx4. Verify Nginx Installation
To verify your nginx working, open the browser and visit:
http://your_server_ipReplace your_server_ip with your actual VPS IP.You should see the default Nginx welcome page.
Note:
If Nginx page does not load:
- Check the firewall allows port 80.
- Run
sudo systemctl status nginxagain.
Now our VPS is ready to deploy the application. Let’s move on to the next section where we will deploy our FastAPI backend.
Deploying FastAPI Backend
In this section we will deploy the FastAPI backend on the VPS. We will perform the following actions:
- Upload project code
- Set up a virtual environment
- Install Dependencies
- Run FastAPI using Uvicorn
1. Upload your Project to VPS
It is recommended to upload your project from Github. Upload your FastAPI project using Git:
git clone https://github.com/your-repo/fastapi-app.git
cd your_project_nameThis repo URL is used as an example. Use your actual project repo URL instead. Replace your_project_name with the actual project folder name.
If your project is not on GitHub, you can use the other methods like:
- SCP
- FTP tools like FileZilla
2. Create a Virtual Environment
A virtual environment keeps your project dependencies isolated. Create a virtual environment using the following command:
python3 -m venv venvNow activate the virtual environment.
source venv/bin/activate3. Install Dependencies
Install required packages from the requirements.txt file if you have.
pip install -r requirements.txtIf you don't have requirements.txt file, create it locally:
pip freeze > requirements.txtAlthough this command creates the requirement.txt file, it can miss some modules. So if you found an error like Module not found while running the app, install that module manually using pip.
4. Test FastAPI Locally on Server
Run FastAPI using Uvicorn:
uvicorn main:app --host 0.0.0.0 --port 8000Now open http://your_server_ip:8000 on your browser. You should see your API running.
Now stop the server by pressing CTRL + C.
Note:
This setup is only for testing. If you close the terminal, the server stops. This method is not suitable for production. Later in this tutorial, we will use the process manager such as PM2 to run our FastAPI app even if the terminal closes.
Deploying Next.js Frontend
In this section, we will deploy the Next.js application on the VPS. We will perform the following actions:
- Upload project code
- Install dependencies
- Build the project
- Run it in production mode
Let’s perform these actions step by step.
1. Upload Your Next.js Project
It is recommended that your project must be on Github. Clone your repository using the following command:
git clone https://github.com/your-repo/nextjs-app.git
cd nextjs-appNote: Use your actual github repo. Replace nextjs-app with your actual project folder name.
2. Install Dependencies
For Next.js project, install the dependencies using the following command:
npm install This will install all the modules required for your Next.js project.
3. Configure Environmental Variables
If your project uses environmental variables, create a .env file:
nano .envNow add your environmental variables in this file such as API URL or secret keys.
4. Build the Project
In development mode we just run npm run dev which runs the development version of your project. However, this version is not optimized for production.
For production we run the production build which is an optimized version of your app. Run the production build using:
npm run build5. Run Next.js In Production
After successful production build, run the following command to start the Next.js app.
npm startBy default it runs on:
http://your_server_ip:30006. Test the Frontend
Now open following URL in the browser:
http://your_server_ip:3000You should see your Next.js app running.
Now, if you close your terminal, the app will stop. We need PM2 for Next.js to run our app in production.
Running Application In Background
Currently, both FastAPI and Next.js are running in the terminal. If you close your terminal, the apps stop. To fix this we will run both applications in the background using PM2.
1. Install PM2
PM2 is the process manager that keeps applications running in the background. Install it using the following command:
sudo npm install -g pm22. Run FastAPI with PM2
Go to your FastAPI project directory:
cd fastapi-appNow start the FastAPI using PM2:
pm2 start "uvicorn main:app --host 0.0.0.0 --port 8000" --name fastapi3. Run Next.js with PM2:
Now go to your Next.js Project:
cd ../nextjs-appStart the Next.js app using PM2:
pm2 start npm --name nextjs -- start4. Check Running Applications
You can check the running application:
pm2 listYou should your apps:
fastapi online
nextjs online5. Enable Auto Restart on Server Reboot
We must make sure that our apps restart automatically if the server reboot. Run the following command:
pm2 startupIt would ask you to paste the given command. Paste the command, then save it using:
pm2 saveConfiguring Nginx as Reverse Proxy
In this section, we will configure Nginx to route traffic:
/for Next.js/api/for FastAPI
This allows users to access everything from a single domain.
1. Create a New Nginx Configuration File
First go to the home directory by entering cd. Create an Nginx configuration file using the following command:
sudo nano /etc/nginx/sites-available/appPaste the following code inside:
server {
listen 80;
server_name your_domain_or_ip;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade
Replace your_domain_or_ip with your server IP. Press CTRL + S to save the file.
3. Enable the Configuration
Enable the Nginx site using the following command.
sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/ 4. Remove Default Configuration
Although it is not necessary to remove the default configuration, it is recommended to avoid any issues in the future.
sudo rm /etc/nginx/sites-enabled/default5. Test Nginx Configuration
To check our Nginx site is working run the following command:
sudo nginx -tIf everything is correct, you will see:
syntax is ok
test is successful6. Restart Nginx
sudo systemctl restart nginx7. Test Your Setup
Now open:
http://your_domain_or_ipYou should see your Next.js app. To test the backend open:
http://your_domain_or_ip/api/docsYou should see FastAPI docs.
Setting Up SSL with Let’s Encrypt
In this section, we will secure our application using HTTPS. We will:
- Install Certbot
- Generate a free SSL certificate
- Configure Nginx automatically
1. Install Certbot
Certbot is used to generate a SSL Certificate from Let’s Encrypt.
sudo apt install certbot python3-certbot-nginx -y2. Make Sure Domain is Pointing to VPS
Before generating SSL, ensure:
- Your domain is pointing to your VPS IP.
- DNS A record is configured.
3. Generate SSL Certificate
Generate the SSL using:
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.comReplace yourdomain.com with your actual domain.
4. Follow the Prompt
Certbot will ask to:
- Enter Email for notification
- Agree to terms. Type Y
- Redirect HTTP to HTTPS. Choose Yes
By following these prompts, certbot will automatically generate certificates, modify Nginx config, and enable HTTPS.
5. Test HTTPS
Open your domain in the browser:
https://yourdomain.comYou should see the secure lock icon.
6. Auto Renewal
SSL certificates usually expire every 90 days. Certbot automatically renews them, but you should test it:
sudo certbot renew --dry-runYou should see something like:
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/www.your_domain.com/fullchain.pem (success)This means your domain is reachable and auto-renewal will work.
Final Testing
In this section, we will verify that everything is working correctly. We will test the following:
- Frontend (Next.js)
- Backend (FastAPI)
- Reverse Proxy (Nginx)
- HTTPS (SSL)
Let's test each one step by step.
1. Test Frontend
Open your domain in the browser:
https://yourdomain.comMake sure your app loads, no error in UI, and pages navigate correctly.
2. Test Backend API
Now open the following URL in the browser to test the FastAPI.
https://yourdomain.com/api/docsMake sure FastAPI Swagger UI loads, and API endpoints are visible.
3. Test Frontend and Backend Connection
This is the most important test. Perform an action in your frontend that needs backend, such as login, fetch data. Check if data is coming from the backend. If this works, your full-stack connection is successful.
Test HTTPS (SSL)
Check your browser shows lock icon on your website. Make sure your website URL starts with https://
5. Test Direct Ports
Try opening:
http://yourdomain.com:3000
http://yourdomain.com:8000These URLs should not be used publicly. They are hidden behind Nginx. Your app should only work through:
https://yourdomain.com6. Test Nginx Status
Check if Nginx is running:
sudo systemctl status nginx7. Test Running Processes (PM2)
Run the following command to check if PM2 is working:
Pm2 listYou should see:
fastapi online
nextjs online8. Test Server Restart
This is the important step as it will make sure our apps must run automatically after the server restart.
Reboot your server:
sudo rebootReconnect via SSH, then check:
pm2 listYour apps should be running.
Common Errors and Fixes
During deployment, it is normal to face issues. Here are the most common problems and how to fix them.
1. Nginx Not Working
Problem:
- Website not loading
- 502 Bad Gateway
Fix:
Check Nginx Status:
sudo systemctl status nginxCheck Configuration:
Sudo nginx -tIf config fails, fix syntax errors and restart:
sudo systemctl restart nginx2. 502 Bad Gateway Error
Problem:
Nginx cannot connect to your app
Cause:
FastAPI or Next.js not running
Check Processes:
pm2 listRestart apps:
pm2 restart all3. App Works on Port But Not on Domain
Problem:
localhost:3000works- domain does not
Fix:
- Check Nginx Config
- Ensure correct
proxy_pass - Restart Nginx
4. SSL Not Working
Problem
- HTTPS not enables
- Browser shows “Not Secure”
Fix:
- Check domain DNS
- Ensure it points to VPS
- Re-run the SSL process:
sudo certbot --nginx -d yourdomain.com5. Firewall Blocking Requests
Problem:
- Website not accessible
Fix
- Check Firewall:
sudo ufw statusAllow required ports:
sudo ufw allow 80
sudo ufw allow 443
sudo ufw allow OpenSSH6. FastAPI not Accessible
Problem:
API not responding.
Fix:
Ensure you used --host 0.0.0.0. Without this, the app is not accessible externally.
7. Environmental Variables Not Working
Problem:
Frontend cannot connect to the backend.
Fix:
- Check
.envfile - Rebuild Next.js:
npm run buildRestart app:
pm2 restart nextjs8. Changes Not Reflecting
Problem:
You updated the code but nothing changed.
Fix:
Every time you change the code you need to rebuild the production version to see the changes.
npm run build
pm2 restart allPermission Issue
Problem:
Cannot access files or run commands.
Fix:
Change the ownership of the user.
sudo chown -R $USER:$USER your-project-folderChange your-project-folder with your actual folder.
Conclusion
In this tutorial, you learned how to deploy a full-stack application using Next.js and FastAPI on a VPS.
We did not just deploy an app. We built a complete production ready setup step by step.
What You Accomplished
- Set up and secured a VPS
- Installed Node.js, Python, and Nginx
- Deployed FastAPI backend
- Deployed Next.js frontend
- Configured Nginx as a reverse proxy
- Enabled HTTPS using Let's Encrypt
- Ran applications in the background using PM2
- Tested the entire system end-to-end
Instead of relying on expensive hosting platforms, you now have:
- Full control over your server
- Lower hosting costs
- A real-world deployment setup used in production
This approach is not only cost-effective but also helps you understand how the system works behind the scenes.
What To Do Next
- Deploy your own projects using this setup
- Add a database (PostgreSQL) to your VPS
- Set up automated backups
- Learn CI/CD for automatic deployments
Final Thoughts
Many developers avoid VPS because it seems complex at first. But as you have seen in this guide, once you break it down step by step, it becomes manageable.
Now you have the ability to deploy full-stack applications on your infrastructure – a skill that sets you apart as a developer. If you still have any specific issue, feel free to contact me.
If you found this tutorial helpful, consider sharing it or saving it for future reference. You can also subscribe to our newsletter for the future tutorials.