Back to guides
🔥 Most Popular⏱ ~2 hours📶 No server experience needed

Move from Supabase to
DigitalOcean

This guide takes you from one click to the next. Every step tells you exactly what to do. Claude Code handles all the code — you just copy and paste prompts into it.

By the end of this guide you will have:

Your own PostgreSQL running on your server
Your own login / signup system
3,000 free emails per month via Resend
Auto-deploy on every git push
$6/mo — 76% cheaper than Supabase Pro
Nobody can pause or delete your project
Create DigitalOcean Account (free $200 credit)

Don't cancel Supabase yet

Keep your Supabase project alive until everything works on the new server. Both can run at the same time — you close Supabase only after you're fully migrated.

00

Get Claude Code running

Claude Code is Claude inside your terminal. It reads your code, writes changes, and runs commands. You just tell it what to do in plain English.

  1. 1Open Terminal (Mac: press Cmd+Space → type "Terminal" → press Enter)
  2. 2Type this and press Enter: npm install -g @anthropic-ai/claude-code
  3. 3Wait for it to finish, then type: claude
  4. 4It will ask for an API key — go to claude.ai/settings/keys → Create Key → copy it → paste it into the terminal
  5. 5Claude Code is now open. Keep this window open for the whole guide.
💡

Using VS Code? You can install the "Claude Code" extension instead — same thing, works right inside your editor.

01

Collect your Supabase credentials

