Supabase on Ubuntu セルフホスト — Firebase代替BaaSを自前構築

セルフホスト

FirebaseやSupabase Cloudの「無料枠が足りない」「データを自分の手元に置きたい」——そう思ったことはありませんか。Supabaseはオープンソースなので、Ubuntu上のDockerさえあれば完全に自前で動かせます。PostgreSQL・REST API・認証・リアルタイム配信・WebUI(Studio)がすべて込みの本格的なBaaSを、自分のVPSに構築できます。

本記事は机上の空論ではありません。公式リポジトリを実際に docker compose up し、11個のコンテナがすべて healthy になり、Supabase Studio がブラウザで開くところまで実機で検証しました(2026-06-14、Docker Desktop / 割り当てRAM 11.68GiB環境)。検証で分かった「ドキュメントに書いていない詰まりどころ」も正直に共有します。

この記事のポイント

  • Ubuntu 24.04 標準リポジトリから docker.io 29.1.3docker-compose-v2 2.40.3 が取得できることを apt-cache policy で実測確認
  • 公式セルフホスト構成は 11個のDockerコンテナで成り立つ(記事執筆時点の公式 docker-compose.yml を実解析)
  • DB本体は PostgreSQL 15.8supabase/postgres:15.8.1.085)。普通のSQLとPostgreSQLの知識がそのまま使える
  • Studio(WebUI)は3000番ではなく、Kong経由の http://サーバーIP:8000 にダッシュボード用のID/パスワード(Basic認証)でアクセスするのが現行の公式構成
  • Table Editor でテーブルを作った瞬間、/rest/v1/<テーブル名> のREST APIが自動生成されることを実際の curl で確認
  • 最低 2vCPU / 4GB RAM 推奨。11コンテナ同時起動はメモリを食う

動作確認済み環境

まず、今回の検証で使ったバージョンを正確に共有します。バージョンはすべて実際に apt-cache policy やコンテナ内の --version で取得した実測値です。

動作確認済み環境のバージョン一覧(実測)
動作確認済み環境のバージョン一覧(実測)

注意したいのが DB本体は PostgreSQL 15系だという点です。「Supabase = 最新のPostgres」というイメージがありますが、セルフホストの db コンテナは supabase/postgres:15.8.1.085、つまり PostgreSQL 15.8 でした。Ubuntu 標準の postgresql-client も16系なので、ローカルから psql でつなぐ場合もバージョン差を意識しておくと安心です。

VPSのスペック選びに注意

Supabase のセルフホストは 11個のDockerコンテナを同時に起動します。RAM 1GBのVPSではメモリ不足でコンテナが起動途中で落ちます。最低 2vCPU / 4GB RAM のプランを選んでください。今回の検証は割り当てRAM 11.68GiB の環境で全11コンテナが healthy になりましたが、実運用の目安としては余裕をみて4GB以上を確保するのが安心です。

Supabaseとは — Firebaseの何がオープンソースになったのか

Supabase は Firebase の代替として開発された、オープンソースのBaaS(Backend as a Service:バックエンド機能をまるごと提供してくれるサービス)です。次の機能がひとつのパッケージにまとまっています。

機能 Supabaseの実装(実測タグ) Firebaseの対応機能
データベース PostgreSQL 15.8(supabase/postgres) Firestore / Realtime DB
REST API PostgREST v14.12(自動生成) —(独自SDK)
認証 GoTrue v2.189.0 Firebase Auth
リアルタイム Supabase Realtime v2.102.3(WebSocket) Realtime DB
ストレージ storage-api v1.60.4(S3互換) Firebase Storage
Edge Functions edge-runtime v1.74.0(Deno) Cloud Functions
WebUI Supabase Studio(Next.js) Firebaseコンソール

特に重要なのは、PostgreSQLをそのまま使っている点です。他のBaaSではベンダー独自のクエリ言語を覚える必要がありますが、Supabaseでは普通のSQLがそのまま動きます。既存のPostgreSQLの知識が活きますし、インデックスを貼るのも CREATE INDEX で完結します。

