Backend Integration Guide
Integrate BoxVault with your existing infrastructure and CI/CD pipelines.
Table of contents
- Overview
- CI/CD Integration
- Infrastructure as Code
- API Integration Examples
- Webhook Integration
- Monitoring and Observability
- Best Practices
Overview
BoxVault provides comprehensive APIs for integrating with existing development workflows, CI/CD pipelines, and infrastructure automation tools.
CI/CD Integration
GitHub Actions
name: Build and Upload Vagrant Box
on:
push:
tags:
- 'v*'
jobs:
build-and-upload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Vagrant Box
run: |
packer build ubuntu.pkr.hcl
- name: Upload to BoxVault
env:
BOXVAULT_URL: $
BOXVAULT_CLIENT_ID: $
BOXVAULT_CLIENT_SECRET: $
run: |
# Get authentication token
TOKEN=$(curl -s -X POST $BOXVAULT_URL/api/auth/service-account \
-H "Content-Type: application/json" \
-d "{\"clientId\":\"$BOXVAULT_CLIENT_ID\",\"clientSecret\":\"$BOXVAULT_CLIENT_SECRET\"}" \
| jq -r '.accessToken')
# Extract version from tag
VERSION=${GITHUB_REF#refs/tags/v}
# Upload box file
curl -X POST $BOXVAULT_URL/api/organization/myorg/box/ubuntu-20.04/version/$VERSION/provider/virtualbox/architecture/amd64/file \
-H "x-access-token: $TOKEN" \
-F "file=@ubuntu-20.04.box"
GitLab CI
stages:
- build
- upload
build-box:
stage: build
script:
- packer build ubuntu.pkr.hcl
artifacts:
paths:
- "*.box"
upload-box:
stage: upload
script:
- |
TOKEN=$(curl -s -X POST $BOXVAULT_URL/api/auth/service-account \
-H "Content-Type: application/json" \
-d "{\"clientId\":\"$BOXVAULT_CLIENT_ID\",\"clientSecret\":\"$BOXVAULT_CLIENT_SECRET\"}" \
| jq -r '.accessToken')
curl -X POST $BOXVAULT_URL/api/organization/myorg/box/ubuntu-20.04/version/$CI_COMMIT_TAG/provider/virtualbox/architecture/amd64/file \
-H "x-access-token: $TOKEN" \
-F "file=@ubuntu-20.04.box"
only:
- tags
Jenkins Pipeline
pipeline {
agent any
environment {
BOXVAULT_URL = credentials('boxvault-url')
BOXVAULT_CLIENT_ID = credentials('boxvault-client-id')
BOXVAULT_CLIENT_SECRET = credentials('boxvault-client-secret')
}
stages {
stage('Build') {
steps {
sh 'packer build ubuntu.pkr.hcl'
}
}
stage('Upload') {
steps {
script {
def token = sh(
script: """
curl -s -X POST \$BOXVAULT_URL/api/auth/service-account \
-H "Content-Type: application/json" \
-d '{"clientId":"'\$BOXVAULT_CLIENT_ID'","clientSecret":"'\$BOXVAULT_CLIENT_SECRET'"}' \
| jq -r '.accessToken'
""",
returnStdout: true
).trim()
sh """
curl -X POST \$BOXVAULT_URL/api/organization/myorg/box/ubuntu-20.04/version/${env.BUILD_NUMBER}/provider/virtualbox/architecture/amd64/file \
-H "x-access-token: ${token}" \
-F "file=@ubuntu-20.04.box"
"""
}
}
}
}
}
Infrastructure as Code
Terraform Integration
# Configure BoxVault provider (hypothetical)
terraform {
required_providers {
boxvault = {
source = "boxvault/boxvault"
version = "~> 1.0"
}
}
}
provider "boxvault" {
endpoint = var.boxvault_url
token = var.boxvault_token
}
# Create organization
resource "boxvault_organization" "example" {
name = "example-org"
description = "Example organization"
is_public = false
}
# Create box
resource "boxvault_box" "ubuntu" {
organization = boxvault_organization.example.name
name = "ubuntu-20.04"
description = "Ubuntu 20.04 LTS"
is_public = true
}
Ansible Integration
---
- name: Upload Vagrant Box to BoxVault
hosts: localhost
vars:
boxvault_url: "https://boxvault.example.com"
organization: "myorg"
box_name: "ubuntu-20.04"
version: "1.0.0"
tasks:
- name: Get authentication token
uri:
url: "/api/auth/service-account"
method: POST
body_format: json
body:
clientId: ""
clientSecret: ""
register: auth_response
- name: Upload box file
uri:
url: "/api/organization//box//version//provider/virtualbox/architecture/amd64/file"
method: POST
headers:
x-access-token: ""
body_format: form-multipart
body:
file:
filename: ".box"
content: ""
mime_type: application/octet-stream
API Integration Examples
Python SDK
import requests
import os
class BoxVaultClient:
def __init__(self, base_url, client_id=None, client_secret=None):
self.base_url = base_url.rstrip('/')
self.token = None
if client_id and client_secret:
self.authenticate_service_account(client_id, client_secret)
def authenticate_service_account(self, client_id, client_secret):
response = requests.post(
f"{self.base_url}/api/auth/service-account",
json={"clientId": client_id, "clientSecret": client_secret}
)
response.raise_for_status()
self.token = response.json()["accessToken"]
def upload_box(self, org, box, version, provider, arch, file_path):
with open(file_path, 'rb') as f:
response = requests.post(
f"{self.base_url}/api/organization/{org}/box/{box}/version/{version}/provider/{provider}/architecture/{arch}/file",
headers={"x-access-token": self.token},
files={"file": f}
)
response.raise_for_status()
return response.json()
def list_boxes(self, org):
response = requests.get(
f"{self.base_url}/api/organization/{org}/box",
headers={"x-access-token": self.token}
)
response.raise_for_status()
return response.json()
# Usage
client = BoxVaultClient(
"https://boxvault.example.com",
os.environ["BOXVAULT_CLIENT_ID"],
os.environ["BOXVAULT_CLIENT_SECRET"]
)
# Upload a box
client.upload_box("myorg", "ubuntu-20.04", "1.0.0", "virtualbox", "amd64", "ubuntu.box")
# List boxes
boxes = client.list_boxes("myorg")
print(f"Found {len(boxes)} boxes")
Node.js SDK
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
class BoxVaultClient {
constructor(baseUrl, clientId, clientSecret) {
this.baseUrl = baseUrl.replace(/\/$/, '');
this.token = null;
if (clientId && clientSecret) {
this.authenticateServiceAccount(clientId, clientSecret);
}
}
async authenticateServiceAccount(clientId, clientSecret) {
const response = await axios.post(`${this.baseUrl}/api/auth/service-account`, {
clientId,
clientSecret
});
this.token = response.data.accessToken;
}
async uploadBox(org, box, version, provider, arch, filePath) {
const form = new FormData();
form.append('file', fs.createReadStream(filePath));
const response = await axios.post(
`${this.baseUrl}/api/organization/${org}/box/${box}/version/${version}/provider/${provider}/architecture/${arch}/file`,
form,
{
headers: {
'x-access-token': this.token,
...form.getHeaders()
}
}
);
return response.data;
}
async listBoxes(org) {
const response = await axios.get(
`${this.baseUrl}/api/organization/${org}/box`,
{
headers: { 'x-access-token': this.token }
}
);
return response.data;
}
}
// Usage
const client = new BoxVaultClient(
'https://boxvault.example.com',
process.env.BOXVAULT_CLIENT_ID,
process.env.BOXVAULT_CLIENT_SECRET
);
// Upload a box
await client.uploadBox('myorg', 'ubuntu-20.04', '1.0.0', 'virtualbox', 'amd64', 'ubuntu.box');
// List boxes
const boxes = await client.listBoxes('myorg');
console.log(`Found ${boxes.length} boxes`);
Webhook Integration
Setting up Webhooks
BoxVault can send webhooks for various events:
# Create webhook
curl -X POST http://localhost:3000/api/admin/webhooks \
-H "x-access-token: ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/boxvault",
"events": ["box.uploaded", "box.deleted", "user.created"],
"secret": "webhook-secret"
}'
Webhook Handler Example
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
app.post('/webhooks/boxvault', (req, res) => {
const signature = req.headers['x-boxvault-signature'];
const payload = JSON.stringify(req.body);
const secret = process.env.WEBHOOK_SECRET;
// Verify signature
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
if (signature !== `sha256=${expectedSignature}`) {
return res.status(401).send('Invalid signature');
}
// Handle event
const { event, data } = req.body;
switch (event) {
case 'box.uploaded':
console.log(`Box uploaded: ${data.organization}/${data.box} v${data.version}`);
// Trigger deployment, notifications, etc.
break;
case 'box.deleted':
console.log(`Box deleted: ${data.organization}/${data.box}`);
// Clean up references, notify teams, etc.
break;
case 'user.created':
console.log(`New user: ${data.username}`);
// Send welcome email, setup permissions, etc.
break;
}
res.status(200).send('OK');
});
Monitoring and Observability
Health Checks
# Basic health check
curl http://localhost:3000/health
# Detailed status
curl http://localhost:3000/api/status
Metrics Integration
# Prometheus configuration
scrape_configs:
- job_name: 'boxvault'
static_configs:
- targets: ['localhost:3000']
metrics_path: '/metrics'
scrape_interval: 30s
Log Aggregation
# Fluentd configuration
<source>
@type tail
path /var/log/boxvault/boxvault.log
pos_file /var/log/fluentd/boxvault.log.pos
tag boxvault
format json
</source>
<match boxvault>
@type elasticsearch
host elasticsearch.example.com
port 9200
index_name boxvault
</match>
Best Practices
Error Handling
- Implement exponential backoff for API calls
- Handle rate limiting gracefully
- Log all API interactions for debugging
- Use circuit breakers for external dependencies
Security
- Store credentials securely (environment variables, secrets management)
- Use service accounts for automation
- Implement proper token rotation
- Validate webhook signatures
Performance
- Use connection pooling for HTTP clients
- Implement caching where appropriate
- Monitor API response times
- Set appropriate timeouts
Reliability
- Implement retry logic with backoff
- Use health checks in load balancers
- Monitor disk space for box storage
- Set up alerting for critical failures