Nextended.Aspire.Hosting.Supabase 10.1.14

dotnet add package Nextended.Aspire.Hosting.Supabase --version 10.1.14
                    
NuGet\Install-Package Nextended.Aspire.Hosting.Supabase -Version 10.1.14
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Nextended.Aspire.Hosting.Supabase" Version="10.1.14" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nextended.Aspire.Hosting.Supabase" Version="10.1.14" />
                    
Directory.Packages.props
<PackageReference Include="Nextended.Aspire.Hosting.Supabase" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nextended.Aspire.Hosting.Supabase --version 10.1.14
                    
#r "nuget: Nextended.Aspire.Hosting.Supabase, 10.1.14"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Nextended.Aspire.Hosting.Supabase@10.1.14
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Nextended.Aspire.Hosting.Supabase&version=10.1.14
                    
Install as a Cake Addin
#tool nuget:?package=Nextended.Aspire.Hosting.Supabase&version=10.1.14
                    
Install as a Cake Tool

Nextended.Aspire.Hosting.Supabase provides Supabase for .NET Aspire

A complete Supabase stack integration for .NET Aspire, providing local development with full Supabase functionality including PostgreSQL, Auth (GoTrue), REST API (PostgREST), Storage, Kong API Gateway, Studio Dashboard, and Edge Functions.

Table of Contents


Quick Start

The simplest way to add a complete Supabase stack to your Aspire application:

var builder = DistributedApplication.CreateBuilder(args);

var supabase = builder.AddSupabase("supabase");

builder.Build().Run();

This starts a fully functional Supabase stack with:

  • PostgreSQL database (port 54322)
  • GoTrue authentication
  • PostgREST API
  • Storage API
  • Kong API Gateway (port 8000)
  • Studio Dashboard (port 54323)
  • Postgres Meta

All services use sensible defaults and are ready for local development and deployment for azure container apps.


Configuration Options

Database Configuration

var supabase = builder.AddSupabase("supabase")
    .ConfigureDatabase(db => db
        .WithPassword("my-secure-password")
        .WithPort(54322));

All Available Configure Methods

Each sub-resource can be configured individually:

var supabase = builder.AddSupabase("supabase")
    // PostgreSQL Database
    .ConfigureDatabase(db => db
        .WithPassword("secure-password")
        .WithPort(54322))

    // GoTrue Authentication
    .ConfigureAuth(auth => auth
        .WithAutoConfirm(true)
        .WithDisableSignup(false)
        .WithJwtExpiration(3600)
        .WithSiteUrl("http://localhost:3000"))

    // PostgREST API
    .ConfigureRest(rest => rest
        .WithSchemas("public", "storage", "graphql_public")
        .WithAnonRole("anon"))

    // Storage API
    .ConfigureStorage(storage => storage
        .WithFileSizeLimit(52428800))  // 50MB

    // Kong API Gateway
    .ConfigureKong(kong => kong
        .WithPort(8000))

    // Postgres Meta
    .ConfigureMeta(meta => meta
        .WithPort(8080))

    // Studio Dashboard
    .ConfigureStudio(studio => studio
        .WithPort(54323)
        .WithOrganizationName("My Organization")
        .WithProjectName("My Project"))

    // Edge Runtime
    .ConfigureEdgeRuntime(edge => edge
        .WithPort(9000));

Direct Container Access

Each sub-resource is a container, so the configure callback already exposes the full Aspire container builder — call WithEnvironment, WithVolume, WithBindMount, etc. directly on it:

.ConfigureDatabase(db => db
    .WithPassword("password")
    .WithEnvironment("CUSTOM_VAR", "value")
    .WithVolume("my-volume", "/data"))

You can also reach each container after the fact via the Get*() accessors.


Database: Internal or External Postgres

By default AddSupabase(...) creates and owns its own PostgreSQL container (the supabase/postgres image) as part of the stack, configured via ConfigureDatabase(...):

var supabase = builder.AddSupabase("supabase")
    .ConfigureDatabase(db => db.WithPassword("secure-password"));

Bring your own Postgres

Alternatively, pass an existing Postgres resource as externalDatabase. The stack then does not create a database — it points every service (Auth, REST, Storage, Realtime, Meta, Edge) at your resource and seeds the Supabase roles it needs into it:

