Penpotマルチプレイヤー編集の深層:WebSocketの仕組みと、社内プロキシ要塞を突破する完全実践ガイド
プロダクトデザイナーとエンジニアが同一のカンバス上でピクセルを議論し、その場でコードの文脈とデザインシステムを同期させる――。オープンソースのプロトタイピングツール「Penpot」は、Figma一強だったデザインツールの勢力図を塗り替えつつある。
しかし、セキュリティが厳格な社内ネットワーク(オンプレミス環境や厳重なプロキシ配下)にPenpotを導入した瞬間、多くのチームが「ある壁」に直面する。
「なぜかマルチプレイヤー(リアルタイム協調編集)が機能しない」「カーソルが同期せず、コネクションが黙々と切断される」という現象だ。
本記事では、Penpotのリアルタイム通信を支えるアーキテクチャの深層を解き明かし、社内プロキシやリバースプロキシの要塞を完全に突破するための具体的なインフラ設定、そして開発スピードを極限まで高めるプロのワークフローハックを共有する。
—
1. 内部構造の理解:Penpotのリアルタイム通信メカニズム
Penpotは、フロントエンドにClojureScript(SVGレンダリング)、バックエンドにClojure(Taiga製)を採用したモダンなアーキテクチャで構築されている。このリアルタイム協調編集の根幹を支えているのが、WebSocketとServer-Sent Events (SSE)のハイブリッド通信だ。
通信のライフサイクル
1. 初期ハンドシェイクと認証:
クライアント(ブラウザ)がHTTP/HTTPS経由でセッションを確立後、バックエンド(`penpot-backend`)との間でWebSocket接続(`/ws`エンドポイント)を初期化する。
2. Operational Transformation (OT) / CRDT的アプローチ:
ユーザーがアートボード上の要素を移動・変形すると、その差分データがJSONペイロードとしてWebSocket経由で即座にサーバーへ送信される。サーバーはそれをブロードキャストし、他の接続クライアントの画面を数ミリ秒単位で更新する。
3. ハートビート(Keep-Alive):
接続の維持を確認するため、数秒おきにPing/Pongフレームが往復する。
—
2. なぜ社内プロキシ環境で接続が切断されるのか?
社内ネットワークやリバースプロキシ(Nginx, Apache, Envoyなど)環境下において、PenpotのWebSocketが頻繁に切断される原因は主に以下の3点に集約される。
1. プロキシのタイムアウト(Idle Timeout):
Nginxや社内プロキシのデフォルト設定では、無通信状態が一定時間(通常60秒)続くと接続が強制切断される。ペン入れや思考に没頭して数分間操作を行わなかった場合、ハートビートの頻度やプロキシ側の設定次第でコネクションが死ぬ。
2. プロトコルアップグレードの拒否:
HTTP/1.1からWebSocketへのプロトコルアップグレード(`Upgrade: websocket`, `Connection: Upgrade`)のリクエストヘッダーが、過剰なセキュリティWAFやリバースプロキシによってストリップ(削除)またはブロックされる。
3. SSL/TLSインスペクションによるバッファリング:
社内の透過型プロキシがパケットを一度終端してスキャンするため、WebSocketの長寿命コネクションが異常な挙動とみなされ、RSTパケットが返される。
—
3. 実践:Nginxリバースプロキシ設定の完全解剖
PenpotをDocker等でセルフホストし、前段にNginxを置いているケースを想定する。WebSocketの接続維持とタイムアウトを防ぐための、プロダクション環境必須のNginx設定は以下の通りだ。
server {
listen 443 ssl http2;
server_name penpot.internal.company.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# クライアントからの巨大なSVG/画像アップロードに対応
client_max_body_size 100M;
location / {
proxy_pass http://penpot-frontend:8080;
proxy_set_header Host $http_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;
}
# バックエンドAPIおよびWebSocketエンドポイントのルーティング
location /api/ {
proxy_pass http://penpot-backend:6060;
proxy_set_header Host $http_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;
# ==========================================
# WebSocket接続を維持するための最重要設定
# ==========================================
proxy_http_version 1.1;
# アップグレードヘッダーの明示的な転送
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;
# タイムアウトの引き上げ(デフォルトの60秒から3600秒へ)
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
# バッファリングを無効化し、リアルタイム性を担保
proxy_buffering off;
}
}
この設定のキモ
- `proxy_http_version 1.1;` と `Connection “upgrade”;`: これがないと、プロキシは単なるHTTP/1.1リクエストと誤認し、WebSocketのハンドシェイクに失敗する。
- `proxy_read_timeout 3600s;`: デザイナーが長時間操作しなくても、アイドル状態による不意の切断を防ぐ。
- `proxy_buffering off;`: パケットがバッファに溜まるのを防ぎ、マルチプレイヤー編集の「リアルタイムなめらかさ」を最大化する。
—
4. チームの生産性を爆発させるプロのプラットフォーム設定
インフラが整ったところで、Penpotを日常的に使い倒すエンジニア/デザイナーチームのために、現場のスピードを数倍に引き上げる実践テクニックを授ける。
① 開発スピードを加速するキーボードショートカット
Figmaから移行したエンジニアがまず覚えるべき、Penpotの神ショートカット群。マウス操作を極限まで排除する。
| 操作内容 | ショートカット (Mac / Windows/Linux) |
| :— | :— |
| コンポーネント化 | `Cmd + Alt + K` / `Ctrl + Alt + K` |
| フレームの作成 | `F` または `A` |
| オートレイアウトの適用 | `Shift + A` |
| オートレイアウトの解除 | `Shift + Alt + A` / `Shift + Ctrl + A` |
| ズームをカンバス全体に合わせる | `Shift + 1` |
| 選択要素にズーム | `Shift + 2` |
| レイヤーの隠蔽/表示トグル | `Cmd + Shift + H` / `Ctrl + Shift + H` |
② チーム開発で絶対入れるべき「神プラグイン・連携」
Penpotはオープンソースであるため、コミュニティプラグインやAPI連携が非常に強力だ。
- Penpot Exporter / Code Connect (自作推奨):
デザインシステムの色定義(CSS Variables / Tailwind config)やタイポグラフィを、CI/CDパイプラインと連携して自動的にリポジトリへ同期するスクリプトを組み込む。これにより「デザインとコードの乖離」が物理的に消滅する。
- SVG Optimiserプラグイン:
外部からインポートした不必要なメタデータ(IllustratorやFigma特有のゴミタグ)をパージし、プロダクションコードにそのまま貼り付けられるクリーンなSVGを出力する。
③ チーム全体のデザインシステム設定共有化ルール
複数のプロジェクトで一貫性を保つため、Penpotの「カラーパレット」「タイポグラフィ」「コンポーネントライブラリ」は、属人化させずコードベースとして管理する。
以下は、チームで共通利用するデザイントークンをJSON形式で定義し、Penpotのインポート機能やCIで共有するためのベストプラクティス構成例だ。
{
“$schema”: “https://json.schemastore.org/design-tokens.json”,
“meta”: {
“author”: “Core Engineering & Design Team”,
“version”: “1.4.0”,
“description”: “Enterprise Design System tokens for Penpot and Frontend codebase sync.”
},
“color”: {
“brand”: {
“primary”: { “value”: “#3B82F6”, “type”: “color”, “comment”: “メインCTA、フォーカス状態” },
“secondary”: { “value”: “#10B981”, “type”: “color”, “comment”: “サクセス状態、完了” }
},
“neutral”: {
“surface”: { “value”: “#F8FAFC”, “type”: “color”, “comment”: “背景色 (Canvas Background)” },
“text”: { “value”: “#0F172A”, “type”: “color”, “comment”: “メインテキスト” }
}
},
“spacing”: {
“xs”: { “value”: “4px”, “type”: “dimension” },
“sm”: { “value”: “8px”, “type”: “dimension” },
“md”: { “value”: “16px”, “type”: “dimension” },
“lg”: { “value”: “24px”, “type”: “dimension” },
“xl”: { “value”: “32px”, “type”: “dimension” }
},
“typography”: {
“fontFamily”: {
“sans”: { “value”: “Inter, ‘Hiragino Sans’, sans-serif”, “type”: “fontFamily” },
“mono”: { “value”: “‘Fira Code’, monospace”, “type”: “fontFamily” }
},
“fontSize”: {
“heading-lg”: { “value”: “32px”, “type”: “dimension” },
“body-md”: { “value”: “14px”, “type”: “dimension” }
}
}
}
—
5. まとめ
ネットワークの制約やプロキシの仕様に阻まれがちなリアルタイム協調編集ツールも、背後にあるWebSocketの挙動を正しく理解し、リバースプロキシのタイムアウトとヘッダー転送を適切にチューニングさえすれば、堅牢な社内インフラの上でも完全に動作させることができる。
デザインとコードの境界線をなくし、チーム全体の開発スピードを極限まで高めるために、今日のインフラ見直しとショートカットの習得をさっそくチームメイトと共有してほしい。プロフェッショナルなエンジニアリングは、細部のインフラの理解から始まる。