Why CI/CD Matters for Small Teams
If you're running a small tech team in Nepal — maybe a startup in Kathmandu or a digital agency in Lalitpur — you might think CI/CD is something "big companies" do. Here's the truth: CI/CD is even more valuable for small teams because every hour saved on manual work is an hour you can spend building features.
In this guide, I'll walk you through setting up a complete CI/CD pipeline with GitLab CI/CD, from zero to production deployment.
What Is GitLab CI/CD?
GitLab CI/CD is a built-in continuous integration and deployment tool. Every time you push code to your GitLab repository, it can automatically:
- Run your tests
- Build your application
- Deploy to staging or production
- Run security scans
All defined in a single .gitlab-ci.yml file.
Prerequisites
- A GitLab account (free tier works fine)
- A project with at least a basic application
- Understanding of basic shell commands
- A server or cloud instance for deployment (AWS, Azure, or a VPS)
Step 1: Create Your .gitlab-ci.yml
Create this file in your project root:
stages:
- test
- build
- deploy
variables:
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
# Stage 1: Run tests
test:
stage: test
image: node:20-alpine
script:
- npm ci
- npm run test
- npm run lint
rules:
- if: $CI_MERGE_REQUEST_IID
- if: $CI_COMMIT_BRANCH == "main"
# Stage 2: Build Docker image
build:
stage: build
image: docker:24.0
services:
- docker:24.0-dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $DOCKER_IMAGE .
- docker push $DOCKER_IMAGE
rules:
- if: $CI_COMMIT_BRANCH == "main"
# Stage 3: Deploy to production
deploy:
stage: deploy
image: alpine:latest
script:
- apk add --no-cache openssh-client
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- ssh -o StrictHostKeyChecking=no [email protected] "
docker pull $DOCKER_IMAGE &&
docker stop app || true &&
docker rm app || true &&
docker run -d --name app -p 3000:3000 $DOCKER_IMAGE
"
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
Step 2: Set Up CI/CD Variables
In your GitLab project, go to Settings → CI/CD → Variables and add:
| Variable | Description |
|---|---|
SSH_PRIVATE_KEY | SSH key for connecting to your server |
CI_REGISTRY_USER | GitLab container registry username |
CI_REGISTRY_PASSWORD | GitLab container registry password |
Step 3: Understand the Pipeline Flow
Here's what happens on each push to main:
graph LR
A[Push to main] --> B[test]
B --> C[build]
C --> D{deploy}
D -->|manual trigger| E[Production]
- Test stage — Installs dependencies, runs tests and linting
- Build stage — Creates a Docker image and pushes to GitLab's registry
- Deploy stage — SSH's into your server and deploys the new image (manual trigger for safety)
Step 4: Add Security Scanning
For teams managing sensitive applications in Nepal (fintech, health tech, etc.), add a security scan:
security-scan:
stage: test
image: aquasec/trivy:latest
script:
- trivy image --severity HIGH,CRITICAL $DOCKER_IMAGE
allow_failure: true
rules:
- if: $CI_COMMIT_BRANCH == "main"
Real-World Results
At Andmine Pvt Ltd, where I work as a System Administrator, implementing CI/CD pipelines reduced our deployment time from ~45 minutes per deployment to under 3 minutes. Manual errors dropped to near zero, and our team gained confidence in shipping code on Fridays.
Common Pitfalls to Avoid
1. Not caching dependencies
test:
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
2. Deploying on every branch
Use rules: to control when pipelines run. Don't deploy feature branches to production.
3. No manual approval for production
The when: manual flag on your deploy stage prevents accidental production deployments.
Next Steps
Once you have the basics working:
- Add monitoring with Prometheus and Grafana
- Set up automatic rollbacks on health check failures
- Implement canary deployments for zero-risk releases
- Use GitLab Environments to track deployment history
Need help setting up CI/CD for your team? I work with organizations across Nepal to build reliable deployment pipelines. Get in touch.