CI/CD Integration
Integrate FireBackup into your CI/CD pipelines to automate backup verification, pre-deployment snapshots, and disaster recovery testing.
Overview
CI/CD integration enables:
- Pre-deployment backups - Automatic snapshots before deployments
- Backup verification - Validate backup integrity in pipelines
- Database seeding - Restore backups to staging/test environments
- Disaster recovery testing - Automated DR drills
- Compliance automation - Scheduled backup audits
API Authentication
Generate API Key
- Go to Settings → API Keys
- Click Create API Key
- Set appropriate permissions:
backups:read- List and view backupsbackups:write- Create backupsrestores:write- Initiate restores
- Copy the API key
Using API Keys
Include in request headers:
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://api.firebackup.io/api/v1/backups
Store securely in CI/CD secrets:
- GitHub Actions: Repository secrets
- GitLab CI: CI/CD variables
- CircleCI: Environment variables
- Jenkins: Credentials store
GitHub Actions
Pre-Deployment Backup
Create a backup before deploying to production:
# .github/workflows/deploy.yml
name: Deploy with Backup
on:
push:
branches: [main]
jobs:
backup-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Pre-Deployment Backup
id: backup
run: |
RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer ${{ secrets.FIREBACKUP_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"projectId": "proj_abc123", "type": "full", "tags": ["pre-deploy", "github-actions"]}' \
https://api.firebackup.io/api/v1/backups)
BACKUP_ID=$(echo $RESPONSE | jq -r '.id')
echo "backup_id=$BACKUP_ID" >> $GITHUB_OUTPUT
- name: Wait for Backup Completion
run: |
BACKUP_ID=${{ steps.backup.outputs.backup_id }}
while true; do
STATUS=$(curl -s \
-H "Authorization: Bearer ${{ secrets.FIREBACKUP_API_KEY }}" \
https://api.firebackup.io/api/v1/backups/$BACKUP_ID | jq -r '.status')
echo "Backup status: $STATUS"
if [ "$STATUS" = "completed" ]; then
echo "Backup completed successfully"
break
elif [ "$STATUS" = "failed" ]; then
echo "Backup failed"
exit 1
fi
sleep 10
done
- name: Deploy to Production
run: |
# Your deployment steps
echo "Deploying..."
- name: Tag Backup as Deployed
if: success()
run: |
curl -X PATCH \
-H "Authorization: Bearer ${{ secrets.FIREBACKUP_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"tags": ["pre-deploy", "deployed", "${{ github.sha }}"]}' \
https://api.firebackup.io/api/v1/backups/${{ steps.backup.outputs.backup_id }}
Backup Verification
Verify backup integrity after creation:
# .github/workflows/verify-backups.yml
name: Verify Backups
on:
schedule:
- cron: '0 6 * * *' # Daily at 6 AM
jobs:
verify:
runs-on: ubuntu-latest
steps:
- name: Get Recent Backups
id: backups
run: |
BACKUPS=$(curl -s \
-H "Authorization: Bearer ${{ secrets.FIREBACKUP_API_KEY }}" \
"https://api.firebackup.io/api/v1/backups?limit=5&status=completed")
echo "backups=$BACKUPS" >> $GITHUB_OUTPUT
- name: Verify Backup Integrity
run: |
echo '${{ steps.backups.outputs.backups }}' | jq -r '.backups[] | .id' | while read BACKUP_ID; do
echo "Verifying backup: $BACKUP_ID"
VERIFY=$(curl -s -X POST \
-H "Authorization: Bearer ${{ secrets.FIREBACKUP_API_KEY }}" \
https://api.firebackup.io/api/v1/backups/$BACKUP_ID/verify)
VALID=$(echo $VERIFY | jq -r '.valid')
if [ "$VALID" != "true" ]; then
echo "Backup verification failed for $BACKUP_ID"
exit 1
fi
echo "Backup $BACKUP_ID verified successfully"
done
- name: Notify on Failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "⚠️ Backup verification failed",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Backup verification failed. Check the workflow logs."
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Reusable Workflow
Create a reusable workflow for backups:
# .github/workflows/backup.yml
name: FireBackup
on:
workflow_call:
inputs:
project_id:
required: true
type: string
backup_type:
required: false
type: string
default: 'full'
wait_for_completion:
required: false
type: boolean
default: true
secrets:
api_key:
required: true
outputs:
backup_id:
description: 'Created backup ID'
value: ${{ jobs.backup.outputs.backup_id }}
jobs:
backup:
runs-on: ubuntu-latest
outputs:
backup_id: ${{ steps.create.outputs.backup_id }}
steps:
- name: Create Backup
id: create
run: |
RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer ${{ secrets.api_key }}" \
-H "Content-Type: application/json" \
-d '{"projectId": "${{ inputs.project_id }}", "type": "${{ inputs.backup_type }}"}' \
https://api.firebackup.io/api/v1/backups)
BACKUP_ID=$(echo $RESPONSE | jq -r '.id')
echo "backup_id=$BACKUP_ID" >> $GITHUB_OUTPUT
- name: Wait for Completion
if: ${{ inputs.wait_for_completion }}
run: |
# Wait logic here
Use in other workflows:
jobs:
backup:
uses: ./.github/workflows/backup.yml
with:
project_id: proj_abc123
secrets:
api_key: ${{ secrets.FIREBACKUP_API_KEY }}
deploy:
needs: backup
runs-on: ubuntu-latest
steps:
- run: echo "Backup ID: ${{ needs.backup.outputs.backup_id }}"
GitLab CI
Pre-Deployment Backup
# .gitlab-ci.yml
stages:
- backup
- deploy
variables:
FIREBACKUP_API_URL: https://api.firebackup.io/api/v1
PROJECT_ID: proj_abc123
backup:
stage: backup
image: curlimages/curl:latest
script:
- |
RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer $FIREBACKUP_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"projectId\": \"$PROJECT_ID\", \"type\": \"full\", \"tags\": [\"gitlab-ci\", \"$CI_COMMIT_SHA\"]}" \
$FIREBACKUP_API_URL/backups)
BACKUP_ID=$(echo $RESPONSE | jq -r '.id')
echo "BACKUP_ID=$BACKUP_ID" >> backup.env
# Wait for completion
while true; do
STATUS=$(curl -s \
-H "Authorization: Bearer $FIREBACKUP_API_KEY" \
$FIREBACKUP_API_URL/backups/$BACKUP_ID | jq -r '.status')
if [ "$STATUS" = "completed" ]; then
echo "Backup completed"
break
elif [ "$STATUS" = "failed" ]; then
echo "Backup failed"
exit 1
fi
sleep 10
done
artifacts:
reports:
dotenv: backup.env
rules:
- if: $CI_COMMIT_BRANCH == "main"
deploy:
stage: deploy
needs:
- job: backup
artifacts: true
script:
- echo "Deploying with backup $BACKUP_ID"
# Your deployment steps
rules:
- if: $CI_COMMIT_BRANCH == "main"
Scheduled Backup Verification
# .gitlab-ci.yml
verify-backups:
stage: test
image: curlimages/curl:latest
script:
- |
# Get recent backups
BACKUPS=$(curl -s \
-H "Authorization: Bearer $FIREBACKUP_API_KEY" \
"$FIREBACKUP_API_URL/backups?limit=5&status=completed")
# Verify each backup
echo $BACKUPS | jq -r '.backups[].id' | while read BACKUP_ID; do
VERIFY=$(curl -s -X POST \
-H "Authorization: Bearer $FIREBACKUP_API_KEY" \
$FIREBACKUP_API_URL/backups/$BACKUP_ID/verify)
VALID=$(echo $VERIFY | jq -r '.valid')
if [ "$VALID" != "true" ]; then
echo "Verification failed for $BACKUP_ID"
exit 1
fi
done
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
CircleCI
Workflow Configuration
# .circleci/config.yml
version: 2.1
orbs:
slack: circleci/slack@4.12.0
commands:
create-backup:
parameters:
project_id:
type: string
steps:
- run:
name: Create FireBackup
command: |
RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer $FIREBACKUP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"projectId": "<< parameters.project_id >>", "type": "full"}' \
https://api.firebackup.io/api/v1/backups)
echo $RESPONSE | jq -r '.id' > /tmp/backup_id
wait-for-backup:
steps:
- run:
name: Wait for Backup
command: |
BACKUP_ID=$(cat /tmp/backup_id)
while true; do
STATUS=$(curl -s \
-H "Authorization: Bearer $FIREBACKUP_API_KEY" \
https://api.firebackup.io/api/v1/backups/$BACKUP_ID | jq -r '.status')
if [ "$STATUS" = "completed" ]; then
exit 0
elif [ "$STATUS" = "failed" ]; then
exit 1
fi
sleep 10
done
jobs:
backup-and-deploy:
docker:
- image: cimg/base:stable
steps:
- checkout
- create-backup:
project_id: proj_abc123
- wait-for-backup
- run:
name: Deploy
command: echo "Deploying..."
- slack/notify:
event: fail
template: basic_fail_1
workflows:
deploy:
jobs:
- backup-and-deploy:
filters:
branches:
only: main
Jenkins
Pipeline Script
// Jenkinsfile
pipeline {
agent any
environment {
FIREBACKUP_API_KEY = credentials('firebackup-api-key')
PROJECT_ID = 'proj_abc123'
}
stages {
stage('Pre-Deployment Backup') {
steps {
script {
def response = httpRequest(
url: 'https://api.firebackup.io/api/v1/backups',
httpMode: 'POST',
customHeaders: [
[name: 'Authorization', value: "Bearer ${FIREBACKUP_API_KEY}"],
[name: 'Content-Type', value: 'application/json']
],
requestBody: """{"projectId": "${PROJECT_ID}", "type": "full", "tags": ["jenkins", "${BUILD_NUMBER}"]}"""
)
def json = readJSON text: response.content
env.BACKUP_ID = json.id
echo "Created backup: ${env.BACKUP_ID}"
}
}
}
stage('Wait for Backup') {
steps {
script {
def completed = false
while (!completed) {
def response = httpRequest(
url: "https://api.firebackup.io/api/v1/backups/${env.BACKUP_ID}",
customHeaders: [
[name: 'Authorization', value: "Bearer ${FIREBACKUP_API_KEY}"]
]
)
def json = readJSON text: response.content
if (json.status == 'completed') {
completed = true
echo "Backup completed successfully"
} else if (json.status == 'failed') {
error "Backup failed"
} else {
sleep 10
}
}
}
}
}
stage('Deploy') {
steps {
echo "Deploying with backup ${env.BACKUP_ID}"
// Your deployment steps
}
}
}
post {
failure {
slackSend(
color: 'danger',
message: "Deployment failed. Backup ID: ${env.BACKUP_ID}"
)
}
}
}
Use Cases
Pre-Deployment Snapshots
Create a backup before every production deployment:
#!/bin/bash
# pre-deploy-backup.sh
set -e
PROJECT_ID=$1
API_KEY=$FIREBACKUP_API_KEY
echo "Creating pre-deployment backup..."
# Create backup
BACKUP=$(curl -s -X POST \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{\"projectId\": \"$PROJECT_ID\", \"type\": \"full\", \"tags\": [\"pre-deploy\"]}" \
https://api.firebackup.io/api/v1/backups)
BACKUP_ID=$(echo $BACKUP | jq -r '.id')
echo "Backup ID: $BACKUP_ID"
# Wait for completion
while true; do
STATUS=$(curl -s \
-H "Authorization: Bearer $API_KEY" \
https://api.firebackup.io/api/v1/backups/$BACKUP_ID | jq -r '.status')
case $STATUS in
completed)
echo "Backup completed successfully"
echo $BACKUP_ID
exit 0
;;
failed)
echo "Backup failed"
exit 1
;;
*)
echo "Status: $STATUS"
sleep 10
;;
esac
done
Staging Environment Seeding
Restore production data to staging:
#!/bin/bash
# seed-staging.sh
set -e
PROD_PROJECT_ID=$1
STAGING_PROJECT_ID=$2
API_KEY=$FIREBACKUP_API_KEY
echo "Getting latest production backup..."
# Get latest backup
LATEST_BACKUP=$(curl -s \
-H "Authorization: Bearer $API_KEY" \
"https://api.firebackup.io/api/v1/backups?projectId=$PROD_PROJECT_ID&status=completed&limit=1" \
| jq -r '.backups[0].id')
echo "Latest backup: $LATEST_BACKUP"
echo "Restoring to staging..."
# Restore to staging
RESTORE=$(curl -s -X POST \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{\"targetProjectId\": \"$STAGING_PROJECT_ID\", \"options\": {\"clearExisting\": true}}" \
https://api.firebackup.io/api/v1/backups/$LATEST_BACKUP/restore)
RESTORE_ID=$(echo $RESTORE | jq -r '.id')
echo "Restore ID: $RESTORE_ID"
# Wait for completion
# ... similar wait logic
Disaster Recovery Testing
Automated DR drill:
# .github/workflows/dr-drill.yml
name: Disaster Recovery Drill
on:
schedule:
- cron: '0 2 1 * *' # Monthly at 2 AM
jobs:
dr-drill:
runs-on: ubuntu-latest
steps:
- name: Get Random Production Backup
id: backup
run: |
BACKUP=$(curl -s \
-H "Authorization: Bearer ${{ secrets.FIREBACKUP_API_KEY }}" \
"https://api.firebackup.io/api/v1/backups?status=completed&limit=10" \
| jq -r '.backups[0]')
BACKUP_ID=$(echo $BACKUP | jq -r '.id')
echo "backup_id=$BACKUP_ID" >> $GITHUB_OUTPUT
- name: Restore to DR Environment
run: |
curl -X POST \
-H "Authorization: Bearer ${{ secrets.FIREBACKUP_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"targetProjectId": "proj_dr_test", "options": {"clearExisting": true}}' \
https://api.firebackup.io/api/v1/backups/${{ steps.backup.outputs.backup_id }}/restore
- name: Validate Restored Data
run: |
# Run validation tests against DR environment
npm run test:dr-validation
- name: Report Results
run: |
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-H "Content-Type: application/json" \
-d '{
"text": "✅ DR Drill completed successfully",
"attachments": [{
"fields": [
{"title": "Backup ID", "value": "${{ steps.backup.outputs.backup_id }}"},
{"title": "Restore Time", "value": "'$(date)'"}
]
}]
}'
Best Practices
Security
- Store API keys in CI/CD secrets, never in code
- Use scoped keys with minimal permissions
- Rotate keys periodically
- Audit key usage via API logs
Reliability
- Always wait for backup completion before deploying
- Implement timeouts to avoid hanging pipelines
- Add notifications for failures
- Tag backups with commit SHA for traceability
Performance
- Run backups in parallel when possible
- Use incremental backups for faster completion
- Cache backup status to reduce API calls
Related
- Webhooks Integration - Event-driven automation
- Backups API Reference - API documentation
- Restores API Reference - Restore operations