{" resume resume "}
…lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elementum, eros at sagittis facilisis, ante est rutrum ligula, at interdum eros sapien vel magna.
☁️ みーきゅんクラウド Nextcloudサービス設計書
引き継ぎ用 / 詳細版
1. サービス概要
Nextcloudは、みーきゅんクラウドにおける 顧客向けクラウドストレージ基盤 である。単なるファイル置き場ではなく、VPN、顧客ポータル、将来のOffice連携、ストレージ販売を束ねる中心サービスとして位置づける。
- ファイルストレージ
- WebDAV
- モバイル同期
- 将来のOffice/Collabora統合
- 顧客ポータルとの連携
- VPN利用者向けプライベートクラウド
2. 全体構成
User ↓ HTTPS / VPN Portal / Reverse Proxy ↓ R640 ↓ Docker Nextcloud Container ↓ NFS Supermicro Storage ↓ /srv/storage
“`
| 層 | 配置 | 役割 |
|---|---|---|
| Edge | VPS / 将来のReverse Proxy | 外部入口 |
| Control | R640 | Nextcloudアプリ、ポータル、VPN |
| Storage | Supermicro | 実データ保管 |
| Network | VLAN30 | NFS / Storage LAN |
“`
3. 実行環境
| 項目 | 内容 |
|---|---|
| ホスト | R640 |
| 方式 | Docker |
| OS | Ubuntu |
| データ保存 | NFS マウント経由 |
| バックエンドストレージ | Supermicro / LUKS / LVM / 約66TB |
“`
想定コンテナ
| コンテナ | 役割 |
|---|---|
| nextcloud | アプリ本体 |
| nginx or apache | Web配信 |
| redis | キャッシュ / ロック |
| mariadb | DB |
“`
4. データパス
Nextcloud ↓ /mnt/maguro/nextclouddata ↓ NFS mount 192.168.30.30:/nextclouddata ↓ Supermicro /srv/storage
“`
| 項目 | 内容 |
|---|---|
| NFS Export | 192.168.30.30:/nextclouddata |
| R640側マウント | /mnt/maguro/nextclouddata |
| 保存先実体 | Supermicro /srv/storage |
重要: Nextcloud本体はR640、実データ本体はSupermicro。この役割分離が、みーきゅんクラウドの設計上の基本。
“`
5. ネットワーク設計
| ネットワーク | 用途 | 備考 |
|---|---|---|
| VLAN10 | 管理 | Nextcloud運用管理、SSH、OOB |
| VLAN20 | サービス本線 | R640の主通信 |
| VLAN30 | ストレージ | NFS / 内部専用 |
| VLAN50 | 更新 | OS更新系 |
“`
Nextcloudデータ通信は VLAN30 を使う。管理・公開・更新・ストレージを分けることで、障害時の切り分けが容易になる。
“`
6. アクセス方式
“`
Web
https://cloud.mikyun.example
WebDAV
https://cloud.mikyun.example/remote.php/dav/files/
モバイル
- Nextcloud App
- WebDAVクライアント
- VPN経由優先
“`
7. 顧客ポータルとの関係
Nextcloudは単体運用ではなく、顧客ポータルの一部として扱う。
“`
| ポータル表示項目 | 内容 |
|---|---|
| ログイン情報 | Nextcloudユーザー名 / 接続先URL |
| 容量 | 契約容量 / 利用量 |
| 状態 | active / disabled など |
| 将来機能 | パスワード再発行、クォータ変更反映 |
“`
8. セキュリティ設計
- 通信: HTTPS
- 内部データ通信: VLAN30
- 保存データ: LUKS暗号化ストレージ
- 入口: VPNまたはReverse Proxy
- 管理操作: admin_logs / 将来 portal_logs で追跡
9. バックアップ対象
- Nextcloud data
- DB
- 設定ファイル
- reverse proxy設定
- ポータルとの連携設定
“`
基本方針
borg backup ``` + DB dump + 設定退避
10. 将来拡張
- Collabora / Office統合
- Nextcloudユーザーの自動作成
- ポータルからクォータ同期
- オブジェクトストレージ化(将来Ceph)
- VPS経由の外部公開最適化
🌐 顧客ポータル完全設計書
Nextcloud / WireGuard / 契約情報を束ねる統合UI
1. 目的
顧客ポータルは、みーきゅんクラウドにおける 顧客セルフ操作基盤 である。利用者はこの画面から、自分の契約、端末、VPN設定、Nextcloud情報を確認・操作する。
- 契約状態確認
- 親端末 / 子端末管理
- WireGuard QR再発行
- 一時停止 / 復帰
- ストレージ利用状況確認
- 将来の請求 / 通知 / パスワード管理
2. 設計思想
“`
セルフサービス
運営手動作業を減らし、顧客が自分で操作できる範囲を広げる。
Zero Trust
重要操作は再認証、親端末承認、場合により電話認証を組み合わせる。
親端末中心
契約の中心となる親端末を1台持ち、追加端末は子端末として扱う。
“`
3. システム構成
顧客 ↓ Portal UI ↓ FastAPI ├ DB (mikyun_cloud) ├ WireGuard engine ├ QR生成 ├ Config出力 └ 将来 Nextcloud連携
“`
| 配置 | 内容 |
|---|---|
| ホスト | R640 |
| 実装 | FastAPI / uvicorn |
| 主要コード | /opt/mikyun-portal/app.py, /opt/mikyun-portal/app/main.py |
| 内部エンジン | /opt/mikyun-portal/mikyun_vpn_engine.py |
| 補助発行スクリプト | /opt/mikyun-admin/add_customer.sh, add_customer_full.sh |
“`
4. 顧客モデル
“`
| 単位 | 内容 |
|---|---|
| 契約 | 1顧客 = 1契約。契約ID、容量、端末上限、帯域、VPNサブネットを持つ。 |
| 端末 | 契約配下に複数端末を持つ。親端末1台 + 子端末複数。 |
契約状態
active / paused / terminated / deleted
端末状態
issued / active / paused / revoked / expired
“`
5. 親端末 / 子端末ルール
- 親端末: 契約の中心端末。重要操作可能。
- 子端末: 追加端末。利用はできるが重要操作不可。
- 親端末紛失時: 電話認証 + 本人確認パスフレーズ + 管理者承認。
- v_parent_conflicts により親端末重複を監査。
6. 主要機能
“`
| 顧客向け | 内容 |
|---|---|
| 契約確認 | 契約状態、容量、端末数、プラン確認 |
| 端末一覧 | 親 / 子、状態、最終接続、WG IP |
| 端末追加 | 子端末を新規発行 |
| QR再表示 | WG設定再取得 |
| 一時停止 / 復帰 | 端末単位制御 |
| Nextcloud情報 | 接続先・ユーザー名・容量(将来自動取得) |
| 管理者向け | 内容 |
|---|---|
| 顧客作成 | 契約作成 + 親端末初回発行 |
| 容量変更 | 契約ストレージ上限変更 |
| 契約停止 / 解約 | 状態変更 |
| 親端末昇格 | child → parent 切替 |
| 監査ログ閲覧 | admin_logs |
“`
7. 生成物と保存場所
/opt/mikyun/output/client-configs /opt/mikyun/output/qr
“`
発行物:
- WireGuard .conf
- QRコードPNG
- 端末説明文(将来)
“`
8. Nextcloudとの連携方針
- 契約に対してNextcloudユーザーを1:1で管理
- ポータル画面にクォータ・使用量・URLを表示
- 将来は契約作成時にNextcloudユーザー自動生成
- 契約停止時にアカウント凍結も可能にする
9. 画面一覧
| 画面 | 内容 |
|---|---|
| 顧客トップ | 契約状態、親端末、利用量、通知 |
| 端末管理 | 端末一覧、追加、停止、QR再発行 |
| ストレージ | Nextcloud接続先、容量、使用量 |
| 管理者一覧 | 顧客一覧、検索、状態変更 |
| 管理者詳細 | 契約・端末・ログを統合表示 |
10. 顧客ポータル接続ポリシー(確定版)
10.1 親IP制
顧客ポータルへ接続できる端末は 親IP 1台のみ とする。
契約単位で以下の構造を持つ。
契約ID: A001 ├ 親IP(Portalアクセス可能) ├ 子IP └ 子IP
“`
親IPが利用できる機能
親IPのみ以下の機能を使用可能とする。
顧客ポータルログイン ``` 契約情報確認 端末一覧表示 QR再発行申請 親端末変更 利用状況確認
“`
子IPの権限
子IPは以下のみ許可。
Nextcloud ``` WebDAV VPN通信 サービス利用
“`
以下は 禁止
顧客ポータルアクセス ``` 契約操作 QR再発行
10.2 親IPの初回発行
初回の親IP発行は 運営のみ実施可能。
“`
操作場所
管理ポータル(wg0)
理由
顧客が初回親端末を自由に設定できると ``` 乗っ取りリスクが発生するため
“`
フロー
顧客契約作成 │ ``` 管理ポータル │ 親IP発行 │ QR発行
10.3 親端末の機種変更
親端末の移行は 既存の子IPからの格上げのみ 許可。
“`
例
現在 ``` A001 ├ 親IP 10.201.10.2 ├ 子IP 10.201.10.3 └ 子IP 10.201.10.4
“`
顧客が子IP 10.201.10.3 を選択
結果
A001 ``` ├ 親IP 10.201.10.3 ├ 子IP 10.201.10.2 └ 子IP 10.201.10.4
“`
つまり
新親 = 選択された子IP ``` 旧親 = 自動降格
10.4 親移行の条件
通常の親移行には 現在の親端末の同意が必須。
“`
操作フロー
親端末 ``` │ 顧客管理画面 │ 子IP一覧表示 │ 次の親を選択 │ 親変更実行
“`
この操作は 親IPからのみ実行可能。
つまり
子IPからは親変更不可
“`
10.5 親端末紛失時
親端末が紛失した場合のみ
運営による救済操作を行う。
救済操作は wg0 管理ポータルからのみ可能。
“`
救済フロー
顧客 ``` │ 電話サポート │ 本人確認 │ 管理画面(wg0) │ 親IP再設定 │ 新QR発行
10.6 本人確認方式
親端末紛失時の救済には
本人確認パスフレーズを使用する。
登録時に顧客へ設定させる。
“`
例
本人確認パスフレーズ ``` 例 ・ペットの名前 ・好きな食べ物 ・秘密のキーワード
“`
電話認証時
顧客 ``` ↓ パスフレーズ回答 ↓ 一致 ↓ 親IP再設定
10.7 セキュリティ意図
この設計の目的
端末乗っ取り防止 ポータル乗っ取り防止 QR悪用防止 アカウント保護
“`
つまり
契約管理は常に1端末のみ
“`
システム内部ロジック(重要)
DBにはこのフラグを持たせます。
device_role parent child
“`
例
device_id ``` contract_id wg_ip device_role created_at last_seen
“`
親IP判定
ポータルアクセス時
if device_role != parent access deny
親変更処理
BEGIN ``` old_parent → child selected_child → parent COMMIT
非常に良いポイント
この設計の強みは
QR盗難 端末乗っ取り ログイン奪取
“`
をかなり防げます。
普通のVPNサービスは
ログインID ``` パスワード
“`
ですが
みーきゅんクラウドは
端末単位管理
です。
これは かなり強い設計です。
“`
次にやる候補
もしよければ次に
このシステムで一番重要な
「顧客IP管理テーブル(完全設計)」
を作ります。
“`
これができると
親IP ``` 子IP QR 契約 トラフィック
“`
全部のDBが確定します。
“`
📘 みーきゅんクラウド
顧客IP管理テーブル(完全設計)
🎯 目的
このテーブルは以下を一元管理する。
契約 親IP / 子IP QR発行 端末状態 親変更 再発行 停止 失効 通信量
“`
つまり
顧客VPN管理の中核テーブル です。
“`
1. 基本思想
“`
1.1 契約単位
1契約 = 1顧客ID
例
A001 ``` A002 A003
“`
1.2 端末単位
1契約に複数のWG IPを紐づける。
例
A001 ``` ├ 親IP ├ 子IP └ 子IP
“`
1.3 親IP制
契約管理操作ができるのは 親IP 1台のみ。
“`
2. テーブル名
おすすめ:
customer_devices
3. カラム設計
“`
3.1 必須カラム
| カラム名 | 型 | 意味 |
|---|---|---|
| id | BIGINT PK | レコードID |
| contract_id | VARCHAR(32) | 顧客契約ID |
| device_id | VARCHAR(64) | 端末識別ID |
| wg_iface | VARCHAR(32) | 利用WG IF名 |
| wg_ip | VARCHAR(64) | 割当IP |
| public_key | TEXT | WireGuard公開鍵 |
| preshared_key | TEXT NULL | PSK |
| device_role | VARCHAR(16) | parent / child |
| status | VARCHAR(16) | issued/active/paused/revoked/expired |
| device_name | VARCHAR(128) NULL | 端末名 |
| platform | VARCHAR(64) NULL | iPhone / Android / Windows 等 |
| created_at | DATETIME | 作成日時 |
| updated_at | DATETIME | 更新日時 |
3.2 QR / 発行管理
| カラム名 | 型 | 意味 |
|---|---|---|
| issued_at | DATETIME NULL | QR発行日時 |
| qr_expires_at | DATETIME NULL | QR失効日時 |
| first_handshake_at | DATETIME NULL | 初回接続日時 |
| last_handshake_at | DATETIME NULL | 最終接続日時 |
| activated_at | DATETIME NULL | 有効化日時 |
3.3 親IP制御
| カラム名 | 型 | 意味 |
|---|---|---|
| is_parent | BOOLEAN | 親端末か |
| parent_changed_at | DATETIME NULL | 親変更日時 |
| parent_changed_by | VARCHAR(64) NULL | customer / admin |
| parent_change_reason | VARCHAR(255) NULL | 変更理由 |
※ device_role と is_parent は二重化なので、実装はどちらか片方でもよいです。
ただし検索性のため is_parent を持つのは便利です。
3.4 停止・失効管理
| カラム名 | 型 | 意味 |
|---|---|---|
| paused_at | DATETIME NULL | 一時停止日時 |
| pause_reason | VARCHAR(255) NULL | 一時停止理由 |
| pause_expires_at | DATETIME NULL | 一時停止期限 |
| revoked_at | DATETIME NULL | 無効化日時 |
| revoked_reason | VARCHAR(255) NULL | 無効化理由 |
| expired_at | DATETIME NULL | QR期限切れ日時 |
3.5 救済・本人確認系
| カラム名 | 型 | 意味 |
|---|---|---|
| recovery_required | BOOLEAN | 親紛失救済中フラグ |
| recovery_requested_at | DATETIME NULL | 救済要求日時 |
| recovery_completed_at | DATETIME NULL | 救済完了日時 |
| recovery_by | VARCHAR(64) NULL | 実施管理者 |
3.6 通信量管理
| カラム名 | 型 | 意味 |
|---|---|---|
| rx_bytes_total | BIGINT DEFAULT 0 | 累計受信 |
| tx_bytes_total | BIGINT DEFAULT 0 | 累計送信 |
| rx_bytes_24h | BIGINT DEFAULT 0 | 24時間受信 |
| tx_bytes_24h | BIGINT DEFAULT 0 | 24時間送信 |
| rx_bytes_7d | BIGINT DEFAULT 0 | 7日受信 |
| tx_bytes_7d | BIGINT DEFAULT 0 | 7日送信 |
| current_rx_bps | BIGINT DEFAULT 0 | 現在受信速度 |
| current_tx_bps | BIGINT DEFAULT 0 | 現在送信速度 |
3.7 管理メモ
| カラム名 | 型 | 意味 |
|---|---|---|
| notes | TEXT NULL | 管理メモ |
| admin_tags | VARCHAR(255) NULL | 異常/注意タグ |
| deleted_at | DATETIME NULL | 論理削除日時 |
“`
4. 状態定義
“`
status
| 値 | 意味 |
|---|---|
| issued | QR発行済み・未使用 |
| active | 利用中 |
| paused | 一時停止 |
| revoked | 無効化 |
| expired | QR期限切れ |
“`
5. 状態遷移
issued ↓ 初回ハンドシェイク active ↓ 一時停止 paused ↓ 再開 active ↓ 強制停止 revoked
“`
期限切れ
issued ``` ↓ 24時間経過 expired
6. 親IPルール
“`
6.1 原則
1契約につき parent は1台のみ
6.2 制約
DB制約として、理想は
contract_id ごとに is_parent = true は1件のみ
6.3 親変更
通常の親変更は 親IPからのみ 実行。
処理:
旧親 is_parent = false ``` 新親 is_parent = true
“`
6.4 親紛失
親紛失時のみ
管理画面(wg0)
から管理者が再設定。
“`
7. QRルール
“`
7.1 発行
新規端末発行時
status = issued ``` issued_at = 現在時刻 qr_expires_at = 現在時刻 + 24h
“`
7.2 初回接続
初回ハンドシェイクで
first_handshake_at = now ``` activated_at = now status = active
“`
7.3 再発行
再発行時
- 旧端末
revoked - 新端末
issued
“`
8. 親端末変更フロー
“`
通常
親IPでログイン ``` ↓ 子IP一覧表示 ↓ 次の親を選択 ↓ 確認 ↓ 親変更
“`
DB処理
BEGIN ``` UPDATE customer_devices SET is_parent = 0, device_role = 'child' WHERE contract_id = :contract_id AND is_parent = 1; UPDATE customer_devices SET is_parent = 1, device_role = 'parent', parent_changed_at = NOW(), parent_changed_by = 'customer', parent_change_reason = 'customer self migration' WHERE id = :selected_device_id AND contract_id = :contract_id AND status = 'active'; COMMIT
9. 親紛失救済フロー
顧客 ↓ 電話サポート ↓ 本人確認パスフレーズ確認 ↓ 管理画面(wg0) ↓ 子IPまたは新IPを親へ設定
“`
管理側ログ
parent_changed_by = 'admin' ``` parent_change_reason = 'lost parent recovery' recovery_completed_at = now
10. 削除通知を送らないボタンとの連携
これは契約テーブル側が本体ですが、端末管理とも連携するためここでも整理します。
“`
契約テーブル側で持つ項目
predelete_notice_suppressed ``` predelete_notice_suppressed_reason predelete_notice_suppressed_at predelete_notice_suppressed_by
“`
用途
- 電話で本人確認済み
- 本人希望で通知不要
- 即時削除
- 個別連絡済み
- 迷惑利用対応
“`
11. インデックス
最低これを貼ります。
CREATE INDEX idx_customer_devices_contract_id ON customer_devices(contract_id); CREATE INDEX idx_customer_devices_wg_ip ON customer_devices(wg_ip); CREATE UNIQUE INDEX uq_customer_devices_public_key ON customer_devices(public_key); CREATE INDEX idx_customer_devices_status ON customer_devices(status); CREATE INDEX idx_customer_devices_last_handshake ON customer_devices(last_handshake_at);
12. 実用上のおすすめ追加カラム
あると後で助かるもの。
| カラム名 | 意味 |
|---|---|
| app_version | クライアントバージョン |
| last_seen_ip | 最後に見えたグローバルIP |
| last_seen_user_agent | 端末情報 |
| bandwidth_profile | 帯域制限プロファイル |
| portal_access_enabled | ポータル接続可否 |
13. SQLたたき台
CREATE TABLE customer_devices ( id BIGINT AUTO_INCREMENT PRIMARY KEY, contract_id VARCHAR(32) NOT NULL, device_id VARCHAR(64) NOT NULL, wg_iface VARCHAR(32) NOT NULL DEFAULT 'wg1', wg_ip VARCHAR(64) NOT NULL, public_key TEXT NOT NULL, preshared_key TEXT NULL, device_role VARCHAR(16) NOT NULL DEFAULT 'child', is_parent BOOLEAN NOT NULL DEFAULT FALSE, status VARCHAR(16) NOT NULL DEFAULT 'issued', device_name VARCHAR(128) NULL, platform VARCHAR(64) NULL, issued_at DATETIME NULL, qr_expires_at DATETIME NULL, first_handshake_at DATETIME NULL, last_handshake_at DATETIME NULL, activated_at DATETIME NULL, parent_changed_at DATETIME NULL, parent_changed_by VARCHAR(64) NULL, parent_change_reason VARCHAR(255) NULL, paused_at DATETIME NULL, pause_reason VARCHAR(255) NULL, pause_expires_at DATETIME NULL, revoked_at DATETIME NULL, revoked_reason VARCHAR(255) NULL, expired_at DATETIME NULL, recovery_required BOOLEAN NOT NULL DEFAULT FALSE, recovery_requested_at DATETIME NULL, recovery_completed_at DATETIME NULL, recovery_by VARCHAR(64) NULL, rx_bytes_total BIGINT NOT NULL DEFAULT 0, tx_bytes_total BIGINT NOT NULL DEFAULT 0, rx_bytes_24h BIGINT NOT NULL DEFAULT 0, tx_bytes_24h BIGINT NOT NULL DEFAULT 0, rx_bytes_7d BIGINT NOT NULL DEFAULT 0, tx_bytes_7d BIGINT NOT NULL DEFAULT 0, current_rx_bps BIGINT NOT NULL DEFAULT 0, current_tx_bps BIGINT NOT NULL DEFAULT 0, portal_access_enabled BOOLEAN NOT NULL DEFAULT FALSE, bandwidth_profile VARCHAR(64) NULL, notes TEXT NULL, admin_tags VARCHAR(255) NULL, deleted_at DATETIME NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
14. 運用ルールの一文
customer_devices テーブルは、契約単位の WireGuard 端末管理の中核テーブルとし、親IP/子IP、QR発行状態、停止・失効状態、通信量、親変更履歴、救済操作履歴を一元管理する。顧客ポータルへのアクセス可否は親IPのみに限定し、通常の親変更は親端末からのみ実行可能とする。親端末紛失時のみ、管理画面(wg0)から本人確認パスフレーズを用いて救済操作を行う。
次の作業
次は contracts テーブル と delete queue / notice suppression を含む契約管理テーブル を続けて固めます。
🔌 顧客ポータル API設計書
1. APIの役割
ポータルAPIは、画面とDB・WireGuard・将来のNextcloud連携を結ぶ中核レイヤである。
画面 ↓ FastAPI ├ contracts 読み書き ├ customer_devices 読み書き ├ admin_logs 記録 ├ WG設定生成 └ 将来 Nextcloud 同期
2. 実装候補ファイル
- /opt/mikyun-portal/app.py
- /opt/mikyun-portal/app/main.py
- /opt/mikyun-portal/mikyun_vpn_engine.py
3. 顧客向けAPI
| Method | Path | 用途 |
|---|---|---|
| GET | /api/me | 契約基本情報 |
| GET | /api/me/devices | 自端末一覧 |
| POST | /api/me/devices | 子端末追加 |
| POST | /api/me/devices/{device_id}/pause | 端末一時停止 |
| POST | /api/me/devices/{device_id}/resume | 停止解除 |
| POST | /api/me/devices/{device_id}/regen | 設定再発行 |
| GET | /api/me/devices/{device_id}/qr | QR再表示 |
| GET | /api/me/storage | 容量表示(将来) |
4. 管理者API
| Method | Path | 用途 |
|---|---|---|
| GET | /api/admin/contracts | 契約一覧 |
| GET | /api/admin/contracts/{contract_id} | 契約詳細 |
| POST | /api/admin/contracts | 新規契約作成 + 親端末初回発行 |
| POST | /api/admin/contracts/{contract_id}/pause | 契約停止 |
| POST | /api/admin/contracts/{contract_id}/terminate | 解約 |
| POST | /api/admin/contracts/{contract_id}/quota | 容量変更 |
| GET | /api/admin/devices | 端末一覧 |
| POST | /api/admin/devices/{device_id}/promote | 親端末昇格 |
| POST | /api/admin/devices/{device_id}/revoke | 端末失効 |
| GET | /api/admin/logs | 監査ログ閲覧 |
5. 内部VPNエンジンAPI
| Method | Path | 用途 |
|---|---|---|
| POST | /internal/wg/issue-parent | 親端末発行 |
| POST | /internal/wg/issue-child | 子端末発行 |
| POST | /internal/wg/reload | wg reload |
| GET | /internal/wg/status | DBとwg実状態の比較 |
| POST | /internal/wg/pause | peer無効化 |
| POST | /internal/wg/resume | peer再有効化 |
| POST | /internal/wg/revoke | peer削除 |
6. 将来のNextcloud連携API
| Method | Path | 用途 |
|---|---|---|
| POST | /internal/nextcloud/users | 契約作成時にNCユーザー作成 |
| PATCH | /internal/nextcloud/users/{contract_id}/quota | 容量同期 |
| GET | /internal/nextcloud/users/{contract_id}/usage | 使用量取得 |
| POST | /internal/nextcloud/users/{contract_id}/disable | 停止・凍結 |
7. APIとDBの対応
| テーブル | 関わる主API |
|---|---|
| contracts | /api/me, /api/admin/contracts, quota変更, 停止, 解約 |
| customer_devices | 端末一覧、追加、停止、復帰、昇格、失効、QR再発行 |
| admin_logs | 全管理操作の監査ログ |
🗃 DBテーブル一覧(mikyun_cloud)
1. DB概要
“`
| DB名 | 内容 |
|---|---|
| mikyun_cloud | 契約・端末・管理ログを持つポータルDB |
現状オブジェクト
- admin_logs
- contracts
- customer_devices
- v_parent_conflicts (VIEW)
“`
2. contracts
契約本体。顧客ID、サブネット、容量、上限、状態を持つ。
“`
| カラム | 意味 |
|---|---|
| contract_id | 契約ID |
| vpn_subnet | 顧客用VPNサブネット |
| next_child_ip | 次の子端末割当IP |
| customer_name / email / phone | 顧客情報 |
| plan_name | プラン名 |
| storage_quota_gb | ストレージ上限 |
| max_devices | 端末上限 |
| max_files | ファイル数上限 |
| bandwidth_profile | 帯域プロファイル |
| contract_status | active / paused / terminated / deleted |
| identity_passphrase | 本人確認パスフレーズ |
“`
3. customer_devices
契約配下の端末 + WireGuard peer 情報。
“`
| カテゴリ | カラム |
|---|---|
| ID | device_id, contract_id |
| WG | wg_iface, wg_ip, public_key, private_key, preshared_key |
| 役割 | device_role, is_parent |
| 状態 | status, issued_at, activated_at, paused_at, revoked_at, expired_at |
| 回復 | recovery_required, recovery_requested_at, recovery_completed_at |
| 統計 | rx_bytes_total, tx_bytes_total, rx_bytes_24h, tx_bytes_24h, rx_bytes_7d, tx_bytes_7d, current_rx_bps, current_tx_bps |
| 端末情報 | device_name, platform, app_version, last_seen_ip, last_seen_user_agent |
| 運用 | portal_access_enabled, bandwidth_profile, notes, admin_tags |
“`
4. admin_logs
管理操作の監査ログ。
“`
| カラム | 意味 |
|---|---|
| action_type | 操作種別 |
| target_type | contract / device |
| target_id | 対象ID |
| message | 詳細メッセージ |
| created_at | 実行時刻 |
“`
5. v_parent_conflicts
同一契約に親端末が複数いないか監査するVIEW。
is_parent = 1 AND deleted_at IS NULL GROUP BY contract_id HAVING COUNT(*) > 1
🧩 DB ER図(関係図)
1. 現状ER図
+------------------+
| contracts |
+------------------+
| contract_id (UK) |
| vpn_subnet |
| next_child_ip |
| customer_name |
| plan_name |
| storage_quota_gb |
| max_devices |
| contract_status |
| identity_passphrase |
+------------------+
|
| 1:N
v
+-----------------------+
| customer_devices |
+-----------------------+
| device_id (UK) |
| contract_id |
| wg_iface |
| wg_ip (UK) |
| public_key |
| preshared_key |
| device_role |
| is_parent |
| status |
| device_name |
| portal_access_enabled |
| recovery_required |
| ... |
+-----------------------+
+------------------+
| admin_logs |
+------------------+
| action_type |
| target_type |
| target_id |
| message |
+------------------+
+------------------------+
| v_parent_conflicts |
| (VIEW) |
+------------------------+
| contract_id |
| parent_count |
+------------------------+2. 関係の意味
- contracts → customer_devices: 1契約に複数端末。
- customer_devices → v_parent_conflicts: 親端末が2台以上いないか監査。
- admin_logs: FKは持たず、target_type / target_id で論理参照。
3. 完成形ER図(推奨拡張)
contracts
| | \__ 1:1 → nextcloud_accounts
|__ 1:N → customer_devices
|__ 1:N → notifications
\__ 1:1 or 1:N → portal_accounts
admin_logs
└ 管理操作監査“`
| 追加推奨テーブル | 理由 |
|---|---|
| portal_accounts | 顧客ログインアカウント |
| nextcloud_accounts | NCユーザー名・quota・使用量同期 |
| notifications | メンテ通知・警告通知 |
| portal_logs | 顧客側操作ログ |
“`
💡 理念とセールスポイント
1. 理念
“`
個人が自分のクラウドを持つ時代へ
みーきゅんクラウドは、広告モデルやブラックボックス管理に依存しない、利用者が理解できるクラウド を目指す。
データの主権はユーザーにある
- データはユーザーの所有物
- 不要なデータ収集はしない
- 構造を説明できる透明性を持つ
“`
2. セールスポイント
“`
| 項目 | 特徴 |
|---|---|
| 完全プライベートネットワーク | WireGuard前提で外部公開面を減らす |
| 端末単位管理 | 親端末 / 子端末という実用的モデル |
| 自動発行 | WG設定とQRを自動生成 |
| 大容量ストレージ | Supermicro + 暗号化 + 高速内部LAN |
| 自前インフラ | 自前DC設計で自由度が高い |
| 顧客ポータル | セルフ管理可能 |
“`
3. キャッチコピー案
- あなた専用のクラウド
- データは、あなたのもの。
- VPNの中にあるクラウド
- 個人のためのプライベートクラウド
🌐 みーきゅんクラウド / 07_API
Notion取り込み用HTML。引き継ぎ前提の詳細版。
7.1 APIの目的
顧客ポータルおよび管理機能は FastAPIベースのAPIサーバ で動作する。
“`
実装配置
/opt/mikyun-portal/ ``` ├─ app.py ├─ app/main.py ├─ mikyun_vpn_engine.py ├─ peers/ ├─ issued/ └─ venv/
“`
役割
- 顧客ポータル
- WireGuard発行
- QR生成
- DB操作
- 管理操作
“`
7.2 API全体構造
Client │ │ HTTPS │ Portal API │ ├─ DB (MariaDB: mikyun_cloud) ├─ WireGuard Engine ├─ Config生成 └─ QR生成
7.3 顧客API
“`
GET /api/me
ログイン中顧客の契約情報を返す。
{
```
"contract_id": "M010",
"customer_name": "みーきゅんわんわん",
"plan_name": "standard",
"contract_status": "active",
"storage_quota_gb": 200,
"max_devices": 3,
"max_files": 10000,
"bandwidth_profile": "standard"
}“`
GET /api/me/devices
自契約の端末一覧を返す。取得元は customer_devices。
[
```
{
"device_id": "M010-DEV-001",
"device_name": "mikyun-iphone",
"device_role": "parent",
"is_parent": true,
"status": "issued",
"wg_ip": "10.200.10.2",
"platform": "ios",
"portal_access_enabled": true
}
]“`
POST /api/me/devices
子端末追加。処理の流れは以下。
- 契約確認
contracts.next_child_ip取得- WG鍵生成
customer_devices登録- config生成
- QR生成
contracts.next_child_ip更新admin_logs記録
POST /api/me/devices/{device_id}/pause
端末一時停止。status = paused、paused_at、pause_reason を記録。
POST /api/me/devices/{device_id}/resume
停止端末再開。status = active へ遷移。
GET /api/me/devices/{device_id}/qr
QR再表示。親端末は子端末分も取得可、自端末分は本人のみ取得可。
POST /api/me/devices/{device_id}/regen
設定再発行。再利用または新鍵発行の方針を実装側で選択。
“`
7.4 管理API
“`
GET /api/admin/contracts
契約一覧。表示項目は契約ID、契約者名、状態、容量、端末上限、次回子IPなど。
GET /api/admin/contracts/{contract_id}
契約詳細。contracts 本体 + 端末一覧 + 最新ログを返す。
POST /api/admin/contracts
新規契約作成 + 親端末初回発行。
{
```
"contract_id": "M011",
"customer_name": "Example User",
"customer_email": "[user@example.com](mailto:user@example.com)",
"customer_phone": "09000000000",
"plan_name": "standard",
"storage_quota_gb": 200,
"max_devices": 3,
"max_files": 10000,
"bandwidth_profile": "standard",
"identity_passphrase": "example-passphrase",
"parent_device_name": "iphone-parent",
"platform": "ios"
}“`
POST /api/admin/contracts/{contract_id}/pause
契約停止。必要に応じて配下端末も一括停止。
POST /api/admin/contracts/{contract_id}/terminate
契約終了。terminated_at 記録、peer revoke、削除スケジュール準備。
POST /api/admin/contracts/{contract_id}/quota
容量変更。将来はNextcloud quota同期も実行。
POST /api/admin/devices/{device_id}/promote
子端末を親端末へ昇格。既存親はchildに降格し、v_parent_conflicts を壊さないよう更新。
POST /api/admin/devices/{device_id}/revoke
端末失効。status = revoked、revoked_at、revoked_reason を記録。
“`
7.5 内部VPNエンジンAPI
mikyun_vpn_engine.py が担当する想定。
“`
| 内部API | 用途 |
|---|---|
| POST /internal/wg/issue-parent | 親端末発行 |
| POST /internal/wg/issue-child | 子端末発行 |
| POST /internal/wg/reload | wg sync / reload |
| GET /internal/wg/status | DBと実WG状態の比較 |
| POST /internal/wg/pause | peer無効化 |
| POST /internal/wg/resume | peer再有効化 |
| POST /internal/wg/revoke | peer削除 |
“`
7.6 将来のNextcloud連携API
“`
| API | 用途 |
|---|---|
| POST /internal/nextcloud/users | NCユーザー作成 |
| PATCH /internal/nextcloud/users/{contract_id}/quota | 容量同期 |
| GET /internal/nextcloud/users/{contract_id}/usage | 使用量取得 |
| POST /internal/nextcloud/users/{contract_id}/disable | NC停止 |
“`
7.7 APIとDBの対応
“`
| 対象 | 読む / 書くAPI |
|---|---|
| contracts | 契約一覧、契約詳細、契約作成、停止、終了、容量変更 |
| customer_devices | 端末一覧、子端末追加、停止、再開、再発行、昇格、失効 |
| admin_logs | 管理操作全般の監査ログ |
“`
7.8 実装優先順位
- 契約一覧 / 契約詳細 / 端末一覧
- 子端末追加
- pause / resume
- QR再取得
- 親端末昇格 / revoke
- Nextcloud連携
🌐 みーきゅんクラウド / 08_DB
mikyun_cloud データベース現状まとめ。
8.1 DB基本情報
| 項目 | 内容 |
|---|---|
| DB名 | mikyun_cloud |
| エンジン | MariaDB |
| 配置 | R640 |
| 現サイズ | 約 0.3 MB |
8.2 テーブル一覧
| 種別 | 名前 | 用途 |
|---|---|---|
| TABLE | contracts | 契約本体 |
| TABLE | customer_devices | 顧客端末 / WireGuard端末 |
| TABLE | admin_logs | 管理操作ログ |
| VIEW | v_parent_conflicts | 親端末重複監査 |
8.3 contracts
顧客契約の本体テーブル。顧客ごとのVPNセグメント、上限値、状態を保持する。
“`
| カラム | 意味 |
|---|---|
| contract_id | 契約ID(例: A001, M010) |
| vpn_subnet | 契約ごとのVPNサブネット(例: 10.200.10.0/24) |
| next_child_ip | 次に払い出す子端末IP |
| customer_name / email / phone | 契約者情報 |
| plan_name | 契約プラン |
| storage_quota_gb | 容量上限 |
| max_devices | 端末上限 |
| max_files | ファイル上限 |
| bandwidth_profile | 帯域プロファイル |
| contract_status | active / paused / terminated / deleted |
| identity_passphrase | 本人確認パスフレーズ |
| notes / admin_tags | 運用補足 |
状態制約
active ``` paused terminated deleted
8.4 customer_devices
顧客ごとの端末管理テーブル。WireGuardの鍵・IP・状態・統計を持つ中核テーブル。
“`
| カテゴリ | 主要カラム |
|---|---|
| 識別 | device_id, contract_id |
| WireGuard | wg_iface, wg_ip, public_key, private_key, preshared_key |
| 端末属性 | device_role, is_parent, device_name, platform, app_version |
| 状態 | status, issued_at, activated_at, paused_at, revoked_at, expired_at |
| 親変更 | parent_changed_at, parent_changed_by, parent_change_reason |
| 復旧 | recovery_required, recovery_requested_at, recovery_completed_at, recovery_by |
| 統計 | rx_bytes_total, tx_bytes_total, rx_bytes_24h, tx_bytes_24h, rx_bytes_7d, tx_bytes_7d, current_rx_bps, current_tx_bps |
| 最終観測 | last_seen_ip, last_seen_user_agent, first_handshake_at, last_handshake_at |
| ポータル | portal_access_enabled |
| 備考 | bandwidth_profile, notes, admin_tags, deleted_at |
device_role 制約
parent ``` child
“`
status 制約
issued ``` active paused revoked expired
“`
ユニーク制約
- device_id
- wg_ip
- public_key(prefix 191)
“`
8.5 admin_logs
監査ログテーブル。管理APIや発行処理の結果を書き残す。
“`
| カラム | 意味 |
|---|---|
| action_type | 操作種別 |
| target_type | contract / device など |
| target_id | 契約IDまたは端末ID |
| message | 詳細メッセージ |
| created_at | 実行時刻 |
“`
8.6 v_parent_conflicts
親端末が複数存在する契約を検出する監査用VIEW。
is_parent = 1 AND deleted_at IS NULL GROUP BY contract_id HAVING COUNT(*) > 1
8.7 インデックス方針
“`
contracts
- PRIMARY(id)
- UNIQUE(contract_id)
- INDEX(contract_status)
- INDEX(delete_scheduled_at)
- INDEX(predelete_notice_sent_at)
- INDEX(predelete_notice_suppressed)
- INDEX(customer_email)
customer_devices
- PRIMARY(id)
- UNIQUE(device_id)
- UNIQUE(wg_ip)
- UNIQUE(public_key prefix)
- INDEX(contract_id)
- INDEX(status)
- INDEX(last_handshake_at)
- INDEX(contract_id, is_parent)
- INDEX(contract_id, status)
“`
8.8 現状評価
- 契約と端末が分離されている
- 親子端末思想がDBに入っている
- WG鍵・IP・状態・統計・復旧フラグまで持っている
- 監査ログと親端末重複チェックVIEWがある
8.9 将来追加推奨
- portal_accounts
- nextcloud_accounts
- notifications
- portal_logs
🌐 みーきゅんクラウド / 09_運用
日常運用・定期確認・保守作業の基準ページ。
9.1 運用対象
- R640(Control Node)
- Supermicro(Storage Node)
- VPS(Gateway)
- Cisco WS-C3850-12XS(CORE)
- Cisco WS-C3850-48T(ACCESS)
- RTX1300(Router)
9.2 日次確認
“`
R640
wg show ``` ip route docker ps df -h systemctl --failed
“`
Supermicro
df -h ``` lsblk lvs vgs pvs systemctl --failed
“`
VPS
wg show ``` ss -lntup ip route iptables -S iptables -t nat -S
9.3 VPN監視
wg show
確認ポイント:
- latest handshake が更新されているか
- transfer が増えているか
- expected peer が欠けていないか
9.4 DB確認
mysql -u root -p -e "SHOW DATABASES;" mysql -u root -p -e "USE mikyun_cloud; SHOW TABLES;" mysql -u root -p -e "USE mikyun_cloud; SELECT COUNT(*) FROM contracts;" mysql -u root -p -e "USE mikyun_cloud; SELECT COUNT(*) FROM customer_devices;"
9.5 ストレージ監視
Supermicro 上の主ストレージを監視する。
df -h lsblk lvs mount | grep /srv/storage
“`
重要マウント
/srv/storage ``` 192.168.30.30:/nextclouddata /mnt/maguro/nextclouddata
9.6 Nextcloud系確認
docker ps df -h | grep nextcloud mount | grep nextclouddata
確認ポイント:
- NFSマウントが有効か
- コンテナが落ちていないか
- 残容量が逼迫していないか
9.7 バックアップ
原則として以下をバックアップ対象にする。
- Nextcloud data
- DB
- ポータル設定 / 出力物
- WireGuard設定
- スイッチ / ルータ設定
9.8 定期点検(週次)
- WG peer状態確認
- 契約 / 端末数の棚卸し
- admin_logsの異常操作確認
- ストレージ残量確認
- Switch uplink / LACPエラー確認
- UPS状態確認
9.9 月次点検
- OSアップデート方針確認
- VPSのKernel / Package更新可否確認
- Nextcloud / Portal / DBバックアップ復元テスト
- 証明書期限確認
- ストレージ増設余力確認
9.10 変更作業ルール
- 本番系変更前に現状バックアップ
- ネットワーク変更は CORE → ACCESS → Host の順で確認
- DB変更はDDL前に dump を取る
- WG設定変更は peer一覧退避後に実施
9.11 よく使う確認コマンド集
“`
R640
ip -br a ``` ip route wg show docker ps df -h cat /etc/netplan/*.yaml
“`
Supermicro
ip -br a ``` ip route df -h lsblk lvs vgs pvs
“`
Cisco
show vlan brief ``` show ip interface brief show interfaces status show etherchannel summary show interfaces trunk
“`
RTX1300
show config ``` show nat descriptor address show status tunnel 1 show status ipv6
