はじめに
この記事では、Open Notebook の利用を検討している方向けに、Azure VM へOpen Notebookをデプロイし、さらにEntraID認証 を統合してセキュリティを確保する手順を解説します。
本記事は、下記投稿をOpen Notebookに適用するために書き換えたものになります。
Open Notebook Ver1.2.2にて動作を確認しています。
目的
- Azure VMにOpen Notebookをデプロイする。
- Entra ID認証を導入し、セキュリティを確保する。
前提条件
- Azureサブスクリプションを持っていること
- SSH接続が可能な環境があること
- 基本的なLinuxコマンドの知識があること
構成
Azure VM上に、nginx、および、Open Notebookを構築します。
nginxはクライアントからのSSL通信を受け付け(SSL終端)、
その通信をOpen Notebookへ転送するリバースプロキシとして構成されます。
1. Azure VMの構築
まず、Azure VMを準備します。OSはUbuntu24.04にしました。
SSH(22)、HTTP(80)、HTTPS(443)ポートを許可します。
ネットワークセキュリティグループはBasic、パブリックIPは作成して下さい。
仮想マシンの構築後、仮想マシン→接続→ネットワーク→ネットワーク設定のネットワーク セキュリティ グループから、ポートルールの作成により、追加で8080ポートも許可して下さい(確認用Webアプリケーションへのアクセスのため)
仮想マシンの概要ページから、「DNS名」をクリックして、DNS名を設定しておいて下さい。
以下、DNS名は、<任意>.<リージョン名>.cloudapp.azure.comと記載します。
ネットワークセキュリティグループの設定について、
この後、HTTP-01 チャレンジ(後述)があるので、IPアドレスでのアクセス制限は後で実施するようにします。
2. 確認用Webアプリケーションのデプロイ
Entra ID認証とNginxの設定が正しく機能するかを確認するため、シンプルなFlaskアプリケーションをデプロイします。
Python, pip, venvのインストール
Pythonのバージョンはその都度変えてください。
sudo apt update
sudo apt install python3 python3-pip -y
sudo apt install python3.12-venv
仮想環境の作成と有効化
python3 -m venv venv
source venv/bin/activate
Flaskのインストール
pip install Flask
簡単なFlaskアプリケーションの作成と動作確認
以下のコードでapp.pyを作成します。
from flask import Flask, request
app = Flask(__name__)
port = 8080 # このポートでリッスンします
@app.route('/')
def home():
user_info = '認証されていません。'
# oauth2-proxy が追加するヘッダーからユーザー情報を取得
user = request.headers.get('X-Auth-Request-User', 'N/A')
email = request.headers.get('X-Auth-Request-Email', 'N/A')
groups = request.headers.get('X-Auth-Request-Groups', 'N/A')
if user != 'N/A' or email != 'N/A':
user_info = f"""
<p><strong>認証済みユーザー情報:</strong></p>
<ul>
<li><strong>ユーザー:</strong> {user}</li>
<li><strong>メールアドレス:</strong> {email}</li>
<li><strong>グループ:</strong> {groups}</li>
</ul>
"""
html_content = f"""
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テスト Web アプリ</title>
<style>
body {{ font-family: sans-serif; margin: 40px; background-color: #f4f4f4; color: #333; }}
.container {{ background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }}
h1 {{ color: #0056b3; }}
ul {{ list-style-type: none; padding: 0; }}
li {{ margin-bottom: 8px; }}
strong {{ color: #007bff; }}
</style>
</head>
<body>
<div class="container">
<h1>ようこそ、テスト Web アプリへ!</h1>
<p>このページは、Azure VM 上で動作し、Nginx と oauth2-proxy を通してアクセスされています。</p>
{user_info}
<p>リバースプロキシと認証が正しく設定されていることを確認してください。</p>
</div>
</body>
</html>
"""
return html_content
if __name__ == '__main__':
app.run(host='0.0.0.0', port=port)
下記プロンプトで起動します。
python3 -m app
を起動し、
http://<任意>.<リージョン名>.cloudapp.azure.com:8080/
へアクセス可能なことを確認します。
アクセス後は仮想環境を終了します。
deactivate
3. Entra IDのアプリケーション登録
Open NotebookへのアクセスにEntra ID認証を利用するため、Azure Portalでアプリケーションを登録します。
- Azure Portal へのサインイン
- Microsoft Entra IDを検索して選択
- 左メニューの「アプリの登録」を選択し、「+ 新規登録」をクリック
- アプリケーションの登録 ページで以下を設定:
- 名前: 任意の分かりやすい名前 (例: MyWebApp-OAuth2Proxy)
- サポートされているアカウントの種類: 要件に応じて選択します。通常は「この組織ディレクトリのみに含まれるアカウント (シングル テナント)」または「任意の組織ディレクトリ内のアカウント (任意の Azure AD ディレクトリ - マルチテナント)」を選択します。
- リダイレクト URI (オプション):
- プラットフォーム: 「Web」を選択
- URI: https://<任意>.<リージョン名>.cloudapp.azure.com/oauth2/callback
oauth2-proxy のデフォルトのコールバックパスは /oauth2/callback です。
- 「登録」をクリック
登録が完了すると、アプリケーションの概要ページが表示されます。以下の情報をメモします。
アプリケーション (クライアント) ID
ディレクトリ (テナント) ID
- 左メニューの「証明書とシークレット」を選択
- 「+ 新しいクライアント シークレット」をクリック
- 説明: 任意の分かりやすい説明 (例: oauth2-proxy-secret)
- 有効期限: 推奨される期間を選択します。
「追加」をクリックします。
- 作成されたシークレットの「値」を必ずメモする
※この値はページを離れると二度と表示されません。
4. NginxとCertbotのインストール
HTTPS通信を有効にし、SSL証明書を取得するためにNginxとCertbotを導入します。
Nginxのインストール
sudo apt update
sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
Certbotのインストール
Certbotは、ウェブサイトをHTTPS化するために必要なSSL/TLS証明書を、無料で自動的に取得・インストール・更新できるツールです。便利。
そのために、Snapパッケージを最新化した上で、インストールしています。
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Nginxの初期設定 (HTTP-01 チャレンジ用)
Let's Encryptが証明書を発行してくれるのは、「あなたが本当にそのドメインの所有者であること」を確認するためです。この確認方法の一つが「HTTP-01チャレンジ」です。
HTTP-01チャレンジの仕組みは非常にシンプルです。
- Certbotが、サーバーの特定のURL (http://<ドメイン>/.well-known/acme-challenge/<トークン>) に、ランダムな文字列(トークン)を含むファイルを作成するよう要求します。
- Let's Encryptの認証局が、インターネット経由でそのURLにアクセスし、ファイルの内容が正しいことを確認します。
- 確認が成功すれば、「このサーバーは確かにこのドメインを管理している」と判断され、証明書が発行される、という流れです。
このプロセスが正しく機能するためには、Let's Encryptの認証局が、指定されたURLにアクセスしたときに、正しくファイルに到達できるようなNginxの設定が必要です。
具体的な手順は下記の通りです。下記でnanoを起動し、ファイルを編集します。
sudo nano /etc/nginx/sites-available/<任意>.<リージョン名>.cloudapp.azure.com
ファイルに書く内容は下記の通りです。
server {
listen 80;
server_name <任意>.<リージョン名>.cloudapp.azure.com;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
シンボリックリンクを作成し、Nginx を再起動します。
sudo ln -s /etc/nginx/sites-available/<任意>.<リージョン名>.cloudapp.azure.com /etc/nginx/sites-enabled/
sudo systemctl restart nginx
SSL証明書の取得
下記を実行します。
sudo certbot --nginx -d <任意>.<リージョン名>.cloudapp.azure.com
プロンプトが表示されたら、メールアドレスを入力し、利用規約に同意します。
これにより、Certbot が自動的に Nginx の設定を更新し、証明書を取得してくれます。
SSL証明書自動更新の設定を確認
sudo snap services certbot
このコマンドの出力で、certbot.renew サービスが enabled になっており、timer 列に何らかのスケジュール (例: daily, 00:00,12:00) が表示されていれば、自動更新は正しく設定されています。
実際に更新が機能するかどうかをテストするには、以下のコマンドを実行します。このコマンドは、証明書の有効期限が近づいている場合にのみ実際の更新が行われます。
sudo certbot renew --dry-run
--dry-run オプションは、実際の証明書を要求せずに更新プロセスをシミュレートします。このコマンドがエラーなく完了すれば、自動更新のメカニズムは機能していると判断できます。
5. oauth2-proxyのインストールと設定
Entra ID認証とNginxを連携させるためのプロキシとして、oauth2-proxyを導入します。
1. oauth2-proxy のダウンロード
GitHubリポジトリを確認し、最新のリリースバージョンをダウンロードします。
wget https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.10.0/oauth2-proxy-v7.10.0.linux-amd64.tar.gz
tar -xvf oauth2-proxy-v7.10.0.linux-amd64.tar.gz
sudo mv oauth2-proxy-v7.10.0.linux-amd64/oauth2-proxy /usr/local/bin/
sudo rm -rf oauth2-proxy-v7.10.0.linux-amd64 oauth2-proxy-v7.10.0.linux-amd64.tar.gz
2. oauth2-proxy の設定ファイルまたは環境変数の準備
oauth2-proxy の設定は、コマンドライン引数、環境変数、または設定ファイルで行えます。ここでは systemd サービスファイルで環境変数を使用する例を示します。
Cookie シークレットの生成
セッション Cookie の署名と暗号化に使用されるランダムな文字列を生成します。
python3 -c 'import os; print(os.urandom(16).hex())'
例: 7b3d1f... (長いランダムな文字列が出力されるのでメモしてください)
3. systemd サービスの作成
sudo nano /etc/systemd/system/oauth2-proxy.service
[Unit]
Description=OAuth2 Proxy for Entra ID
After=network.target
[Service]
ExecStart=/usr/local/bin/oauth2-proxy \
--http-address="0.0.0.0:4180" \
--upstream="http://localhost:8502" \
--provider="azure" \
--client-id="<アプリの登録:アプリケーションID>" \
--client-secret="<アプリの登録:クライアントシークレット>" \
--redirect-url="https://<任意>.<リージョン名>.cloudapp.azure.com/oauth2/callback" \
--oidc-issuer-url="https://login.microsoftonline.com/<テナントID>/v2.0" \
--cookie-secret="<Cookie シークレットの生成で作成したシークレット>" \
--cookie-domain="<任意>.<リージョン名>.cloudapp.azure.com" \
--cookie-secure=true \
--cookie-expire=24h \
--set-xauthrequest=true \
--email-domain="*" # すべての Entra ID ユーザーを許可する場合。特定のドメインのみ許可する場合は 'yourtenant.onmicrosoft.com' など。
Environment="GOMAXPROCS=1" # 必要に応じて調整
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=oauth2-proxy
[Install]
WantedBy=multi-user.target
注意点:
- --upstream: Web アプリケーションがリッスンしている内部アドレスとポート。(Open Notebookはポート8502でリッスンするように初期設定されているため、8502を設定します)
- --redirect-url: Entra ID アプリ登録で設定したリダイレクト URI と同じである必要があります。
- --cookie-domain: 認証 Cookie のドメイン。yourdomain.com または .yourdomain.com を指定します。
- --email-domain: 認証を許可するメールアドレスのドメイン。* は任意のドメインを許可します。特定の Entra ID テナント内のユーザーのみを許可する場合は、テナントのドメイン (例: yourtenant.onmicrosoft.com) を指定します。
- --oidc-issuer-url: これは Entra ID (Azure AD) の OIDC ディスカバリーエンドポイントです。common または特定のテナント ID (<Your_Tenant_ID>) を指定します。シングルテナントの場合は https://login.microsoftonline.com/< Your_Tenant_ID >/v2.0 が一般的です。
4. oauth2-proxy サービスの有効化と起動:
sudo systemctl daemon-reload
sudo systemctl enable oauth2-proxy
sudo systemctl start oauth2-proxy
sudo systemctl status oauth2-proxy
下記コマンドでログを確認し、エラーがないことを確認してください。
sudo journalctl -u oauth2-proxy -f
6. Nginxの設定更新
oauth2-proxyと連携するようにNginxの設定を更新します。
Nginxのバーチャルホスト設定ファイルの編集
既存の内容を以下の内容で上書きします。Certbot によって追加された SSL 証明書のパスはそのまま利用します。
sudo nano /etc/nginx/sites-available/<任意>.<リージョン名>.cloudapp.azure.com
server {
listen 80;
server_name <任意>.<リージョン名>.cloudapp.azure.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name <任意>.<リージョン名>.cloudapp.azure.com;
# Certbot が生成したSSL証明書とキーのパス
ssl_certificate /etc/letsencrypt/live/<任意>.<リージョン名>.cloudapp.azure.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<任意>.<リージョン名>.cloudapp.azure.com/privkey.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1h;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE';
ssl_prefer_server_ciphers on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
client_max_body_size 50M;
# oauth2-proxy の認証エンドポイント
location /oauth2 {
proxy_pass http://localhost:4180; # oauth2-proxy がリッスンしているアドレスとポート
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Scheme $scheme; # oauth2-proxy が HTTPS を認識できるように
proxy_set_header Cookie $http_cookie; # クッキーを転送
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_buffering off;
}
# Web アプリケーションへのリバースプロキシと認証
location / {
auth_request /oauth2/auth; # oauth2-proxy に認証を要求
error_page 401 = /oauth2/start?rd=$request_uri; # 認証失敗時に oauth2-proxy のログインページへリダイレクト
# oauth2-proxy から受け取ったユーザー情報を Web アプリケーションに転送
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-Auth-Request-User $user;
proxy_set_header X-Auth-Request-Email $email;
# Web アプリケーションへのプロキシ設定
proxy_pass http://localhost:8502; # Web アプリケーションのポート
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
}
この設定によるポート別の挙動について記載します。
ポート80 (HTTP)
ポート80でアクセスすると、HTTPリクエストはHTTPS (ポート443) へと、301 Moved Permanentlyステータスコードでリダイレクトされます。要するに、HTTPS通信を強制します。ポート443 (HTTPS)
ポート443でアクセスすると、SSL通信のための必要な処理がなされ、リクエストを認証します。 その後、Webアプリケーションまたはoauth2-proxyへプロキシされます。1. URIが/oauth2で始まる場合
リクエストは、http://localhost:4180で稼働しているoauth2-proxyにプロキシされます。
2. その他のURI (/oauth2以外)
リクエストはまずoauth2-proxyによって認証され、認証が成功した場合にのみ、http://localhost:8502で稼働しているWebアプリケーションにプロキシされます。
最後に、Nginx の設定をテストし、再起動します。
sudo nginx -t
sudo systemctl restart nginx
7. 認証の確認
2.で作成した確認用Webアプリケーションにアクセスし、Entra ID認証が正しく機能することを確認します。
確認用アプリケーションのリッスンポートの変更
app.pyを開き、リッスンポートを8502に変更します。
from flask import Flask, request
app = Flask(__name__)
port = 8502 # このポートでリッスンします
(以下略)
確認用アプリケーションの起動
source venv/bin/activate
python3 -m app
ブラウザから
https://<任意>.<リージョン名>.cloudapp.azure.com/
にアクセスし、Entra IDの認証画面が表示されること、認証後、正しくアプリケーションにアクセスできることが確認できるはずです。
ここまでできたら、Azure VMにおいて、仮想マシン→接続→ネットワーク→ネットワーク設定のネットワーク セキュリティ グループから、8080ポートを削除したり、接続元IPアドレスを制限するなど、必要なセキュリティ対策を講じて下さい。
8. Open Notebookの構築
いよいよOpen Notebookをデプロイします。DockerとDocker Composeを使用します。
DockerとDocker Composeのインストール
sudo apt-get update
# ca-certificates と curlのインストール
sudo apt-get install ca-certificates curl
# Dockerの公式リポジトリをシステムのソースリストに追加
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
# Docker、Docker Composeをインストール
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 現在のユーザをdockerグループに追加
sudo usermod -aG docker $USER
# 新しく追加されたグループの変更を現在のシェルセッションに適用
newgrp docker
# Docker動作確認
docker run hello-world
# Docker Composeバージョン確認
docker compose version
フォルダの作成
mkdir open-notebook
cd open-notebook
yamlファイルの作成
docker-compose.yml
services:
open_notebook:
image: lfnovo/open_notebook:v1-latest-single
ports:
- "8502:8502" # Web UI
- "5055:5055" # API (required!)
env_file:
- ./docker.env
pull_policy: always
volumes:
- ./notebook_data:/app/data
- ./surreal_single_data:/mydata
restart: always
docker.env
# CRITICAL: Replace YOUR_SERVER_IP with your server's actual IP address
# Example: API_URL=http://192.168.1.100:5055
API_URL=https://<任意>.<リージョン名>.cloudapp.azure.com
# Database connection (required for single-container)
SURREAL_URL="ws://localhost:8000/rpc"
SURREAL_USER="root"
SURREAL_PASSWORD="root"
SURREAL_NAMESPACE="open_notebook"
SURREAL_DATABASE="production"
# Azure OpenAI Serviceの設定
AZURE_OPENAI_API_KEY=your_key
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/
AZURE_OPENAI_API_VERSION=2024-12-01-preview
Azure OpenAI Serviceにデプロイするモデルですが、
- GPT
- Embedding
- TTS (tts) ※必要ならば
- STT (Whisper) ※必要ならば
があります。
これらモデルが同一リソースにデプロイされているならば、上記の例のように1つ記載すれば良いです。
各モデル毎にリソースが異なる(APIキーが異なる)場合は、下記のように記載することが説明されています。
# Mode-specific configuration (for different deployments per modality)
# Use these when you have separate Azure deployments for different capabilities
AZURE_OPENAI_API_KEY_LLM=your_llm_key
AZURE_OPENAI_ENDPOINT_LLM=https://llm-resource.openai.azure.com/
AZURE_OPENAI_API_VERSION_LLM=2024-12-01-preview
AZURE_OPENAI_API_KEY_EMBEDDING=your_embedding_key
AZURE_OPENAI_ENDPOINT_EMBEDDING=https://embedding-resource.openai.azure.com/
AZURE_OPENAI_API_VERSION_EMBEDDING=2024-12-01-preview
# STT and TTS also supported with _STT and _TTS suffixes
Docker Composeを利用したOpen Notebookの起動
docker compose up -d
https://<任意>.<リージョン名>.cloudapp.azure.com/
にアクセスすれば、Open Notebookが起動するはずです!
Open Notebookで利用するモデルの設定
Open Notebookにアクセスして、利用するモデルの設定を行います。
MANAGE -> Modelsにアクセスします。

AI Providersの「Azure」にチェックボックスが入っている状況を確認して下さい。
チェックが入っていない場合はdocker.envでのAzureの設定を見直して下さい。

同ページ下部のLanguage Models、Embedding Models、Text-to-Speech、Speech-to-Textを設定します。それぞれ、「Add Model」をクリックします。

ProviderはAzureを、Model NameはAzure AI Foundaryで表示されるモデルデプロイ名と同じものを入力します(モデルは予めデプロイしておいて下さい)。


Language ModelsとEmbedding Modelsが設定できたら、
Default Model Assignmentsにて、先ほど設定したモデルを選択します。

これで準備が完了です!
※Text-to-Speech、Speech-to-Textは必要に応じて設定して下さい。
Text-to-Speechは「tts」モデル、Speech-to-Textは「Whisper」モデルをデプロイすれば良いです。
しかしながら、これらモデルはデプロイ出来るリージョンが限定されていますので、こちらのページを確認して、該当のリージョンでデプロイするようにします。
Foundry Models sold directly by Azure
※2025年11月27日時点では、下記のようになっていました。

Open Notebookの動作確認
Create→Sourceで、ソースを登録します。URLや、ファイル、テキストが登録できます。

登録したソースを開いて、そのソースのページの「Chat with Source」からチャットを実施することもできます。

次に、Create→Notebookで、ノートブックを作ります。

ノートブックに、先ほど登録したソースを追加します。
Sourcesの「Add Source」から、「Add Existing Sources」を選択します。


Chat with Notebookで、これらSourcesやNotesを元にしたチャットを実行することが出来ます。

まとめ
この記事では、Azure VM上にOpen Notebookをデプロイし、Entra ID認証を組み合わせることで、セキュアな環境を構築する手順を解説しました。これにより、社内でのOpen Notebookの試用を安全かつスムーズに進めることができます。

