لوگوی هاکان سرور
لوگوی هاکان سرور

نصب IIS روی ویندوز سرور؛ راه‌اندازی سایت، PHP و SSL رایگان

پنجرهٔ نصب IIS با نوار پیشرفت و نشان ویندوز کنار جعبهٔ دانلود؛ آموزش نصب IIS روی ویندوز سرور
فهرست مطالب
  1. IIS چیست و چه زمانی انتخاب درستی است؟
  2. پیش‌نیازهای نصب IIS
  3. نصب IIS با Server Manager
  4. نصب IIS با PowerShell
  5. سرویس‌های نقش که شاید لازم داشته باشید
  6. باز کردن پورت‌های 80 و 443
  7. راه‌اندازی سایت روی IIS
  8. استخر برنامه و هویت آن
  9. ساخت سایت در IIS Manager
  10. ساخت سایت با PowerShell
  11. binding و سایت پیش‌فرض
  12. چند سایت HTTPS روی یک IP با SNI
  13. دسترسی پوشه‌ها: IUSR، IIS_IUSRS و هویت استخر
  14. سند پیش‌فرض و خطای 403.14
  15. اجرای PHP و ASP.NET روی IIS
  16. نصب PHP با FastCGI
  17. سقف حجم آپلود در PHP و IIS
  18. ASP.NET Core و Hosting Bundle
  19. نصب SSL رایگان روی IIS با win-acme
  20. گرفتن گواهی با win-acme
  21. تمدید خودکار و عمر کوتاه‌تر گواهی‌ها
  22. نصب گواهی خریداری‌شده (فایل pfx)
  23. ریدایرکت HTTP به HTTPS
  24. روش ۱: ماژول URL Rewrite
  25. روش ۲: ریدایرکت و HSTS داخلی IIS
  26. لاگ‌ها و رفع خطاهای رایج IIS
  27. لاگ‌های IIS کجا هستند؟
  28. پیغام کامل خطا و Failed Request Tracing
  29. جدول خطاهای رایج
  30. امنیت IIS؛ چک‌لیست کوتاه
  31. نکته‌های مخصوص کاربران ایران
  32. سرور مناسب برای IIS
  33. پرسش‌های متداول
  34. IIS رایگان است؟
  35. IIS روی ویندوز ۱۰ و ۱۱ هم نصب می‌شود؟
  36. وردپرس را روی IIS نصب کنم یا روی لینوکس؟
  37. چرا سایت روی خود سرور باز می‌شود ولی از بیرون نه؟
  38. IIS را چطور حذف کنم؟
  39. جمع‌بندی

نصب IIS روی ویندوز سرور با یک دستور PowerShell یا چند کلیک در Server Manager تمام می‌شود؛ کار اصلی بعد از آن است: ساخت سایت با binding درست، تنظیم دسترسی پوشه‌ها، اجرای PHP یا ASP.NET و گرفتن SSL رایگان. این راهنما همهٔ این مراحل را روی Windows Server 2022 و 2025 با دستورهای دقیق و راه رفع خطاهای رایج نشان می‌دهد.

IIS (Internet Information Services) وب‌سرور مایکروسافت است که به‌صورت یک نقش (Role) در ویندوز سرور نصب می‌شود و در Windows Server 2016 تا 2025 نسخهٔ 10.0 دارد. دستورها را در Windows PowerShell با «Run as administrator» اجرا کنید، مگر جایی که Command Prompt گفته شده است، و به‌جای example.com و 203.0.113.10 دامنه و IP خودتان را بگذارید.

به‌طور خلاصه:

  1. نصب با Install-WindowsFeature -Name Web-Server -IncludeManagementTools و باز کردن http://localhost روی سرور.
  2. باز کردن پورت‌های 80 و 443 در فایروال ویندوز و پنل ارائه‌دهنده.
  3. ساخت پوشه، Application Pool جدا و binding با نام دامنه و www.
  4. اجازهٔ خواندن برای IIS AppPool\example.com و اجازهٔ نوشتن فقط برای پوشهٔ آپلود.
  5. برای PHP نقش CGI، نسخهٔ NTS x64 و نگاشت FastCGI؛ برای ASP.NET Core بستهٔ Hosting Bundle.
  6. SSL رایگان با win-acme و سپس ریدایرکت HTTP به HTTPS.
  7. عیب‌یابی با کد کامل خطا (مثل 500.19) در %SystemDrive%\inetpub\logs\LogFiles.

IIS چیست و چه زمانی انتخاب درستی است؟

IIS درخواست‌ها را از راه HTTP.sys، درایور HTTP هستهٔ ویندوز، می‌گیرد و کد هر سایت را در یک استخر برنامه (Application Pool)، یعنی پروسهٔ جدای w3wp.exe با هویت خودش، اجرا می‌کند تا مشکل یک سایت به بقیه سرایت نکند. تنظیمات سراسری در applicationHost.config است و تنظیمات هر سایت می‌تواند در web.config خود آن سایت باشد.

وب‌سرور IIS انتخاب طبیعی است برای برنامه‌های ASP.NET روی .NET Framework 4.x (Web Forms و MVC) که فقط روی ویندوز اجرا می‌شوند، برای ASP.NET Core وقتی میزبانی روی ویندوز را می‌خواهید (ASP.NET Core روی لینوکس هم اجرا می‌شود) و برای نرم‌افزارهایی که به Classic ASP، اجزای COM یا احراز هویت ویندوز (Windows Authentication) وابسته‌اند.

