Skip to content
Tutorials

Deploy an ASP.NET Blog on Windows Server and IIS

A practical walkthrough for putting a self-hosted ASP.NET Core blog on Windows Server behind IIS, including the app pool settings and permissions that catch most people out.

To host an ASP.NET Core blog on IIS, install the ASP.NET Core Hosting Bundle, publish the app, create a site pointing at the publish folder, and set its application pool to No Managed Code. IIS then runs as a reverse proxy in front of Kestrel, which is what actually serves the application.

Most self-hosting guides assume Linux. That is fine until your blog runs on .NET and the server you already pay for, already patch, and already know how to restore is running Windows. Hosting an ASP.NET Core blog on IIS is well-supported and genuinely straightforward, but it has a handful of settings that are non-obvious the first time, and each of them produces an unhelpful error.

How ASP.NET Core actually runs under IIS

Worth understanding before you touch anything, because it explains most of the confusing settings. IIS is not executing your application the way it ran classic ASP.NET. Your app runs in Kestrel, the .NET web server, as its own process. IIS sits in front as a reverse proxy, handing requests over through the ASP.NET Core Module.

That is why the application pool must be set to No Managed Code: you are explicitly telling IIS not to load the .NET Framework runtime, because your app brings its own. Setting it to a CLR version is the single most common cause of a site that returns 500.30 and nothing useful.

The steps

  1. Install the ASP.NET Core Hosting Bundle on the server. Not the SDK, not the runtime on its own. The bundle installs the runtime plus the ASP.NET Core Module that IIS needs. Install it after IIS, or the module will not register.
  2. Publish the app and copy the output to the server, for example C:\inetpub\blog.
  3. Create the site in IIS Manager, pointing the physical path at that folder and binding your hostname.
  4. Set the application pool to No Managed Code, and set its identity to an account that can read the folder.
  5. Grant permissions. The app pool identity needs read on the publish folder and write on any folder the app writes to, such as logs, uploads or an App_Data directory.
  6. Bind HTTPS. Windows has no Caddy-style automatic certificate, so use win-acme for free automated Let's Encrypt certificates, or install a certificate you already own.

The settings that cost people a weekend

  • Idle time-out. By default IIS shuts an app pool down after 20 minutes of no traffic, so the next visitor waits for a cold start. On a low-traffic blog that is most visitors. Set Idle Time-out to 0 and Start Mode to AlwaysRunning.
  • The nightly recycle. App pools recycle every 1740 minutes by default, at an unpredictable hour. Set a fixed overnight time instead, so a restart never lands mid-afternoon.
  • Environment variables. Set ASPNETCORE_ENVIRONMENT to Production for the site, or you may ship developer error pages to the public.
  • Connection strings. Keep them out of the publish folder. Use environment variables or a secrets store, never a committed config file.
  • Logging. Enable stdout logging in web.config only long enough to diagnose a startup failure, then turn it off. Left on, it grows without limit.
If the site returns 500.30 with no detail, it is almost always the app pool CLR setting or a missing hosting bundle. Check those two before anything else.

Windows or Linux?

Neither is wrong, and the honest answer is that you should use the one you can operate confidently at 2am. Windows and IIS win when you already run Windows Server, when your database is SQL Server on the same network, and when your team knows IIS Manager. Linux wins on cost per month and on automatic HTTPS being genuinely one line.

If you would rather take the Linux route, our VPS walkthrough covers it end to end, and the container route is in Docker and Caddy. For a blog engine built for the .NET side of this choice, the options are compared in the best .NET blog engines.

Before you call it done

Restart the server and confirm the site comes back without you touching it. Check that a request over plain HTTP redirects to HTTPS. Then set up backups of both the database and any uploads folder, and test a restore, because an untested backup is a hope rather than a plan. Our guide on backing up a self-hosted blog covers what to include.

Frequently asked questions

Can I host an ASP.NET Core blog on IIS?

Yes. Install the ASP.NET Core Hosting Bundle, publish the application, create an IIS site pointing at the publish folder, and set the application pool to No Managed Code. IIS acts as a reverse proxy in front of Kestrel, which runs the application itself.

Why does my ASP.NET Core site return HTTP 500.30 on IIS?

Almost always one of two things: the application pool is set to a managed CLR version instead of No Managed Code, or the ASP.NET Core Hosting Bundle is missing or was installed before IIS. Enable stdout logging in web.config temporarily to see the real startup exception.

How do I get free HTTPS on IIS?

Use win-acme, a Windows client for Let's Encrypt that requests and renews certificates automatically and installs them into IIS bindings. Unlike Caddy on Linux there is no built-in automatic HTTPS, so this step is explicit.

Why is my IIS-hosted blog slow for the first visitor?

The application pool has idled out and is cold-starting. Set the pool Idle Time-out to 0 and Start Mode to AlwaysRunning, and give the nightly recycle a fixed overnight time so a restart never lands during the day.

Ready to host your own blog?

Inkwell is free, open-source, and self-hosted — your content, your server, your rules. Deploy in minutes on .NET 10.

Read the install guide ← Back to the blog