پیش از اولین دستور؛ بکاند روی اوبونتو دقیقاً از چه اجزایی ساخته میشود؟
در این درس ۵ بخش
در دورهٔ ویندوز، یک برنامهٔ Node.js را روی رایانهٔ خودمان اجرا کردیم. اکنون مسئله عوض میشود: چگونه همان برنامه روی دستگاهی دیگر، با هویت مشخص، پس از قطع اتصال ما و پس از روشنشدن دوبارهٔ سیستم آمادهٔ پاسخگویی بماند؟ اگر فقط چند دستور نصب را حفظ کنیم، هنگام اولین خطا نمیدانیم باید کدام بخش را بررسی کنیم. بنابراین این درس ابتدا تصویر سامانه را میسازد. خروجی امروز یک نقشهٔ اجرایی و برگهٔ شناسنامهٔ آزمایشگاه است، نه سایتی که هنوز ساخته نشده باشد. از درس دوم هر جزء را واقعاً آماده میکنیم و در هر ایستگاه، نتیجهٔ قابل مشاهده را میسنجیم.
زبان، محیط اجرا، پردازه و دستگاه؛ چهار مفهوم متفاوت
جاوااسکریپت زبان برنامه است: قاعدهٔ تعریف #function، ساخت #object و تصمیمگیری را مشخص میکند. Node.js محیطی است که این زبان را بیرون از مرورگر اجرا میکند و امکاناتی مانند شبکه و فایل را در اختیارش میگذارد. یک فایل server.mjs تا وقتی اجرا نشده، فقط متن روی دیسک است. وقتی Node آن را اجرا میکند، سیستمعامل یک پردازه ایجاد میکند؛ یعنی نمونهای زنده با شناسه، حافظه، فایلهای باز و مجوزهای کاربر. دو اجرای همزمان یک فایل، دو پردازهاند و ممکن است برای یک پورت رقابت کنند. نصب مجدد زبان چنین رقابتی را حل نمیکند، چون مسئله در مرحلهٔ اجراست.
اوبونتو سیستمعامل میزبان این پردازه است؛ زمان پردازنده، حافظه، فایلها و شبکه را مدیریت میکند. واژهٔ سرور نیز دو کاربرد دارد: گاهی دستگاه یا ماشین مجازی را میگوییم، گاهی خود برنامهای که به درخواست پاسخ میدهد. VPS یک ماشین مجازی اجارهای با منابع و شبکهٔ مشخص است، نه یک چارچوب جاوااسکریپت. میتوان همین تمرین را روی ماشین مجازی محلی نیز انجام داد. یک VPS لزوماً آمادهٔ میزبانی امن برنامه نیست؛ باید نسخهٔ سیستمعامل، روش ورود، دسترسی مدیریتی و سیاست شبکهاش را بررسی کنیم. میزبان آزمایشگاه این دوره، Ubuntu Server 24.04 LTS تازه و مستقل است؛ روی سروری که کسبوکار دیگری در آن فعال است آزمایش نمیکنیم.
برای پیوند این مفاهیم به آموختههای قبلی، اکنون دو ارجاع مشخص را مرور کنید. درس معرفی Node تفاوت زبان و محیط اجرا را نشان میدهد؛ درس پردازههای لینوکس توضیح میدهد یک برنامهٔ در حال اجرا چگونه دیده میشود. لازم نیست همهٔ آن دورهها را دوباره بخوانید؛ اگر نمیتوانید با زبان خود تفاوت فایل برنامه و پردازه را بگویید، همان بخش را تمرین کنید. سپس در یادداشت خود بنویسید «روی دستگاه اوبونتو، یک پردازهٔ Node با حساب کاربری محدود اجرا میشود». همین جمله بعداً مانع اشتباه اجرای دائمی برنامه با root خواهد شد.
معرفی Node.js: https://www.darsavand.com/courses/nodejs-windows-backend-start?lesson=1693c406-5a53-45bf-b075-05e0b9785d02
پردازهها در لینوکس: https://www.darsavand.com/courses/linux-server-from-zero?lesson=f17a796d-a6ba-4a67-bfde-3ad4cfa7f111
یک درخواست چه مسیری را طی میکند؟
کلاینت برنامهای است که درخواست میفرستد؛ ممکن است مرورگر، برنامهٔ موبایل یا ابزار خط فرمان باشد. HTTP قراردادی برای بیان این درخواست و پاسخ است. درخواست دارای روش، مسیر و سرآیند است و گاهی بدنه دارد؛ مثلاً GET برای خواندن فهرست کارها به کار میرود. پاسخ نیز وضعیت و سرآیند و بدنه دارد. #json فقط یکی از قالبهای نمایش داده در بدنه است؛ وجود JSON به معنی موفقیت درخواست یا معتبر بودن داده نیست. کلاینت باید وضعیت HTTP و سپس ساختار داده را بررسی کند. نمایش یک متن در Console نیز پاسخ شبکه نیست؛ برنامه باید واقعاً پاسخ را روی اتصال HTTP بنویسد.
در معماری این دوره، کاربر ابتدا به Nginx متصل میشود. Nginx وبسروری است که نقش پراکسی معکوس را نیز انجام میدهد: درخواست ورودی را طبق قواعد مشخص به برنامهٔ داخلی میفرستد و پاسخ آن را برمیگرداند. واژهٔ معکوس را اینگونه به خاطر بسپارید: این واسطه از طرف سرویسدهنده تنظیم شده است، نه از طرف هر کاربر برای خروج به اینترنت. Nginx میتواند اتصال HTTPS را مدیریت کند و مسیرهای قابل دسترسی را محدود کند. اما خودبهخود منطق ثبت کار، بررسی مالکیت یا مجوز کاربر را برای برنامهٔ ما ایجاد نمیکند. مسئولیت هر بخش باید صریح بماند تا یک پاسخ ۵۰۲ را با اشتباه محاسبهٔ داخل برنامه یکی ندانیم.
دامنه نامی مانند api.example.com است و DNS آن نام را به اطلاعات نشانی مرتبط میکند. دامنه، خود برنامه نیست و خرید آن Node را نصب نمیکند. IP نشانی یک میزبان یا رابط در شبکه است؛ پورت مشخص میکند اتصال به کدام نقطهٔ شنود نرمافزاری آن میزبان برود. در این دوره، ورودی عمومی وب معمولاً پورتهای ۸۰ و ۴۴۳ است، اما برنامهٔ Node روی پورت ۳۰۰۰ گوش میدهد. این تفکیک اجازه میدهد وبسرور ورودی عمومی را مدیریت کند و برنامه با حساب محدود و بدون تصرف پورتهای وب کار کند. یک دستگاه میتواند چند سرویس داشته باشد، به شرط آنکه نشانی و پورت مورد استفادهٔ آنها با هم تعارض نداشته باشد.
نشانی 127.0.0.1 یا loopback به همان دستگاهی اشاره میکند که درخواست از آن آغاز شده است. اگر روی اوبونتو curl را به این نشانی بفرستید، با اوبونتو صحبت میکنید؛ اگر در ویندوز همان نشانی را در مرورگر باز کنید، منظور رایانهٔ ویندوز شماست. برنامهٔ ما فقط روی 127.0.0.1:3000 گوش میدهد تا اتصال مستقیم عمومی به آن در دسترس نباشد. Nginx چون روی همان اوبونتو اجرا میشود میتواند به آن برسد. بازکردن پورت ۳۰۰۰ در فایروال، برنامهای را که فقط روی loopback گوش میدهد عمومی نمیکند؛ البته چنین قانونی هم برای این معماری لازم نیست. محل شنود و قانون فایروال دو تصمیم جدا هستند.
HTTPS، سرویس دائمی و مرز امنیت را روشن کنیم
HTTPS همان استفاده از HTTP درون اتصال محافظتشده با TLS است. TLS به محرمانگی و یکپارچگی ارتباط و شناسایی مقصد مطابق گواهی کمک میکند؛ قفل مرورگر به معنی درستبودن منطق برنامه، معتبر بودن کاربر یا امکان بازیابی اطلاعات نیست. گواهی باید برای دامنهٔ واقعی صادر و پیش از پایان اعتبار تمدید شود. در این دوره ابتدا HTTP را مرحلهای آزمایش میکنیم، بعد دامنه و گواهی را اضافه میکنیم تا اگر مرحلهای شکست خورد، بدانیم نقطهٔ شکست کجاست. نام api.example.com فقط نمونهٔ مستندات است؛ با آن گواهی واقعی نمیگیریم و کاربر باید دامنهٔ تحت کنترل خودش را جایگزین کند.
وقتی در SSH دستور node server.mjs را اجرا میکنید، برنامه به محیط همان نشست وابسته است. برای آزمون اولیه خوب است، اما مسئولیت شروع دوباره، توقف منظم و ثبت وضعیت را باید به مدیر سرویس بسپاریم. systemd در اوبونتو چنین نقشی دارد. تعریف واحد سرویس به آن میگوید برنامه از چه مسیر، با کدام کاربر و تنظیمات اجرا شود و در چه شکستهایی دوباره تلاش کند. فعالسازی برای شروع هنگام بوت با شروع همین لحظه یکسان نیست؛ درس مربوط، هر دو را جدا بررسی میکند. اجرای برنامه زیر چند مدیر همزمان، مثلاً اجرای دستی و systemd با یک پورت، طراحی مورد نظر ما نیست.
پروژهٔ مشترک دوره، API مدیریت کارهای دورهٔ قبلی است. دادهٔ آن در حافظهٔ همان پردازه قرار میگیرد؛ با شروع دوباره از بین میرود. این ویژگی را پنهان نمیکنیم و آن را پایگاه دادهٔ دائمی معرفی نمیکنیم. در ورودی عمومی فقط مسیر سلامت و خواندن فهرستِ نمونه ارائه میشود؛ ایجاد و ویرایش را برای آزمایش داخلی نگه میداریم. اطلاعات واقعی دانشجو، رمز یا تیکت شخصی در آن وارد نکنید. انتشار عمومی نوشتن داده پیش از طراحی احراز هویت، کنترل مجوز و ذخیرهسازی قابل بازیابی، تمرین این دوره نیست. وقتی بعدها پایگاه داده اضافه میکنید، مالکیت داده و نسخهٔ طرح و آزمون بازیابی نیز بخشی از کار خواهد شد.
همین حالا چه کاری انجام دهید؟ شناسنامهٔ آزمایشگاه
مرحلهٔ اول: یک فایل یادداشت شخصی باز کنید و پنج بخش بسازید: رایانهٔ محلی، میزبان اوبونتو، راه ورود، نام دامنه و نتیجهٔ هر آزمون. در بخش محلی، سیستمعامل و شل را بنویسید؛ مسیر اصلی ما Windows و PowerShell است. در بخش میزبان، نسخهٔ مورد انتظار اوبونتو و این واقعیت را ثبت کنید که ماشین آزمایشی تازه است. نشانی واقعی و نام حساب مدیریتی را در یادداشت خصوصی خود نگه دارید، اما رمز یا کلید خصوصی را در آن نچسبانید. عدد 203.0.113.10 در درسها نشانی نمونه است و نباید انتظار اتصال موفق به آن داشته باشید. اگر هنوز ماشین ندارید، تا آمادهکردن ماشین آزمایشی وارد مرحلهٔ نصب نشوید.
مرحلهٔ دوم: پیشنیاز را با یک کار کوچک بسنجید، نه با احساس آشنایی با واژهها. باید بتوانید یک فایل mjs را اجرا کنید، خروجی موفق را از خطا تشخیص دهید، به پوشهٔ درست بروید و در API دادهٔ نامعتبر را رد کنید. مفهوم #async-await و مسیر خطای #try-catch برای خواندن پروژه لازم است؛ اما طراحی پیشرفتهٔ worker یا پایگاه داده، پیشنیاز شروع این راهاندازی نیست. درس آزمون آمادگی Node و درس مسیرهای لینوکس برای جبران ضعف مشخصاند. پس از مرور، بنویسید کدام گام را بدون راهنما انجام دادید و کدام گام هنوز به تمرین نیاز دارد.
آزمون آمادگی Node: https://www.darsavand.com/courses/nodejs-windows-backend-start?lesson=475704de-98f0-48f0-81eb-f03fb39799a3
مسیرها و پوشهها: https://www.darsavand.com/courses/linux-server-from-zero?lesson=9ea841e0-0cd7-4232-9059-54c638a5f78b
node -p "process.platform"
node -p "process.arch"
node -p "process.execPath"این سه دستور را فعلاً در PowerShell رایانهٔ محلی اجرا کنید، نه داخل یک فایل جاوااسکریپت و نه در نشست اوبونتو. انتظار داریم نام بستر، معماری باینری و مسیر فایل اجرایی Node محلی چاپ شود. در ویندوز بومی، win32 نام تاریخی بستر است و به معنی ۳۲بیتیبودن همهٔ اجراها نیست. اگر node شناخته نمیشود، به درس نصب ویندوز برگردید؛ مشکل را با فرمان sudo یا دستکاری تصادفی PATH درمان نکنید. این آزمون هنوز چیزی دربارهٔ نصب Node روی سرور ثابت نمیکند. هدفش تمرین این پرسش است که «این دستور دقیقاً روی کدام دستگاه و با کدام فایل اجرایی انجام شد؟»
تمرین با پاسخ؛ درخواست نرسید، کجا را بررسی کنیم؟
فرض کنید برنامه روی اوبونتو با curl داخلی پاسخ میدهد، اما مرورگر ویندوز هنگام بازکردن 127.0.0.1:3000 خطای اتصال نشان میدهد. نخست توضیح بدهید این دو درخواست به یک مقصد اشاره نمیکنند: loopback ویندوز، اوبونتو نیست. پاسخ درست، عمومیکردن شتابزدهٔ Node نیست؛ در فصل وب، از دامنه و Nginx استفاده میکنیم و برای آزمون داخلی، تونل SSH را میآموزیم. تمرین دوم: قفل HTTPS دیده میشود ولی ثبت یک کار دادهٔ کاربر دیگر را تغییر میدهد. TLS ارتباط را محافظت کرده، اما مجوز کاربردی خراب است؛ بنابراین تغییر گواهی مشکل مالکیت داده را حل نمیکند. برای هر سناریو، لایهٔ مسئله و یک مشاهدهٔ لازم را بنویسید.
معیار پایان این درس سه خروجی است: نقشهای که کلاینت، Nginx، پردازهٔ Node و محل داده را جدا نشان دهد؛ شناسنامهای بدون رمز با نام محیط و روش ورود؛ و توضیحی که بگوید چرا پورت ۳۰۰۰ عمومی نیست و چرا داده با restart از بین میرود. اگر هنوز اینها روشن نیست، همین درس و ارجاع مربوط را مرور کنید و وارد نصب نشوید. در درس بعد، فقط اتصال و آمادهبودن میزبان را اثبات میکنیم. سپس Node را نصب میکنیم، بعد کد و سرویس و وب را اضافه میکنیم. این ترتیب، هر بار تنها یک مجموعهٔ محدود از علتهای خطا را پیش روی ما میگذارد.
منابع رسمی انگلیسی برای مطالعهٔ تکمیلی:
Node.js introduction: https://nodejs.org/learn/getting-started/introduction-to-nodejs
Node.js browser differences: https://nodejs.org/learn/getting-started/differences-between-nodejs-and-the-browser
Node.js HTTP API: https://nodejs.org/docs/latest-v24.x/api/http.html
Nginx reverse proxy: https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
Ubuntu Server web services: https://ubuntu.com/server/docs/how-to/web-services/
MDN HTTP overview: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Overview
تألیف، سناریوها و مسیر تمرین: تحریریه درسآوند. این درس بخشی از دورهٔ رایگان راهاندازی بکاند روی اوبونتو است.
متن درسهای عمومی را بدون ورود بخوانید.