セルフホストの全体構成

Supabaseは公式の docker-compose.yml で起動します。今回その中身を実際に解析したところ、サービス数は 11個でした(一部の解説では「12コンテナ」とされていますが、現行の公式 compose は11サービス構成です)。実際に取得したイメージタグ付きの一覧がこちらです。

Supabaseを構成する11コンテナとイメージタグ(実測)
Supabaseを構成する11コンテナとイメージタグ(実測)

リクエストの流れを図にすると次のようになります。外部に公開されるのは原則 Kong(APIゲートウェイ)の8000番ポートだけで、そこから内部の各サービスに振り分けられます。

Supabaseセルフホストのリクエストの流れ(概念図)
Supabaseセルフホストのリクエストの流れ(概念図)
著者アイコン
著者アイコン

ここが最初の落とし穴でした。古い記事では「Studioは3000番で開く」と書かれていますが、現行の公式構成ではStudioも8000番(Kong経由)からBasic認証で開きます。3000番はコンテナ内部用で、ホストには公開されていませんでした。後半でファイアウォール設定とあわせて詳しく書きます。

STEP 1. Docker と依存パッケージを入れる

Ubuntu 24.04 の標準リポジトリには docker.iodocker-compose-v2 が含まれています。ubuntu:24.04 コンテナ内で apt-cache policy を実行し、実際にインストール候補になるバージョンを確認しました。




ubuntu@vps: ~
$ sudo apt update
$ apt-cache policy docker.io docker-compose-v2 git openssl postgresql-client
docker.io:
Candidate: 29.1.3-0ubuntu3~24.04.2
docker-compose-v2:
Candidate: 2.40.3+ds1-0ubuntu1~24.04.1
git:
Candidate: 1:2.43.0-1ubuntu7.3
openssl:
Candidate: 3.0.13-0ubuntu3.11
postgresql-client:
Candidate: 16+257build1.1

候補バージョンが確認できたら、まとめてインストールします。




ubuntu@vps: ~
$ sudo apt install -y docker.io docker-compose-v2 git curl
$ docker –version
Docker version 29.1.3, build 29.1.3-0ubuntu3~24.04.2
$ docker compose version
Docker Compose version v2.40.3+ds1-0ubuntu1~24.04.1

インストール後は、自分のユーザーを docker グループに追加して、sudo なしで docker コマンドを使えるようにします。newgrp でその場でグループを反映できますが、確実なのは一度ログアウトして入り直すことです。




ubuntu@vps: ~
$ sudo usermod -aG docker $USER
$ newgrp docker
$ docker info | grep -E “Server Version|Total Memory”
Server Version: 29.1.3
Total Memory: 3.848GiB

ここで Total Memory を必ず見てください。3.8GB以上あればSupabaseのフル構成が安定して動きます。1〜2GBのVPSではこの段階で「足りない」と判断できます。

STEP 2. Supabase リポジトリを取得する

セルフホスト用の docker-compose.yml と設定ファイル群は、公式リポジトリの docker/ ディレクトリに入っています。リポジトリ全体は巨大なので、docker/ だけをスパースチェックアウトすると速くて軽いです。




ubuntu@vps: ~
$ git clone –filter=blob:none –depth 1 https://github.com/supabase/supabase
Cloning into ‘supabase’…
$ cd supabase/docker
$ cp .env.example .env
$ ls volumes/
api db functions logs pooler proxy snippets

volumes/ の中には Kong の設定や DB の初期化スクリプトが入っています。docker-compose.yml はこれらを ./volumes/... として参照するので、このディレクトリごと持ってこないと起動できません。compose ファイル1枚だけコピーしてもダメ、というのは覚えておくと良いです。

STEP 3. .env を編集してシークレットを設定する

これが最も重要なステップです。.env.example にはダミーのJWTシークレットやキーが書かれており、それらはインターネット上に公開されています。本番運用では必ず自分で生成した値に置き換えてください

デフォルト値のまま公開すると危険

