Relayium

Relayium をセルフホスト:自分専用のファイル・テキスト転送サーバーを運用

最終更新: 2026-08-06

Relayium は AGPL-3.0 ライセンスのオープンソースで、サーバーは1つの自己完結型イメージです——外部データベースも、サードパーティのストレージバケットも不要で、登録するものもありません。relayium.com に頼るのではなく全体を自分で運用したいなら、本ガイドで Docker によりサーバーを立ち上げ、CLI をそこに向ける方法を案内します。

セルフホストすることで、データがどこに置かれるかを完全に管理でき、自分のドメインと TLS 証明書を使え、他人のインフラ運用判断に依存しません。以下の内容はすべてリポジトリに実際に存在するファイル——docker-compose.yml、server/.env.example、docs/self-hosting.md——に基づいており、実在しないフラグや設定は登場しません。

なぜセルフホストするのか

Relayium のリアルタイム転送はエンドツーエンドで暗号化されています。セルフホストした TURN リレーは暗号文のバイトを運ぶことがあり、サーバーはシグナリングのメタデータを処理しますが、どちらもファイルの平文を読んだり復号したりできません。サーバーもリレーも、リアルタイム内容のサーバー側コピーや履歴を保存しません。サーバーはアカウントを保持し、また保存型/リンク型の転送については、暗号化されたブロブと小さな SQLite データベースを保持します。セルフホストとは、そのデータが自分が管理するインフラ上に、自分のドメインの下に置かれ、他人の運用判断が介在しないということです。

このプロジェクトは AGPL-3.0 ライセンスでオープンソース(github.com/relayium/relayium)なので、何かを任せる前にサーバーが正確に何をしているかを読んで確認でき、自由に fork したり改変したりできます。

Docker でクイックスタート

手順1の前に必要なもの

  • Docker Engine と Compose プラグインが入ったホスト。docker compose version はバージョン文字列を表示します。「docker: 'compose' is not a docker command」と出る場合はプラグインが入っていません。
  • リポジトリのクローン。compose ファイルはこのソースツリーからイメージをビルドするため、隣に Dockerfile と web/ が必要です——取得できる事前ビルド済みイメージはありません。
  • 名前付きボリューム relayium-data 用のディスク容量。SQLite データベースと、保持する保存型転送の暗号文が入ります。
  • 自分以外も使うなら、ドメインと TLS を終端するリバースプロキシ。コンテナは平文 HTTP しか話さず、既定ではループバックインターフェースにしか公開されません。
  • 必要なものはこれだけです。外部データベースも、オブジェクトストレージのバケットも、第三者のアカウントも要りません。

リポジトリのルートには Dockerfile と docker-compose.yml があり、これらは1つの自己完結型イメージ——事前ビルド済みの Web アプリを配信する静的 Go バイナリ——をビルドします。実行するためだけに別途 Node、Go ツールチェーン、nginx は不要です。

  1. リポジトリをクローンして、そのディレクトリに移動します。

    git clone https://github.com/relayium/relayium.git
    cd relayium
  2. ビルドして起動します。リレーが無効でもこのプレースホルダーの秘密鍵は省けません。Compose はファイルを解析する時点で、プロファイルによって無効化されている coturn サービスの必須変数まで検証するため、素の docker compose up は拒否されます。

    RELAYIUM_TURN_SECRET=placeholder docker compose up -d --build
  3. コンテナが再起動を繰り返さずに立ち上がったままか確認します。

    docker compose ps
  4. このインスタンスが実際に応答できる状態かを尋ねます。/healthz ではなく /readyz を使ってください——両者の違いこそがこの確認の要点で、下の期待結果ボックスがその理由を説明します。

    curl -s http://127.0.0.1:8080/readyz
  5. 設定テンプレートをコピーし、公開 URL を設定します。RELAYIUM_BASE_URL は送信メール内のリンクを組み立て、セッション Cookie に Secure フラグを付けるかどうかも決めるため、実際の https:// アドレスである必要があります。

    cp server/.env.example server/.env
    chmod 600 server/.env
  6. 前段に nginx か Caddy を置き、自分のドメインで TLS を終端して、すべてのパス——/、/api、/ws、/admin——を 8080 番ポートへプロキシします。その後、server/.env を反映させるために再起動します。

    docker compose up -d

正常なインスタンスの見え方

コンテナが Up となり、両方のエンドポイントが応答します。意味を持つのは ready のほうです。/healthz は何も開かれる前に無条件で ok を返すため、データベースやブロブディレクトリが使えないインスタンスでも通ってしまいます。/readyz は SQLite データベースとブロブディレクトリに ping を送り、どちらかが壊れていれば 503 を返します。

$ docker compose ps
NAME                IMAGE                     STATUS          PORTS
relayium-server-1   relayium/relayium:local   Up 12 seconds   127.0.0.1:8080->8080/tcp

