Self-Host Your Supabase Next.js App
Run a full Supabase stack locally via Docker with zero cloud dependency.
Introduction
30 Second Summary
Every time your app talks to a cloud database, your users' data travels through someone else's servers. For teams handling sensitive information, that can be a dealbreaker.
In this project, you will set up a fully self-hosted Supabase instance on your Windows laptop using Docker. You will then connect your existing Next.js app to it, proving that your entire stack can run without any third-party database service.
What You'll Build
A complete self-hosted Supabase infrastructure running locally via Docker Compose, with your existing Next.js app connected to it instead of Supabase's cloud.
By the end of this project, you'll have:
- A running self-hosted Supabase stack with PostgreSQL, Auth, Storage, Realtime, API Gateway, and Studio dashboard.
- Your Next.js app reconfigured with environment variables to use the local Supabase instance instead of cloud.
- A working demo of auth, database, storage, and realtime features running entirely on your machine with zero cloud dependency.
- Secret Mission: Export your actual production data from Supabase cloud and restore it to your self-hosted instance.
Are there any prerequisites?
This project assumes you already have a Next.js + TypeScript app connected to Supabase cloud (using database, auth, storage, and realtime). You also need a Windows laptop with at least 8 GB of RAM, plus Node.js, VS Code, and Git already installed.
Before We Start
Your existing Next.js app works great on Supabase cloud. But your supervisor wants proof that all user data can stay on company-controlled infrastructure with zero third-party dependency.
To prove self-hosting is viable, you need Docker running on your Windows laptop. Docker lets you spin up the entire Supabase stack (database, auth, storage, realtime) locally with a single command.
In this step, get ready to:
- Install Docker Desktop with the WSL 2 backend.
- Verify Docker and Docker Compose are working.
- Allocate enough memory for the Supabase stack.
Install Docker Desktop
Docker Desktop is the tool that runs containers on Windows. It uses WSL 2 (Windows Subsystem for Linux) as its backend engine to run Linux-based containers efficiently.
- Open your browser and go to the Docker Desktop download page:
https://docs.docker.com/desktop/setup/install/windows-install/
- Click the download button to get Docker Desktop Installer.exe.
- Double-click the installer to run it.
- When the installer asks which installation mode you prefer, choose Per-user installation (recommended). This does not require administrator privileges.
- On the Configuration page, ensure the Use WSL 2 instead of Hyper-V option is selected.
What is WSL 2?
WSL 2 (Windows Subsystem for Linux) is a lightweight Linux environment built into Windows. Docker uses it to run Linux containers without needing a full virtual machine.
The per-user installation mode only supports WSL 2. If your system already has WSL 2 enabled, the option may be selected automatically.
Will the installer ask me to restart?
The installer may prompt for a reboot if it needs to enable WSL features on your system. If it does, restart your computer and reopen the installer to finish setup.
Start Docker Desktop and verify the installation
Once the installer finishes, you need to start Docker Desktop and confirm both docker and docker compose are accessible from your terminal.
- Press the Windows key to open your search bar.
- Type Docker Desktop and press Enter to open it.
- Wait for Docker Desktop to fully initialize. The whale icon in the system tray should stop animating.
- Open a terminal by pressing the Windows key, typing PowerShell, and pressing Enter.
- Check that Docker is installed by running this command:
docker --version
- Check that Docker Compose is available by running:
docker compose version
✔️ I see version numbers for both commands
Docker is ready to go. Both commands returning version numbers means Docker Desktop is running and your terminal can communicate with it.
ⓧ Command not found or error message
If either command fails, try these steps:
- Make sure Docker Desktop is fully started. Look for the whale icon in your system tray and wait until it stops animating.
- Close your PowerShell window and open a new one. The terminal needs to reload its PATH after Docker installs.
- If Docker Desktop shows an error about WSL, open PowerShell as Administrator and run:
wsl --install
- Restart your computer after that command completes, then open Docker Desktop again.
If you are still stuck, help me troubleshoot Docker Desktop not starting on Windows.
Allocate memory for Docker
The self-hosted Supabase stack runs multiple containers at once. You need to ensure Docker has at least 4 GB of memory available to handle all the services.
- In Docker Desktop, click the gear icon to open Settings.
- Select Resources in the left sidebar.
- Set the Memory slider to at least 4 GB. If your laptop has 16 GB RAM, set it to 6 GB for better performance.
- Click Apply & Restart.
Why 4 GB minimum?
Self-hosted Supabase runs PostgreSQL, Auth, Storage, Realtime, an API gateway, and the Studio dashboard simultaneously. Each service needs its own slice of memory. With less than 4 GB allocated, containers may crash or fail to start.
Don't see the Resources option?
If you are using the WSL 2 backend and the Resources page only shows a WSL Integration section, memory is managed by WSL itself. Open PowerShell and create a .wslconfig file in your user folder with memory settings. For most learners, the Resources page shows memory controls directly.
If you need help, help me configure Docker Desktop memory on Windows.
Your Docker environment is ready. Next up, you will clone the official Supabase Docker configuration and set up the environment variables for your local instance.
Install Docker Desktop
Self-hosting Supabase means running a full database stack on your own machine. Docker makes this possible by packaging each Supabase service (database, auth, storage, realtime) into isolated containers that run together.
In this step, you will install Docker Desktop on Windows so your laptop can run the entire Supabase infrastructure locally.
In this step, get ready to:
- Download and install Docker Desktop with the WSL 2 backend.
- Verify Docker is running correctly from the terminal.
- Allocate enough memory for the Supabase stack.
Download and install Docker Desktop
Docker Desktop is the application that lets you run containers on Windows. The per-user installation is recommended because it does not require administrator privileges.
- Open your browser and go to the Docker Desktop download page:
- https://docs.docker.com/desktop/setup/install/windows-install/
- Click the download button for Docker Desktop for Windows.
- Run the installer once the download finishes.
- Choose the Per-user installation option (recommended).
- On the Configuration page, ensure Use WSL 2 instead of Hyper-V is selected.
- Click Install and wait for the installation to complete.
What is WSL 2?
WSL 2 (Windows Subsystem for Linux 2) is a lightweight Linux environment built into Windows. Docker Desktop uses it to run Linux containers on your machine without needing a full virtual machine.
The per-user installation uses WSL 2 as its only backend. If your system has never had WSL 2 enabled before, the installer may prompt you to enable it. This is a one-time setup that may require a restart.
Installer asks for a restart?
If Windows needs to enable WSL 2 for the first time, a reboot is required. Save your work, restart, then run the Docker Desktop installer again. The second time it will complete without needing another restart.
help me troubleshoot the Docker Desktop installer on Windows
Start Docker Desktop and verify the installation
After installation, you need to start Docker Desktop and confirm both docker and docker compose are available from your terminal.
- Press the Windows key to open the Start menu.
- Type Docker Desktop and press Enter to launch it.
- Wait for Docker Desktop to fully initialize. The whale icon in the system tray should stop animating once it is ready.
How do I know Docker is ready?
Look for the whale icon in your system tray (bottom-right corner of the taskbar). While Docker is starting up, the icon animates. Once it becomes still, Docker is ready to accept commands.
- Open a terminal by pressing the Windows key, typing PowerShell, and pressing Enter.
- Verify Docker is installed by running this command:
docker --version
- Verify Docker Compose is available by running:
docker compose version
✔️ I see version numbers for both commands
Docker and Docker Compose are both installed and working. You are ready to move on to the memory configuration.
ⓧ Command not found or error message
This means Docker Desktop did not finish installing, or it has not started yet.
- Make sure Docker Desktop is running (check for the whale icon in the system tray).
- Close your PowerShell window and open a new one. Docker adds itself to the system PATH during installation, but existing terminal sessions may not pick it up.
- If you still see errors, restart your computer and launch Docker Desktop again from the Start menu.
help me fix Docker not being recognized in my terminal
Allocate enough memory for Supabase
Supabase runs multiple services simultaneously (database, auth, storage, realtime, and more). The default memory allocation may not be enough, so you need to increase it.
- In Docker Desktop, click the gear icon to open Settings.
- Select Resources from the left sidebar.
- Set Memory to at least 4 GB. If your laptop has 16 GB of RAM, set it to 6 GB for smoother performance.
- Click Apply & restart.
Why 4 GB minimum?
Supabase's official self-hosting documentation recommends 4 GB minimum RAM and 8 GB or more for comfortable operation. Since you are running the full stack (PostgreSQL, Auth, Storage, Realtime, Kong, Studio), giving Docker at least 4 GB ensures no service crashes from memory pressure.
Wait for Docker Desktop to restart. The whale icon will animate briefly and then become still again.
Don't see a Resources section?
If you are using the WSL 2 backend, Docker Desktop may manage memory dynamically through WSL instead of showing a dedicated slider. In that case, WSL 2 automatically allocates up to 50% of your system RAM (so 8 GB RAM gives Docker up to 4 GB). If your laptop has at least 8 GB of RAM, you are fine to proceed.
help me configure Docker Desktop memory settings on Windows with WSL 2
Docker Desktop is ready with enough memory to run the full Supabase stack. Next up, you will clone the official Supabase Docker configuration and set it up for local development.
Clone and Configure Self-Hosted Supabase
Docker is running and ready to pull container images. Now it's time to get the actual Supabase infrastructure onto your machine.
Supabase provides an official Docker Compose configuration that includes all their services pre-configured. In this step, you'll clone this configuration and prepare it for your local environment.
In this step, get ready to:
- Clone the official Supabase repository and set up the project directory.
- Configure environment variables for local development.
- Pull all required Docker images.
Clone the Supabase repository
Supabase publishes their entire self-hosting setup as a public Git repository. Cloning it gives you the Docker Compose file and a template for all the environment variables the services need.
- Move to your Desktop by running this command:
cd ~/Desktop
- Clone the Supabase repository, move into the Docker directory, and create your environment file by running these commands:
# Clone only the latest commit (faster download)
git clone --depth 1 https://github.com/supabase/supabase
# Move into the Docker configuration directory
cd supabase/docker
# Create your environment file from the template
copy .env.example .env
What do these commands do?
- git clone --depth 1 downloads the Supabase repository without its full history, saving time and disk space.
- cd supabase/docker moves into the folder containing the Docker Compose configuration for self-hosting.
- copy .env.example .env creates your own environment file from the provided template. This file holds all the configuration values for your Supabase services.
- Confirm the clone worked by running:
ls
You should see files like docker-compose.yml and .env listed in the output.
Seeing 'git' is not recognized?
Make sure Git is installed and added to your PATH. Close and reopen your terminal after installing Git so the PATH updates take effect.
If copy is not recognized, make sure you are using PowerShell or Windows Terminal (not Git Bash, which uses cp instead).
Help me troubleshoot cloning the Supabase repository on Windows.
Configure your environment variables
The .env file controls how each Supabase service connects to the others. You need to set three URL values so the services know they're running on your local machine.
- Open the .env file in VS Code by running:
code .env
What are these three URL variables?
- SUPABASE_PUBLIC_URL is the base URL passed to client libraries (your Next.js app will use this to reach the API gateway).
- API_EXTERNAL_URL is used by the Auth service to configure callback URLs.
- SITE_URL is the default redirect URL after login. It should match where your Next.js app runs.
- In VS Code, press Ctrl+H to open the Find and Replace panel.
- Find the line that starts with SUPABASE_PUBLIC_URL and make sure its value is set to:
SUPABASE_PUBLIC_URL=http://localhost:8000
- Find the line that starts with API_EXTERNAL_URL and make sure its value is set to:
API_EXTERNAL_URL=http://localhost:8000
- Find the line that starts with SITE_URL and make sure its value is set to:
SITE_URL=http://localhost:3000
- Save the file by pressing Ctrl+S.
Leave the other values as defaults
The .env.example template includes pre-generated keys and passwords that work out of the box for local development. Do not change them for this proof-of-concept. For a production deployment, you would regenerate all secrets.
VS Code not opening from the terminal?
On Windows, the VS Code installer adds code to your PATH automatically. If the command is not recognized, close and reopen your terminal so the updated PATH takes effect.
If it still doesn't work, open VS Code manually (press the Windows key, type VS Code, press Enter), then use File > Open File to navigate to Desktop\supabase\docker\.env.
Help me open a file in VS Code from my Windows terminal.
Pull the Docker images
With the configuration in place, you need to download all the Docker images that make up the Supabase stack. This is a one-time download of approximately 5-8 GB.
- Switch back to your terminal. Make sure you are still in the supabase/docker directory.
- Pull all the required images by running:
docker compose pull
This may take a few minutes
Docker is downloading images for PostgreSQL, Auth, Storage, Realtime, the API gateway (Kong), Studio, and several supporting services. The total download is approximately 5-8 GB depending on your platform.
You'll see progress bars for each image. Let it finish completely before moving on.
Once the command finishes, you should see each image listed without any error messages.
Pull failing or timing out?
Make sure Docker Desktop is running. Check for the whale icon in your system tray. If it's not there, start Docker Desktop from the Windows Start menu and wait for it to fully initialize.
If you see network timeout errors, check your internet connection and try running docker compose pull again. Docker will resume from where it left off.
Help me fix Docker image pull failures on Windows.
All the Supabase images are now cached locally on your machine. Next up, you'll start the entire stack and see Supabase Studio running on your own hardware.
Start the Supabase Stack
With all the Docker images downloaded and your .env configured, it is time to bring the entire Supabase stack to life.
A single command spins up every service your app depends on: the database, authentication, file storage, realtime messaging, the API gateway, and a visual dashboard called Studio. Once everything is running, you will confirm it all works by logging into Studio and querying the database directly.
In this step, get ready to:
- Start all Supabase containers in detached mode.
- Access the Supabase Studio dashboard in your browser.
- Run a test SQL query to confirm the database is operational.
Start all Supabase services
Docker Compose reads the docker-compose.yml file and launches every service defined in it as a separate container. Running in detached mode means the containers run in the background and your terminal stays free.
- In your terminal (still in the supabase/docker directory from the previous step), start all services by running this command:
docker compose up -d
What does this command do?
The up subcommand creates and starts containers for every service defined in the Compose file.
The -d flag stands for "detached." Without it, all container logs would flood your terminal and you would need a new terminal window for anything else.
The containers take 1-2 minutes to fully initialize and pass their internal health checks.
- Wait about 1-2 minutes, then check the status of your containers by running:
docker compose ps
You should see services like supabase-db, supabase-auth, supabase-storage, supabase-realtime, supabase-kong, and supabase-studio all showing as "running" or "healthy" in the output.
Some containers show "unhealthy" or keep restarting?
If you ran the command too quickly after startup, some services may still be initializing. Wait another minute and run docker compose ps again.
If a specific container remains unhealthy, check its logs with docker compose logs <service-name> (for example, docker compose logs supabase-db). The output usually reveals the issue, such as a port conflict or insufficient memory.
Make sure Docker Desktop has at least 4 GB of memory allocated (you configured this in Step 1).
help me troubleshoot why my Supabase Docker containers are unhealthy
Access the Supabase Studio dashboard
Supabase Studio is a web-based dashboard for managing your self-hosted instance. It is served through the API gateway (Kong) on port 8000.
- Open your browser and navigate to http://localhost:8000.
- You will be prompted for a username and password. This is HTTP basic authentication.
- Open your .env file in the supabase/docker directory and find the line starting with DASHBOARD_PASSWORD=.
- Enter the username (the value from DASHBOARD_USERNAME in your .env, which defaults to supabase) and the password (the DASHBOARD_PASSWORD value).
After logging in, you should see the Supabase Studio dashboard with navigation on the left side.
Why is Studio protected with a password?
Studio gives full access to your database, authentication settings, and storage. The HTTP basic auth layer prevents anyone on your network from accessing it without credentials.
Can't reach localhost:8000?
Confirm that supabase-kong is running by checking docker compose ps. Kong is the API gateway that serves Studio on port 8000.
If another application is using port 8000, Kong will fail to start. Close the conflicting application or change the port mapping in docker-compose.yml.
help me fix why I cannot reach Supabase Studio at localhost:8000
Verify the database with a test query
The final confirmation is running an actual SQL query against the PostgreSQL database through Studio. This proves the database is running and the API gateway is routing requests correctly.
- In Studio, click **SQL Editor** in the left navigation sidebar.
- In the query editor area, type the following query:
SELECT version();
- Click **Run** (or press **Ctrl+Enter**) to execute the query.
You should see a result row containing a PostgreSQL version string (for example, something starting with "PostgreSQL 15"). This confirms the database is operational and accessible through the full stack.
What does SELECT version() prove?
This query travels from your browser, through the API gateway (Kong), into the database container, and back. A successful result means every layer of the self-hosted stack is communicating correctly.
Query returns an error?
If you see a connection error, the database container may still be initializing. Check docker compose ps and confirm supabase-db shows "healthy" before retrying.
help me debug why my SQL query fails in self-hosted Supabase Studio
Your entire Supabase infrastructure is now running locally. Next up, you will point your existing Next.js app at this self-hosted instance instead of Supabase cloud.
Connect Your Next.js App
Your self-hosted Supabase stack is fully operational. Every service your app depends on (auth, database, storage, realtime) is running on your machine.
Now it's time for the real test. You'll point your existing Next.js app at this local instance instead of Supabase cloud. The switch is surprisingly simple because only the environment variables change, not your application code.
In this step, get ready to:
- Find the API keys generated by your self-hosted Supabase instance.
- Update your Next.js app's environment variables to point at localhost.
- Start your app and confirm it connects to the local instance.
Find your self-hosted API keys
Your self-hosted Supabase instance generated its own set of API keys during setup. These keys live in the same .env file you configured earlier in the supabase/docker directory.
- Switch back to VS Code and open the .env file inside your supabase/docker folder.
- Search for the line that starts with ANON_KEY. Its value is a long JWT string starting with eyJ....
- Select and copy the entire ANON_KEY value. You'll paste this into your Next.js app in the next substep.
What is the ANON_KEY?
The ANON_KEY is the public API key for your Supabase instance. It's the equivalent of the anon/publishable key you got from Supabase cloud when you first set up your app.
Your Next.js app uses this key to authenticate client-side requests to the Supabase API gateway. Since it's a public key (safe to expose in the browser), it only grants access that your Row Level Security policies allow.
Also note the SERVICE_ROLE_KEY
If your app uses server-side operations (API routes or server components that bypass Row Level Security), also copy the SERVICE_ROLE_KEY value. You'll need it for any server-side Supabase client in your app.
Update your Next.js environment variables
Your Next.js app currently points at Supabase cloud through environment variables in .env.local. Swapping these values is all it takes to redirect every request to your local instance.
- In VS Code, open the .env.local file in your Next.js project's root folder.
- Find the line that sets NEXT_PUBLIC_SUPABASE_URL. It currently points to your Supabase cloud project URL (something like https://abc123.supabase.co).
- Find the line that sets your Supabase key. This is either NEXT_PUBLIC_SUPABASE_ANON_KEY or NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY depending on when you set up your app.
- Replace both values so your file looks like this:
NEXT_PUBLIC_SUPABASE_URL=http://localhost:8000
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-from-supabase-docker-env
What does this change do?
NEXT_PUBLIC_SUPABASE_URL tells your app where to send API requests. Changing it from the cloud URL to http://localhost:8000 redirects all traffic to your local Kong API gateway.
NEXT_PUBLIC_SUPABASE_ANON_KEY authenticates those requests. Your local instance has its own keys, so you need the ANON_KEY value from supabase/docker/.env instead of your cloud key.
- Paste the ANON_KEY value you copied earlier in place of your-anon-key-from-supabase-docker-env.
- Keep the variable name exactly as it already exists in your file. Only the value changes.
- Save .env.local.
What if my variable is named differently?
If your app uses NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY instead of NEXT_PUBLIC_SUPABASE_ANON_KEY, keep that same variable name. Paste the ANON_KEY value from your Docker .env as the value. Your app code references the variable name, so changing it would break things.
Not sure which variable name to use?
Open your .env.local and look at what's already there. The variable name that currently holds your Supabase cloud key is the one to keep. Only replace the value after the = sign.
help me figure out which Supabase env variable name my Next.js app uses
Start your app and verify the connection
With your environment variables updated, your Next.js app is ready to talk to the local Supabase instance. Time to start it up and confirm the connection works.
- Open a new terminal in your Next.js project directory.
- Start your development server by running:
npm run dev
- Open your app in the browser (typically http://localhost:3000).
- Open your browser's developer tools by pressing Ctrl+Shift+I (Windows) or Cmd+Option+I (macOS).
- Click the Network tab.
- Refresh the page and watch the network requests appear.
You should see requests going to localhost:8000 instead of your previous Supabase cloud URL. This confirms your app is now communicating with your self-hosted instance.
Why is the database empty?
Your app connects successfully, but you won't see any existing data. This is a fresh Supabase instance with empty tables. Your cloud data still lives on Supabase's servers.
In the next step, you'll verify each feature works by creating new test data locally. If you want to bring your production data over, the Secret Mission covers that.
App showing connection errors?
Make sure your Docker containers are still running. Switch to your terminal in the supabase/docker directory and run docker compose ps to check.
Verify that NEXT_PUBLIC_SUPABASE_URL is set to http://localhost:8000 (not https). The local instance uses HTTP, not HTTPS.
Double check that you pasted the full ANON_KEY value with no extra spaces or missing characters. The key is a long string that starts with eyJ.
help me debug my Next.js app not connecting to self-hosted Supabase
Your app is now fully wired to your self-hosted Supabase. Next up, you'll verify that each feature (auth, database, storage, and realtime) actually works end-to-end on your local machine.
Verify All Features Work
Your Next.js app is connected to the self-hosted Supabase stack. The final step is proving that all four core features (auth, database, storage, realtime) actually work against your local instance.
In this step, you'll exercise each feature through your app and verify the results in Studio. Every user, record, file, and event stays on your machine with zero data leaving your network.
In this step, get ready to:
- Test user authentication by signing up through your app.
- Verify database writes appear in Studio.
- Confirm storage uploads and realtime updates work locally.
Test authentication with a new user
Self-hosted Supabase has email verification disabled by default. This means you can sign up and immediately use the account without needing an SMTP server or confirmation email.
- Switch to the browser tab running your Next.js app.
- Navigate to your app's signup or login page.
- Create a new test user with any email and password (e.g. test@example.com).
- Complete the signup flow. You should be signed in immediately.
- Open a new browser tab and go to http://localhost:8000 to return to Studio.
- Click Authentication in the left sidebar.
- You should see the user you just created listed in the users table.
Why does this prove data sovereignty?
This user exists ONLY on your machine. No signup request left your network. The auth service, the database storing the user record, and the JWT token minting all happened inside your local Docker containers.
Signup not working?
Make sure your Next.js app's NEXT_PUBLIC_SUPABASE_URL is set to http://localhost:8000 in .env.local. If you changed the value after starting the dev server, restart it with npm run dev for the new value to take effect.
help me debug why my signup isn't working against self-hosted Supabase
Test database writes
Auth is working. Now confirm that your app can write to and read from the local PostgreSQL database through the Supabase API gateway.
- Switch to the browser tab running your Next.js app.
- Perform any action that writes to the database (create a record, update a profile, post a message, etc.).
- Return to Studio at http://localhost:8000.
- Click Table Editor in the left sidebar.
- Verify that the data you just created appears in the relevant table.
For additional confirmation, run a query directly against the database. This verifies the API gateway, auth tokens, and PostgreSQL are all working together.
- In Studio, click SQL Editor in the left sidebar.
- Run this query to list all users in the auth schema:
SELECT * FROM auth.users;
What does this query show?
The auth.users table is managed by Supabase Auth. It stores every user who has signed up. Seeing your test user here confirms that both the auth service and the database are fully operational on your local machine.
- You should see at least one row returned showing the test user you created earlier, including their email and creation timestamp.
Query returns no results?
If the query runs but returns zero rows, your signup may not have completed successfully. Check the Network tab in your browser's dev tools for failed requests to localhost:8000. A 400 or 500 response will show the exact error.
help me figure out why auth.users is empty in my self-hosted Supabase
Test storage and realtime
The last two features to verify are file storage and realtime subscriptions. Storage confirms that uploaded files stay on your local filesystem. Realtime confirms that database changes push live updates to connected clients.
- In your Next.js app, perform an action that uploads a file (a profile photo, document, or any file your app handles).
- Return to Studio at http://localhost:8000.
- Click Storage in the left sidebar.
- Verify the uploaded file appears in the appropriate bucket.
What if my app doesn't have file uploads?
If your app doesn't use Storage, you can skip this sub-test. The auth and database verification already proves your self-hosted instance is operational. Storage can be tested later when you add upload functionality.
Now test realtime to confirm that live updates propagate between clients without leaving your machine.
- Open your Next.js app in two separate browser tabs (or two different browsers).
- In one tab, perform an action that should trigger a realtime update (e.g. create a new item, send a message, update a record).
- Check the second tab. You should see the update appear without manually refreshing the page.
What if my app doesn't use realtime?
If your app doesn't subscribe to realtime channels, you can skip this sub-test. The auth and database tests are sufficient to prove your self-hosted stack is functional. You can add realtime subscriptions later.
Realtime updates not appearing?
Realtime requires an active WebSocket connection to localhost:8000. Check the browser console in the second tab for WebSocket connection errors. Make sure the supabase-realtime container is healthy by running docker compose ps in your terminal.
help me debug realtime not working on self-hosted Supabase
Secret mission
Migrate Your Production Data
Your self-hosted Supabase is running with test data. But what about your real users, real records, and real files? In this secret mission, you'll export your actual production data from Supabase cloud and restore it to your self-hosted instance, creating a complete local mirror of your live app.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally via Docker, so there are no ongoing cloud costs. However, the running containers consume approximately 4 GB of RAM and the Docker images take up 5-8 GB of disk space.
Resources you used:
- Docker containers (approximately 4 GB RAM while running).
- Docker images (approximately 5-8 GB disk space).
- Database data stored in Docker volumes.
- Cloned supabase repository.
- Supabase CLI (global npm package).
- Dump files: roles.sql, schema.sql, data.sql.
Keep everything running
No action needed. Choose this if you're still actively building or demonstrating your self-hosted setup to your supervisor. Docker Desktop stays running and your Next.js app continues to work against the local Supabase instance.
- Your self-hosted Supabase stack stays up and accessible at http://localhost:8000.
- RAM usage continues at approximately 4 GB while containers are running.
- Your Next.js app works against the local instance whenever you run npm run dev.
Pause - I'll come back to this later
Stop the running containers to free up RAM. Your data is preserved in Docker volumes, so you can restart anytime without losing anything.
- Open a terminal and navigate to the supabase/docker directory.
- Stop all containers by running:
docker compose stop
- This frees your RAM immediately. All database data, auth records, and storage files remain saved in Docker volumes.
- When you want to resume, navigate back to supabase/docker and run:
docker compose start
- Your self-hosted Supabase comes back up with all your data intact.
Delete - I don't want to use this again
Remove all project resources and reclaim your disk space. This destroys your local database and all migrated production data.
- Open a terminal and navigate to the supabase/docker directory.
- Remove all containers and data volumes by running:
docker compose down -v
- This removes all containers AND their data volumes. Your local database is gone.
- Remove the Docker images to reclaim 5-8 GB of disk space by running:
docker system prune -a
- Confirm the prompt when asked. This removes all unused images.
- Uninstall the Supabase CLI by running:
npm uninstall -g supabase
- Delete the cloned repository and dump files. Navigate to the parent folder containing the supabase folder, then run:
rmdir /s /q supabase
del roles.sql schema.sql data.sql
- Finally, revert your Next.js app's .env.local file. Replace the local Supabase values with your original Supabase cloud values for NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY.
That's a Wrap!
That's a Wrap!
Nice work! You've just proved that your entire app stack can run on your own hardware with zero third-party dependency.
Your supervisor now has a working demo showing that all user data stays on company-controlled infrastructure.
You've learned how to:
- Deploy a complete self-hosted Supabase stack (PostgreSQL, Auth, Storage, Realtime, API Gateway, Studio) using Docker Compose on Windows.
- Connect an existing Next.js app to a self-hosted Supabase instance with a simple environment variable swap.
- Verify all four features (auth, database, storage, realtime) work entirely on your local machine with zero cloud dependency.
- Secret Mission: Migrated your actual production data from Supabase cloud to the self-hosted instance using the Supabase CLI.
Ready to quiz yourself?