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

فهرست مطالب
- IIS چیست و چه زمانی انتخاب درستی است؟
- پیشنیازهای نصب IIS
- نصب IIS با Server Manager
- نصب IIS با PowerShell
- سرویسهای نقش که شاید لازم داشته باشید
- باز کردن پورتهای 80 و 443
- راهاندازی سایت روی IIS
- استخر برنامه و هویت آن
- ساخت سایت در IIS Manager
- ساخت سایت با PowerShell
- binding و سایت پیشفرض
- چند سایت HTTPS روی یک IP با SNI
- دسترسی پوشهها: IUSR، IIS_IUSRS و هویت استخر
- سند پیشفرض و خطای 403.14
- اجرای PHP و ASP.NET روی IIS
- نصب PHP با FastCGI
- سقف حجم آپلود در PHP و IIS
- ASP.NET Core و Hosting Bundle
- نصب SSL رایگان روی IIS با win-acme
- گرفتن گواهی با win-acme
- تمدید خودکار و عمر کوتاهتر گواهیها
- نصب گواهی خریداریشده (فایل pfx)
- ریدایرکت HTTP به HTTPS
- روش ۱: ماژول URL Rewrite
- روش ۲: ریدایرکت و HSTS داخلی IIS
- لاگها و رفع خطاهای رایج IIS
- لاگهای IIS کجا هستند؟
- پیغام کامل خطا و Failed Request Tracing
- جدول خطاهای رایج
- امنیت IIS؛ چکلیست کوتاه
- نکتههای مخصوص کاربران ایران
- سرور مناسب برای IIS
- پرسشهای متداول
- IIS رایگان است؟
- IIS روی ویندوز ۱۰ و ۱۱ هم نصب میشود؟
- وردپرس را روی IIS نصب کنم یا روی لینوکس؟
- چرا سایت روی خود سرور باز میشود ولی از بیرون نه؟
- IIS را چطور حذف کنم؟
- جمعبندی
نصب 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 خودتان را بگذارید.
بهطور خلاصه:
- نصب با
Install-WindowsFeature -Name Web-Server -IncludeManagementToolsو باز کردنhttp://localhostروی سرور.- باز کردن پورتهای 80 و 443 در فایروال ویندوز و پنل ارائهدهنده.
- ساخت پوشه، Application Pool جدا و binding با نام دامنه و www.
- اجازهٔ خواندن برای
IIS AppPool\example.comو اجازهٔ نوشتن فقط برای پوشهٔ آپلود.- برای PHP نقش CGI، نسخهٔ NTS x64 و نگاشت FastCGI؛ برای ASP.NET Core بستهٔ Hosting Bundle.
- SSL رایگان با win-acme و سپس ریدایرکت HTTP به HTTPS.
- عیبیابی با کد کامل خطا (مثل 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
- در Server Manager منوی Manage › Add Roles and Features را باز کنید، در Installation Type گزینهٔ Role-based or feature-based installation و در Server Selection سرور خودتان را انتخاب کنید.
- در Server Roles تیک Web Server (IIS) را بزنید و در پنجرهٔ بعد، با روشن ماندن Include management tools (if applicable)، روی Add Features بزنید تا IIS Manager هم نصب شود.
- صفحههای Features و Web Server Role (IIS) را با Next رد کنید و در Role Services فقط موارد لازم را اضافه کنید (جدول بخش بعد)؛ مثلاً CGI یا ASP.NET 4.x زیر Application Development و Tracing زیر Health and Diagnostics.
- تا صفحهٔ 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) کارها را دارد.
- پوشهٔ سایت را بیرون از
C:\inetpub\wwwrootبسازید، مثلاًC:\sites\example.com، و یکindex.htmlآزمایشی در آن بگذارید. - روی Sites راستکلیک و Add Website را بزنید. Site name را
example.comبگذارید تا استخری همنام ساخته شود و Physical path را پوشهٔ سایت بدهید. - در بخش Binding مقدار Type را
http، IP address را All Unassigned، Port را 80 و Host name راexample.comبگذارید. - از Actions › Bindings › Add یک binding دیگر با Host name برابر
www.example.comبسازید. - در 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"
- نقش CGI:
Install-WindowsFeature -Name Web-CGI؛ ماژول FastCGI با همین نقش نصب میشود. - دریافت 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 است. - Visual C++: بستهٔ Visual C++ Redistributable نسخهٔ x64 (
vc_redist.x64.exe) را از لینک همان صفحه نصب کنید. این بسته در صفحهٔ PHP «for Visual Studio 2015-2022» نام دارد و مایکروسافت حالا نسخهٔ جاری آن را Visual C++ v14 Redistributable مینامد. - استخراج و 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
- بعد از IIS، بستهٔ .NET Hosting Bundle نسخهٔ .NET برنامه را از لینک رسمی نسخهٔ جاری یا صفحهٔ دانلود .NET نصب کنید. اگر آن را پیش از IIS نصب کردهاید، طبق مستندات مایکروسافت نصبکننده را دوباره اجرا و تعمیر (Repair) کنید.
- IIS را ریاستارت کنید تا مسیر تازه را بشناسد:
net stop was /y net start w3svc - خروجی
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 انجام میشود.
- فایل zip نسخهٔ x64 (مثل
win-acme.v2.2.9.1701.x64.trimmed.zip) را از win-acme.com یا صفحهٔ Releases پروژه در GitHub بگیرید و در پوشهای ماندگار مثلC:\Program Files\win-acmeباز کنید؛ تسک تمدید از همین پوشه اجرا میشود. wacs.exeرا با Run as administrator اجرا کنید و در منوی اصلیNیعنی Create certificate (default settings) را بزنید.- سایت را از فهرست سایتهای 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) را به کار ببرید:
- سایت را انتخاب کنید و در Actions › Configure › Failed Request Tracing تیک Enable را بزنید.
- در Failed Request Tracing Rules با Add و گزینهٔ All content، کد خطا (مثلاً 500 یا 401.3) را در Status code(s) بنویسید و با پیشفرضها تا Finish بروید.
- خطا را تکرار کنید و فایلهایی مثل
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 مرور کنید.