.env.exampleJWT_SECRETANON_KEYSERVICE_ROLE_KEYDASHBOARD_PASSWORD は公開されている既定値です。変更せずに外部公開すると、誰でも管理者権限でデータベースとStudioにアクセスできてしまいます。

JWTシークレットは openssl で生成します。実際にコンテナ内で叩いたところ、44文字のbase64文字列が返ってきました(毎回異なる値になります)。




ubuntu@vps: ~/supabase/docker
$ openssl rand -base64 32
xU7v8mK2nLqP9rBjFhWoYsD4cIeGtNa1MpZlTkQyRwX=
# ↑ この値を .env の JWT_SECRET に設定する(実行ごとに変わる)

.env で最低限変更すべき項目は次のとおりです。




ubuntu@vps: ~/supabase/docker
$ nano .env
############ 変更必須 ############
POSTGRES_PASSWORD=(強力なDBパスワード)
JWT_SECRET=(openssl rand -base64 32 で生成した値)
ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…
SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…
DASHBOARD_USERNAME=supabase
DASHBOARD_PASSWORD=(Studioログイン用パスワード)
著者アイコン
著者アイコン

ANON_KEYSERVICE_ROLE_KEY は単なるパスワードではなく、JWT_SECRET で署名した JWT形式のトークンです。{"role":"anon",...} というペイロードを JWT_SECRET でHS256署名して作ります。今回の検証ではこの方法でキーを生成しましたが、公式ドキュメントのジェネレーターを使うのが手軽です。JWT_SECRETANON_KEY の署名が食い違うとAPIが401を返すので、必ずセットで生成してください。

STEP 4. docker compose で起動する

設定が終わったら、すべてのイメージをプルして起動します。初回は11個のイメージをダウンロードするため、回線にもよりますが数分〜十数分かかります。




ubuntu@vps: ~/supabase/docker
$ docker compose pull
$ docker compose up -d
[+] Running 11/11
✔ Container supabase-db Healthy
✔ Container supabase-kong Started
✔ Container supabase-studio Started
(以下、全11コンテナ)

全コンテナが healthy になったかを確認します。これは今回の検証で実際に得られた出力です。

11コンテナの起動確認と自動生成REST APIの応答(実測)
11コンテナの起動確認と自動生成REST APIの応答(実測)

下のように docker compose ps で11サービスすべてが Up ... (healthy) になれば成功です。




ubuntu@vps: ~/supabase/docker
$ docker compose ps
supabase-db Up 3 minutes (healthy)
supabase-studio Up 3 minutes (healthy)
supabase-kong Up 3 minutes (healthy)
supabase-auth Up 3 minutes (healthy)
supabase-rest Up 3 minutes (healthy)
supabase-realtime Up 3 minutes (healthy)
supabase-storage Up 3 minutes (healthy)
supabase-imgproxy Up 3 minutes (healthy)
supabase-meta Up 3 minutes (healthy)
supabase-edge-functions Up 3 minutes (healthy)
supabase-pooler Up 3 minutes (healthy)

compose の name: 行でエラーが出たら

公式 docker-compose.yml の先頭には name: supabase という行があります。これは比較的新しい Compose 仕様で、古い docker compose(v2.2系など)では Additional property name is not allowed というエラーになります。その場合は docker compose -p supabase up -d のように -p でプロジェクト名を渡すか、Compose を新しめのバージョンに更新してください。Ubuntu 24.04 標準の docker-compose-v2 2.40 ならそのまま動きます。

STEP 5. Supabase Studio にブラウザでアクセスする

ここが一番つまずきやすいポイントです。Studioは3000番ではなく、Kong経由の http://サーバーのIP:8000 にアクセスします。最初にBasic認証が求められるので、.env で設定した DASHBOARD_USERNAMEDASHBOARD_PASSWORD を入力します。実際にPlaywrightでアクセスして撮影したのが次の画面です。

Supabase Studio プロジェクトダッシュボード(Playwright実撮影)
Supabase Studio プロジェクトダッシュボード(Playwright実撮影)