var postgres = builder.AddPostgres("mypg")
    .WithImage("supabase/postgres", "15.8.1.085")
    .WithPassword(builder.AddParameter("pg-password", secret: true))
    .WithPgAdmin();

var supabase = builder.AddSupabase("supabase", externalDatabase: postgres);

The external database must use the supabase/postgres image — a vanilla postgres image lacks the roles, extensions and init scripts the stack relies on. In this mode you own the database: configure its image, password, data volume and deployment on your own resource.

Because the stack no longer owns the database, ConfigureDatabase(...) throws when an external database was supplied. Use ConfigureDatabaseIf(...) to keep a single code path that works both ways:

bool useExternalDb = false;

var postgres = useExternalDb
    ? builder.AddPostgres("mypg")
        .WithImage("supabase/postgres", "15.8.1.085")
        .WithPassword(builder.AddParameter("pg-password", secret: true))
    : null;

var supabase = builder.AddSupabase("supabase", externalDatabase: postgres)
    // only applied when there is an internal database to configure
    .ConfigureDatabaseIf(postgres is null, db => db.WithPassword("secure-password"));

Syncing from Remote Supabase Project

Synchronize schema, data, storage, and more from an existing Supabase cloud project:

Basic Sync

const string projectRef = "your-project-ref";
const string serviceKey = "eyJhbGciOiJIUzI1NiIs...";  // service_role key

var supabase = builder.AddSupabase("supabase")
    .WithProjectSync(projectRef, serviceKey);

Sync Options

Control what gets synchronized using SyncOptions:

var supabase = builder.AddSupabase("supabase")
    .WithProjectSync(
        projectRef,
        serviceKey,
        SyncOptions.Schema | SyncOptions.Data | SyncOptions.StorageBuckets);

Available options:

Option Description
Schema Table structures (columns, types, constraints)
Data Table data
Policies Row Level Security policies (requires DB password)
Functions Stored procedures and functions (requires DB password)
Triggers Database triggers (requires DB password)
Types Custom types and enums (requires DB password)
Views Database views (requires DB password)
Indexes Table indexes (requires DB password)
StorageBuckets Storage bucket definitions
StorageFiles Storage files (downloads from remote)
EdgeFunctions Edge Functions (requires Management API token)
AllSchema All schema-related options
AllStorage StorageBuckets + StorageFiles
All Everything

Full Sync with Database Password

For complete schema sync including policies, functions, and triggers:

const string dbPassword = "your-database-password";  // From Dashboard → Project Settings → Database

var supabase = builder.AddSupabase("supabase")
    .WithProjectSync(
        projectRef,
        serviceKey,
        SyncOptions.All,
        dbPassword);

Edge Functions Sync

To sync Edge Functions, you need a Management API token:

const string managementApiToken = "sbp_...";  // From Dashboard → Account → Access Tokens

var supabase = builder.AddSupabase("supabase")
    .WithProjectSync(
        projectRef,
        serviceKey,
        SyncOptions.All,
        dbPassword,
        managementApiToken);

Note: The Supabase Management API returns compiled ESZIP bundles, not source code. The sync creates placeholder files with instructions to manually copy the source code from the Dashboard or use supabase functions download.

Where to Find Keys

Key Location
Project Ref Dashboard URL: https://supabase.com/dashboard/project/{project-ref}
Service Role Key Dashboard → Project Settings → API → service_role (secret)
Database Password Dashboard → Project Settings → Database → Database password
Management API Token Dashboard → Account (top right) → Access Tokens

Local Migrations

Apply local SQL migration files to your Supabase instance:

var migrationsPath = Path.Combine(builder.AppHostDirectory, "..", "supabase", "migrations");

var supabase = builder.AddSupabase("supabase")
    .WithMigrations(migrationsPath);

Migration files should follow the naming convention: YYYYMMDDHHMMSS_description.sql

Each file is tracked in public._aspire_applied_migrations and applied at most once (like the Supabase CLI), so migrations are safe to leave in place across restarts and redeploys — they will not re-run against a persistent database.

Example structure:

supabase/
  migrations/
    20240101000000_create_users_table.sql
    20240102000000_add_profiles.sql
    20240103000000_create_policies.sql

Edge Functions

Using Local Edge Functions

Point to your local Edge Functions directory:

var edgeFunctionsPath = Path.Combine(builder.AppHostDirectory, "..", "supabase", "functions");

