🎄 科学と神々株式会社 アドベントカレンダー 2025
License System Day 20: 実際に動かしてみよう - セットアップガイド
📖 今日のテーマ
今日は、実際にライセンスシステムを動かすための完全なセットアップガイドです。
Nim環境のセットアップから、サーバー起動、WebAssemblyクライアントのビルド、ブラウザ拡張機能のインストールまで、ステップバイステップで解説します。
🎯 環境要件
必須環境
オペレーティングシステム:
✅ Linux (Ubuntu 20.04+ / Debian 11+)
✅ macOS (12.0 Monterey以降)
✅ Windows 10/11 (WSL2推奨)
ソフトウェア:
✅ Nim 2.0.0以降
✅ OpenSSL 1.1.1+
✅ SQLite 3.35+
✅ Git 2.30+
✅ Google Chrome / Microsoft Edge (拡張機能用)
推奨スペック:
- CPU: 2コア以上
- RAM: 4GB以上
- ディスク: 500MB以上の空き容量
🛠️ ステップ1: Nim環境のセットアップ
Nimのインストール
Linux / macOS
# choosenimを使った推奨インストール方法
curl https://nim-lang.org/choosenim/init.sh -sSf | sh
# シェル設定ファイルに追加(~/.bashrc または ~/.zshrc)
export PATH=$HOME/.nimble/bin:$PATH
# 設定の再読み込み
source ~/.bashrc # または source ~/.zshrc
# バージョン確認
nim --version
# 出力例:
# Nim Compiler Version 2.0.0 [Linux: amd64]
Windows (WSL2推奨)
# WSL2でUbuntuを起動してから
curl https://nim-lang.org/choosenim/init.sh -sSf | sh
export PATH=$HOME/.nimble/bin:$PATH
# または、Windows用バイナリ
# https://nim-lang.org/install_windows.html
# からインストーラーをダウンロード
依存パッケージのインストール
# Nimble経由でフレームワーク・ライブラリをインストール
nimble install jester
nimble install nimcrypto
nimble install jwt
OpenSSL確認
# OpenSSLのバージョン確認
openssl version
# OpenSSL 1.1.1 以上必要
# Linux: 必要に応じてインストール
sudo apt update
sudo apt install openssl libssl-dev
# macOS: Homebrewでインストール
brew install openssl@3
📦 ステップ2: プロジェクトのセットアップ
リポジトリのクローン
# プロジェクトディレクトリに移動
cd ~/projects
# license-systemプロジェクトをクローン
git clone https://github.com/your-org/license-system.git
cd license-system
# プロジェクト構造の確認
tree -L 2
# nim-implementation/
# ├── server/
# ├── client-wasm/
# ├── browser-extension/
# ├── shared/
# └── build.sh
ディレクトリ構造の確認
# 実装ディレクトリに移動
cd nim-implementation
# ディレクトリの確認
ls -la
# server/ - サーバー実装
# client-wasm/ - WebAssemblyクライアント
# browser-extension/ - ブラウザ拡張機能
# shared/ - 共通型定義
# build.sh - ビルドスクリプト
# keys/ - 暗号鍵(生成後)
🔐 ステップ3: ECDSA鍵ペアの生成
鍵生成スクリプトの実行
# keysディレクトリ作成
mkdir -p keys
chmod 700 keys
# ECDSA P-256秘密鍵の生成
openssl ecparam -name prime256v1 -genkey -noout -out keys/private_key.pem
# パーミッション設定(所有者のみ読み取り可能)
chmod 400 keys/private_key.pem
# 公開鍵の抽出
openssl ec -in keys/private_key.pem -pubout -out keys/public_key.pem
# 公開鍵は読み取り可能
chmod 644 keys/public_key.pem
echo "✅ 鍵ペア生成完了"
鍵の検証
# 秘密鍵の確認
openssl ec -in keys/private_key.pem -text -noout
# 出力例:
# Private-Key: (256 bit)
# priv:
# 00:c9:0e:f7:3f:4c:7e:...
# pub:
# 04:b7:63:5c:0f:...
# ASN1 OID: prime256v1
# NIST CURVE: P-256
# 公開鍵の確認
openssl ec -in keys/public_key.pem -pubin -text -noout
# 出力例:
# Public-Key: (256 bit)
# pub:
# 04:b7:63:5c:0f:...
# ASN1 OID: prime256v1
# NIST CURVE: P-256
🖥️ ステップ4: データベースのセットアップ
SQLiteデータベースの初期化
# サーバーディレクトリに移動
cd server
# データディレクトリ作成
mkdir -p data
# データベースファイル作成とスキーマ適用
sqlite3 data/license_system.db < schema.sql
# データベース確認
sqlite3 data/license_system.db
スキーマ確認
-- SQLiteプロンプトで実行
.tables
-- 出力:
-- users subscriptions licenses rate_limits devices
.schema users
-- 出力:
-- CREATE TABLE users (
-- user_id TEXT PRIMARY KEY,
-- email TEXT UNIQUE NOT NULL,
-- password_hash TEXT NOT NULL,
-- created_at DATETIME DEFAULT CURRENT_TIMESTAMP
-- );
.quit
初期データの投入(テスト用)
# 初期データ投入スクリプト
sqlite3 data/license_system.db <<EOF
-- テストユーザーの追加(パスワード: test123)
INSERT INTO users (user_id, email, password_hash)
VALUES (
'test-user-001',
'test@example.com',
'\$2b\$10\$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy'
);
-- Premiumサブスクリプション
INSERT INTO subscriptions (subscription_id, user_id, plan_type, status, start_date, end_date)
VALUES (
'sub-001',
'test-user-001',
'premium_monthly',
'active',
datetime('now'),
datetime('now', '+30 days')
);
-- 確認
SELECT * FROM users;
SELECT * FROM subscriptions;
EOF
echo "✅ テストデータ投入完了"
🚀 ステップ5: サーバーのビルドと起動
サーバーのビルド
# サーバーディレクトリで実行
cd server
# Nimでサーバーをコンパイル
nim c -d:release src/main.nim
# 実行ファイルの確認
ls -lh src/main
# 出力例:
# -rwxr-xr-x 1 user group 2.3M Jun 15 10:00 src/main
環境変数の設定
# .envファイルを作成
cat > .env <<EOF
# サーバー設定
SERVER_PORT=8080
SERVER_HOST=localhost
# 鍵パス
PRIVATE_KEY_PATH=../keys/private_key.pem
PUBLIC_KEY_PATH=../keys/public_key.pem
# JWT設定
JWT_SECRET=your-super-secret-jwt-key-change-me-in-production
# データベース
DATABASE_PATH=data/license_system.db
# ログ設定
LOG_LEVEL=info
LOG_PATH=logs/application.log
EOF
# ログディレクトリ作成
mkdir -p logs
echo "✅ 環境変数設定完了"
サーバーの起動
# サーバー起動
./src/main
# 出力例:
# 🚀 License System Server v1.0.0
# 📍 Listening on http://localhost:8080
# 🔐 Crypto keys loaded
# 💾 Database connected: data/license_system.db
# ✅ Server ready!
動作確認(別ターミナル)
# ヘルスチェック
curl http://localhost:8080/health
# 出力:
# {"status":"ok","version":"1.0.0"}
# ライセンス認証テスト
curl -X POST http://localhost:8080/api/v1/license/activate \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "test123",
"client_id": "browser-extension-001"
}'
# 出力例:
# {
# "status": "activated",
# "activation_key": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
# "plan_type": "premium_monthly",
# "expires_at": "2026-06-15T00:00:00Z"
# }
🌐 ステップ6: WebAssemblyクライアントのビルド
クライアントディレクトリに移動
# プロジェクトルートから
cd ../client-wasm
WebAssemblyターゲットでのコンパイル
# Nim→JavaScript (WebAssembly互換) コンパイル
nim js -d:release src/license_client.nim
# 出力ファイル確認
ls -lh src/license_client.js
# 出力例:
# -rw-r--r-- 1 user group 45K Jun 15 10:05 src/license_client.js
# ビルドされたJavaScriptをブラウザ拡張機能にコピー
cp src/license_client.js ../browser-extension/js/
ビルドスクリプトの自動化(オプション)
# プロジェクトルートのbuild.shを使用
cd ..
chmod +x build.sh
# ビルドスクリプト実行
./build.sh
# 出力:
# 🔐 Generating ECDSA key pair...
# ✅ Keys generated
# 🖥️ Building server...
# ✅ Server built
# 🌐 Building WebAssembly client...
# ✅ Client built
# 📦 Copying to browser extension...
# ✅ Build complete!
🔌 ステップ7: ブラウザ拡張機能のロード
Chrome / Edgeでの拡張機能インストール
1. 拡張機能管理画面を開く
Chrome: chrome://extensions/
Edge: edge://extensions/
2. デベロッパーモードを有効化
右上の「デベロッパーモード」トグルをON
3. パッケージ化されていない拡張機能を読み込む
「パッケージ化されていない拡張機能を読み込む」をクリック
フォルダ選択:
nim-implementation/browser-extension/
読み込み完了後、拡張機能一覧に表示:
📦 License System Client
ID: abcdefghijklmnopqrstuvwxyz123456
バージョン: 1.0.0
拡張機能の動作確認
# 1. 拡張機能アイコンをクリック
# 2. ポップアップが表示される
# 3. ログインフォームが表示される
# テスト用アカウントでログイン:
Email: test@example.com
Password: test123
# 認証成功後:
✅ Authenticated
Plan: Premium Monthly
Expires: 2025-07-15
# デバッグコンソールで確認(F12 → Console)
console.log("License token:", localStorage.getItem("license_token"))
# 出力: eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...
✅ ステップ8: 動作確認とテスト
エコー機能のテスト
# サーバーが起動している状態で
curl -X POST http://localhost:8080/api/v1/echo \
-H "Content-Type: application/json" \
-H "X-Activation-Key: YOUR_JWT_TOKEN_HERE" \
-d '{
"message": "Hello, License System!"
}'
# 出力(Freeプラン: 最大100文字):
# {
# "echo": "Hello, License System!",
# "length": 24,
# "reversed": "!metsyS esneciL ,olleH",
# "plan": "free"
# }
# 出力(Premiumプラン: 最大1000文字):
# {
# "echo": "Hello, License System!",
# "length": 24,
# "reversed": "!metsyS esneciL ,olleH",
# "uppercase": "HELLO, LICENSE SYSTEM!",
# "plan": "premium_monthly"
# }
ブラウザ拡張機能でのテスト
// 拡張機能のContent Script内で実行
// 任意のWebページで右クリック → 検証 → Consoleタブ
// ライセンス検証
fetch("http://localhost:8080/api/v1/license/validate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Activation-Key": localStorage.getItem("license_token")
}
})
.then(res => res.json())
.then(data => console.log("License validation:", data));
// 出力:
// {
// "status": "valid",
// "premium": true,
// "plan_type": "premium_monthly",
// "expires_at": "2025-07-15T00:00:00Z"
// }
レート制限のテスト
# 同じエンドポイントに連続リクエスト
for i in {1..15}; do
echo "Request $i:"
curl -X POST http://localhost:8080/api/v1/echo \
-H "Content-Type: application/json" \
-H "X-Activation-Key: YOUR_JWT_TOKEN_HERE" \
-d '{"message": "Test"}' \
-w "\nStatus: %{http_code}\n" \
-s
sleep 0.5
done
# 出力例(Freeプラン: 10 requests/hour):
# Request 1: Status: 200
# Request 2: Status: 200
# ...
# Request 10: Status: 200
# Request 11: Status: 429 ← レート制限超過
# {
# "error": "Rate limit exceeded",
# "retry_after": 3540
# }
🔍 ステップ9: ログの確認
サーバーログの確認
# アプリケーションログ(構造化JSON)
tail -f server/logs/application.log
# 出力例:
# {
# "timestamp": "2025-06-15T10:30:45Z",
# "level": "INFO",
# "message": "License activation request",
# "module": "main",
# "function": "activate",
# "request_id": "req-12345678",
# "metadata": {
# "email": "test@example.com",
# "client_id": "browser-extension-001"
# }
# }
エラーログのフィルタリング
# エラーレベルのみ抽出
cat server/logs/application.log | jq 'select(.level == "ERROR")'
# 出力例:
# {
# "timestamp": "2025-06-15T10:35:12Z",
# "level": "ERROR",
# "message": "Invalid credentials",
# "module": "main",
# "function": "activate",
# "request_id": "req-87654321",
# "metadata": {
# "error": "Invalid email or password"
# }
# }
🐛 トラブルシューティング
よくある問題と解決策
問題1: Nimがインストールされていない
# 症状
bash: nim: command not found
# 解決策
curl https://nim-lang.org/choosenim/init.sh -sSf | sh
export PATH=$HOME/.nimble/bin:$PATH
source ~/.bashrc
問題2: OpenSSL鍵生成エラー
# 症状
Error: unable to load EC parameters
# 解決策
# OpenSSLのバージョン確認
openssl version # 1.1.1以上必要
# Linuxの場合
sudo apt update && sudo apt install openssl libssl-dev
# macOSの場合
brew install openssl@3
export PATH="/usr/local/opt/openssl@3/bin:$PATH"
問題3: サーバー起動時のポート競合
# 症状
Error: Address already in use (port 8080)
# 解決策1: ポートを変更
export SERVER_PORT=8081
./src/main
# 解決策2: 既存プロセスを停止
lsof -i :8080 # PIDを確認
kill -9 <PID>
問題4: データベース接続エラー
# 症状
Error: unable to open database file
# 解決策
# データディレクトリの確認
ls -la server/data/
# パーミッション修正
chmod 755 server/data/
chmod 644 server/data/license_system.db
# スキーマ再適用
cd server
sqlite3 data/license_system.db < schema.sql
問題5: ブラウザ拡張機能が読み込めない
# 症状
Manifest version 2 is deprecated...
# 解決策
# manifest.jsonのバージョン確認
cat browser-extension/manifest.json | grep manifest_version
# 出力: "manifest_version": 3
# Chrome/Edgeが最新版か確認
# chrome://settings/help
# edge://settings/help
# Manifest V3対応ブラウザが必要:
# Chrome 88+, Edge 88+
問題6: CORS エラー
# 症状
Access to fetch at 'http://localhost:8080' from origin 'chrome-extension://...' has been blocked by CORS policy
# 解決策
# server/src/main.nim のCORS設定確認
# すでに設定されているはず:
resp.setHeader("Access-Control-Allow-Origin", "*")
resp.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
resp.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Activation-Key")
# サーバー再起動
pkill -f main
cd server && ./src/main
問題7: WebAssemblyコンパイルエラー
# 症状
Error: expression 'js' cannot be used in this mode
# 解決策
# JavaScriptターゲット指定を明示
nim js -d:release src/license_client.nim
# コンパイラバージョン確認
nim --version # 2.0.0以上必要
# 必要に応じてアップグレード
choosenim update stable
📊 システム状態の確認
ヘルスチェックダッシュボード
# サーバー状態確認
curl http://localhost:8080/health | jq
# データベース統計
sqlite3 server/data/license_system.db <<EOF
SELECT
'Users' AS table_name, COUNT(*) AS count FROM users
UNION ALL
SELECT 'Subscriptions', COUNT(*) FROM subscriptions
UNION ALL
SELECT 'Licenses', COUNT(*) FROM licenses
UNION ALL
SELECT 'Devices', COUNT(*) FROM devices;
EOF
# 出力例:
# table_name count
# Users 1
# Subscriptions 1
# Licenses 0
# Devices 0
リソース使用状況
# サーバープロセスのメモリ使用量
ps aux | grep main | grep -v grep
# 出力例:
# user 12345 0.1 0.3 45672 12345 ? Sl 10:00 0:00 ./src/main
# ポート監視
netstat -an | grep 8080
# 出力例:
# tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN
🎉 セットアップ完了チェックリスト
完了項目:
✅ Nim 2.0.0以上がインストールされている
✅ OpenSSL 1.1.1以上がインストールされている
✅ ECDSA P-256鍵ペアが生成されている
✅ SQLiteデータベースが初期化されている
✅ サーバーが起動して http://localhost:8080 で応答する
✅ WebAssemblyクライアントがビルドされている
✅ ブラウザ拡張機能がロードされている
✅ テストアカウントでライセンス認証できる
✅ エコー機能が正常に動作する
✅ レート制限が機能している
✅ ログが正常に出力されている
トラブルシューティング:
✅ 各種エラーの解決策を把握している
✅ ログの確認方法を理解している
✅ システム状態の監視方法を知っている
🌟 次のステップ
セットアップが完了したら、次は以下のステップに進みましょう:
-
テストシナリオの実行 (Day 21)
- 単体テスト
- 統合テスト
- E2Eテスト
-
スケーラビリティの向上 (Day 22)
- ロードバランシング
- データベースシャーディング
- キャッシング戦略
-
機能拡張 (Day 23)
- 高度な機能追加
- カスタマイズ方法
-
本番デプロイ (Day 24)
- Docker化
- CI/CDパイプライン
- クラウドデプロイ
🌟 まとめ
セットアップガイドの要点:
-
環境構築
- Nim 2.0.0+
- OpenSSL 1.1.1+
- SQLite 3.35+
-
鍵管理
- ECDSA P-256鍵ペア生成
- 適切なパーミッション設定
- 環境変数での管理
-
サーバー起動
- Nimコンパイル
- データベース初期化
- ログ設定
-
クライアント構築
- Nim→JavaScript変換
- ブラウザ拡張機能統合
- 動作確認
-
トラブルシューティング
- 一般的な問題と解決策
- ログ確認方法
- システム監視
前回: Day 19: エラーハンドリングとロギング
次回: Day 21: テストシナリオと検証方法
Happy Learning! 🎉