برای وردپرس، لاراول و بیشتر سایت‌های PHP، لینوکس با Nginx، Apache یا LiteSpeed ساده‌تر است: بیشتر آموزش‌ها و ابزارهای PHP برای لینوکس‌اند و بعضی افزونه‌های PHP، مثل pcntl، روی ویندوز کار نمی‌کنند. برای یک سایت وردپرسی، هاست لینوکس بر پایهٔ cPanel انتخاب کوچک‌تر و کم‌دردسرتری است. اگر نمی‌خواهید سرور ویندوزی را خودتان نگه دارید، هاست ویندوز را بررسی کنید؛ در هاست اشتراکی معمولاً به ریموت دسکتاپ و تنظیمات سراسری وب‌سرور دسترسی ندارید، پس پیش از خرید بپرسید نسخهٔ .NET یا PHP موردنیاز برنامه‌تان پشتیبانی می‌شود یا نه.

پیش‌نیازهای نصب IIS

  • ویندوز سرور و دسترسی مدیر: Windows Server 2022 یا 2025 با رابط گرافیکی (Desktop Experience)؛ روش اتصال در آموزش اتصال به سرور مجازی ویندوز آمده است.
  • منابع: طبق مستندات مایکروسافت، Windows Server 2025 با رابط گرافیکی دست‌کم ۲ گیگابایت رم (۴ گیگابایت توصیه‌شده) و ۳۲ گیگابایت فضای دیسک سیستم می‌خواهد؛ منابع برنامهٔ شما جداست.
  • دامنه: رکورد A برای example.com و www به IP سرور؛ برای دامنهٔ .ir در nic.ir فقط Nameserverها تعیین می‌شوند.

IIS همراه ویندوز وصله می‌شود؛ پس ویندوز بدون پشتیبانی یعنی IIS بدون وصله. برای سرور تازه Windows Server 2025 را انتخاب کنید که تازه‌ترین نسخهٔ LTSC (پشتیبانی بلندمدت) است:

نسخه وصلهٔ امنیتی تا
Windows Server 2025 نوامبر ۲۰۳۴
Windows Server 2022 اکتبر ۲۰۳۱ (پشتیبانی اصلی ۲۱ مهر ۱۴۰۵ تمام شد)
Windows Server 2019 ژانویهٔ ۲۰۲۹
Windows Server 2016 ۲۲ دی ۱۴۰۵ (۱۲ ژانویهٔ ۲۰۲۷)

نصب IIS با Server Manager

  1. در Server Manager منوی Manage › Add Roles and Features را باز کنید، در Installation Type گزینهٔ Role-based or feature-based installation و در Server Selection سرور خودتان را انتخاب کنید.
  2. در Server Roles تیک Web Server (IIS) را بزنید و در پنجرهٔ بعد، با روشن ماندن Include management tools (if applicable)، روی Add Features بزنید تا IIS Manager هم نصب شود.
  3. صفحه‌های Features و Web Server Role (IIS) را با Next رد کنید و در Role Services فقط موارد لازم را اضافه کنید (جدول بخش بعد)؛ مثلاً CGI یا ASP.NET 4.x زیر Application Development و Tracing زیر Health and Diagnostics.
  4. تا صفحهٔ Confirmation با Next جلو بروید، Install و در پایان Close را بزنید.

حالا http://localhost را روی خود سرور باز کنید؛ صفحهٔ خوش‌آمد IIS یعنی وب‌سرور کار می‌کند. نصب پیش‌فرض فقط سرویس‌های پایه را دارد و مایکروسافت توصیه می‌کند فقط ماژول‌های لازم را اضافه کنید تا سطح حمله کوچک بماند.

نصب IIS با PowerShell

گزینهٔ -IncludeManagementTools را جا نیندازید؛ این cmdlet برخلاف Server Manager بدون آن IIS Manager را نصب نمی‌کند:

Install-WindowsFeature -Name Web-Server -IncludeManagementTools

نمونهٔ خروجی:

Success Restart Needed Exit Code      Feature Result
------- -------------- ---------      --------------
True    No             Success        {Common HTTP Features, Default Document, ...

سرویس‌های بیشتر را با نام فنی اضافه کنید و فهرست نصب‌شده‌ها را ببینید:

# FastCGI for PHP, ASP.NET 4.x, Failed Request Tracing, IIS PowerShell modules
Install-WindowsFeature -Name Web-CGI, Web-Asp-Net45, Web-Http-Tracing, Web-Scripting-Tools
Get-WindowsFeature -Name Web-* | Where-Object Installed

سرویس‌های نقش که شاید لازم داشته باشید

نام در PowerShell نام در Server Manager کاربرد
Web-CGI CGI اجرای PHP با FastCGI
Web-Asp-Net45 ASP.NET 4.x برنامه‌های .NET Framework
Web-WebSockets WebSocket Protocol برنامه‌های بلادرنگ مثل SignalR
Web-Dyn-Compression Dynamic Content Compression فشرده‌سازی خروجی PHP و ASP.NET
Web-Http-Tracing Tracing Failed Request Tracing
Web-Scripting-Tools IIS Management Scripts and Tools ماژول‌های PowerShell مثل WebAdministration
Web-Mgmt-Service Management Service فقط برای مدیریت از راه دور

ASP.NET Core نقش جدا نمی‌خواهد و با Hosting Bundle اجرا می‌شود.

باز کردن پورت‌های 80 و 443

از کامپیوتر خودتان، نه روی سرور، تست کنید؛ TcpTestSucceeded : True یعنی پورت باز است (در مک یا لینوکس: nc -vz 203.0.113.10 80):

Test-NetConnection 203.0.113.10 -Port 80

اگر False بود، روی سرور قاعدهٔ ورودی بسازید:

New-NetFirewallRule -DisplayName "Web HTTP 80" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
New-NetFirewallRule -DisplayName "Web HTTPS 443" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow

اگر باز هم بسته بود، فایروال پنل ارائه‌دهنده را بررسی کنید؛ جزئیات مدیریت قاعده‌ها در آموزش فعال‌سازی فایروال در ویندوز سرور آمده است.

راه‌اندازی سایت روی IIS

استخر برنامه و هویت آن

برای هر سایت یک Application Pool جدا بسازید. هویت پیش‌فرض آن ApplicationPoolIdentity است: حسابی مجازی به نام IIS AppPool\example.com که رمز ندارد و فقط مال همین استخر است. تنظیم مهم دیگر .NET CLR version است:

نوع سایت .NET CLR version پیش‌نیاز
HTML و فایل‌های ایستا No Managed Code هیچ
PHP No Managed Code نقش CGI و PHP
ASP.NET Core No Managed Code Hosting Bundle
ASP.NET روی .NET Framework 4.x v4.0 نقش ASP.NET 4.x

ساخت سایت در IIS Manager

IIS Manager را از Server Manager › Tools یا با inetmgr باز کنید: ستون چپ (Connections) سرور، Application Pools و سایت‌ها را نشان می‌دهد و هر تنظیم روی سطحی اعمال می‌شود که آنجا انتخاب کرده‌اید؛ بخش وسط (Features View) قابلیت‌ها و ستون راست (Actions) کارها را دارد.

  1. پوشهٔ سایت را بیرون از C:\inetpub\wwwroot بسازید، مثلاً C:\sites\example.com، و یک index.html آزمایشی در آن بگذارید.
  2. روی Sites راست‌کلیک و Add Website را بزنید. Site name را example.com بگذارید تا استخری هم‌نام ساخته شود و Physical path را پوشهٔ سایت بدهید.
  3. در بخش Binding مقدار Type را http، IP address را All Unassigned، Port را 80 و Host name را example.com بگذارید.
  4. از Actions › Bindings › Add یک binding دیگر با Host name برابر www.example.com بسازید.
  5. در Application Pools مقدار .NET CLR version استخر را طبق جدول بالا تنظیم کنید.

ساخت سایت با PowerShell

همین کار با PowerShell؛ خط پنجم استخر را روی No Managed Code می‌گذارد و برای ASP.NET روی .NET Framework اجرایش نکنید. اگر Import-Module WebAdministration خطا داد، نقش Web-Scripting-Tools را نصب کنید:

Import-Module WebAdministration
New-Item -ItemType Directory -Path "C:\sites\example.com" -Force
Set-Content -Path "C:\sites\example.com\index.html" -Value "<h1>example.com works</h1>"
New-WebAppPool -Name "example.com"
Set-ItemProperty -Path "IIS:\AppPools\example.com" -Name managedRuntimeVersion -Value ""
New-Website -Name "example.com" -PhysicalPath "C:\sites\example.com" -ApplicationPool "example.com" -Port 80 -HostHeader "example.com"
New-WebBinding -Name "example.com" -Protocol http -Port 80 -HostHeader "www.example.com"

binding و سایت پیش‌فرض

binding ترکیب پروتکل، IP، پورت و نام میزبان (Host name) است و IIS از روی هدر Host سایت را پیدا می‌کند؛ پس ده‌ها سایت روی یک IP و پورت 80 کار می‌کنند. Default Web Site با binding بدون نامش به هر درخواستی که سایت دیگری برایش نیست، مثل باز کردن سرور با IP، جواب می‌دهد. اگر لازمش ندارید، با دستور زیر حذفش کنید (محتوای wwwroot می‌ماند)؛ بعد از آن چنین درخواستی از HTTP.sys خطای 400 با پیام Bad Request – Invalid Hostname می‌گیرد.

Remove-Website -Name "Default Web Site"

چند سایت HTTPS روی یک IP با SNI

در HTTPS سرور باید پیش از دیدن هدر Host گواهی بفرستد. SNI (Server Name Indication) نام دامنه را در دست‌دهی TLS می‌فرستد و از IIS 8 به بعد اجازه می‌دهد هر سایت روی همان IP و پورت 443 گواهی خودش را داشته باشد. در Add Site Binding از نوع https، نام میزبان را بنویسید و Require Server Name Indication را تیک بزنید؛ win-acme این binding را خودش می‌سازد.

دسترسی پوشه‌ها: IUSR، IIS_IUSRS و هویت استخر

هویت چیست نکته
IIS AppPool\example.com هویت پروسهٔ استخر سایت کد سایت با آن اجرا می‌شود
IUSR حساب پیش‌فرض بازدیدکنندهٔ ناشناس فایل‌ها به‌طور پیش‌فرض با آن خوانده می‌شوند
IIS_IUSRS گروهی که IIS خودکار به همهٔ استخرها می‌دهد اجازه به آن یعنی اجازه به همهٔ سایت‌ها

ساده‌ترین روش امن این است که احراز هویت ناشناس هم با هویت استخر انجام شود تا فقط یک هویت مهم باشد: سایت › Authentication › Anonymous Authentication › Edit › Application pool identity. معادل PowerShell:

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" -Location "example.com" -Filter "system.webServer/security/authentication/anonymousAuthentication" -Name userName -Value ""

بعد به همین هویت برای کل سایت اجازهٔ خواندن و فقط برای پوشه‌ای که برنامه در آن می‌نویسد، مثل آپلود، اجازهٔ تغییر بدهید:

New-Item -ItemType Directory -Path "C:\sites\example.com\uploads" -Force
icacls "C:\sites\example.com" /grant "IIS AppPool\example.com:(OI)(CI)RX"
icacls "C:\sites\example.com\uploads" /grant "IIS AppPool\example.com:(OI)(CI)M"

(OI)(CI) یعنی ارث‌بری به فایل‌ها و زیرپوشه‌ها، RX خواندن و اجرا و M تغییر است. به Everyone یا IIS_IUSRS اجازهٔ نوشتن ندهید و هویت استخر را عضو Administrators نکنید.

سند پیش‌فرض و خطای 403.14

برای نشانی بدون نام فایل، IIS دنبال Default.htm، Default.asp، index.htm، index.html و iisstart.htm می‌گردد (با نصب ASP.NET، Default.aspx هم). index.php در فهرست نیست و اگر چیزی پیدا نشود، خطای 403.14 می‌آید. فهرست را در web.config ریشهٔ سایت بنویسید؛ <clear /> فهرست ارثی را کنار می‌گذارد:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <defaultDocument>
      <files>
        <clear />
        <add value="index.php" />
        <add value="index.html" />
      </files>
    </defaultDocument>
  </system.webServer>
</configuration>

برای رفع 403.14 فهرست پوشه (Directory Browsing) را روشن نکنید؛ فهرست فایل‌های سایت را به همه نشان می‌دهد.

اجرای PHP و ASP.NET روی IIS

نصب PHP با FastCGI

پیش از این تغییرات از تنظیمات IIS پشتیبان بگیرید؛ برگرداندن با restore backup به‌جای add backup است:

& "$env:windir\system32\inetsrv\appcmd.exe" add backup "before-php"
  1. نقش CGI: Install-WindowsFeature -Name Web-CGI؛ ماژول FastCGI با همین نقش نصب می‌شود.
  2. دریافت PHP: از صفحهٔ دانلود PHP برای ویندوز (که حالا به php.net می‌رود) آخرین نسخهٔ 8.5 یا 8.4 با برچسب VS17 x64 Non Thread Safe را بگیرید، مثل php-8.5.x-nts-Win32-vs17-x64.zip. در زمان نگارش این مطلب (آبان ۱۴۰۵) این دو شاخه پشتیبانی فعال دارند و طبق همان صفحه، نسخهٔ NTS برای FastCGI و IIS است.
  3. Visual C++: بستهٔ Visual C++ Redistributable نسخهٔ x64 (vc_redist.x64.exe) را از لینک همان صفحه نصب کنید. این بسته در صفحهٔ PHP «for Visual Studio 2015-2022» نام دارد و مایکروسافت حالا نسخهٔ جاری آن را Visual C++ v14 Redistributable می‌نامد.
  4. استخراج و php.ini: فایل zip را در C:\PHP باز کنید و این دو دستور را بزنید:
    Copy-Item "C:\PHP\php.ini-production" "C:\PHP\php.ini"
    C:\PHP\php.exe -v

    اگر به‌جای شمارهٔ نسخه، خطای پیدا نشدن VCRUNTIME140 آمد، بستهٔ Visual C++ نصب نشده است.

در C:\PHP\php.ini این خطوط را پیدا و به این شکل تنظیم کنید؛ اگر اول خط علامت ; دارد، حذفش کنید:

extension_dir = "C:\PHP\ext"
cgi.force_redirect = 0
cgi.fix_pathinfo = 1
fastcgi.impersonate = 1
date.timezone = Asia/Tehran
expose_php = Off
extension=curl
extension=mbstring
extension=mysqli
extension=openssl
opcache.enable=1

خود php.ini می‌نویسد cgi.force_redirect زیر IIS باید خاموش باشد و fastcgi.impersonate = 1 را برای IIS توصیه می‌کند؛ expose_php = Off هم نسخهٔ PHP را از هدرها برمی‌دارد. در PHP 8.4 خط zend_extension=opcache را هم فعال کنید؛ در PHP 8.5، OPcache همیشه جزو خود PHP است و آن خط فقط هشدار می‌دهد.

نگاشت handler: در IIS Manager روی نام سرور، Handler Mappings › Add Module Mapping را بزنید: Request path را *.php، Module را FastCgiModule، Executable را C:\PHP\php-cgi.exe (نه php.exe) و Name را PHP-FastCGI بگذارید. در Request Restrictions تیک Invoke handler only if request is mapped to را با File or Folder بزنید تا نشانی‌های بدون فایل واقعی به PHP نرسند و بعد از OK، به پرسش ساخت FastCGI application پاسخ Yes بدهید. یا به‌جای آن، این دستورهای مستندات مایکروسافت را در Command Prompt مدیر بزنید:

%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='C:\PHP\php-cgi.exe',instanceMaxRequests='10000']" /commit:apphost
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='C:\PHP\php-cgi.exe'].environmentVariables.[name='PHP_FCGI_MAX_REQUESTS',value='10000']" /commit:apphost
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/handlers /+"[name='PHP-FastCGI',path='*.php',verb='*',modules='FastCgiModule',scriptProcessor='C:\PHP\php-cgi.exe',resourceType='Either',requireAccess='Script']" /commit:apphost

