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

  1. Export Packages: List all packages and note their metadata
  2. Export Sessions: Export session data if you need to preserve learner progress
  3. Export Webhooks: Note webhook configurations
  4. Export API Keys: Document existing API keys (you'll need to recreate them)

Step 2: Set Up Cloud Instance

  1. Create Account: Sign up for cloud SCORM API
  2. Get API Key: Generate a new API key
  3. Get Tenant ID: Note your tenant UUID
  4. 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

  1. Revoke Old Keys: Revoke API keys from self-hosted instance
  2. Create New Keys: Generate new API keys in cloud instance
  3. Update Environment Variables: Update all environment variables
  4. Update Application Config: Update application configuration files

Step 6: Update Webhooks

If you have webhooks configured:

  1. Create New Webhooks: Set up webhooks in cloud instance
  2. Update Webhook URLs: Ensure webhook URLs are publicly accessible
  3. Test Webhooks: Verify webhook delivery works

Step 7: Update DNS/Configuration

If you were using a custom domain:

  1. Update DNS: Point custom domain to cloud instance (if supported)
  2. Update CORS: Update CORS settings if needed
  3. 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:

  1. Keep self-hosted instance running during migration
  2. Use feature flags to switch between instances
  3. Maintain database backups
  4. Document all changes for easy reversal

Support

For migration assistance:


Last Updated: 2025-01-15