The Mux Supabase integration syncs your Mux assets, live streams, and uploads to your Supabase database using webhooks and edge functions.
The @mux/supabase package provides a CLI that integrates your Mux account with Supabase. It creates a mux schema in your database with tables for assets, live streams, uploads, and webhook events, keeping everything in sync automatically.
After setup, your Supabase database will have a mux schema containing:
Before you begin, make sure you have:
First, make sure Supabase is initialized in your project, then run the Mux initialization:
npx supabase init
npx @mux/supabase initThe initialization process will:
mux schema with tables for assets, live streams, uploads, and webhook eventssupabase/functions/mux-webhook.env file at supabase/functions/.env with placeholder values for your Mux credentialsconfig.toml to expose the mux schema and disable JWT verification for the webhook functionAfter initialization, update the .env file in the supabase/functions directory with your actual Mux API credentials:
MUX_TOKEN_ID=your-mux-token-id
MUX_TOKEN_SECRET=your-mux-token-secret
MUX_WEBHOOK_SECRET=your-webhook-secretYou can find your API credentials in the Mux Dashboard. The webhook secret will be generated when you configure the webhook in step 4.
Start your local Supabase instance:
npx supabase startTo test the webhook locally, serve the edge function:
npx supabase functions serve mux-webhookTo receive webhooks locally, you'll need to expose your local server using a tool like ngrok. Configure the ngrok URL as your webhook endpoint in the Mux dashboard.
In the Mux Dashboard, create a new webhook with the following settings:
https://your-project.supabase.co/functions/v1/mux-webhook)After creating the webhook, copy the signing secret and add it to your environment variables as MUX_WEBHOOK_SECRET.
If you have existing assets in Mux that you want to sync to Supabase, run the backfill command:
npx @mux/supabase backfillThis will import all your existing Mux assets and live streams into your Supabase database.
You can also run the backfill programmatically using the sync engine:
import { MuxSync } from '@mux/sync-engine';
const muxSync = new MuxSync({
databaseUrl: 'your-supabase-database-url',
muxTokenId: 'your-mux-token-id',
muxTokenSecret: 'your-mux-token-secret',
muxWebhookSecret: 'your-mux-webhook-secret',
});
const result = await muxSync.syncBackfill({ object: 'all' });When you're ready to deploy:
Push database migrations:
npx supabase db pushSet production secrets:
npx supabase secrets set MUX_TOKEN_ID=your-token-id
npx supabase secrets set MUX_TOKEN_SECRET=your-token-secret
npx supabase secrets set MUX_WEBHOOK_SECRET=your-webhook-secretDeploy the edge function:
npx supabase functions deploy mux-webhookUpdate your Mux webhook URL in the dashboard to point to your production edge function URL.
Once synced, you can query your Mux data directly from Supabase. The mux schema uses Row Level Security (RLS) that blocks access from anon and authenticated roles by default, so you'll need to use the service role key for server-side queries:
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
'your-supabase-url',
'your-supabase-service-role-key',
{ db: { schema: 'mux' } }
);
// Get all ready assets
const { data: assets } = await supabase
.from('assets')
.select('*')
.eq('status', 'ready');
// Get a specific asset by ID
const { data: asset } = await supabase
.from('assets')
.select('*')
.eq('id', 'asset-id')
.single();The service role key bypasses RLS and should only be used in server-side code. Never expose it in client-side applications. If you need client-side access to Mux data, add your own RLS policies to the tables in the mux schema.
If you're using PostgreSQL without Supabase, you can use the @mux/sync-engine package directly:
npm install @mux/sync-engineThe sync engine works with any PostgreSQL database and provides the same synchronization capabilities.