Migrating from Self-Hosted to Cloud
This guide helps you migrate from a self-hosted SCORM API instance to the cloud-hosted version.
Overview
If you're currently running a self-hosted instance of the SCORM API and want to migrate to the cloud-hosted version, this guide will walk you through the process.
Prerequisites
- Access to your self-hosted SCORM API instance
- Access to your database (for data export if needed)
- Cloud SCORM API account created
- API key generated for cloud instance
Migration Steps
Step 1: Export Data from Self-Hosted Instance
- Export Packages: List all packages and note their metadata
- Export Sessions: Export session data if you need to preserve learner progress
- Export Webhooks: Note webhook configurations
- Export API Keys: Document existing API keys (you'll need to recreate them)
Step 2: Set Up Cloud Instance
- Create Account: Sign up for cloud SCORM API
- Get API Key: Generate a new API key
- Get Tenant ID: Note your tenant UUID
- Configure Webhooks: Set up webhook endpoints if needed
Step 3: Re-upload Packages
For each package in your self-hosted instance:
# Download from self-hosted
curl -X GET "http://localhost:3001/api/v1/packages/{packageId}/download" \
-H "X-API-Key: old-api-key" \
-o package.zip
# Upload to cloud (presigned flow — see docs/API/package-upload-integration.md)
set -euo pipefail
command -v curl >/dev/null || { echo "error: curl is required" >&2; exit 1; }
command -v jq >/dev/null || { echo "error: jq is required" >&2; exit 1; }
BASE="https://app.allureconnect.com"
SIZE=$(wc -c <package.zip | tr -d ' ')
[[ -n "${SIZE:-}" && "${SIZE}" -gt 0 ]] || { echo "error: could not read package.zip" >&2; exit 1; }
TICKET_FILE=$(mktemp)
PROC_FILE=$(mktemp)
trap 'rm -f "$TICKET_FILE" "$PROC_FILE"' EXIT
HTTP_CODE=$(curl -sS -o "$TICKET_FILE" -w "%{http_code}" -X POST "${BASE}/api/v1/packages/upload-url" \
-H "Authorization: Bearer new-api-key" \
-H "Content-Type: application/json" \
-d "{\"tenant_id\":\"new-tenant-id\",\"uploaded_by\":\"migration-script\",\"filename\":\"package.zip\",\"file_size\":${SIZE}}")
if [[ "$HTTP_CODE" -lt 200 || "$HTTP_CODE" -ge 300 ]]; then
echo "error: upload-url failed HTTP ${HTTP_CODE}: $(cat "$TICKET_FILE")" >&2
exit 1
fi
TICKET=$(cat "$TICKET_FILE")
PRESIGNED=$(echo "$TICKET" | jq -e -r .presigned_url)
STORAGE=$(echo "$TICKET" | jq -e -r .storage_path)
[[ -n "$PRESIGNED" && "$PRESIGNED" != "null" ]] || { echo "error: missing presigned_url in response" >&2; exit 1; }
PUT_ARGS=(-sS -o /dev/null -w "%{http_code}" -X PUT)
while IFS= read -r hk; do
hv=$(echo "$TICKET" | jq -r --arg k "$hk" '.required_put_headers[$k]')
PUT_ARGS+=(-H "$hk: $hv")
done < <(echo "$TICKET" | jq -r '.required_put_headers | keys[]')
PUT_ARGS+=(--data-binary @package.zip "$PRESIGNED")
PUT_CODE=$(curl "${PUT_ARGS[@]}")
if [[ "$PUT_CODE" -lt 200 || "$PUT_CODE" -ge 300 ]]; then
echo "error: storage PUT failed HTTP ${PUT_CODE}" >&2
exit 1
fi
PROC_CODE=$(curl -sS -o "$PROC_FILE" -w "%{http_code}" -X POST "${BASE}/api/v1/packages/process" \
-H "Authorization: Bearer new-api-key" \
-H "Content-Type: application/json" \
-d "{\"tenant_id\":\"new-tenant-id\",\"uploaded_by\":\"migration-script\",\"storage_path\":\"${STORAGE}\",\"original_filename\":\"package.zip\"}")
cat "$PROC_FILE"
if [[ "$PROC_CODE" -lt 200 || "$PROC_CODE" -ge 300 ]]; then
echo "error: process failed HTTP ${PROC_CODE}: $(cat "$PROC_FILE")" >&2
exit 1
fi
Step 4: Update API Endpoints
Update all API calls in your application:
Before (Self-Hosted):
const API_URL = 'http://localhost:3001';
After (Cloud):
const API_URL = 'https://app.allureconnect.com';
Step 5: Update API Keys
- Revoke Old Keys: Revoke API keys from self-hosted instance
- Create New Keys: Generate new API keys in cloud instance
- Update Environment Variables: Update all environment variables
- Update Application Config: Update application configuration files
Step 6: Update Webhooks
If you have webhooks configured:
- Create New Webhooks: Set up webhooks in cloud instance
- Update Webhook URLs: Ensure webhook URLs are publicly accessible
- Test Webhooks: Verify webhook delivery works
Step 7: Update DNS/Configuration
If you were using a custom domain:
- Update DNS: Point custom domain to cloud instance (if supported)
- Update CORS: Update CORS settings if needed
- Update Allowed Domains: Configure allowed domains for launch tokens
Data Migration Considerations
Package Migration
- Package IDs: Will change (new UUIDs in cloud)
- Launch URLs: Will change (new base URL)
- Storage: Packages stored in cloud storage (Supabase or R2)
Session Migration
- Session IDs: Will change (new UUIDs)
- CMI Data: Can be exported and re-imported if needed
- Learner Progress: May need to recreate sessions
Webhook Migration
- Webhook IDs: Will change
- Secrets: Need to be reconfigured
- URLs: Must be publicly accessible
Testing Checklist
After migration:
- All packages uploaded successfully
- Sessions launch correctly
- CMI data saves and retrieves
- Webhooks are received
- API keys work correctly
- Rate limiting functions properly
- Error handling works as expected
Rollback Plan
If you need to rollback:
- Keep self-hosted instance running during migration
- Use feature flags to switch between instances
- Maintain database backups
- Document all changes for easy reversal
Support
For migration assistance:
- Documentation: See API Reference
- Support: Email support@allurelms.com
- Troubleshooting: See Troubleshooting Guide
Last Updated: 2025-01-15