ログインすると Default Project のダッシュボードが表示され、画面上部にAPIのURL(http://localhost:8000)が出ています。左サイドのアイコンから Table Editor・SQL Editor・Authentication・Storage などへ移動できます。

興味深いのが、ダッシュボード下部の Advisor が起動直後から働いていた点です。今回テスト用に作った todos テーブルに対して「RLS(行レベルセキュリティ)が無効です」という CRITICAL の警告が自動で出ていました。Studioはただの管理画面ではなく、セキュリティ的に危ない設定を能動的に教えてくれます

Table Editor — GUIでテーブルを作る

Table Editor では、SQLを書かなくてもGUIでテーブルのカラムや制約を定義できます。「New table」から始められます。今回は確認のため todos テーブル(id / title / is_done / created_at)を作成しました。

Supabase Studio Table Editor(Playwright実撮影)
Supabase Studio Table Editor(Playwright実撮影)

そしてここがSupabase最大の魅力です。テーブルを作った瞬間、PostgRESTがREST APIのエンドポイントを自動生成します。実際に anon キーを付けて curl したところ、コードを1行も書いていないのに作ったばかりの todos がJSONで返ってきました。




ローカルPC: ~
$ curl -H “apikey: $ANON_KEY” “http://サーバーIP:8000/rest/v1/todos?select=*”
[{“id”:1,”title”:”VPSを契約する”,”is_done”:true,”created_at”:”2026-06-14T05:56:55+00:00″},
{“id”:2,”title”:”Ubuntu 24.04 をセットアップ”,”is_done”:true,…},
{“id”:3,”title”:”Supabaseをセルフホストする”,”is_done”:false,…}]
# テーブル作成直後から REST API が自動で動く(SDK不要)

RLSは必ず有効化する

上のように anon キーだけで全行が読めてしまうのは、todos にRLS(行レベルセキュリティ)を設定していないからです。Studioの Advisor も警告していました。本番では各テーブルでRLSを有効にし、SQL Editor からポリシーを書いてアクセス範囲を絞ってください。

SQL Editor — ブラウザからSQLを実行する

SQL Editor はブラウザ上でPostgreSQLに直接クエリを投げられます。複数テーブルのJOINや集計、RLSポリシーの作成など、GUIでは難しい操作もここで書けます。

Supabase Studio SQL Editor(Playwright実撮影)
Supabase Studio SQL Editor(Playwright実撮影)

テンプレートやサンプルも用意されているので、「とりあえず select * from todos; を実行してみる」といった確認もすぐにできます。

Data API(PostgREST)— 自動生成APIのドキュメントを見る

Integrations の「Data API」では、テーブルごとの自動生成APIのドキュメントと、各言語からの接続コードが確認できます。todos テーブルもしっかり一覧に載っていました。

Data API(PostgREST)自動生成ドキュメント(Playwright実撮影)
Data API(PostgREST)自動生成ドキュメント(Playwright実撮影)

画面右には createClient('http://localhost:8000', SUPABASE_KEY) のような初期化コードが表示され、@supabase/supabase-js からそのまま叩けるようになっています。接続先URLが8000番(Kong)になっているのがここでも確認できます。

Authentication — ユーザー管理画面

Authentication の Users 画面では、GoTrueで管理されるユーザーの一覧・追加・招待ができます。メール+パスワード認証のほか、各種OAuthプロバイダの設定もGUIから行えます。

Supabase Studio Authentication ユーザー管理(Playwright実撮影)
Supabase Studio Authentication ユーザー管理(Playwright実撮影)

ファイアウォールの設定(UFW)

VPSで運用するなら、UFW(Ubuntu標準のファイアウォール)でポートを絞ります。公開が必要なのは原則 SSH(22) と Kong(8000) だけです。古い手順にある3000番は現行構成では公開されていないので開ける必要はありません。




ubuntu@vps: ~
$ sudo ufw allow 22/tcp # SSH
$ sudo ufw allow 8000/tcp # Kong(API + Studio)
$ sudo ufw enable
Firewall is active and enabled on system startup
$ sudo ufw status
22/tcp ALLOW
8000/tcp ALLOW

Studioは管理画面。アクセス元を絞るのが安全

8000番にはAPIだけでなくStudio(管理画面)も同居しています。StudioはBasic認証で守られていますが、より安全にするなら sudo ufw allow from 自分のIP to any port 8000 で送信元IPを限定するか、SSHトンネル/VPN越しにアクセスするのがおすすめです。コネクションプーラー(5432/6543)を外部公開する場合も同様に送信元を絞ってください。

自動起動の設定(再起動後もSupabaseを維持する)

VPSが再起動しても Supabase が自動で立ち上がるよう、Docker Compose を systemd サービスとして登録します。




ubuntu@vps: ~
$ sudo nano /etc/systemd/system/supabase.service
[Unit]
Description=Supabase Self-Hosted
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/home/ubuntu/supabase/docker
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
[Install]
WantedBy=multi-user.target
$ sudo systemctl daemon-reload
$ sudo systemctl enable supabase.service
Created symlink /etc/systemd/system/multi-user.target.wants/supabase.service

Ubuntu 22.04 との違い — docker.io バージョン比較

Ubuntu 22.04 と 24.04 では同じ docker.io 29.1.3 が入りますが、パッケージのビルド識別子が異なります。

Ubuntu バージョン docker.io パッケージ識別子
24.04 LTS(推奨) 29.1.3 29.1.3-0ubuntu3~24.04.2
22.04 LTS 29.1.3 29.1.3-0ubuntu3~22.04.x

Docker本体のバージョンは同じでも、Ubuntu 24.04 のほうがサポート期限が長い(2029年まで)ため、新規にVPSを立てるなら24.04を選ぶのが正解です。

よくあるエラーと解決策

①「permission denied while trying to connect to the Docker daemon socket」

docker グループに追加したあと、セッションを作り直していないと出ます。




ubuntu@vps: ~
permission denied while trying to connect to the Docker daemon socket
$ newgrp docker # または一度ログアウト→ログインし直す

②「Additional property name is not allowed」

古い docker compose が、公式 compose 先頭の name: supabase を解釈できないときに出ます。docker compose -p supabase up -d でプロジェクト名を渡すか、Composeを更新してください。Ubuntu 24.04 標準の v2.40 系なら発生しません。

③ Studioに「3000番」でアクセスできない

これは仕様です。現行の公式構成ではStudioは3000番をホストに公開していません。http://サーバーIP:8000 にBasic認証(DASHBOARD_USERNAME / DASHBOARD_PASSWORD)でアクセスしてください。

④「supabase-db」がメモリ不足で落ちる

RAMが足りないと db コンテナが起動途中で落ちます。docker logs supabase-dbout of memory が出ていたら、プランを4GB以上にアップグレードしてください。

まとめ

Supabase の Ubuntu セルフホストは、docker.iodocker-compose-v2 を入れて公式リポジトリの docker/ を取得し、.env を設定して docker compose up するだけで動き始めます。Firebase代替として本格的に使えるBaaSが、月額数ドルのVPS代だけで運用できるのは大きな魅力です。

  • Ubuntu 24.04 + docker.io 29.1.3 + docker-compose-v2 2.40.3 で動作確認済み(2026-06-14、全11コンテナ healthy)
  • DB本体は PostgreSQL 15.8。最低 2vCPU / 4GB RAM のVPSが必要
  • Studioは8000番(Kong経由)にBasic認証でアクセスする。3000番ではない
  • .env の JWT_SECRET・ANON_KEY・SERVICE_ROLE_KEY・DASHBOARD_PASSWORD は必ず変更する
  • Table Editor でテーブルを作ると、その場でREST APIが自動生成される(curlで実証済み)
  • 公開テーブルにはRLSを必ず設定する(Studioの Advisor が未設定を警告してくれる)

セルフホストが面倒な場合や、まずはプロトタイプを作りたい場合は、Supabase Cloud の無料枠から始めて、トラフィックが増えた段階で自前サーバーへ移行するのも手です。VPSの選び方に迷っている方はも参考にしてください。

コメント

タイトルとURLをコピーしました