Python API Development with FastAPI
Deployment
Deploy Ubuntu VM
In this guide, you'll learn how to deploy a FastAPI application on an Ubuntu server. Although these steps remain the same regardless of the cloud provider (AWS, Azure, GCP, DigitalOcean, VirtualBox, or Raspberry Pi), we will use DigitalOcean for demonstration purposes due to its cost-effective fixed pricing.
Once your DigitalOcean account is created and you are logged in, follow the instructions below.
1. Creating a Droplet on DigitalOcean
Start by selecting Get Started with a Droplet on the DigitalOcean dashboard. Choose the following options:
- Image: Ubuntu 20.04 (or a newer version if available; the commands remain the same).
- CPU Options: Regular Intel with SSD for optimum pricing.
- Plan: Select the $5/month option (0.007 per hour).
- Data Center: Pick the regional data center closest to you (e.g., East Coast).
- Authentication: Either set a strong password (ensuring you meet DigitalOcean’s password criteria) or use SSH keys if preferred.
- Hostname: Use a descriptive name for your droplet, such as
ubuntu-fastapi
.
DigitalOcean will create your Ubuntu VM and assign it a public IP address. This IP will be used to connect to your server.
2. Connecting to Your Ubuntu VM
Once your droplet is ready, connect via SSH:
Open your terminal (or Command Prompt/VS Code integrated terminal).
Execute the SSH command:
ssh root@<PUBLIC_IP_ADDRESS>
For example:
ssh [email protected]
Type “yes” when prompted to accept the fingerprint and then enter your password.
After a successful login, you'll notice your home directory (which might include a snap
folder). It is vital to update your Ubuntu system:
sudo apt update && sudo apt upgrade -y
Tip
Using the -y
flag automatically confirms prompts during the upgrade process. You may be asked to confirm configuration changes for applications like openssh-server
.
3. Installing Python, pip, and Virtual Environment
First, verify that Python is installed:
python --version
If the command isn’t found, try:
python3 --version
A typical outcome might be:
Python 3.8.10
If pip is missing, you will receive a suggestion such as:
Command 'pip' not found, but can be installed with:
sudo apt install python3-pip
Install pip with:
sudo apt install python3-pip
Then, install the virtual environment tool:
sudo pip3 install virtualenv
This isolates your FastAPI application and its dependencies.
4. Installing and Configuring PostgreSQL
Set up PostgreSQL and its additional libraries with:
sudo apt install postgresql postgresql-contrib -y
Start PostgreSQL if it’s not running already:
pg_ctlcluster 12 main start
Access PostgreSQL using the psql
command. By default, a PostgreSQL user named postgres
is created with peer authentication:
psql -U postgres
If you see an error like:
psql: error: FATAL: Peer authentication failed for user "postgres"
Follow these steps:
Switch to the
postgres
user:su - postgres
Access psql:
psql -U postgres
Set a new password for the
postgres
user:\password postgres
Exit psql:
\q
Next, modify the PostgreSQL configuration files located in /etc/postgresql/12/main
:
In
pg_hba.conf
, change:local all postgres peer
to:
local all postgres md5
To enable remote connections (if needed), edit
postgresql.conf
and set:listen_addresses = '*'
Now, restart PostgreSQL:
sudo systemctl restart postgresql
Test the connection:
psql -U postgres
You should now be prompted for the password.
5. Creating a Non-Root User and Setting Up the Application Environment
For enhanced security, create a non-root user instead of running your application as root. For example, create a user named sanjeev
:
adduser sanjeev
Follow the prompts to set a password and enter the user details. Next, add this user to the sudo group:
usermod -aG sudo sanjeev
Now, log in as the new user:
ssh sanjeev@<PUBLIC_IP_ADDRESS>
Prepare your application environment by creating an application directory:
mkdir app
cd app
Create and activate a virtual environment:
virtualenv venv
source venv/bin/activate
Within your application directory, create a folder (e.g., src
) for your source code and clone your FastAPI project from GitHub:
cd src
git clone https://github.com/Sanjeev-Thiyagarajan/fastapi-course .
If files are nested within a repository folder and you wish to have them directly in src
, clone them directly by appending a dot (.) at the end.
Install the necessary project dependencies:
pip install -r requirements.txt
If you encounter errors related to PostgreSQL or missing header files (like libpq-fe.h
), install the development libraries:
sudo apt install libpq-dev
Then, rerun the pip install command.
Test your FastAPI application locally using Uvicorn:
uvicorn app.main:app --host 0.0.0.0
Your API should now be accessible on port 8000.
6. Running the Application with Gunicorn and Creating a systemd Service
Production with Gunicorn
For production environments, use Gunicorn with Uvicorn workers. Install Gunicorn (if not already included in your requirements):
pip install gunicorn
Test Gunicorn using Uvicorn workers:
gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:app --bind 0.0.0.0:8000
You should see output confirming that Gunicorn has booted four worker processes.
Creating a systemd Service
To ensure that your application runs in the background and starts automatically on reboot, create a systemd service file. Create a file named api.service
in /etc/systemd/system/
with the following contents (adjust the paths and usernames to match your environment):
[Unit]
Description=Demo FastAPI Application
After=network.target
[Service]
User=sanjeev
Group=sanjeev
WorkingDirectory=/home/sanjeev/app/src/
Environment="PATH=/home/sanjeev/app/venv/bin"
EnvironmentFile=/home/sanjeev/.env
ExecStart=/home/sanjeev/app/venv/bin/gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:app --bind 0.0.0.0:8000
[Install]
WantedBy=multi-user.target
Note
The EnvironmentFile
directive loads additional environment variables from your .env
file. Ensure this file contains all required credentials and settings.
Reload systemd to apply the new service configuration:
sudo systemctl daemon-reload
Start and verify the service status:
sudo systemctl start api.service
sudo systemctl status api.service
If you experience issues related to missing environment variables (e.g., secret_key
or access_token_expire_minutes
), ensure your .env
file (located in your home directory) includes lines similar to:
DATABASE_HOSTNAME=localhost
DATABASE_PORT=5432
DATABASE_PASSWORD=password123
DATABASE_NAME=fastapi
DATABASE_USERNAME=postgres
SECRET_KEY=09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=300
Then, restart the systemd service:
sudo systemctl restart api.service
Finally, enable the service to start on boot:
sudo systemctl enable api.service
7. Configuring Nginx as a Reverse Proxy
Installing Nginx
Install Nginx with:
sudo apt install nginx -y
Start (or restart) the Nginx service:
sudo systemctl start nginx
sudo systemctl restart nginx
Visiting your droplet’s IP in a browser should display the default Nginx page.
Configuring the Reverse Proxy
Edit the default server block for Nginx by modifying the configuration file located at /etc/nginx/sites-available/default
:
sudo vi /etc/nginx/sites-available/default
Replace the contents (or modify the location block) with the following configuration:
server {
listen 80;
listen [::]:80;
server_name sanjeev.xyz www.sanjeev.xyz; # Replace with your domain
location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
}
}
Save the file and restart Nginx:
sudo systemctl restart nginx
Your domain should now forward requests to your FastAPI application running on port 8000.
8. Setting Up DNS and Domain Name
If you have a custom domain (e.g., purchased from Namecheap), point its DNS to your DigitalOcean droplet:
Log in to your domain registrar and update the name servers to:
- ns1.digitalocean.com
- ns2.digitalocean.com
- ns3.digitalocean.com
In the DigitalOcean dashboard, navigate to Manage DNS and add your domain (for example,
sanjeev.xyz
). Create:- An A record (with
@
) pointing to your droplet’s IP. - A CNAME record for
www
pointing to@
.
- An A record (with
Once DNS changes propagate (this may take a few minutes to an hour), visiting your domain should serve your application.
9. Securing Your Site with HTTPS (SSL)
Use Certbot from Let’s Encrypt to secure your site with HTTPS at no additional cost.
Install Certbot via Snap:
sudo snap install core; sudo snap refresh core sudo snap install --classic certbot sudo ln -s /snap/bin/certbot /usr/bin/certbot
Run Certbot with the Nginx plugin:
sudo certbot --nginx
Follow the interactive prompts:
- Enter your email address.
- Agree to the Terms of Service.
- Decide if you want to share your email with the EFF.
- Provide the domain names (e.g.,
sanjeev.xyz
andwww.sanjeev.xyz
) for the certificate.
Certbot will update your Nginx configuration to enable HTTPS and set up proper redirection from HTTP.
Once complete, you should see a secure padlock in your browser, indicating that HTTPS is active.
10. Configuring the Firewall with UFW
Configure UFW (Uncomplicated Firewall) to allow only essential traffic:
Check the current UFW status:
sudo ufw status
Allow HTTP, HTTPS, and SSH traffic:
sudo ufw allow http sudo ufw allow https sudo ufw allow ssh
Optionally, if remote access to PostgreSQL is required, allow port 5432:
sudo ufw allow 5432
Enable UFW:
sudo ufw enable
Verify the active firewall rules:
sudo ufw status
You should see allowed entries for ports 80, 443, 22, and optionally 5432.
11. Deploying Code Changes
When updating your application, push the changes to your Git repository and then pull them on the server.
On your local machine, make changes and push them:
# Edit your code (e.g., app/main.py)
git add --all
git commit -m "Update Hello World message"
git push origin main
On your production server:
Navigate to your application source directory:
cd ~/app/src
Pull the latest changes:
git pull
Restart the API service to apply the changes:
sudo systemctl restart api.service
Reload your browser (or use an HTTP client) to verify that the updates are active.
12. Summary
Your FastAPI deployment is now fully configured and running:
- Your Ubuntu server is updated and ready.
- Python, Virtualenv, and PostgreSQL are installed and configured.
- The FastAPI application runs on Gunicorn, managed by systemd for automatic restarts.
- Nginx functions as a reverse proxy and is secured with a Let’s Encrypt SSL certificate.
- UFW ensures only necessary ports (HTTP, HTTPS, SSH, etc.) are exposed.
- Code updates can be deployed using Git followed by a service restart.
This setup improves performance, enhances security, and provides a robust production environment for your FastAPI application.
By following these comprehensive steps, you have successfully deployed your FastAPI application using an Ubuntu VM, DigitalOcean Droplets, Gunicorn, Nginx, and Let's Encrypt SSL. In upcoming guides, we will explore how to automate code updates via a CI/CD pipeline to further streamline your deployment process.
Happy deploying!
Watch Video
Watch video content