Before touching anything, grab your passwords and connection strings from Supabase. Open a Notepad or TextEdit — you'll paste things there as you go.

  1. 1Open a new browser tab → go to app.supabase.com
  2. 2Click on your project
  3. 3Look at the left sidebar — click the gear icon at the bottom (Settings)
  4. 4In the Settings menu, click "API"
  5. 5You'll see a page with keys. Copy these one by one into your Notepad:
  6. 6→ "Project URL" — starts with https:// (example: https://abcdef.supabase.co) — label it SUPABASE_URL=
  7. 7→ "anon public" key — a long string starting with eyJ — label it SUPABASE_ANON_KEY=
  8. 8→ "service_role" key — another long string starting with eyJ — label it SUPABASE_SERVICE_ROLE_KEY=
  9. 9Now click "Database" in the left sidebar
  10. 10Scroll down to "Connection string" → click the "URI" tab
  11. 11Copy the whole string (starts with postgresql://postgres:...) — label it DATABASE_URL=
💡

Your Notepad should now have 4 lines: SUPABASE_URL=, SUPABASE_ANON_KEY=, SUPABASE_SERVICE_ROLE_KEY=, DATABASE_URL=

Never share your service_role key or commit it to GitHub. It gives full access to your database.

02

Create your DigitalOcean account and server

DigitalOcean gives you $200 free credit. You need a card but won't be charged for the first 60 days.

  1. 1Go to m.do.co/c/0ba2a121fd3a (use this link to get the $200 credit)
  2. 2Click "Sign Up" → enter email and password → verify your email
  3. 3Enter your card details (you won't be charged — $200 free credit covers everything)
  4. 4In the left sidebar, click "Droplets" → click the green "Create Droplet" button
  5. 5"Choose Region" → pick the city closest to your users
  6. 6"Choose an image" → click Ubuntu → select 22.04 LTS x64
  7. 7"Choose Size" → Basic → Regular → pick the $6/mo option (1 GB RAM, leftmost)
  8. 8"Authentication Method" → select "Password" → type a strong password → write it in your Notepad as DO_PASSWORD=
  9. 9Scroll down → click "Create Droplet"
  10. 10Wait about 60 seconds → your droplet appears with an IP address (like 64.225.12.5) → copy it to your Notepad as DO_IP=
💡

Your Notepad now has: DO_IP= and DO_PASSWORD= added to the previous lines. Keep this Notepad open.

03

Let Claude Code set up the server

Go back to your terminal. You'll give Claude Code your server IP and password, and it will install everything needed.

  1. 1Go back to your terminal where Claude Code is running
  2. 2Copy the prompt below
  3. 3Replace [YOUR_IP] and [YOUR_PASSWORD] with the values from your Notepad
  4. 4Paste it into Claude Code and press Enter
  5. 5When Claude asks "Should I proceed?" or similar — type Y and press Enter
Paste this into Claude Code:select all → copy
I just created an Ubuntu 22.04 server on DigitalOcean.
IP: [YOUR_IP]
Root password: [YOUR_PASSWORD]

SSH into it and set it up:
1. Update all packages (apt update && apt upgrade -y)
2. Configure UFW firewall — allow only ports 22, 80, and 443
3. Install Node.js 20 (use NodeSource)
4. Install PostgreSQL 15
5. Install Nginx
6. Install PM2 globally (npm install -g pm2)

Do each step and tell me when it's done.
💡

This takes 3–5 minutes. Claude Code runs each command on your server. If anything fails it will tell you and fix it.

04

Export your Supabase database

Pull all your tables and data out of Supabase and save them to your computer. This does not delete or change anything in Supabase.

  1. 1Open a new terminal tab (Cmd+T on Mac) — don't close Claude Code
  2. 2Navigate to your project folder: cd ~/Desktop/your-project-name
  3. 3Open Claude Code here: claude
  4. 4Copy the prompt below, replace [DATABASE_URL] with the value from your Notepad
  5. 5Paste it and press Enter
Paste this into Claude Code:select all → copy
Create a folder called "migration" on the Desktop.

Then run this command (use my Supabase DATABASE_URL):

pg_dump "[DATABASE_URL]" --schema=public --no-owner --no-privileges -f ~/Desktop/migration/backup.sql

When it finishes, tell me how many lines the file has and show me all the CREATE TABLE lines in it.

If Claude Code says pg_dump is not installed — just tell it "install it for me" and it will.

05

Import the database into your new server

Send the backup file to your DigitalOcean server and load it into PostgreSQL.

  1. 1Stay in Claude Code (same session)
  2. 2Copy the prompt below
  3. 3Replace [YOUR_IP] and [YOUR_PASSWORD] with your values
  4. 4Replace the table list at the bottom with your actual table names
  5. 5Paste and press Enter
Paste this into Claude Code:select all → copy
Server IP: [YOUR_IP], root password: [YOUR_PASSWORD]
Backup file: ~/Desktop/migration/backup.sql

Do this:
1. Send the backup file to the server using scp
2. On the server: create a PostgreSQL database called "myapp"
3. Create a user called "appuser" with a strong password (tell me what password you picked)
4. Import the backup.sql into that database
5. List all the tables to confirm everything imported correctly

My tables are: [list your table names here, example: users, products, orders]
06

Replace Supabase Auth with your own login system

Supabase handles your signups and logins. We're replacing that with a simple system you own. Claude Code will go through your files and make all the changes.

  1. 1Make sure Claude Code is open in your project folder
  2. 2Copy the prompt below and paste it in
  3. 3Claude Code will show you each file it changes — review them as it goes
Paste this into Claude Code:select all → copy
I'm using Supabase Auth in this Next.js project. Replace it with a custom JWT system.

First, list every file that uses supabase.auth so I can see what we're changing.

Then make these changes:
1. Create a SQL file that adds a users table: id (UUID), email, password_hash, email_confirmed (boolean), created_at
2. Create lib/user-auth.ts with: createUser(), signIn(), verifyToken() — use bcryptjs for passwords, jsonwebtoken for tokens
3. Create API routes: POST /api/auth/signup, POST /api/auth/login, POST /api/auth/logout, GET /api/auth/me
4. Replace supabase.auth.signUp() → POST request to /api/auth/signup
5. Replace supabase.auth.signInWithPassword() → POST request to /api/auth/login
6. Replace supabase.auth.getSession() → read "app_token" from localStorage, verify with /api/auth/me
7. Replace supabase.auth.signOut() → POST to /api/auth/logout, clear localStorage

Tokens go in localStorage as "app_token", expire in 30 days.

Show me each file change one at a time.
💡

This is the longest step — Claude Code might work for 10–20 minutes. If it hits an error, just type "that failed, fix it" and it will.

07

Replace the database calls (supabase.from)

Every supabase.from() query in your app needs to talk directly to your PostgreSQL instead. Claude Code handles all of it.

  1. 1Still in the same Claude Code session — paste the prompt below
Paste this into Claude Code:select all → copy
Now replace all the database queries.

1. Install postgres.js: npm install postgres
2. Create lib/db.ts — connect to PostgreSQL using the DATABASE_URL environment variable
3. Find every file that uses supabase.from() and replace each one:
   - supabase.from('table').select() → sql`SELECT * FROM table`
   - supabase.from('table').insert(data) → sql`INSERT INTO table (...) VALUES (...)`
   - supabase.from('table').update(data).eq() → sql`UPDATE table SET ... WHERE ...`
   - supabase.from('table').delete().eq() → sql`DELETE FROM table WHERE ...`
4. Add DATABASE_URL to .env.local pointing to the new server:
   postgresql://appuser:[password from step 05]@[YOUR_IP]/myapp

Show me every file you change.
08

Set up email sending (Resend — 3,000/mo free)

Supabase was sending your verification and password reset emails. Resend replaces that — free up to 3,000 emails per month.

  1. 1Open a new browser tab → go to resend.com
  2. 2Click "Sign Up" → create an account
  3. 3In the left sidebar, click "API Keys" → click "Create API Key" → copy it → paste into Notepad as RESEND_API_KEY=
  4. 4Go back to Claude Code and paste the prompt below
  5. 5Replace [YOUR_RESEND_KEY] with the key you just copied
Paste this into Claude Code:select all → copy
Set up email sending with Resend.

1. Install: npm install resend
2. Create lib/email.ts with a sendEmail(to, subject, html) function using the Resend API
3. Add buildVerificationEmail(verifyUrl) — dark background, red button, clean HTML email
4. Add buildPasswordResetEmail(resetUrl) — same style
5. In /api/auth/signup — after creating the user, send a verification email
6. Add RESEND_API_KEY=[YOUR_RESEND_KEY] and EMAIL_FROM=noreply@yourdomain.com to .env.local

RESEND_API_KEY: [YOUR_RESEND_KEY]
09

Deploy your app to the server

Push your code to GitHub and then let Claude Code pull it onto your server, build it, and start it.

  1. 1First make sure your project is on GitHub (if not, ask Claude Code: "push my project to a new GitHub repo")
  2. 2Paste the prompt below into Claude Code
  3. 3Replace all the placeholder values with yours
Paste this into Claude Code:select all → copy
Deploy my Next.js app to my DigitalOcean server.

Server IP: [YOUR_IP], root password: [YOUR_PASSWORD]
GitHub repo: [github.com/yourname/yourrepo]

Steps:
1. SSH into the server
2. Clone the repo to /var/www/myapp
3. Create /var/www/myapp/.env.local with these values:
   DATABASE_URL=postgresql://appuser:[password]@localhost:5432/myapp
   JWT_SECRET=[generate a random 32-character string]
   RESEND_API_KEY=[my key]
   EMAIL_FROM=noreply@[my domain]
   NEXT_PUBLIC_APP_URL=http://[YOUR_IP]
4. Run: npm ci && npm run build
5. Start with PM2: pm2 start npm --name myapp -- start
6. Run pm2 save and pm2 startup
7. Set up Nginx to forward http://[YOUR_IP] to localhost:3000
8. Open http://[YOUR_IP] in the browser — tell me if the app loads
💡

This step takes 5–10 minutes. Don't interrupt Claude Code — if it hits an error it will tell you.

10

Set up auto-deploy (push to GitHub = live in 2 min)

Right now you have to manually deploy. This step makes it automatic — every time you push code to GitHub, it goes live on your server.

  1. 1Paste the prompt below into Claude Code
Paste this into Claude Code:select all → copy
Set up GitHub Actions so every push to main auto-deploys to my server.

Server IP: [YOUR_IP], user: root
GitHub repo: [github.com/yourname/yourrepo]

Do this:
1. On the server: generate a deploy SSH key (ssh-keygen -t ed25519 -f ~/.ssh/github_deploy -N "")
2. Add the public key to authorized_keys
3. Show me the private key — I'll add it to GitHub Secrets
4. Create .github/workflows/deploy.yml:
   - Triggers on push to main
   - Builds the app on the GitHub runner (not on the server)
   - SSHes in and runs: git pull, npm ci --omit=dev, npm run build, pm2 restart myapp
5. Tell me exactly which GitHub Secrets I need to add and what values to use
  1. 1Claude Code will show you a private key — copy it
  2. 2Go to your GitHub repo → Settings → Secrets and variables → Actions → New repository secret
  3. 3Add each secret Claude Code tells you to (DO_HOST, DO_USER, DO_SSH_KEY etc.)
  4. 4Make a small change to your code → git push → go to the Actions tab in GitHub → watch the deploy run
🎉

You're self-hosted.

Your database, login system, and emails all run on a $6/mo server you own. Nobody can pause it. Nobody can raise the price on you.