$ curl -s http://127.0.0.1:8080/healthz
ok
$ curl -s http://127.0.0.1:8080/readyz
ready

ネットワークをまたぐ転送用に TURN リレーを追加する

同一ネットワーク(LAN)の転送や、SSH ベースの push/pull は、追加設定なしで動作します。ネットワークをまたぐリアルタイム転送(それぞれ異なる NAT の背後にある2台のデバイス)は、経路確立のために TURN リレーが必要になることがあります——リレーは常に暗号文しか見ず、ファイルの中身を見ることは決してありません。

docker-compose.yml には任意の relay プロファイルがあり、メインサーバーと合わせて coturn(TURN サーバー)と、リレーバイト計測用の小さな Redis インスタンスを起動できます。

この秘密鍵は2か所に届ける必要があり、間違えても何のエラーも出ません。coturn は Compose の変数展開で受け取り、その展開はシェルかプロジェクトルートの .env からしか解決されません。サーバーは自分自身の環境変数——つまり server/.env——から読み、秘密鍵が空なら TURN は完全に無効になります。片方だけ設定すると、動いてはいるがサーバーが決して資格情報を発行しない coturn ができあがります。コンテナはすべて健全と報告し、ログには何も出ず、厳しい NAT をまたぐ転送はリレーを追加する前とまったく同じように失敗し続けます。

  1. 十分に長いランダムな秘密鍵を1つ生成します。以下ではすべて同じ値を使います。

    openssl rand -hex 32
  2. その秘密鍵と、自分のドメインが解決するリレーアドレスを server/.env に書きます。これでサーバー側の TURN が有効になります。

    RELAYIUM_TURN_SECRET=<the value from step 1>
    RELAYIUM_TURN_URLS=turn:example.com:3478,turns:example.com:5349
  3. 同じファイルをシェルに読み込ませ、Compose の変数展開が coturn へ同一の秘密鍵を渡せるようにします。source する方法なら情報源が1つに保たれ、ps から見える形でコマンドラインに秘密鍵が載ることもありません。

    set -a; . ./server/.env; set +a
  4. relay プロファイルを付けてスタックを起動します。

    docker compose --profile relay up -d --build
  5. ホストのファイアウォールでリレーポートを開けます。coturn はホストネットワークで動くため、これは Docker ではなくホスト側のルールです: UDP 3478 と 49152-65535、TCP 3478 と 5349。

  6. coturn だけでなくサーバーが秘密鍵を持って起動したことを確認します。これが、音もなく起きる失敗を捕まえるための確認です。

    docker compose exec server env | grep RELAYIUM_TURN

正常なリレーの見え方

サーバーコンテナの内側から見て、両方のキーが空でない値を返します。coturn が動いていること自体は何の証明にもなりません——ブラウザが受け取るリレー資格情報は、サーバーが発行したものだけです。

$ docker compose exec server env | grep RELAYIUM_TURN
RELAYIUM_TURN_SECRET=3f7a…
RELAYIUM_TURN_URLS=turn:example.com:3478,turns:example.com:5349

自分のマシンに CLI をインストール

この最後の手順はサーバーではなく自分のコンピュータで relayium CLI を実行します。未インストールならまず入れてください。macOS または Linux:

curl -fsSL https://relayium.com/install.sh | sh

CLI を自分のサーバーに向ける

Relayium CLI は、ネットワークをまたぐ send/receive と text で既定では relayium.com のランデブーサーバーを使います。--server を渡せば、代わりに自分のサーバーを使えます。

  1. 前の節で CLI を入れたマシンで、relayium.com ではなく自分のサーバーにサインインします。URL とコードが表示されるので、自分のインスタンスにサインイン済みのブラウザで承認します。

    relayium login --server https://your-domain
  2. 保存された資格情報がどのサーバーに結び付いているかを確認します。whoami はフラグを取りません——ログインが実際に書き込んだ内容をそのまま報告するので、実行する価値があります。

    relayium whoami
  3. 送信時にも同じ --server を渡します。付け忘れると CLI は relayium.com でペアリングコードを発行してしまい、相手は自分のインスタンス上でそれを見つけられません。

    relayium send ./report.pdf --server https://your-domain
  4. もう一方のマシンで、表示されたコードと同じ --server を使って受け取ります。テキストセッションも同じ要領です。

    relayium receive 483920 --server https://your-domain
    relayium text --server https://your-domain
    relayium text 483920 --server https://your-domain

自分のインスタンスに向いていると分かる形

whoami はアカウントに続けて、結び付いているサーバーを括弧内に表示します。そこが relayium.com ではなく自分のドメインになっていれば確認完了です。