در هر دو روش، در Handler Mappings روی View Ordered List بزنید؛ ردیف PHP-FastCGI باید بالاتر از StaticFile باشد و اگر نبود، با Move Up بالا ببریدش.

تست: این فایل را بسازید و http://example.com/info.php را باز کنید؛ Server API باید CGI/FastCGI و Loaded Configuration File باید C:\PHP\php.ini باشد:

Set-Content -Path "C:\sites\example.com\info.php" -Value "<?php phpinfo();"

هشدار: صفحهٔ phpinfo اطلاعات سرور را به همه نشان می‌دهد؛ بلافاصله بعد از تست با Remove-Item "C:\sites\example.com\info.php" پاکش کنید.

بعد از هر تغییر در php.ini، استخر سایت را با Restart-WebAppPool -Name "example.com" دوباره راه‌اندازی کنید.

سقف حجم آپلود در PHP و IIS

آپلود فایل بزرگ دو سقف دارد: upload_max_filesize و post_max_size در php.ini (در نسخهٔ production ۲ و ۸ مگابایت) و سقف Request Filtering خود IIS که پیش‌فرض حدود ۲۸٫۶ مگابایت است؛ مستندات مایکروسافت برای رد درخواست بزرگ‌تر هم کد 404.13 آورده و هم 413.1. برای فایل تا ۱۰۰ مگابایت، upload_max_filesize = 100M و post_max_size = 110M بگذارید و سقف IIS را در web.config سایت، داخل <system.webServer>، روی همان ۱۱۰ مگابایت ببرید:

