DB 設計 — mikyun_cloud

// DATABASE — 最終更新: 2026-05-14 / maguro Docker MariaDB (compose-db-1) に統合済

運用中 Nextcloud と同じ MariaDB スタックに統合 Docker 内部のみ 外部からの直接接続なし

1. DB 基本情報 (2026-05-14)
項目内容
DB名mikyun_cloud
エンジンMariaDB 11
配置maguro Docker compose-db-1 (Nextcloud と同居)
ネットワークDocker 内部ネット (compose-default) のみ。 ホスト側 3306 露出なし
ユーザーmikyun (権限: mikyun_cloud DB のみ)
接続元mikyun-portal コンテナ から DSN db:3306 で接続
バックアップmaguro /srv/storage/SM-storage/backup/mikyun_cloud/*.sql.gz (14日保持、 daily 02:30)
歴史: 旧 R640 ホスト MariaDB (127.0.0.1:3306) → Phase A (2026-05-13) で maguro ホスト MariaDB に統合 → Phase 2 (2026-05-14) で maguro Docker MariaDB へ最終統合。 ホスト直 MariaDB は両機とも disable 済。 SQLite 時代 (mikyun.db: customers/devices/wg_peers) は完全廃止。
2. テーブル一覧
種別名前用途
TABLEcontracts契約本体
TABLEcustomer_devices顧客端末 / WireGuard ピア
TABLEadmin_logs管理操作ログ
TABLEcontract_notes顧客メモ / 通話記録 / 警告
TABLEpoint_transactionsポイント取引履歴 (2026-04-10 追加)
TABLEtraffic_daily日次トラフィック集計
VIEWv_parent_conflicts親端末重複監査
3. contracts (契約テーブル)

契約本体。 顧客ID、 サブネット、 容量、 上限、 状態、 課金情報を持つ。

カラム型説明
idbigint PK auto内部ID
contract_numberint unsigned UNI連番 (表示用)
contract_idvarchar(32) UNI契約ID (例: 0001, M010) 永久不変
vpn_subnetvarchar(32)割当 VPN サブネット (主に 10.200.0.0/16 = wg-clients)
next_child_ipvarchar(32)次割当IP候補 (現状は DB スキャン採番のため未使用)
customer_namevarchar(128)顧客名
customer_emailvarchar(255) MULメール
customer_phonevarchar(64)電話
plan_namevarchar(64)プラン名 (例: standard)
storage_quota_gbint DEFAULT 200契約総容量 (GB)
max_devicesint DEFAULT 3最大端末数
max_filesint DEFAULT 10000最大ファイル数
bandwidth_profilevarchar(64)帯域プロファイル (例: standard)
contract_statusvarchar(16) MULactive / paused / terminated / deleted
identity_passphrasetext顧客ポータル ログイン用 (改善TODO: Argon2)
nc_passwordvarchar(255)Nextcloud 親アカウントPW (改善TODO: Fernet)
nc_quota_gbint DEFAULT 200NC割当容量 (GB)
opt_video_calltinyint DEFAULT 0ビデオ通話オプション (現在は常に0、 後述)
guest_video_enabledenum(‘yes’,’no’) DEFAULT ‘no’互換性のため残置 (常に no、 2026-04-05 ロールバック)
point_balanceint DEFAULT 0ポイント残高 (1pt=1円)
monthly_amountint DEFAULT 1980月額料金 (自動計算)
next_payment_atdatetime NULL次回支払日
billing_warning_atdatetime NULL残高不足警告日
billing_suspended_atdatetime NULLアクセス停止日
delivery_methodvarchar(32)連絡方法 (Telegram / Email / SMS 等)
created_at / updated_atdatetime作成/更新
4. customer_devices (端末テーブル)

契約配下の端末管理テーブル。 WireGuard 鍵・IP・状態・統計を持つ中核テーブル。

カラム型説明
idbigint PK autoレコードID
contract_idvarchar(32) MUL所属契約ID
device_idvarchar(64) UNI端末識別ID (例: 0001-DEV-001)
wg_ifacevarchar(32)WGインターフェース名 (wg-clients / wg-customers)
wg_ipvarchar(64) UNI割当WG IP (10.200.0.x 等)
public_keytext UNIクライアント公開鍵
private_keytextクライアント秘密鍵 (DB保存、 教訓: 平文格納の歴史的経緯あり)
preshared_keytextWG事前共有鍵
device_rolevarchar(16)parent / child
is_parenttinyint DEFAULT 0親端末フラグ
statusvarchar(16) MULissued / active / paused / revoked / expired / deleted
device_namevarchar(128)端末名
platformvarchar(64)iPhone / Android / Windows 等
app_versionvarchar(64)アプリバージョン
issued_atdatetimeQR発行日時
qr_expires_atdatetimeQR失効 (+24h)
first_handshake_at / last_handshake_atdatetime MULWG接続日時 (cron収集)
activated_atdatetime有効化日時
parent_changed_at / parent_changed_by / parent_change_reason—親変更履歴
paused_at / pause_reason—一時停止記録
rx_bytes_total / tx_bytes_totalbigint累計受信/送信
rx_bytes_24h / tx_bytes_24hbigint24h 受信/送信
rx_bytes_month / tx_bytes_monthbigint月次 受信/送信
nc_used_bytesbigint DEFAULT 0NC使用量 (1h cron で collect_file_count.py 集計)
nc_used_updated_atdatetime使用量最終更新
file_count / file_count_alertint / tinyintファイル数 + max_files 超過警告
storage_quota_gbint DEFAULT 0端末個別割当容量
nc_user / nc_password / nc_quota_gb / nc_enabled—Nextcloud アカウント情報
deleted_atdatetime NULL論理削除日時
created_at / updated_atdatetime作成/更新
5. admin_logs (管理操作ログ)
カラム型説明
idbigint PK auto内部ID
action_typevarchar(64)操作種別
target_typevarchar(64)対象種別 (contract / device)
target_idvarchar(64)対象ID
messagetext操作内容テキスト
created_atdatetime auto記録日時
6. point_transactions (ポイント取引履歴 2026-04-10〜)
カラム型説明
idbigint PK autoID
contract_idvarchar(32)契約ID
typeenum(‘charge’,’monthly_deduct’,’refund’,’manual_adjust’)取引種別
amountint金額 (正=加算、 負=消費)
balance_afterint取引後残高
stripe_payment_intent_idvarchar(128) NULLStripe PI ID
notetext NULL備考
created_atdatetime作成日時
7. traffic_daily (日次集計)
カラム型説明
daydate集計日
contract_idvarchar(32)契約ID
device_idvarchar(64)端末ID
rx_bytes / tx_bytesbigint受信/送信

集計元: wg_traffic_collector.py (旧 SSH経由 → 2026-04-10 ローカル wg show wg-clients dump に修正済)

8. v_parent_conflicts (VIEW)

1契約に親端末が複数存在する異常検出ビュー。 cron で定期確認 + Telegram 通知。

SELECT contract_id, COUNT(*) AS parent_count
FROM customer_devices
WHERE is_parent = 1 AND deleted_at IS NULL
GROUP BY contract_id
HAVING COUNT(*) > 1
バックアップ / リストア
項目内容
保存先maguro /srv/storage/SM-storage/backup/mikyun_cloud/
頻度daily 02:30 (systemd timer)
保持期間14日
形式YYYYMMDD_HHMM.sql.gz (gzip mysqldump)
監視cert-watch / db-backup-watch で失敗 + サイズ異常を Telegram 通知
# dump
docker compose -f /opt/nextcloud/compose/compose.yml exec db \
  mysqldump --single-transaction -u root -p mikyun_cloud | gzip > backup.sql.gz

# restore
zcat backup.sql.gz | docker compose -f /opt/nextcloud/compose/compose.yml exec -T db \
  mysql -u root -p mikyun_cloud
歴史的経緯: 旧 SQLite (mikyun.db: customers/devices/wg_peers) と MySQL が並存していた時代があり、 wg_peers テーブルに WG秘密鍵が平文保存されていた。 現在の customer_devices.private_key も同じ形式で残るが、 これは「再発行コスト > 漏洩リスク」で意図的選択。 DB アクセスは Docker 内部ネット限定、 ホスト経由でしか root にならない設計で防御。