
Supabase is an open-source Backend-as-a-Service (BaaS) platform built on PostgreSQL. It offers database management, authentication, real-time subscriptions, file storage, edge functions, and a robust API layer, letting you focus on application logic instead of backend infrastructure. Its modular architecture scales easily from small prototypes to enterprise-grade applications.
When paired with the Vultr Marketplace Application, you can deploy a self-hosted, production-ready Supabase instance in minutes on a server you manage. This guide walks you through setting up the Supabase backend on a Vultr server, configuring the database and access rules, connecting a frontend application, and setting up a custom domain with SSL certificates. A simple Next.js notes app is used as an example to demonstrate the process. However, the instructions can be applied to most web projects with minimal modification.
Deploying Supabase on Vultr is quick and seamless. You can provision a new Vultr Compute instance from the Vultr Console by selecting your preferred server type, region, and plan, then switching to Marketplace Apps and choosing Supabase as the image. During setup, configure essential parameters such as SSH access, the hostname, and enable Limited User Login with sudo privileges under Additional Features for improved security. Once the instance is live, you can connect via SSH to perform environment configuration. For a complete, step-by-step deployment walkthrough, see How to Use Vultr’s Supabase Marketplace Application.
When provisioning the instance programmatically:
image_id to supabase to use the Supabase Marketplace Application.--image "supabase" with vultr-cli instance create command.After deploying the Supabase Marketplace Application, the next step is to configure the environment with secure API keys. Supabase uses an ANON_KEY for client-side operations and a SERVICE_ROLE_KEY for server-side tasks that require elevated privileges. While default keys are generated during deployment, it is recommended to regenerate them using the JWT secret provided in the instance’s App Instructions. This ensures secure communication between your frontend and the Supabase instance by replacing the weak default keys.
To regenerate the keys, follow the steps outlined in the Update Supabase API Keys section of the How to Use Vultr’s Supabase Marketplace Application guide. After generating the new keys, update the .env file in your Supabase Docker directory with the new values, and restart the containers to apply the changes.
By default, the application is accessible directly via your instance's IP address. However, configuring a custom domain and setting up Nginx as a reverse proxy enables you to access both your application and Supabase services through a unified domain, ensuring proper CORS handling and providing a professional deployment foundation. While this guide uses a Next.js notes application as an example, a similar configuration can be applied to any web application.
The following steps establish the minimal DNS configuration required for your domain to work with your Vultr Cloud Compute instance.
Purchase or use an existing domain name from any domain registrar (e.g., Namecheap, GoDaddy, or Cloudflare).
In your domain registrar’s DNS management console or by using Vultr DNS, create A records that point to the public IP address of your Vultr instance.
Root domain (@):
Subdomain (www):
This ensures both yourdomain.com and www.yourdomain.com point to your instance.
Save the DNS configuration and allow 5-60 minutes for global DNS propagation.
Verify DNS propagation by testing domain resolution.
The above command should return your Vultr instance's IP address, confirming successful DNS configuration.
Update the package index to ensure access to the latest software versions.
Install Nginx.
Start Nginx immediately so it can serve requests.
Enable Nginx to start automatically after system reboots.
Verify that Nginx is active and running.
The output should show active (running) status, indicating successful installation.
Create an Nginx configuration file for your domain. Replace yourdomain.com with your actual domain name:
Add the following server configuration. Replace yourdomain.com and ports to match your setup.
This configuration defines two proxy rules:
If your application listens on a different port, update the proxy_pass directive accordingly. To expose additional Supabase services such as Auth or Realtime, add separate proxy blocks pointing to their respective ports. Save the file and exit the editor when finished.
Enable the site by creating a symbolic link.
Test the Nginx configuration for syntax errors.
If the configuration is valid, you should see a message confirming the syntax is ok and the test is successful.
Reload Nginx to apply the new configuration.
Verify domain and proxy configuration by testing connectivity.
An HTTP response from Nginx confirms that the domain and proxy configuration are working. A 502 Bad Gateway error is expected at this stage because the frontend application is not running and is not listening on the configured port. When the application runs, Nginx forwards requests successfully, and the error disappears.
This section is dedicated to project setup and configuration. It covers preparing the backend database, defining tables and access policies, and connecting the frontend application to Supabase. The Notes App serves as an example to demonstrate how to structure tables, implement row-level security, configure environment variables, and connect a frontend to the backend. For your own project, follow the same steps while customizing tables, policies, and frontend configuration to match your application’s requirements.
Before your frontend application can interact with Supabase, the database must be properly configured. Supabase uses PostgreSQL as its core database engine and provides features such as authentication, row-level security (RLS), and API keys to control access. Understanding these essentials ensures your application can securely read, write, and manage data:
Tables and Columns: The frontend interacts with tables in the database. Each project defines its own schema (tables, columns, and data types) depending on the functionality required. At minimum, define a table structure that matches your app’s data model.
Row-Level Security (RLS): Supabase enforces RLS by default to ensure production safety. RLS defines which users can access or modify specific rows. Enabling and configuring RLS protects sensitive data while allowing authorized operations.
API Keys and Roles:
ANON_KEY: A public key for client-side operations such as fetching data or inserting new records with restricted privileges.SERVICE_ROLE_KEY: A secret key for server-side operations requiring elevated privileges, such as admin tasks.The combination of RLS and properly configured API keys ensures your frontend can securely access the database.
Extensions: PostgreSQL supports optional packages called extensions that add extra functionality to your database. Extensions can provide new data types, functions, operators, or utilities that simplify common tasks. Supabase is pre-configured with over 50 extensions, including common PostgreSQL extensions such as UUID generation (uuid-ossp) and cryptographic functions (pgcrypto). To see the full list of supported extensions, visit the Supabase Postgres Extensions Documentation.
Follow this method to use the Docker command-line interface to access the running Supabase PostgreSQL container and execute SQL commands directly inside the container for custom database configurations.
To run Docker commands without sudo, add your user to the docker group.
Apply the group changes to your current session so they take effect immediately.
List running containers to identify the Supabase database container.
Look for the container name or image associated with Supabase’s database, typically something like supabase-db.
Open an interactive shell inside the PostgreSQL container. Replace supabase-db with the actual container name if different.
Connect to PostgreSQL using the default postgres user
PostgreSQL automatically connects you to the default database named postgres.
Create a table that matches your application's data model.
Supabase enforces RLS by default in production. Enable RLS on a table before defining policies.
Policies control which roles can read or modify specific rows in a table. Define them according to the access requirements of your application to ensure secure and appropriate data access.
Exit the PostgreSQL shell.
Exit the container shell.
Next, deploy the frontend application and connect it to the Supabase backend. The example used here is a full-stack notes application built with Next.js and Supabase. The app lets you create, read, update, and delete notes while handling authentication and real-time updates via Supabase.
Clone the application repository. Replace the repository URL with your own GitHub repository.
Navigate into the project directory.
Examine the project structure:
Key files and directories include:
src/ - Contains the application source code and components, including the lib/ directory where the Supabase client is initialized.package.json - Defines project dependencies and build scripts.Dockerfile - Specifies container configuration for deployment.docker-compose.yml - Defines service orchestration and container setup..env.example - Provides a template for required environment variables.Create your environment configuration file.
Update the .env file with Supabase credentials and domain:
Configure the required variables.
NEXT_PUBLIC_SUPABASE_URL: This URL points to your domain with the /supabase/ path, which Nginx proxies to port 8000. The NEXT_PUBLIC_ prefix makes this variable available in the browser for client-side API calls.
[!Note] For now, use
httpin theNEXT_PUBLIC_SUPABASE_URL.
NEXT_PUBLIC_SUPABASE_ANON_KEY: The anonymous key you generated earlier, used for public API operations with Row-Level Security policies applied.
The SUPABASE_SERVICE_ROLE_KEY generated earlier, bypasses Row-Level Security and should only be used in server-side code for administrative operations. Never expose this key in client-side code or commit it to public repositories.
The Vultr Supabase Marketplace instance comes pre-installed with Node.js, npm, and Docker, giving you flexible deployment options. You can run the application directly with Node.js/npm or use Docker for consistent containerized deployment.
Running the application directly via Node.js is ideal for development, testing, or lightweight production deployments where Docker is not required.
Install Node.js packages defined in package.json.
Compile the Next.js application into an optimized production build.
Launch the application on the configured port (default is 3000).
Running npm start directly occupies your terminal session. The process stops if the SSH connection is closed. To prevent this, run the process in the background using nohup npm start &.
Using Docker is recommended when you want a self-contained, portable deployment that works consistently across environments. Docker isolates the application, its dependencies, and its runtime, which simplifies scaling, updates, and migration.
Review the Docker configuration
The Dockerfile defines how to build your application container, including dependency installation, application building, and runtime configuration.
Examine the Docker Compose configuration:
This file orchestrates the container deployment, including port mapping, environment variable injection, and networking configuration.
Build and deploy the application.
This builds a Docker image containing your application, creates and starts a container in detached mode (background), maps port 3000 from the container to the host, injects environment variables from the .env file, and configures restart policies for reliability.
Verify the deployment.
The output should show your application container running with status "Up" and port mapping 0.0.0.0:3000->3000/tcp.
Inspect the container logs to view startup messages and confirm that the application is running correctly. Replace <service-name> with the name of the service defined in your docker-compose.yml file (e.g., notes-app).
After deploying the frontend application and configuring Nginx to proxy requests to your instance, the application becomes accessible through the configured domain. Open a web browser and navigate to,
At this stage, SSL/TLS is not yet configured. Your browser may display a warning such as “Connection is not secure” or “Continue to site (unsafe)”. This is expected for testing purposes. You can safely proceed to the site, but enabling HTTPS is recommended for production.
Once the page loads, you should see the Notes App interface. This interface allows you to create, view, edit, and delete notes. All interactions are backed by Supabase, with data stored in your PostgreSQL database and row-level security (RLS) enforced.
To verify the application's functionality:
Enter a Title and Content for a new note, then click Add Note.
The newly added notes appear in the list and are stored in the database. From here, you can Edit or Delete any existing note. Editing updates the database in real time, and deletion removes the corresponding row.
Open your PostgreSQL database and check the notes table. Any changes made through the frontend (adding, editing, or deleting notes) should be reflected in the table immediately. This confirms that the frontend is correctly connected to Supabase and RLS policies are applied as expected.
Open the application in multiple tabs or devices. Adding or editing notes in one tab should update the view in other tabs instantly, demonstrating Supabase’s real-time subscription functionality.
HTTPS encrypts data transmission between users and your server, protects against man-in-the-middle attacks, and is required by modern browsers for many features like geolocation and camera access. Plus, search engines favor HTTPS sites, and users expect the security assurance provided by the padlock icon in their browser.
This section uses Let's Encrypt, a free, automated certificate authority that provides SSL/TLS certificates trusted by all major browsers. The process is automated using Certbot, which integrates directly with Nginx to obtain and configure certificates.
Install Certbot with required system dependencies.
ca-certificates: Contains trusted certificate authorities needed to verify Let's Encrypt's SSL certificates.curl: Used by Certbot to communicate with Let's Encrypt servers.gnupg: Provides cryptographic functions for certificate validation.lsb-release: System information utilities used by Certbot.certbot: The core certificate management tool.python3-certbot-nginx: Plugin that automatically configures Nginx for SSL.Generate SSL certificates for your domain. Replace yourdomain.com with your actual domain and admin@example.com with your email address.
Verify the certificate installation.
Let's Encrypt certificates expire after 90 days. To simulate and test certificate renewal, run:
A successful dry run confirms that automatic renewal works when certificates approach expiration.
Now that HTTPS is enabled, update your application’s environment variables to use the https protocol.
If you are not already in your application directory, navigate to it first:
Open the environment configuration file for editing.
Change the NEXT_PUBLIC_SUPABASE_URL to use HTTPS.
Restart the application to apply changes.
If you deployed the application directly using npm without containerization, you need to restart the Node.js process.
Identify the running Next.js process.
Stop the current process.
Rebuild the application to apply the updated .env values.
Restart the application.
If you deployed using Docker Compose, the application needs to be restarted to pick up the updated environment variables from the .env file.
Stop the running container.
Rebuild the image with updated configuration and start the container.
Access the application again by visiting,
Your browser should now display a padlock icon, confirming that the connection is secure and the SSL certificate is active. All data transmitted between users and your server is encrypted. The application continues to function as before, now with production-grade security.
You have successfully deployed a Next.js application with Vultr’s Supabase Marketplace Application, configured PostgreSQL with row-level security, and secured the deployment with Nginx and SSL certificates. Your Supabase instance now delivers a complete backend with database, authentication, and API services accessible through your custom domain. By using the Vultr Supabase Marketplace, you reduce setup effort and can focus on building application features with Supabase’s full capabilities.
0 Comments
Be the first to comment and share your perspective with the community.