$ relayium login --server https://your-domain
Open https://your-domain/device and enter code: WDJB-MJHT
logged in as you@example.com

$ relayium whoami
you@example.com (https://your-domain)

うまくいかないとき

失敗するセルフホストのほぼすべては、次の5つのどれかです。それぞれに、読めば分かる1行か、実行すれば決着がつくコマンドがあります。そして5つのうち3つは、その確認を走らせるまで成功したように見えます。

症状、確認、対処

ビルドが始まる前に、docker compose up がそもそも起動を拒否する。
docker compose up -d --build
# required variable RELAYIUM_TURN_SECRET is missing a value

Compose はプロファイルで絞り込む前にファイル全体を変数展開するため、リレーが無効でも、無効化された coturn サービスの必須変数まで検証されます。任意のプレースホルダーを前置してください——RELAYIUM_TURN_SECRET=placeholder docker compose up -d --build——実際に relay プロファイルを有効化するときに本物の秘密鍵へ置き換えます。

コンテナは Up なのに、別のマシンのブラウザから到達できない。
docker compose ps
# PORTS  127.0.0.1:8080->8080/tcp

そのループバックへのバインドは既定の動作で、公開ホストが平文 HTTP をインターネットに晒さないためのものです。本番ではそのままにして、同じホスト上のリバースプロキシで TLS を終端してください。プロキシのない LAN 専用機なら、RELAYIUM_BIND=0.0.0.0 docker compose up -d でより広く公開します——この変数を読むのは compose であって、サーバー自身ではありません。

/healthz は ok を返すのに、サインアップが失敗し、保存型リンクがいつまでも現れない。
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/readyz
# 503

/healthz は無条件に ok を返し、プロセスが待ち受けていることしか証明しません。/readyz は SQLite データベースとブロブディレクトリに ping を送るため、503 はそのどちらかが使えないという意味です——relayium-data ボリュームがマウントされているか、RELAYIUM_DB と RELAYIUM_BLOB_DIR がその内側を指しているかを確認してください。

relayium login が、開けるはずのない localhost の確認 URL を表示する。
relayium login --server https://your-domain
# Open http://localhost:8080/device and enter code: WDJB-MJHT

その URL はサーバーが RELAYIUM_BASE_URL から組み立てており、既定値は http://localhost:8080 です。server/.env で実際の https:// アドレスに設定して再起動してください。この値はセッション Cookie に Secure フラグを付けるかどうかも決めるので、間違ったままにするのは見た目だけの問題ではありません。

coturn は動いているのに、厳しい NAT をまたぐ転送が失敗し続ける——しかもログには何も出ない。
docker compose exec server env | grep RELAYIUM_TURN
# 出力なし

秘密鍵は Compose の変数展開で coturn には届いたものの、サーバーには一度も届いておらず、サーバー側は秘密鍵が空なので TURN が完全に無効です。RELAYIUM_TURN_SECRET と RELAYIUM_TURN_URLS を server/.env に書き、set -a; . ./server/.env; set +a でシェルに読み込ませて変数展開にも同じ値を見せ、relay プロファイルを再起動してください。先ほどの確認で両方のキーが空でない値を返すことが条件です。

よくある質問

TURN を設定する必要はありますか?

ネットワークをまたぐリアルタイム転送を厳しい NAT 越しでも機能させたい場合にのみ必要です。同一ネットワークの転送、SSH ベースの push/pull、デーモン直結はいずれも TURN なしで動作します——TURN はネットワークをまたぐペアリングコード経路での NAT 越え専用です。

セルフホストしても CLI は無料のままですか?

はい。relayium.com でも自分のサーバーでも CLI は完全無料です。コードなしの send または text でコードを発行するときと、up でファイルを保存するときは、指し先サーバーのアカウントが必要です。receive、down、表示されたコードで参加する text はログイン不要です。

自分のドメインと TLS 証明書を使えますか?

使えます。Docker イメージ自体は :8080 で平文の HTTP を待ち受けます。前段に nginx か Caddy を置き、自分のドメインと証明書(例えば certbot/Let's Encrypt 経由)を設定してください。docs/self-hosting.md はプロキシすべき内容を説明しています。Relayium 自身の本番 nginx 設定は公開されていないため、自分で用意する必要があります。

セルフホストしたサーバーはどんなデータを保存しますか?

RELAYIUM_DB にある SQLite データベース(アカウント、セッション)と、保存型/リンク型の転送については RELAYIUM_BLOB_DIR にある暗号化されたブロブ——これはサーバー自身も復号できません。サーバーはリアルタイムのファイルやメッセージ本文を保存せず、シグナリングのハンドシェイクだけを中継しますが、受信端末はファイルやテキストを保持できます。

無料の Relayium CLI をインストールし、--server で自分のサーバーに向けましょう。

CLI を入手

続けて読む