var supabase = builder.AddSupabase("supabase")
    .WithEdgeFunctions(edgeFunctionsPath);

Expected directory structure:

supabase/
  functions/
    my-function/
      index.ts
    another-function/
      index.ts

Edge Function Format

Each function should be in its own directory with an index.ts file:

// supabase/functions/hello-world/index.ts
import { serve } from "https://deno.land/std@0.177.0/http/server.ts";

serve(async (req) => {
  const { name } = await req.json();

  return new Response(
    JSON.stringify({ message: `Hello ${name}!` }),
    { headers: { "Content-Type": "application/json" } }
  );
});

Calling Edge Functions

Edge Functions are available through Kong at:

http://localhost:8000/functions/v1/{function-name}

Example:

curl -X POST http://localhost:8000/functions/v1/hello-world \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ANON_KEY" \
  -d '{"name": "World"}'

Registered Users

Pre-create users for development and testing:

var supabase = builder.AddSupabase("supabase")
    .WithRegisteredUser("admin@example.com", "password123", "Admin User")
    .WithRegisteredUser("test@example.com", "test1234", "Test User");

These users:

  • Are created with confirmed email status
  • Automatically get a profile in public.profiles (if table exists)
  • Automatically get an admin role in public.user_roles (if table exists)

Dashboard Commands

Add a "Clear All Data" button to the Aspire dashboard:

var supabase = builder.AddSupabase("supabase")
    .WithClearCommand();

This adds a command in the Aspire dashboard that truncates all tables in the public schema.


Accessing Resources

Get Sub-Resource Builders

Access individual container resources for advanced configuration:

var supabase = builder.AddSupabase("supabase");

var kong = supabase.GetKong();
var studio = supabase.GetStudio();
var database = supabase.GetDatabase();
var auth = supabase.GetAuth();
var rest = supabase.GetRest();
var storage = supabase.GetStorage();
var meta = supabase.GetMeta();
var edge = supabase.GetEdgeRuntime();

Access Keys and Endpoints

var supabase = builder.AddSupabase("supabase");

// Get the anon key for client-side use
var anonKey = supabase.Resource.AnonKey;

// Get the service role key for server-side use
var serviceRoleKey = supabase.Resource.ServiceRoleKey;

// Get the Kong endpoint (main API gateway)
var kongEndpoint = supabase.Resource.Kong!.GetEndpoint("http");

Environment Variables for Frontend

Configure your frontend application with Supabase environment variables:

var supabase = builder.AddSupabase("supabase");

var frontend = builder.AddNpmApp("frontend", "../frontend")
    .WithEnvironment("VITE_SUPABASE_URL", supabase.Resource.Kong!.GetEndpoint("http"))
    .WithEnvironment("VITE_SUPABASE_ANON_KEY", supabase.Resource.AnonKey);

Or for a JavaScript/TypeScript app:

var frontend = builder.AddJavaScriptApp("frontend", "../frontend", "dev")
    .WithEnvironment("VITE_SUPABASE_URL", supabase.Resource.Kong!.GetEndpoint("http"))
    .WithEnvironment("VITE_SUPABASE_PUBLISHABLE_KEY", supabase.Resource.AnonKey);

Deployment

The stack targets Azure Container Apps, deployed with azd:

azd init
azd up

Persistent Storage on Azure Container Apps

Container filesystems on Azure Container Apps are ephemeral — a restart or redeploy wipes the internal database and any uploaded files. To persist data across redeploys, wire NFS-backed storage in publish mode:

if (builder.ExecutionContext.IsPublishMode)
{
    var containerEnv = builder.AddAzureContainerAppEnvironment("acaenv");

    // Premium Azure Files NFS shares (one for storage, one for the Postgres data dir),
    // plus the VNet/subnet NFS requires. Omit postgresEnvStorageName to persist storage only.
    builder.AddSupabaseNfsStorage(containerEnv,
        nfsEnvStorageName: "supabasenfs",
        postgresEnvStorageName: "supabasepgnfs");

    // Run MinIO on the storage NFS share and point the Storage API at it as an S3 backend.
    // (Azure Files NFS has no extended attributes, so storage-api's FILE backend can't use it.)
    builder.AddMinioS3OnNfs(nfsEnvStorageName: "supabasenfs");

    // Mount the second NFS share at the internal Postgres data dir so the whole DB survives.
    SupabaseBuilderExtensions.PostgresDataVolumeName = "supabasepgnfs";
}