<security>
  <requestFiltering>
    <requestLimits maxAllowedContentLength="115343360" />
  </requestFiltering>
</security>

ASP.NET Core و Hosting Bundle

  1. بعد از IIS، بستهٔ .NET Hosting Bundle نسخهٔ .NET برنامه را از لینک رسمی نسخهٔ جاری یا صفحهٔ دانلود .NET نصب کنید. اگر آن را پیش از IIS نصب کرده‌اید، طبق مستندات مایکروسافت نصب‌کننده را دوباره اجرا و تعمیر (Repair) کنید.
  2. IIS را ری‌استارت کنید تا مسیر تازه را بشناسد:
    net stop was /y
    net start w3svc
  3. خروجی dotnet publish را، که web.config لازم را هم دارد، در پوشهٔ سایت بگذارید و .NET CLR version استخر را No Managed Code کنید.

در زمان نگارش این مطلب (آبان ۱۴۰۵)، .NET 10 نسخهٔ پشتیبانی بلندمدت (LTS) است و پشتیبانی .NET 8 و .NET 9 در ۱۹ آبان ۱۴۰۵ به پایان می‌رسد؛ برنامهٔ تازه را روی .NET 10 بسازید.

نصب SSL رایگان روی IIS با win-acme

Let’s Encrypt گواهی رایگان DV (اعتبارسنجی دامنه) می‌دهد که مرورگرهای رایج قبولش دارند؛ تفاوتش با گواهی پولی را در مقالهٔ SSL چیست بخوانید. روی IIS، ابزار رایگان و متن‌باز win-acme کلاینت ACME (پروتکل صدور خودکار گواهی) است که گواهی را می‌گیرد، binding پورت 443 را می‌سازد و تمدید را زمان‌بندی می‌کند؛ نسخهٔ پایدار آن در زمان نگارش این مطلب (آبان ۱۴۰۵) 2.2.9.1 است.

گرفتن گواهی با win-acme

پیش‌نیاز: سایت برای example.com و www.example.com binding با نام میزبان داشته باشد (win-acme نام‌ها را از همین bindingها برمی‌دارد)، رکورد A هر دو نام به IP همین سرور اشاره کند و پورت 80 از اینترنت باز باشد؛ روش HTTP-01 فقط روی پورت 80 انجام می‌شود.

  1. فایل zip نسخهٔ x64 (مثل win-acme.v2.2.9.1701.x64.trimmed.zip) را از win-acme.com یا صفحهٔ Releases پروژه در GitHub بگیرید و در پوشه‌ای ماندگار مثل C:\Program Files\win-acme باز کنید؛ تسک تمدید از همین پوشه اجرا می‌شود.
  2. wacs.exe را با Run as administrator اجرا کنید و در منوی اصلی N یعنی Create certificate (default settings) را بزنید.
  3. سایت را از فهرست سایت‌های IIS انتخاب و نام‌ها را تأیید کنید؛ بار اول شرایط استفاده را بپذیرید و یک ایمیل برای حساب ACME بدهید.

win-acme بعد از اعتبارسنجی، گواهی را در مخزن Web Hosting ویندوز (یا اگر نبود، Personal) می‌گذارد، binding از نوع https روی پورت 443 را می‌سازد یا به‌روز می‌کند و تسکی زمان‌بندی‌شده می‌سازد که هر روز از ساعت ۹ صبح (با تأخیر تصادفی تا ۴ ساعت) با حساب SYSTEM اجرا می‌شود. حالا https://example.com را باز کنید و تاریخ انقضای گواهی‌ها را ببینید:

