مقایسه ابزارهای رسم نمودار self-hosted
بررسی draw.io، Excalidraw و Kroki برای میزبانی شخصی. بدانید کدام ابزار دادهها را در مرورگر پردازش میکند و کدام یک برای امنیت حریم خصوصی به سرور شما نیاز دارد.
کدام ابزار رسم نمودار self-hosted را باید اجرا کنید؟
ابزارهای رسم نمودار self-hosted در دو قالب ارائه میشوند و این قالب از لیست ویژگیها اهمیت بیشتری دارد. draw.io و Excalidraw برنامههای مبتنی بر مرورگر هستند: کانتینر، JavaScript را ارائه میدهد، مرورگر شما عملیات رسم را انجام میدهد و سرور هرگز نمودار را مشاهده نمیکند. Kroki دقیقاً برعکس عمل میکند. شما متن نمودار را از طریق HTTP برای آن میفرستید و آن یک تصویر بازمیگرداند، بنابراین هر نمودار از طریق ماشین شما پردازش میشود.
اگر به یک ویرایشگر کامل در کنار یک ویکی نیاز دارید، draw.io را اجرا کنید. اگر به یک تختهسفید برای طراحی سریع نیاز دارید و میپذیرید که هیچچیز خارج از مرورگری که در آن طراحی کردهاید ذخیره نمیشود، Excalidraw را اجرا کنید. اگر نمودارهای شما متنی هستند که در کنار کدی که توصیف میکنند در git قرار دارند، Kroki را اجرا کنید.
آنچه میزبانی شخصی (self-hosting) یک ابزار رسم نمودار واقعاً تغییر میدهد
دقیق باشید که کدام بخشها با سرور شما در تعامل هستند، زیرا همین یک نکته تعیین میکند که آیا میزبانی شخصی باعث افزایش حریم خصوصی میشود یا صرفاً در دسترس بودن را تضمین میکند.
- ابزار draw.io در مرورگر رندر میشود. کانتینر شما فقط کد برنامه را سرو میکند. فایل نهایی به هر کجا که در ویرایشگر تعیین کنید، ذخیره میشود.
- ابزار Excalidraw در مرورگر رندر میشود و صحنه فعلی را در local storage همان مرورگر نگه میدارد. هیچ چیزی در سمت سرور نوشته نمیشود.
- ابزار Kroki روی سرور رندر میشود. هم منبع نمودار و هم تصویر نهایی، هر دو درون کانتینر شما وجود دارند.
تنها در مورد سوم است که دادهها به سختافزاری که کنترل آن را در دست دارید منتقل میشوند. در دو مورد اول، میزبانی شخصی باعث کنترل بر داراییها و تضمین در دسترس بودن میشود: کدهای JavaScript از میزبان شما بارگذاری میشوند، بنابراین وقتی یک سرویسدهنده شخص ثالث دچار قطعی شود، شرایط استفاده خود را تغییر دهد یا از شبکه شما غیرقابل دسترس شود، ویرایشگر همچنان کار میکند. این موضوع برای برخی تیمها ارزش واقعی دارد. این ادعایی متفاوت از این است که بگوییم «نمودار هرگز از ساختمان خارج نمیشود».
draw.io: یک کانتینر رسمی که هیچچیز را ذخیره نمیکند
این پروژه تصویر (image) اختصاصی خود را منتشر میکند و راهنمای شروع سریع در فایل README آن تنها یک خط است.
docker run -it --rm --name="draw" -p 8080:8080 -p 8443:8443 jgraph/drawioاین دستور، ویرایشگر را روی تمام آدرسهای موجود در سرور در دسترس قرار میدهد. در یک VPS، پورت منتشرشده را به loopback محدود کنید و از طریق یک reverse proxy یا تونل SSH به آن دسترسی پیدا کنید.
docker run -d --name drawio --restart unless-stopped -p 127.0.0.1:8080:8080 jgraph/drawioاز طریق تونل به http://127.0.0.1:8080/?offline=1&https=0 متصل شوید. فایل README از ?offline=1 به عنوان «یک قابلیت امنیتی که پشتیبانی از فضای ابری را غیرفعال میکند» یاد میکند. بدون این تنظیم، ویرایشگر گزینههای Google Drive، OneDrive و GitHub را به عنوان مقاصد ذخیرهسازی پیشنهاد میدهد که در واقع سرورهای اشخاص ثالث هستند.
اتصال به 127.0.0.1 همان چیزی است که پورت را از دسترس اینترنت عمومی خارج میکند. یک دستور -p 8080:8080 ساده توسط ufw فیلتر نمیشود، زیرا Docker قوانین iptables خود را پیش از زنجیرههای مدیریتشده توسط ufw تزریق میکند؛ بنابراین در حالی که وضعیت فایروال درست به نظر میرسد، پورت همچنان به درخواستهای عمومی پاسخ میدهد. انتشار Docker و عبور از ufw مکانیزم این مشکل و راهحل آن را توضیح میدهد.
به محض اینکه ویرایشگر روی localhost نباشد، دو متغیر محیطی اهمیت پیدا میکنند.
services:
drawio:
image: jgraph/drawio
container_name: drawio
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
environment:
DRAWIO_SERVER_URL: "https://drawio.example.com/"
DRAWIO_BASE_URL: "https://drawio.example.com"اسلش انتهایی (trailing slash) اشتباه تایپی نیست. فایل README متغیر DRAWIO_SERVER_URL را به عنوان «URL استقرار عمومی با یک اسلش در انتها» و DRAWIO_BASE_URL را به عنوان «همان URL بدون اسلش انتهایی» تعریف میکند که توسط viewer، lightbox و مسیرهای کد embed استفاده میشوند. اگر ویرایشگر را در یک زیرمسیر مانند https://www.example.com/drawio/ میزبانی میکنید، هر دو مقدار باید شامل آن زیرمسیر باشند، زیرا برنامه URLهای viewer و embed خود را بر اساس آنها میسازد.
ماندگاری (Persistence): هیچ دادهای ماندگار نیست و این بخشی از طراحی است. هیچ volume در آن فایل Compose وجود ندارد زیرا کانتینر هیچ دادهای از نمودارها را نگه نمیدارد. یک فایل .drawio در واقع XML است که ویرایشگر به مرورگر شما تحویل میدهد و مقصد ذخیرهسازی که انتخاب میکنید تعیین میکند فایل کجا قرار بگیرد: دانلود روی دستگاه شخصی خودتان یا برنامهای که ویرایشگر را در خود جای داده است. از آن مقصد نسخه پشتیبان تهیه کنید. اگر پاسخ یک پوشه روی VPS است، پس چیزی که ارزش محافظت دارد همان پوشه و مدیریت فایلی است که برای دسترسی به آن استفاده میکنید، زیرا draw.io هیچ نسخهای از هیچچیز را نگه نمیدارد.
چه چیزی همچنان از سرور شما خارج میشود. خروجی PDF واضحترین مورد است. فایل README متغیر DRAWIO_SELF_CONTAINED را اینگونه توصیف میکند: «برای هدایت درخواستهای خروجی از طریق ExportProxyServlet (/service/0) در Tomcat بهجای فراخوانی مستقیم سرور خروجی، آن را روی 1 تنظیم کنید». این را برعکس بخوانید: بهصورت پیشفرض، یک درخواست خروجی (export) در داخل استقرار شما باقی نمیماند. این پروژه همچنین jgraph/export-server را منتشر میکند که یک «سرور مستقل خروجی تصویر برای draw.io» است، برای کسانی که میخواهند این رندرینگ روی سختافزار خودشان انجام شود. ENABLE_DRAWIO_PROXY بهصورت پیشفرض غیرفعال است و یک endpoint از نوع /proxy را فعال میکند که URLهای تصاویر خارجی را از طرف مرورگر دریافت میکند؛ بنابراین تا زمانی که به آن نیاز ندارید، آن را غیرفعال نگه دارید.
Excalidraw: یک بسته ایستا بدون سرور پشتیبان
صفحه رسمی این ایمیج، دستور زیر را ارائه میدهد.
docker run --rm -dit --name excalidraw -p 5000:80 excalidraw/excalidraw:latestبه همان دلیلی که پیشتر ذکر شد، پورت منتشرشده را روی loopback قرار دهید.
docker run -d --name excalidraw --restart unless-stopped -p 127.0.0.1:5000:80 excalidraw/excalidraw:latestدرون کانتینر، Nginx یک بسته JavaScript کامپایلشده را روی پورت 80 ارائه میدهد. حجم ایمیج منتشرشده حدود 41 مگابایت (فشردهشده در Docker Hub، اوت 2026) است که نشان میدهد چه محتوای اندکی در آن وجود دارد. هیچ دیتابیس، ذخیرهساز نشست (session store) یا دایرکتوری آپلودی وجود ندارد، زیرا هیچ چیزی روی سرور برای ذخیرهسازی نیست.
صفحه ایمیج این محدودیت را بهصراحت بیان میکند: «در حال حاضر، میزبانی شخصی یک نمونه (instance) از این سرویس، از قابلیتهای اشتراکگذاری یا همکاری پشتیبانی نمیکند.» دکمهها همچنان در رابط کاربری وجود دارند، بنابراین دانستن دلیل آن ارزشمند است. همکاری زنده (Live collaboration) به یک سرور websocket نیاز دارد که بهصورت جداگانه با نام excalidraw/excalidraw-room منتشر میشود. لینک اشتراکگذاری نیز به یک سرویس ذخیرهسازی برای نگهداری صحنههای رمزنگاریشده نیاز دارد. آدرس هر دو سرویس در زمان build بهعنوان متغیرهای Vite (VITE_APP_WS_SERVER_URL، VITE_APP_BACKEND_V2_GET_URL، VITE_APP_BACKEND_V2_POST_URL) در بسته کامپایل میشوند و مقادیر پیشفرض در مخزن کد، به سرویسهای میزبانیشده توسط خود Excalidraw اشاره دارند. Vite این مقادیر را در حین build جایگزین میکند، بنابراین آنها بهصورت رشتههای متنی ثابت درون فایلهای JavaScript قرار میگیرند. تنظیم آنها بهعنوان متغیرهای محیطی کانتینر (environment variables) هیچ تغییری ایجاد نمیکند، زیرا هیچ کدی در زمان اجرا (runtime) آنها را نمیخواند. اشاره دادن قابلیت همکاری به سرور اتاق (room server) شخصی خودتان، مستلزم ساخت (build) فرانتاند از روی سورسکد با مقادیر اختصاصی خودتان است. پیش از برنامهریزی برای آن، وضعیت آن سرور را بررسی کنید: ایمیج excalidraw/excalidraw-room در Docker Hub تا اوت 2026 بیش از دو سال بود که بازسازی (rebuild) نشده بود.
یک طرح واقعاً کجا ذخیره میشود؟ صحنه در حافظه محلی (local storage) مرورگر، روی همان دستگاه و برای همان مبدأ (origin) قرار میگیرد. همان URL را در یک پنجره ناشناس (private window) باز کنید تا ببینید بوم نقاشی خالی است؛ این سریعترین راه برای اثبات این موضوع به خودتان است. پاک کردن دادههای سایت، طرح را حذف میکند و هیچ نسخه سروری برای بازیابی وجود ندارد. بنابراین به کاربران بیاموزید که از گزینه "Save to..." استفاده کنند و فایل .excalidraw را که یک فایل JSON است، در جایی که از آن نسخه پشتیبان تهیه میشود، نگهداری کنند. یک نمونه اشتراکی به هر فرد بوم نقاشی خصوصی خودش را میدهد. با آن بهعنوان یک دفترچه یادداشت شخصی برخورد کنید که اتفاقاً روی سرور میزبانی میشود.
Kroki: نمودارها به عنوان کد، رندر شده روی سرور شما
Kroki یک درگاه HTTP در مقابل چندین رندرکننده است. شما متن را POST میکنید و SVG یا PNG تحویل میگیرید. Graphviz، PlantUML، D2 و چندین مورد دیگر در image درگاه تعبیه شدهاند. رندرکنندههای Mermaid، BPMN و Excalidraw در کانتینرهای جانبی (companion) قرار دارند، بنابراین استفاده از Compose منطقیترین روش برای اجرای آن است. این نمونهای از مستندات Kroki است.
services:
kroki:
image: yuzutech/kroki
depends_on:
- mermaid
- bpmn
- excalidraw
environment:
- KROKI_MERMAID_HOST=mermaid
- KROKI_BPMN_HOST=bpmn
- KROKI_EXCALIDRAW_HOST=excalidraw
ports:
- "8000:8000"
tmpfs:
- /tmp:exec
mermaid:
image: yuzutech/kroki-mermaid
expose:
- "8002"
bpmn:
image: yuzutech/kroki-bpmn
expose:
- "8003"
excalidraw:
image: yuzutech/kroki-excalidraw
expose:
- "8004"expose هیچ پورتی را روی host منتشر نمیکند، بنابراین کانتینرهای جانبی فقط از طریق شبکه Compose برای درگاه قابل دسترسی هستند. این دقیقاً همان چیزی است که نیاز دارید. خط درگاه را به "127.0.0.1:8000:8000" تغییر دهید، مگر اینکه ویکی که آن را فراخوانی میکند روی host دیگری اجرا شود. اگر قبلاً فایل Compose روی سرور ننوشتهاید، اجرای Docker Compose روی VPS ساختار فایل و چرخه docker compose up -d را پوشش میدهد.
دو تست سلامت (smoke test) را به همین ترتیب اجرا کنید، زیرا به دلایل متفاوتی ممکن است شکست بخورند.
curl -s -X POST http://127.0.0.1:8000/graphviz/svg \
-H 'Content-Type: text/plain' \
--data-binary 'digraph G {Hello->World}' | head -c 60Graphviz داخل درگاه اجرا میشود، بنابراین یک سند SVG در اینجا ثابت میکند که خود درگاه سالم است. حالا مسیری را که از کانتینرها عبور میکند تست کنید.
curl -s -X POST http://127.0.0.1:8000/mermaid/svg \
-H 'Content-Type: text/plain' \
--data-binary 'graph TD; A-->B;' | head -c 60خروجی SVG از دستور دوم ثابت میکند که KROKI_MERMAID_HOST به درستی resolve شده و کانتینر جانبی پاسخ داده است. اگر اولی کار میکند و دومی خیر، خطا بین دو کانتینر است؛ بنابراین پیش از تغییر در سینتکس نمودار، docker compose logs kroki را مطالعه کنید.
فرم GET، نمودار را در URL انکود میکند؛ این همان روشی است که یک ویکی بدون نیاز به هیچ پلاگینی، تصویر را embed میکند. مستندات این انکودر را ارائه دادهاند.
cat hello.dot | python -c "import sys; import base64; import zlib; print(base64.urlsafe_b64encode(zlib.compress(sys.stdin.read().encode('utf-8'), 9)).decode('ascii'))"در Ubuntu این دستور python: command not found را چاپ میکند، زیرا سیستم python3 را ارائه میدهد و python بدون نسخه وجود ندارد. از python3 استفاده کنید. خروجی در انتهای URL با فرمت /{diagram-type}/{output-format}/{encoded-diagram} قرار میگیرد و هر تگ <img> میتواند به آن اشاره کند. یک محدودیت وجود دارد: KROKI_MAX_URI_LENGTH بهطور پیشفرض 4096 بایت است، بنابراین نمودارهای طولانی باید از طریق POST ارسال شوند.
Kroki متنی را که برایش میفرستید میخواند، بنابراین تنظیمات امنیتی آن اهمیت حیاتی دارند. KROKI_SAFE_MODE بهطور پیشفرض روی SECURE تنظیم شده است که محدودکنندهترین سطح از میان سه سطح موجود است و KROKI_PLANTUML_ALLOW_INCLUDE بهطور پیشفرض false است. این مقادیر پیشفرض به این دلیل وجود دارند که دستور !include در PlantUML، فایلها و URLها را از دیدگاه رندرکننده میخواند. اگر این محدودیتها را در endpointای که برای همه قابل دسترسی است کاهش دهید، در واقع به اینترنت اجازه دادهاید از طریق کانتینر شما فایل بخواند. آنها را تغییر ندهید مگر اینکه دقیقاً بدانید به چه مسیر includeای نیاز دارید، سپس آن را با KROKI_PLANTUML_INCLUDE_PATH مشخص کنید.
حافظه: کدامیک در یک VPS کوچک فشار بیشتری وارد میکند
هنگامی که بدانید هر کانتینر چه کاری انجام میدهد، ترتیب مصرف منابع قابل پیشبینی است.
- ایمیج Excalidraw یک Nginx است که فایلهای استاتیک را سرو میکند. این مورد در مقایسه با دو مورد دیگر، بسیار کمهزینهتر است.
- برنامه draw.io از Tomcat استفاده میکند که یک application server جاوا است؛ بنابراین چه کسی در حال رسم باشد و چه نباشد، یک JVM (ماشین مجازی جاوا) را همراه خود دارد.
- سرویس Kroki نیز یک سرویس جاوا است که برای نصب دستی به صورت یک فایل jar ارائه میشود.
- سرویس جانبی mermaid پرهزینهترین مورد است. فایل Dockerfile آن، Chromium را نصب کرده و
PUPPETEER_EXECUTABLE_PATH=/usr/lib/chromium/chromeرا تنظیم میکند، زیرا Mermaid در یک موتور مرورگر واقعی رندر میشود.
بنابراین، اعداد در حالت idle (بیکار) اطلاعات بسیار کمی به شما میدهند. عددی که اهمیت دارد، جهش مصرف حافظه هنگام رندر شدن یک نمودار است و KROKI_MERMAID_MAX_CONCURRENCY بهطور پیشفرض روی 6 تنظیم شده است؛ یعنی شش رندر مرورگر میتوانند همزمان در حال اجرا باشند. بهجای اعتماد به ارقام منتشرشده، آن را روی سرور خودتان اندازهگیری کنید.
docker stats --no-stream
docker system dfابتدا در حالی که همه چیز در حالت idle است، دستور را اجرا کنید و سپس دوباره در حالی که یک نمودار بزرگ mermaid را در یک حلقه رندر میکنید، آن را تکرار نمایید. اگر این جهش مصرف در یک پلن کوچک آزاردهنده است، بهجای حدس زدن، آن را محدود کنید: تنظیم محدودیت حافظه برای یک سرویس Compose نحو (syntax) این کار و اتفاقی که هنگام رسیدن کانتینر به سقف مجاز رخ میدهد را نشان میدهد. حذف سرویس جانبی mermaid نیز یک راهکار معتبر است، زیرا gateway همچنان به سرویسدهی به تمام رندرهای داخلی خود ادامه میدهد.
هیچکدام از اینها مدل کاربری ندارند، پس یکی در مقابل آنها قرار دهید
سرویس draw.io هیچ حساب کاربری ندارد. Excalidraw نیز فاقد حساب کاربری است. سرویس Kroki به هر درخواستی که به آن برسد پاسخ میدهد. هرگونه احراز هویت باید از طریق proxy انجام شود.
sudo apt update && sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd aliceدستور htpasswd -c فایل را ایجاد کرده و روی فایل موجود بازنویسی میکند، بنابراین فقط در اولین مرتبه از -c استفاده کنید و پس از آن دیگر نیازی به آن نیست.
server {
listen 443 ssl;
server_name drawio.example.com;
location / {
auth_basic "diagrams";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}آن را با sudo nginx -t && sudo systemctl reload nginx اعمال کنید. بخش nginx -t اهمیت ویژهای دارد: reload کردن یک پیکربندی معیوب باعث میشود پیکربندی قبلی همچنان اجرا شود، بنابراین سایت به کار خود ادامه میدهد و تغییرات شما اعمال نمیشود. پیکربندی reverse proxy، توضیح خط به خط بلوک header و مسیرهای گواهی که در این قطعهکد حذف شدهاند را پوشش میدهد.
احراز هویت پایه (Basic authentication) ابزار مناسبی برای Kroki نیست و دلیل آن ارزش درک کردن دارد. یک صفحه ویکی، تصویر Kroki را با تگ <img> جایگذاری میکند. مرورگر کاربر آن URL را به عنوان یک subresource فراخوانی میکند و اعتبارنامههای شما را به یک origin متفاوت ارسال نمیکند، بنابراین درخواست با خطای 401 مواجه شده و تمام نمودارهای موجود در صفحه به صورت تصویر شکسته نمایش داده میشوند. Kroki را از دسترس اینترنت عمومی خارج کنید. آن را در همان شبکه Docker که container ویکی قرار دارد بگذارید و اجازه دهید ویکی از طریق نام سرویس به آن دسترسی پیدا کند، بدون اینکه هیچ پورتی روی host منتشر شود. نحوه حل نام سرویسها در شبکههای Compose بخشی است که این سناریو را عملی میکند.
نمودارهایی که در کنار یک ویکی self-hosted قرار میگیرند
این معمولترین دلیلی است که افراد به دنبال چنین راهکارهایی هستند. یک صفحه ویکی به تصویر نیاز دارد و هیچکس نمیخواهد آن تصویر، اسکرینشاتی از لپتاپ شخصی باشد.
نرمافزار BookStack یک قلاب (hook) سطح بالا برای ویرایشگرهای self-hosted دارد. آدرس embed پیشفرض آن https://embed.diagrams.net/?embed=1&proto=json&spin=1&configure=1 است و با افزودن یک خط در .env، میتوانید آن را به کانتینر خود هدایت کنید.
DRAWIO=https://drawio.example.com/?embed=1&proto=json&spin=1&configure=1رشته پرسوجو (query string) را دقیقاً کپی کنید. مستندات BookStack بیان میکند که embed=1&proto=json&spin=1 «برای عملکرد یکپارچهسازی با BookStack ضروری هستند»، زیرا پروتکل پیام JSON را که دو صفحه برای ارتباط با یکدیگر استفاده میکنند، انتخاب میکنند. همان صفحه به stealth=1 اشاره میکند که «اگر نمیخواهید از سرویسهای خارجی دیگر استفاده کنید» کاربرد دارد؛ این همان گزینهای است که وقتی هدف از self-hosting جلوگیری از تماسهای خروجی است، باید اضافه کنید. با انجام این تنظیمات، BookStack نقاشی را در فضای ذخیرهسازی تصویر خود در کنار صفحه ذخیره میکند، بنابراین نسخه پشتیبانی که از ویکی تهیه میکنید، شامل نسخه پشتیبان نمودارها نیز خواهد بود.
اگر هنوز در انتخاب خودِ ویکی تردید دارید، ابتدا آن را تعیین تکلیف کنید. انتخاب بین BookStack، Wiki.js و Outline تصمیمی است که باید پیش از این بگیرید، زیرا ویکی تعیین میکند که نمودار چگونه به صفحه پیوست شود و در نتیجه مشخص میکند که کدامیک از این ابزارها را باید به آن متصل کنید.
حالتهای شکست و پیامهایی که مشاهده خواهید کرد
ویرایشگر ترسیم در BookStack باز میشود و بینهایت میچرخد. این چرخاننده (spinner) منتظر spin=1 برای دستدادن (handshake) است که هرگز نمیرسد. بررسی کنید که embed=1&proto=json&spin=1 در مقدار DRAWIO شما موجود باشد و بخش میزبان (host) غلط املایی نداشته باشد.
قاب ویرایشگر در یک ویکی با پروتکل HTTPS خالی میماند. کنسول مرورگر محتوای ترکیبی (mixed content) را گزارش میدهد که در حال بارگذاری http:// درون https:// است. مرورگر قاب را مسدود میکند و draw.io هرگز اجرا نمیشود. ویرایشگر را از طریق HTTPS ارائه دهید.
سرویس Kroki مقدار 413 Request Entity Too Large را برمیگرداند. این رشته از سمت nginx میآید، نه از Kroki. مقدار پیشفرض client_max_body_size در nginx برابر با 1 MB است و مقدار پیشفرض KROKI_MAX_BODY_SIZE در خود Kroki برابر با 1mb است، بنابراین یک منبع PlantUML بزرگ به هر کدام از این محدودیتها که کمتر باشد برخورد میکند. هر دو را افزایش دهید.
سرویس Mermaid با خطا مواجه میشود در حالی که graphviz کار میکند. درگاه (gateway) سالم است اما به سرویس همراه (companion) دسترسی پیدا نمیشود. با استفاده از docker compose ps بررسی کنید که سرویس بالا باشد، سپس چک کنید که KROKI_MERMAID_HOST با نام سرویس مطابقت داشته باشد، زیرا مقدار پیشفرض آن 127.0.0.1 است که در داخل کانتینر درگاه، به معنای خودِ درگاه است.
قابلیت همکاری (collaboration) در Excalidraw متصل نمیشود. اگر فرانتاند را برای سرور اتاق خودتان ساختهاید و آن را پشت nginx قرار دادهاید، پروکسی باید اتصال را با proxy_set_header Upgrade $http_upgrade; و proxy_set_header Connection "upgrade"; ارتقا دهد. بدون این موارد، دستدادن وبسوکت (websocket handshake) به عنوان یک درخواست HTTP معمولی پاسخ داده میشود و نشست (session) هرگز آغاز نمیگردد.
بوم (canvas) پس از پاکسازی مرورگر خالی است. صحنه در حافظه محلی (local storage) آن دستگاه بوده و هیچ نسخهای روی سرور وجود ندارد. راهحل این مشکل یک عادت است تا یک تنظیم: برای هر چیزی که ارزش نگهداری دارد، فایل .excalidraw را خروجی بگیرید.
FAQ
آیا میزبانی شخصی draw.io نمودارهای من را خصوصی نگه میدارد؟
این کار کد برنامه را روی سرور شما نگه میدارد، که با خصوصی نگه داشتن دادهها متفاوت است. draw.io در مرورگر شما رندر میشود، بنابراین کانتینر هرگز نمودار را در خود ذخیره نمیکند. در نتیجه، حریم خصوصی به این بستگی دارد که فایل را کجا ذخیره میکنید و کدام تماسهای خروجی را فعال میگذارید. از ?offline=1 برای غیرفعال کردن مقصدهای ذخیرهسازی ابری استفاده کنید و به یاد داشته باشید که درخواستهای خروجی (export) به یک سرور export ارسال میشوند، مگر اینکه DRAWIO_SELF_CONTAINED=1 را تنظیم کرده و jgraph/export-server را خودتان اجرا کنید.
چرا قابلیت همکاری (collaboration) در نسخه میزبانیشده Excalidraw من کار نمیکند؟
صفحه رسمی ایمیج اعلام میکند که میزبانی شخصی «از قابلیتهای اشتراکگذاری یا همکاری پشتیبانی نمیکند». همکاری زنده به سرور وبسکت جداگانه excalidraw/excalidraw-room نیاز دارد و لینکهای اشتراکگذاری به یک سرویس ذخیرهسازی وابسته هستند. آدرس هر دوی اینها در زمان build در باندل JavaScript به عنوان متغیرهای Vite مانند VITE_APP_WS_SERVER_URL کامپایل میشوند، بنابراین تنظیم متغیر محیطی (environment variable) روی کانتینر در حال اجرا تأثیری ندارد. استفاده از سرور اتاق (room server) شخصی به معنای build کردن فرانتاند از روی سورسکد با مقادیر دلخواه شماست.
چگونه نمودارهای Mermaid را روی سرور شخصی خود رندر کنم؟
Kroki را به همراه کانتینر جانبی mermaid آن اجرا کنید و KROKI_MERMAID_HOST را روی نام آن سرویس تنظیم نمایید. سپس متن نمودار را با متد POST به /mermaid/svg ارسال کرده و SVG را از پاسخ دریافت کنید، یا نمودار را در یک URL با متد GET انکود کرده و یک تگ <img> را به آن ارجاع دهید. کانتینر جانبی، Chromium را از طریق Puppeteer هدایت میکند زیرا Mermaid به یک موتور مرورگر نیاز دارد؛ بنابراین برای حافظه برنامهریزی کنید: KROKI_MERMAID_MAX_CONCURRENCY بهصورت پیشفرض 6 رندر همزمان را مدیریت میکند.
آیا به یک رمز عبور در مقابل این ابزارها نیاز دارم؟
بله، زیرا هیچکدام از آنها سیستم حساب کاربری ندارند. draw.io و Excalidraw یک ویرایشگر کامل را در اختیار هر کسی که URL را پیدا کند قرار میدهند و Kroki هر متنی که به آن ارسال شود را رندر میکند. احراز هویت پایه (Basic authentication) در reverse proxy برای این دو ویرایشگر کافی است. برای Kroki، آن را در یک شبکه Docker که با ویکی مشترک است، منتشرنشده نگه دارید؛ زیرا یک درخواست <img> از مرورگر خواننده، اعتبارنامهها را به مبدأ (origin) دیگری منتقل نمیکند و هر نمودار تعبیهشده از کار میافتد.