Full-Stack VPS Deployment Commands – FastAPI, Next.js & PM2
Feb 28, 2026
Want To Stay Updated?
Subscribe to get the latest articles delivered directly to your inbox.
Feb 28, 2026
Subscribe to get the latest articles delivered directly to your inbox.
Check current user:
whoamiCheck current directory:
pwdConnect to server:
ssh username@server_ipConnect using SSH key:
ssh -i /path/to/private_key username@server_ipCopy file to server:
scp file.txt username@server_ip:/path/to/destinationUpdate package list:
sudo apt updateUpgrade installed packages:
sudo apt upgrade -yFull upgrade:
sudo apt full-upgrade -yInstall package:
sudo apt install package_nameRemove package:
sudo apt remove package_nameList installed packages:
dpkg -lCreate new user:
sudo adduser usernameAdd user to sudo group:
sudo usermod -aG sudo usernameSwitch user:
su - usernameList users:
cut -d: -f1 /etc/passwdCheck service status:
systemctl status service_nameStart service:
sudo systemctl start service_nameStop service:
sudo systemctl stop service_nameRestart service:
sudo systemctl restart service_nameReload service:
sudo systemctl reload service_nameEnable on boot:
sudo systemctl enable service_nameDisable on boot:
sudo systemctl disable service_nameList running services:
systemctl list-units --type=serviceShow running processes:
ps auxInteractive process viewer:
topIf installed:
htopKill process by PID:
kill PIDForce kill:
kill -9 PIDFind process by name:
ps aux | grep process_nameCheck memory:
free -mCheck disk usage:
df -hCheck folder size:
du -sh folder_nameCheck uptime:
uptimeCheck firewall status:
sudo ufw statusEnable firewall:
sudo ufw enableAllow port:
sudo ufw allow 8000Allow specific service:
sudo ufw allow 'Nginx Full'Delete rule:
sudo ufw delete allow 8000View environment variables:
printenvTemporary variable:
export VARIABLE_NAME=valueEdit global environment:
sudo nano /etc/environmentReload bash:
source ~/.bashrcEdit cron jobs:
crontab -eList cron jobs:
crontab -lCheck current time:
dateCheck timezone:
timedatectlSet timezone:
sudo timedatectl set-timezone Asia/KarachiReboot server:
sudo rebootShutdown server:
sudo shutdown nowSchedule shutdown:
sudo shutdown +10Print current directory:
pwdChange directory:
cd /path/to/directoryGo back one directory:
cd ..Go to home directory:
cd ~List directory tree (if tree installed):
treeList files in current directory:
lsLong listing with permissions, owner, size:
ls -lInclude hidden files:
ls -aHuman-readable sizes:
ls -lhFull listing (long + hidden):
ls -lahCreate a new directory:
mkdir folder_nameCreate nested directories:
mkdir -p parent/child/grandchildCreate an empty file:
touch file_nameCreate file with content:
echo "Hello World" > file_nameCopy file:
cp source_file destination_fileCopy directory recursively:
cp -r source_folder destination_folderMove / rename file or folder:
mv old_name new_nameDelete file:
rm file_nameDelete directory recursively:
rm -r folder_nameForce delete without prompt:
rm -rf folder_name_or_fileView file permissions:
ls -lChange permissions:
chmod 755 file_nameChange owner:
sudo chown user:group file_nameChange recursively:
sudo chown -R user:group folder_nameCompress folder to tar.gz:
tar -czvf archive_name.tar.gz folder_nameExtract tar.gz:
tar -xzvf archive_name.tar.gzZip a folder:
zip -r archive_name.zip folder_nameUnzip:
unzip archive_name.zipFind files by name:
find /path -name "file_name"Search inside files:
grep "search_text" file_namegrep -r "search_text" /path/to/folder
grep -r "search_text" /path/to/folderView file:
cat file_nameView with paging:
less file_nameScroll forward/backward:
more file_nameTail last lines:
tail file_nameFollow log file:
tail -f file_nameHead first lines:
head file_nameCheck disk usage for file/folder:
du -sh folder_nameCheck all folder sizes in current directory:
du -sh *Check free disk space:
df -hInstall Nginx:
sudo apt update
sudo apt install nginx -yRemove Nginx:
sudo apt remove nginx -yPurge Nginx completely (config + data):
sudo apt purge nginx -y
sudo apt autoremove -yStart Nginx:
sudo systemctl start nginxStop Nginx:
sudo systemctl stop nginxRestart Nginx:
sudo systemctl restart nginxReload Nginx (keep running connections):
sudo systemctl reload nginxEnable Nginx on boot:
sudo systemctl enable nginxDisable Nginx on boot:
sudo systemctl disable nginxCheck Nginx status:
systemctl status nginxNginx main config file:
/etc/nginx/nginx.confDefault server block:
/etc/nginx/sites-available/defaultAvailable sites directory:
/etc/nginx/sites-available/Enabled sites directory:
/etc/nginx/sites-enabled/Test configuration syntax:
sudo nginx -tReload after changes:
sudo systemctl reload nginxCreate a new server block:
sudo nano /etc/nginx/sites-available/example.comEnable site:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/Disable site:
sudo rm /etc/nginx/sites-enabled/example.comTest new configuration:
sudo nginx -tReload Nginx to apply changes:
sudo systemctl reload nginxExample for FastAPI on port 8000:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}For Next.js on port 3000:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}Test syntax before reload:
sudo nginx -tCheck Nginx version:
nginx -vCheck which ports Nginx is listening on:
sudo lsof -i :80
sudo lsof -i :443Access logs:
tail -f /var/log/nginx/access.logError logs:
tail -f /var/log/nginx/error.logCheck logs for a specific site:
tail -f /var/log/nginx/example.com-error.log502 Bad Gateway:
# Check backend service
sudo systemctl status fastapi_service_name
sudo systemctl restart fastapi_service_namePort conflicts:
sudo lsof -i :80
sudo lsof -i :443Permission denied errors:
sudo chown -R www-data:www-data /var/www/example.com
sudo chmod -R 755 /var/www/example.comUpdate package list:
sudo apt updateInstall Certbot and Nginx plugin:
sudo apt install certbot python3-certbot-nginx -yCheck Certbot version:
certbot --versionAutomatic SSL for Nginx:
sudo certbot --nginx -d example.com -d www.example.comManual SSL (if needed):
sudo certbot certonly --nginx -d example.com -d www.example.comCheck the generated certificate files:
ls /etc/letsencrypt/live/example.com/Check auto-renewal status:
sudo systemctl status certbot.timerTest renewal manually:
sudo certbot renew --dry-runRenew all certificates:
sudo certbot renewCheck SSL on your server:
sudo nginx -tCheck certificate expiration:
sudo certbot certificatesTest using curl:
curl -Ik https://example.comRevoke certificate:
sudo certbot revoke --cert-path /etc/letsencrypt/live/example.com/fullchain.pemDelete certificate completely:
sudo certbot delete --cert-name example.comEdit Nginx server block:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}Certificate not found:
sudo ls /etc/letsencrypt/live/Port 443 blocked:
sudo ufw allow 443
sudo ufw statusRenewal failed:
sudo certbot renew --dry-run
sudo systemctl restart nginxBrowser shows old certificate:
sudo systemctl reload nginxInitialize a new Git repository:
git init**Clone an existing repository:
git clone git@github.com:username/repository.gitSet global username and email:
git config --global user.name "Your Name"
git config --global user.email "you@example.com"Check configuration:
git config --listGenerate SSH key:
ssh-keygen -t ed25519 -C "you@example.com"Check existing SSH keys:
ls ~/.sshCopy public key to clipboard (Ubuntu):
cat ~/.ssh/id_ed25519.pubAdd SSH key to GitHub via web UI. Test connection:
ssh -T git@github.comCheck status:
git statusAdd changes:
git add file_nameAdd all changes:
git add .Commit changes:
git commit -m "Commit message"Push to remote:
git push origin mainPull latest changes:
git pull origin mainCreate a new branch:
git checkout -b branch_nameSwitch branches:
git checkout branch_nameMerge branch into current:
git merge branch_nameDelete a branch locally:
git branch -d branch_nameDelete a branch remotely:
git push origin --delete branch_nameStash current changes:
git stashList stashes:
git stash listApply stash:
git stash applyDrop a stash:
git stash dropReset staged changes:
git reset file_nameReset to previous commit (soft):
git reset --soft HEAD~1Reset to previous commit (hard):
git reset --hard HEAD~1Revert a commit:
git revert commit_hashShow commit history:
git logCompact log:
git log --onelineGraphical log:
git log --oneline --graph --allShow changes for a file:
git diff file_nameAdd submodule:
git submodule add git@github.com:username/repo.git path/to/submoduleUpdate submodules:
git submodule update --init --recursivePull latest changes on server:
cd /var/www/project
git fetch --all
git reset --hard origin/mainCheck status:
git statusRestart service after pull (FastAPI example):
sudo systemctl restart fastapi_servicePermission denied (SSH):
ssh-add ~/.ssh/id_ed25519Merge conflicts:
# Resolve manually, then:
git add file_name
git commit -m "Resolved conflict"Detached HEAD:
git checkout mainUpdate packages:
sudo apt updateInstall PostgreSQL and contrib package:
sudo apt install postgresql postgresql-contrib -yCheck PostgreSQL version:
psql --versionStart PostgreSQL service:
sudo systemctl start postgresqlEnable PostgreSQL on boot:
sudo systemctl enable postgresqlCheck service status:
sudo systemctl status postgresqlSwitch to postgres user:
sudo -i -u postgresEnter PostgreSQL shell:
psqlExit PostgreSQL shell:
\qList all databases:
\lCreate a new database:
CREATE DATABASE database_name;Connect to a database:
\c database_nameDrop a database:
DROP DATABASE database_name;List all users:
\duCreate a new user:
CREATE USER username WITH PASSWORD 'password';Grant privileges:
GRANT ALL PRIVILEGES ON DATABASE database_name TO username;Modify user:
ALTER USER username WITH PASSWORD 'new_password';Delete user:
DROP USER username;List tables in current database:
\dtCreate table:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);Insert data:
INSERT INTO users (name, email) VALUES ('Usama', 'usama@example.com');Query data:
SELECT * FROM users;Update data*
UPDATE users SET email='newemail@example.com' WHERE id=1;Delete data:
DELETE FROM users WHERE id=1;Drop table:
DROP TABLE users;Show running queries
SELECT pid, query, state, usename, client_addr FROM pg_stat_activity;Terminate a query:
SELECT pg_terminate_backend(PID);Check database size:
SELECT pg_size_pretty(pg_database_size('database_name'));Backup database:
pg_dump database_name > backup_file.sqlBackup with compression:
pg_dump database_name | gzip > backup_file.sql.gzRestore database:
psql database_name < backup_file.sqlRestore compressed backup:
gunzip -c backup_file.sql.gz | psql database_nameEdit PostgreSQL config:
sudo nano /etc/postgresql/14/main/postgresql.conf
# Set listen_addresses = '*'Allow remote connections in pg_hba.conf:
sudo nano /etc/postgresql/14/main/pg_hba.conf
# Add: host all all 0.0.0.0/0 md5Restart PostgreSQL:
sudo systemctl restart postgresqlTest remote connection:
psql -h server_ip -U username -d database_nameCheck indexes:
\d table_nameExplain query plan:
EXPLAIN ANALYZE SELECT * FROM table_name WHERE id=1;Check active connections:
SELECT count(*) FROM pg_stat_activity;Default log location:
/var/log/postgresql/postgresql-14-main.logTail logs:
tail -f /var/log/postgresql/postgresql-14-main.logSearch for errors:
grep ERROR /var/log/postgresql/postgresql-14-main.logInstall Python and pip:
sudo apt install python3 python3-pip -yCreate virtual environment:
python3 -m venv venvActivate virtual environment:
source venv/bin/activateDeactivate:
deactivateInstall requirements from file:
pip install -r requirements.txtFreeze dependencies:
pip freeze > requirements.txtRun FastAPI with Uvicorn:
uvicorn main:app --reload --host 0.0.0.0 --port 8000Run with Uvicorn workers:
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4Run with Gunicorn + Uvicorn workers:
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000Create service file:
sudo nano /etc/systemd/system/fastapi.serviceExample service file:
[Unit]
Description=FastAPI Service
After=network.target
[Service]
User=youruser
Group=www-data
WorkingDirectory=/var/www/fastapi_app
ExecStart=/var/www/fastapi_app/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000
Restart=always
[Install]
WantedBy=multi-user.targetReload systemd:
sudo systemctl daemon-reloadStart service:
sudo systemctl start fastapiEnable on boot:
sudo systemctl enable fastapiCheck status:
sudo systemctl status fastapiRestart service:
sudo systemctl restart fastapiExample content:
DATABASE_URL=postgresql://user:password@localhost/dbname
SECRET_KEY=your_secret_key
DEBUG=TrueLoad environment variables in Python:
from dotenv import load_dotenv
import os
load_dotenv()
database_url = os.getenv("DATABASE_URL")Reload after changes:
source ~/.bashrcView systemd logs for FastAPI:
journalctl -u fastapi.service -fCheck Uvicorn logs:
tail -f /var/www/fastapi_app/uvicorn.logEnable CORS in FastAPI:
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)Check processes using port 8000:
sudo lsof -i :8000Kill process:
kill -9 PIDRestart manually:
sudo systemctl restart fastapiRestart after pull:
git pull origin main
sudo systemctl restart fastapiReload on config change:
sudo systemctl reload fastapiUpdate packages:
sudo apt update
sudo apt upgrade -yInstall Node.js and npm:
sudo apt install nodejs npm -yCheck versions:
node -v
npm -vUsing create-next-app:
npx create-next-app@latest my-nextjs-appNavigate to project folder:
cd my-nextjs-appInstall additional dependencies (optional):
npm install axios dotenvStart dev server:
npm run devAccess locally:
http://localhost:3000
Custom port:
PORT=4000 npm run devBuild project:
npm run buildStart production server:
npm startCustom host/port:
HOST=0.0.0.0 PORT=5000 npm startCreate .env.local file:
nano .env.localExample content:
NEXT_PUBLIC_API_URL=https://api.example.com
DATABASE_URL=postgresql://user:password@localhost/dbnameAccess variables in code:
const apiUrl = process.env.NEXT_PUBLIC_API_URL;Install PM2 globally:
npm install -g pm2Start Next.js app with PM2:
pm run build
pm run start &
pm2 start npm --name my-nextjs-app -- startList PM2 processes:
pm2 listRestart app:
pm2 restart my-nextjs-appStop app:
pm2 stop my-nextjs-appSave PM2 process list:
pm2 saveView PM2 logs:
pm2 logs my-nextjs-appCheck error logs:
pm2 logs my-nextjs-app --lines 100Tail server logs manually:
tail -f .next/server/logs/*.logPort already in use:
sudo lsof -i :3000
kill -9 PIDDependencies issues:
rm -rf node_modules package-lock.json
npm installNext.js build errors:
npm run build --cleanInstall PM2 globally:
npm install -g pm2Check PM2 version:
pm2 -vUpdate PM2 to latest version:
pm install pm2@latest -gStart a Node.js app:
pm2 start app.js --name my-appStart a Next.js app:
pm run build
pm2 start npm --name my-nextjs-app -- startStart with custom environment variables:
pm2 start app.js --name my-app --env productionStart multiple apps:
pm2 start app1.js --name app1
pm2 start app2.js --name app2List all PM2 processes:
pm2 listStop an app:
pm2 stop my-appRestart an app:
pm2 restart my-appDelete an app from PM2:
pm2 delete my-appReload app (zero downtime):
pm2 reload my-appLive monitoring:
pm2 monitShow app details:
pm2 describe my-appCheck resource usage:
pm2 listView logs:
pm2 logs my-appTail last N lines:
pm2 logs my-app --lines 100Clear logs:
pm2 flushSave logs to file manually:
pm2 logs my-app > app.logGenerate startup script:
pm2 startupSave current process list:
pm2 saveCheck startup script:
pm2 listApp not starting:
pm2 logs my-appPort conflicts:
sudo lsof -i :PORT
kill -9 PIDDependencies missing:
rm -rf node_modules package-lock.json
npm installPM2 not running on reboot:
pm2 save
pm2 startup