Get-ChildItem Cert:\LocalMachine\WebHosting, Cert:\LocalMachine\My | Select-Object Subject, NotAfter

تمدید خودکار و عمر کوتاه‌تر گواهی‌ها

گواهی Let’s Encrypt فعلاً ۹۰ روزه است و win-acme به‌طور پیش‌فرض ۵۵ روز بعد از صدور تمدیدش می‌کند، مگر اینکه Let’s Encrypt از راه ARI (ACME Renewal Information) زودتر بخواهد یا کمتر از ۷ روز از اعتبار گواهی مانده باشد. برای آزمایش تمدید این دستور را در پوشهٔ win-acme بزنید؛ --nocache کش win-acme را دور می‌زند و واقعاً گواهی تازه می‌گیرد، پس پشت سر هم تکرارش نکنید:

.\wacs.exe --renew --force --nocache

Let’s Encrypt اعلام کرده است که عمر گواهی پیش‌فرض کوتاه‌تر می‌شود و هر تغییر از اولین تمدید بعد از آن تاریخ اعمال می‌شود:

از تاریخ عمر گواهی پیش‌فرض
اکنون ۹۰ روز
۲۱ بهمن ۱۴۰۵ (۱۰ فوریهٔ ۲۰۲۷) ۶۴ روز
۲۷ بهمن ۱۴۰۶ (۱۶ فوریهٔ ۲۰۲۸) ۴۵ روز

با گواهی ۶۴ روزه، تمدید در روز ۵۵ فقط ۹ روز فرصت جبران می‌گذارد. اگر ARI کار نکند یا سرور گاهی به اینترنت بین‌الملل دسترسی ندارد، RenewalDays را در settings.json پوشهٔ win-acme کم کنید، مثلاً ۴۲، یعنی حدود دوسوم عمر گواهی که Let’s Encrypt مناسب می‌داند. Let’s Encrypt از خرداد ۱۴۰۴ ایمیل هشدار انقضا هم نمی‌فرستد؛ انقضا را خودتان پایش کنید.

نصب گواهی خریداری‌شده (فایل pfx)

اگر گواهی پولی دارید، مثلاً با خرید SSL، فایل .pfx را همراه کلید خصوصی بگیرید و در IIS Manager روی نام سرور با Server Certificates › Import در مخزن Web Hosting وارد کنید؛ یا با PowerShell:

$pw = Read-Host -AsSecureString "PFX password"
Import-PfxCertificate -FilePath "C:\certs\example.com.pfx" -CertStoreLocation "Cert:\LocalMachine\WebHosting" -Password $pw

سپس در Bindings سایت، binding از نوع https با پورت 443، نام میزبان و تیک Require Server Name Indication بسازید، گواهی را در SSL certificate انتخاب کنید و همین کار را برای www تکرار کنید. طبق قواعد CA/Browser Forum، عمر گواهی‌های عمومی از ۲۴ اسفند ۱۴۰۴ حداکثر ۲۰۰ روز است و از ۲۴ اسفند ۱۴۰۵ به ۱۰۰ روز می‌رسد؛ پس گواهی پولی را هم باید چند بار در سال جایگزین کنید.

ریدایرکت HTTP به HTTPS

وقتی HTTPS درست باز شد، نه زودتر، درخواست‌های HTTP را با 301 به HTTPS بفرستید. Let’s Encrypt ریدایرکت را دنبال می‌کند و گواهی مقصد را بررسی نمی‌کند؛ پس تمدید خراب نمی‌شود، به شرط باز ماندن پورت 80.

روش ۱: ماژول URL Rewrite

Web Platform Installer (WebPI) که آموزش‌های قدیمی معرفی می‌کنند، ۱۰ دی ۱۴۰۱ بازنشسته شد. URL Rewrite 2.1 را مستقیم از صفحهٔ رسمی آن در iis.net بگیرید (فایل rewrite_amd64_en-US.msi) و نصب کنید؛ این ماژول برای پیوندهای یکتای وردپرس و بیشتر فریم‌ورک‌ها هم لازم است. سپس این قاعده را در web.config ریشهٔ سایت بگذارید:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Redirect HTTP to HTTPS" stopProcessing="true">
          <match url="(.*)" />
          <conditions>
            <add input="{HTTPS}" pattern="off" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

رشتهٔ پرس‌وجو (Query String) خودکار به نشانی مقصد اضافه می‌شود. اگر سایت از قبل web.config دارد، فقط بلوک <rewrite> را داخل همان <system.webServer> بگذارید؛ بدون نصب URL Rewrite، این بلوک خطای 500.19 می‌دهد.

روش ۲: ریدایرکت و HSTS داخلی IIS

در Windows Server 2019 و بعد (IIS 10.0 نسخهٔ 1709 به بعد)، خود IIS بدون URL Rewrite ریدایرکت به HTTPS و هدر HSTS را در سطح سایت دارد. HSTS مرورگر را تا max-age ثانیه به HTTPS محدود می‌کند؛ پس با ۳۰۰ ثانیه شروع کنید و بعد از پایدار شدن HTTPS بیشترش کنید. در Command Prompt مدیر:

