Building a CI/CD Pipeline with Bitbucket Pipelines and AWS EC2 (Auto Deployment with SSH)
Manual deployment is slow, error-prone, and not scalable.
In modern development, every code push should automatically:
✅ Update the server
✅ Restart the application
✅ Deploy without downtime
This is where CI/CD pipelines come in.
In this article, you’ll learn how to build a complete automatic deployment pipeline using:
- Bitbucket Pipelines
- SSH
- AWS EC2
- systemd
- Nginx
By the end, every push to Bitbucket will instantly deploy your code to EC2
Final CI/CD Architecture
Developer pushes code ↓ Bitbucket Pipeline triggers ↓ SSH connects to EC2 ↓ Pulls latest code ↓ Restarts backend (systemd) ↓ Nginx serves updated app
This setup is used in real production systems.
Step 1: Prepare EC2 Server
Create Key Pair from AWS Console
Go to AWS Console → EC2 → Key Pairs
Click Create key pair
Fill:
— Name: my-ec2-key (any name)
— Key pair type: RSA
— Private key format: .pem (for Linux/Mac/Ubuntu)
Click Create key pair
👉 The .pem file will download automatically.
⚠️ Save it safely (you can’t download it again).
Connect EC2 from Local Ubuntu Terminal
Open terminal and run:
ssh -i your-ec2-key.pem ec2-user@your-ec2-public-ip
If successful, you’ll be logged into EC2 securely.
Install required tools:
sudo dnf update -y sudo dnf install git -y sudo dnf install nginx -y
Clone your repository:
cd /var/www git clone https://bitbucket.org/your_username/your_repo.git ABC
Step 2: Run Backend with systemd
Create service file:
sudo nano /etc/systemd/system/ABC.service
Add:
[Unit] Description=ABC After=network.target [Service] User=ec2-user WorkingDirectory=/var/www/ABC ExecStart=/home/ec2-user/.local/bin/uv run python app.py Restart=always Environment="PATH=/home/ec2-user/.local/bin:/usr/bin" [Install] WantedBy=multi-user.target
Enable service:
sudo systemctl daemon-reload sudo systemctl enable ABC.service sudo systemctl start ABC.service
systemctl: This is the main command-line utility we use to manage services (programs that run in the background) on Linux. Think of it as a remote control for your apps and services.
daemon-reload: This is a subcommand for systemctl. When executed, it performs the following actions:
— Refreshes systemd’s memory — systemd forgets old service configurations.
— Loads new changes — if you changed a service file, it reads the new version.
— Rebuilds service order — systemd figures out which services should start first and which later.
Check status:
systemctl status ABC.service
Secure Your EC2 App with Nginx + HTTPS (Step-by-Step)
After connecting to your EC2 instance and running your backend (FastAPI) on localhost using service, the next step is to expose it securely using Nginx as a reverse proxy with HTTPS.
Open Nginx Site Configuration
mkdir -p /etc/nginx/sites-available sudo cat /etc/nginx/sites-available/ABC
Configure Nginx for HTTPS + Reverse Proxy
# ------------------------
# HTTPS SERVER
# ------------------------
server {
listen 443;
listen [::]:443;
server_name faizanarif.me www.faizanarif.me;
# Static files
location /static/ {
alias /var/www/abc/static/;
}
# Backend (FastAPI)
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;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# ------------------------
# HTTP → HTTPS REDIRECT
# ------------------------
server {
listen 80;
listen [::]:80;
server_name faizanarif.me www.faizanarif.me;
return 301 https://$host$request_uri;
}
Create Symbolic Link
sudo ln -s /etc/nginx/sites-available/ABC /etc/nginx/sites-enabled/
This links:
sites-available/ABC → sites-enabled/ABC
Test Nginx Configuration
sudo nginx -t
You should see:
✅ syntax is ok
✅ test is successful
Join The Writer's Circle event
Reload Nginx (No Downtime)
sudo systemctl reload nginx
Now your backend:
✔ Starts automatically
✔ Restarts on crash
✔ Runs in background
Step 3: Bitbucket SSH for Automatic Deployment
Using Bitbucket SSH Key for EC2 CI/CD Deployment
Generate SSH Key in Bitbucket
1. Go to your
Bitbucket repository → Repository settings → Pipelines → SSH keys.
2. Click Generate key or Add key:
— Bitbucket provides a private key (used in Pipelines automatically) and a public key.
— The public key will go on your EC2 server.
Add Public Key to EC2
1. Connect to your EC2 instance:
ssh -i your-ec2-key.pem your-username@your-ec2-ipv4
2. Add the public key to authorized_keys:
mkdir -p ~/.ssh nano ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys
Now Bitbucket can securely connect to EC2.
Step 4: Create Bitbucket Pipeline
In repository root create: bitbucket-pipelines.yml
Add:
image: python:version-name
pipelines:
branches:
main:
- step:
name: Deploy to EC2
deployment: production
script:
- pipe: atlassian/ssh-run:0.6.1
variables:
SSH_USER: "Your_EC2_username"
SERVER: "YOUR_EC2_PUBLIC_IPv4"
COMMAND: |
cd /var/www/ABC &&
git pull origin main &&
sudo systemctl restart ABC
Step 5: Enable Pipelines
In Bitbucket:
Repository → Pipelines → Enable
That’s it! Automatic Deployment is Live
Now every time you run:
git push origin main
The pipeline will:
✔ Connect to EC2
✔ Pull latest code
✔ Restart backend
✔ Update live site
No manual SSH needed anymore 🚀
Real Production Workflow
Backend update:
git pull origin main systemctl restart ABC.service
Nginx config update:
nginx -t systemctl reload nginx
Best Practices
✅ Keep backend running on localhost only
✅ Use Nginx as reverse proxy
✅ Restart backend with systemd
✅ Reload nginx (no downtime)
✅ Never expose backend port publicly
Common Issues & Fixes
Permission error:
sudo chown -R username:username /var/www/ABC
SSH timeout:
✔ Check EC2 Security Group allows port 22
✔ Verify correct IP
Pipeline git pull fails first time:
Run manually on EC2:
git pull origin main
Accept SSH fingerprint.
Why This CI/CD Setup is Powerful
Without CI/CD:
❌ Manual deploy
❌ Human mistakes
❌ Downtime
❌ Slow updates
With CI/CD:
✅ Fast releases
✅ Reliable deployment
✅ Automated workflow
✅ Production ready
Final Thoughts
CI/CD is not just for big companies — even small projects benefit hugely.
Using:
• Bitbucket Pipelines
• SSH
• EC2
• systemd
• Nginx
You get a:
✔ Professional deployment system
✔ Automatic updates
✔ Scalable infrastructure
This is the foundation of modern DevOps.
Happy deploying 🚀