var supabase = builder.AddSupabase("supabase") /* ... */;
Call Effect
AddSupabaseNfsStorage(env, nfsEnvStorageName, postgresEnvStorageName?) Provisions a VNet + delegated subnet, a Premium Azure Files account with one or two NFS shares, and registers them as managedEnvironmentStorage on the ACA environment.
AddMinioS3OnNfs(nfsEnvStorageName) Adds a MinIO container backed by that NFS share and points the Storage API at it as an S3 backend.
SupabaseBuilderExtensions.PostgresDataVolumeName Env-storage name to mount at the internal Postgres data dir. The DB is pinned to a single replica. Leave unset to keep an ephemeral database.
SupabaseBuilderExtensions.PersistentStorageVolumeName Alternative to MinIO: mount an env-storage directly at storage-api's file directory. Leave unset when using AddMinioS3OnNfs.

PostgresDataVolumeName applies to the internal database only. With an external Postgres you persist its data on your own resource; AddSupabaseNfsStorage + AddMinioS3OnNfs still apply for storage.


Complete Example

Here's a complete example combining multiple features:

var builder = DistributedApplication.CreateBuilder(args);

// Paths
var supabasePath = Path.GetFullPath(Path.Combine(builder.AppHostDirectory, "..", "supabase"));
var migrationsPath = Path.Combine(supabasePath, "migrations");
var edgeFunctionsPath = Path.Combine(supabasePath, "functions");

// Supabase configuration
var supabase = builder.AddSupabase("supabase")
    // Database settings
    .ConfigureDatabase(db => db
        .WithPassword("secure-dev-password")
        .WithPort(54322))

    // Studio settings
    .ConfigureStudio(studio => studio
        .WithPort(54323)
        .WithProjectName("My Project"))

    // Apply local migrations
    .WithMigrations(migrationsPath)

    // Enable local Edge Functions
    .WithEdgeFunctions(edgeFunctionsPath)

    // Pre-create dev users
    .WithRegisteredUser("admin@example.com", "Admin123!", "Admin User")
    .WithRegisteredUser("user@example.com", "User123!", "Regular User")

    // Add clear data command to dashboard
    .WithClearCommand();

// Frontend
var frontend = builder.AddJavaScriptApp("frontend", "../..", "dev")
    .WithHttpEndpoint(port: 3000, targetPort: 3000)
    .WithEnvironment("VITE_SUPABASE_URL", supabase.Resource.Kong!.GetEndpoint("http"))
    .WithEnvironment("VITE_SUPABASE_ANON_KEY", supabase.Resource.AnonKey);

builder.Build().Run();

Default Ports

Service Default Port
PostgreSQL 54322
Kong (API Gateway) 8000
Studio Dashboard 54323
GoTrue (Auth) 9999 (internal)
PostgREST 3000 (internal)
Storage API 5000 (internal)
Postgres Meta 8080 (internal)
Edge Runtime 9000 (internal)

Troubleshooting

Edge Functions not working

  1. Check that the functions directory exists and contains subdirectories with index.ts files
  2. Verify the function follows the expected format with serve() from Deno std library
  3. Check the Edge Runtime container logs in the Aspire dashboard

Database connection issues

  1. Ensure no other PostgreSQL instance is running on port 54322
  2. Check the database container logs for startup errors
  3. Verify the password matches between configurations

Sync not working

  1. Verify the service key is the service_role key (starts with eyJ...), not the CLI key
  2. For full schema sync, ensure the database password is provided
  3. Check the console output for specific sync errors

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.1.14 36 7/16/2026
10.1.13 95 7/12/2026
10.1.12 86 7/12/2026
10.1.11 95 7/6/2026
10.1.10 113 6/16/2026
10.1.9 116 5/29/2026
10.1.8 107 5/19/2026
10.1.7 113 5/16/2026
10.1.6 125 5/12/2026
10.1.5 102 5/12/2026
10.1.4 107 5/11/2026
10.1.3 105 5/11/2026
10.1.2 131 4/9/2026
10.1.1 125 4/7/2026
10.1.0 105 4/7/2026
10.0.9 153 3/20/2026
10.0.8 130 2/28/2026
10.0.7 122 2/25/2026
10.0.6 3,939 1/22/2026
10.0.5 127 1/17/2026