%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/sites "/[name='example.com'].hsts.enabled:True" /commit:apphost
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/sites "/[name='example.com'].hsts.max-age:300" /commit:apphost
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/sites "/[name='example.com'].hsts.redirectHttpToHttps:True" /commit:apphost

فقط یکی از دو روش را به کار ببرید. اگر سایت پشت Cloudflare است و حالت SSL/TLS آن Flexible است، Cloudflare با HTTP به سرور وصل می‌شود و هر دو روش حلقهٔ ریدایرکت (خطای ERR_TOO_MANY_REDIRECTS) می‌سازند؛ چون حالا روی سرور گواهی معتبر دارید، آن حالت را روی Full (strict) بگذارید.

لاگ‌ها و رفع خطاهای رایج IIS

لاگ‌های IIS کجا هستند؟

لاگ هر سایت در %SystemDrive%\inetpub\logs\LogFiles، در پوشه‌ای با نام W3SVC و شمارهٔ ID سایت (ستون ID در فهرست Sites) است و هر روز فایل تازه‌ای دارد. زمان‌ها به UTC ثبت می‌شوند، یعنی ۳ ساعت و ۳۰ دقیقه عقب‌تر از وقت تهران. ۲۰ خط آخر لاگ سایتی با ID برابر 2:

Get-ChildItem "C:\inetpub\logs\LogFiles\W3SVC2" | Sort-Object LastWriteTime | Select-Object -Last 1 | Get-Content -Tail 20

ستون‌های sc-status و sc-substatus با هم کد کامل خطا را می‌سازند؛ 500 و 19 یعنی 500.19. خطاهایی که HTTP.sys پیش از رسیدن درخواست به سایت برمی‌گرداند، مثل Invalid Hostname، در %SystemRoot%\System32\LogFiles\HTTPERR ثبت می‌شوند.

پیغام کامل خطا و Failed Request Tracing

IIS به‌طور پیش‌فرض (حالت DetailedLocalOnly) پیغام کامل خطا را فقط در مرورگر خود سرور نشان می‌دهد. برای خطایی که سخت تکرار می‌شود، Failed Request Tracing (نقش Web-Http-Tracing) را به کار ببرید:

  1. سایت را انتخاب کنید و در Actions › Configure › Failed Request Tracing تیک Enable را بزنید.
  2. در Failed Request Tracing Rules با Add و گزینهٔ All content، کد خطا (مثلاً 500 یا 401.3) را در Status code(s) بنویسید و با پیش‌فرض‌ها تا Finish بروید.
  3. خطا را تکرار کنید و فایل‌هایی مثل fr000001.xml را در %SystemDrive%\inetpub\logs\FailedReqLogFiles باز کنید؛ رویدادهای WARNING و ERROR ماژول مقصر را نشان می‌دهند. بعد خاموشش کنید، چون سربار دارد.

جدول خطاهای رایج

خطا علت محتمل راه‌حل
500.19 با 0x8007000d بخشی در web.config که ماژولش نصب نیست (مثل <rewrite>، یا در ASP.NET Core نبود Hosting Bundle) یا XML خراب نصب ماژول یا اصلاح XML
500.19 با 0x80070005 IIS_IUSRS اجازهٔ خواندن web.config یا پوشهٔ سایت را ندارد دادن اجازهٔ Read به IIS_IUSRS یا هویت استخر
401.3 هویت ناشناس (IUSR یا هویت استخر) اجازهٔ NTFS خواندن فایل را ندارد دستورهای icacls بخش دسترسی‌ها
403.14 سند پیش‌فرض پیدا نشد افزودن index.php یا index.html به Default Document
404.3 برای این پسوند MIME Type یا handler تعریف نشده است نگاشت FastCGI برای .php؛ نقش ASP.NET برای .aspx
503 (503.0) استخر متوقف شده؛ معمولاً بعد از ۵ کرش در ۵ دقیقه (Rapid-Fail Protection) Start کردن استخر و خواندن علت در Event Viewer
500 با پیام The FastCGI process exited unexpectedly معمولاً Visual C++ Redistributable نصب نیست یا معماری‌اش (x64 یا x86) با PHP جور نیست اجرای C:\PHP\php-cgi.exe -v روی سرور و خواندن خطا
500.30 یا 502.5 در ASP.NET Core برنامه بالا نمی‌آید؛ مثلاً runtime نسخهٔ موردنیاز نصب نیست یا کد هنگام شروع خطا می‌دهد Event Viewer و لاگ stdout ماژول ASP.NET Core (بعد از عیب‌یابی خاموشش کنید)

امنیت IIS؛ چک‌لیست کوتاه

  • استخرها: یک استخر برای هر سایت با ApplicationPoolIdentity؛ هیچ استخری را با LocalSystem یا حساب مدیر اجرا نکنید.
  • پوشهٔ آپلود: اجرای اسکریپت را در آن ببندید تا فایل PHP یا ASPX آپلودشده اجرا نشود. این web.config را داخل همان پوشه بگذارید؛ خط handlers اجرای PHP و ASP.NET را آنجا می‌بندد و بخش requestFiltering درخواست فایل‌های .php را با خطای 404.7 رد می‌کند:
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
      <system.webServer>
        <handlers accessPolicy="Read" />
        <security>
          <requestFiltering>
            <fileExtensions>
              <add fileExtension=".php" allowed="false" />
            </fileExtensions>
          </requestFiltering>
        </security>
      </system.webServer>
    </configuration>
  • پنهان کردن نسخه: در Windows Server 2019 و بعد، removeServerHeader="true" روی <requestFiltering> هدر Server را حذف می‌کند.
  • TLS قدیمی: گزینهٔ Disable Legacy TLS در binding از نوع https (Windows Server 2022 و 2025) نسخه‌های قدیمی TLS و رمزهای ضعیف را برای همان binding می‌بندد.
  • به‌روزرسانی: IIS با Windows Update وصله می‌شود، اما PHP، URL Rewrite، Hosting Bundle و win-acme را باید خودتان به‌روز نگه دارید.

