ESC

Start typing to search across invoices, services, domains, tickets, and more...

Search... Ctrl+K
Windows Server

Host a Website on Windows Server with IIS: Install, Bind IPs, Free SSL and PHP

5 steps 13 min read 5 views 0
On this page

If you prefer Windows or need to run ASP.NET applications, hosting a website with IIS on Windows Server is the natural choice. Using Windows Server 2016/2019/2022, this guide shows how to install IIS with PowerShell, bind a site to a specific IP and host header (very handy on multi-IP site-cluster servers), get a free auto-renewing SSL certificate with win-acme, and run PHP through IIS FastCGI.

Step 1: Install IIS with Install-WindowsFeature

Run the commands below in an elevated PowerShell. IIS and its management console are installed within a few minutes. If you plan to run PHP, add the CGI feature (it includes FastCGI) at the same time. Browse to the server IP afterwards: the IIS welcome page means it worked.

Install-WindowsFeature -Name Web-Server -IncludeManagementTools
# Optional: CGI/FastCGI support (needed for PHP)
Install-WindowsFeature -Name Web-CGI

Get-WindowsFeature Web-Server, Web-CGI
Installing IIS enables the "World Wide Web Services (HTTP Traffic-In)" firewall rule automatically. If port 443 is not allowed, see our guide on opening ports in Windows Firewall.

Step 2: Create an IIS Website and Bind an IP and Host Header

An IIS binding is made of IP address + port + host header. The example below creates site1 that answers www.example.com only on 203.0.113.11 and adds the bare domain as a second host header. Replace the IP and domain with your own and point the domain's A record to that IP first.

Import-Module WebAdministration
New-Item -ItemType Directory -Path C:\inetpub\site1 -Force
Set-Content -Path C:\inetpub\site1\index.html -Value "site1 OK"

New-Website -Name "site1" -PhysicalPath "C:\inetpub\site1" -IPAddress "203.0.113.11" -Port 80 -HostHeader "www.example.com"
New-WebBinding -Name "site1" -IPAddress "203.0.113.11" -Port 80 -HostHeader "example.com"

Get-WebBinding -Name "site1"

Step 3: IIS Bindings on Multi-IP Site-Cluster Servers

On IMIDC multi-IP and site-cluster servers a common requirement is one dedicated IP per website. First add all IPs to the network adapter (see our "add IP addresses on Windows" guide), then bind each site to its own IP. Without a host header, that site answers every domain pointed at the IP. Stop the Default Web Site so its "All Unassigned:80" binding does not steal requests.

# One site per IP, no host header (answers any domain pointed at that IP)
New-Website -Name "site2" -PhysicalPath "C:\inetpub\site2" -IPAddress "203.0.113.12" -Port 80
New-Website -Name "site3" -PhysicalPath "C:\inetpub\site3" -IPAddress "203.0.113.13" -Port 80

# Stop the Default Web Site so it does not catch *:80
Stop-Website -Name "Default Web Site"
Set-ItemProperty "IIS:\Sites\Default Web Site" -Name serverAutoStart -Value $false
Each IP + port + host header combination can belong to only one site; duplicates prevent the site from starting. Check existing bindings with Get-WebBinding before adding many sites.

Step 4: Free SSL Certificate for IIS with win-acme

win-acme (wacs.exe) is a widely used Let's Encrypt client for Windows. It detects IIS sites, completes validation, installs the certificate, adds the 443 binding and creates a renewal task. Download the x64 zip from the official win-acme website or its GitHub releases page, extract it to C:\tools\win-acme and run it. Choose to create a certificate with default settings, then select your IIS site and domains.

cd C:\tools\win-acme
.\wacs.exe

# Check the renewal task created by win-acme
Get-ScheduledTask | Where-Object TaskName -like "win-acme*"

Before requesting a certificate make sure the domain resolves to the IP bound to the site, port 80 is reachable from the internet (HTTP validation needs it) and the site bindings contain every host name you want on the certificate.

Step 5: Run PHP on IIS via FastCGI

Download the NTS (Non Thread Safe) x64 zip for your PHP version from the official PHP for Windows site, extract it to C:\PHP, install the matching Visual C++ Redistributable and copy php.ini-production to php.ini. Then register the FastCGI application, map *.php to it and add index.php as a default document with appcmd:

$appcmd = "$env:windir\System32\inetsrv\appcmd.exe"
& $appcmd set config /section:system.webServer/fastCgi /+"[fullPath='C:\PHP\php-cgi.exe']"
& $appcmd set config /section:system.webServer/handlers /+"[name='PHP_via_FastCGI',path='*.php',verb='*',modules='FastCgiModule',scriptProcessor='C:\PHP\php-cgi.exe',resourceType='Either']"
& $appcmd set config /section:defaultDocument /+"files.[value='index.php']"

Set-Content -Path C:\inetpub\site1\info.php -Value "<?php phpinfo();"
iisreset

Open http://your-domain/info.php; a PHP information page means PHP works. Delete info.php after testing so you do not leak server details.

FAQ

The site will not start: "the port may be in use by another website".

Another site already uses the same IP + port + host header, most often the Default Web Site. Stop it or change its binding and start your site again.

win-acme validation fails.

Check that the A record points to the right IP, that port 80 is reachable from outside and that no CDN or redirect rule blocks the /.well-known/acme-challenge/ path.

Should I use IIS or aaPanel/BaoTa?

Choose Windows + IIS for ASP.NET and MSSQL. For PHP/MySQL sites, Linux with aaPanel/BaoTa is usually lighter; see our BaoTa installation guide.

Still stuck after following these steps? Open a support ticket and the IMIDC 24/7 technical team will help. Please include the server IP, OS version, the commands you ran and a screenshot of the error so we can pinpoint the issue faster.

Was this answer helpful?

Related Tutorials