نکته‌های مخصوص کاربران ایران

  • دانلودها را از قبل آماده کنید: URL Rewrite و Hosting Bundle از مایکروسافت، PHP از php.net و win-acme از GitHub دانلود می‌شوند و دسترسی سرورهای داخل ایران به آن‌ها ممکن است فرق کند یا در اختلال قطع شود؛ فایل‌ها را روی کامپیوتر خودتان بگیرید و با ریموت دسکتاپ به سرور ببرید.
  • اعتبارسنجی از بیرون ایران: Let’s Encrypt از خارج اعتبارسنجی می‌کند؛ بستن ورودی خارجی پورت 80 یا قطع اینترنت بین‌الملل، صدور و تمدید را متوقف می‌کند. گواهی فعلی تا انقضا کار می‌کند و win-acme هر روز دوباره تلاش می‌کند.

سرور مناسب برای IIS

اندازهٔ سرور را برنامهٔ شما تعیین می‌کند، نه خود IIS؛ برای یک سایت ASP.NET یا PHP کوچک، ۴ گیگابایت رم (مقدار توصیه‌شدهٔ مایکروسافت) شروع معقولی است. سرور مجازی هاکان سرور در ۵۲ لوکیشن ارائه می‌شود. سیستم‌عامل‌های قابل تحویل بسته به لوکیشن فرق می‌کند؛ لینوکس روی همهٔ لوکیشن‌ها هست و اگر ویندوز یا سیستم‌عامل خاصی لازم دارید، پیش از خرید با تیکت بپرسید. ارتقای منابع سرویس با ثبت تیکت انجام می‌شود. پس می‌توانید با پلن کوچک شروع کنید.

اگر چند سایت پربازدید دارید یا SQL Server هم روی همان ماشین اجرا می‌شود و منابع سرور مجازی کم می‌آید، سرور اختصاصی منابع جدا می‌دهد؛ سرورهای اختصاصی هاکان با لینوکس، ویندوز یا هر پلتفرم مجازی‌سازی که مشتری بخواهد تحویل داده می‌شوند. پشتیبانی فنی ۲۴ ساعته از طریق تیکت در دسترس است.

پرسش‌های متداول

IIS رایگان است؟

بله. IIS جزئی از ویندوز سرور است و هزینهٔ جداگانه ندارد؛ فقط خود ویندوز سرور مجوز می‌خواهد و ماژول‌هایی مثل URL Rewrite هم رایگان‌اند.

IIS روی ویندوز ۱۰ و ۱۱ هم نصب می‌شود؟

بله، از Control Panel › Programs › Turn Windows features on or off و گزینهٔ Internet Information Services؛ برای توسعه و آزمایش مناسب است، اما سایت عمومی را روی ویندوز سرور بگذارید.

وردپرس را روی IIS نصب کنم یا روی لینوکس؟

اگر دلیل خاصی برای ویندوز ندارید، لینوکس. وردپرس روی IIS با PHP، MySQL و URL Rewrite اجرا می‌شود، اما قاعده‌هایی که افزونه‌ها در .htaccess می‌نویسند روی IIS اثری ندارند و بیشتر آموزش‌ها و ابزارهای وردپرس برای لینوکس‌اند.

چرا سایت روی خود سرور باز می‌شود ولی از بیرون نه؟

معمولاً پورت 80 یا 443 در فایروال ویندوز یا پنل ارائه‌دهنده بسته است، رکورد DNS به IP دیگری اشاره می‌کند یا نام میزبان binding اشتباه است. با Test-NetConnection از بیرون و Resolve-DnsName example.com شروع کنید.

IIS را چطور حذف کنم؟

با Uninstall-WindowsFeature -Name Web-Server -IncludeManagementTools و یک ری‌استارت. فایل‌های سایت‌ها، مثلاً در C:\sites، با حذف IIS پاک نمی‌شوند؛ اگر لازمشان ندارید، جداگانه حذف یا بایگانی‌شان کنید.

جمع‌بندی

نصب IIS کار یک دستور است و کیفیت راه‌اندازی به چند تصمیم بعد از آن بستگی دارد: استخر جدا برای هر سایت، binding با نام میزبان، دسترسی حداقلی برای هویت استخر و HTTPS با تمدید خودکار. IIS برای ASP.NET و نرم‌افزارهای ویندوزی انتخاب درستی است؛ برای وردپرس و بیشتر سایت‌های PHP، لینوکس ساده‌تر است.

قدم بعدی: تمدید گواهی را یک بار با دستور بخش win-acme آزمایش کنید و یک هفته بعد لاگ‌ها را برای خطاهای 4xx و 5xx مرور کنید.