Consolidated ASP Classic MVC framework from best components
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7.5KB

IIS Deployment Guide

Isolation boundary

This pipeline owns one dedicated IIS site and one dedicated application pool. It never discovers, copies configuration from, adopts, or changes another IIS site. In particular, no existing Schedulicious site, app pool, binding, path, or configuration is a deployment source or target.

Defaults (each may be overridden explicitly):

SiteName        AspClassicUnifiedFramework
AppPoolName     AspClassicUnifiedFramework
DeployRoot      D:\Deployments\AspClassicUnifiedFramework
Binding         http://100.97.39.23:8085/  (empty host header)
ExpectedBranch  master

An existing target is accepted only when its name, app pool, sole HTTP binding, and physical path exactly match this pipeline's expected dedicated state. The physical path must be a public directory under <DeployRoot>\releases. A partial or mismatched target fails closed; there is no adoption mode. Unrelated sites, pools, and bindings are left unchanged.

Release and web-root model

D:\Deployments\AspClassicUnifiedFramework\
  releases\
    <release-id>\
      app\
      core\
      db\
      public\       <- only this directory is served by IIS
      scripts\
      tests\
      ...
  shared\
    public.web.config
  deployment-state.json

The complete repository is packaged because public/Default.asp uses parent includes from sibling directories. Releases are extracted into <release-id>.staging, checked for required files, safe paths/reparse points, and valid public\web.config XML, overlaid with shared configuration, and renamed to an immutable release directory. IIS serves only <release>\public.

On the first deployment, shared configuration is initialized from the packaged release's public\web.config. Supply -InitialWebConfigPath only when an explicitly managed host-local configuration file should seed the first deployment. The script validates that file as XML. It never copies configuration from any IIS site. Once created, the shared file is reused and is not automatically refreshed.

Classic ASP parent paths are enabled with a location-scoped system.webServer/asp setting for this dedicated site only.

Scripts

  • scripts/deploy-iis-git.ps1: controller entry point; validates source, branch, XML, package structure, and safety; hashes and optionally transfers the package.
  • scripts/install-iis-release.ps1: elevated Windows PowerShell 5.1 host installer; performs read-only host preflight, stages and validates releases, creates/manages only the dedicated target, switches releases, smoke tests, and rolls back target mutations on failure.

Gitea 1.11.4 predates Gitea Actions. Run the controller from a trusted external worker or operator workstation with approved Tailscale/OpenSSH access. No credentials or production configuration belong in this repository.

Preflight sequence

1. Local/controller preflight (no network)

Run from a clean standalone master checkout:

.\scripts\deploy-iis-git.ps1 -LocalPreflightOnly

This validates the dedicated names/binding/root, source provenance, required source files, repository public\web.config XML, package creation, extracted package layout, and reparse-point/symlink safety. It does not call SSH/SCP and makes no host change. -AllowAnyBranch is still required when the source is not a standalone Git checkout.

-DryRun also avoids network access but prints the remote operation that would be performed.

2. Full preflight (connects, read-only)

.\scripts\deploy-iis-git.ps1 -PreflightOnly -RemoteTarget 'webserver-1'

After the local/package checks, the controller streams the installer over SSH and runs it in memory; it does not create a remote transport directory or copy a remote file. The host phase checks elevation, WebAdministration, Classic ASP feature/module, URL Rewrite module, deployment drive/path and resource names, binding conflicts (including wildcard IP overlap), shared-pool conflicts, and existing dedicated target consistency. The dedicated site and pool do not need to exist. No IIS or deployment-root change is made. -HostPreflightOnly and -RemotePreflightOnly remain aliases.

First deployment

The installer creates the dedicated app pool and site only after the staged release and selected initial web.config validate. Example using all defaults:

.\scripts\deploy-iis-git.ps1 -RemoteTarget 'webserver-1'

Example with explicit overrides:

.\scripts\deploy-iis-git.ps1 `
  -SiteName 'AspClassicUnifiedFramework-Test' `
  -AppPoolName 'AspClassicUnifiedFramework-Test' `
  -DeployRoot 'E:\Deployments\AspClassicUnifiedFramework-Test' `
  -BindingIpAddress '100.97.39.23' `
  -BindingPort 8185 `
  -HostHeader 'framework-test.internal' `
  -InitialWebConfigPath 'E:\ManagedConfig\framework-test.web.config' `
  -RemoteTarget 'webserver-1' `
  -ExpectedBranch 'master'

The new app pool uses no managed CLR. Configure any required app-pool identity and ACL policy through separately reviewed host preparation; the deployment does not borrow another pool's identity or permissions.

Existing target and cutover

For later deployments, the host preflight requires the dedicated site to use:

  • exactly AppPoolName;
  • exactly one HTTP binding matching IP, port, and host header;
  • a physical path ending in \public under <DeployRoot>\releases.

Any mismatch fails without mutation. After the new release validates, the installer changes only the dedicated site's physical path, applies the site-location parent-path setting, recycles/starts the dedicated pool, and smoke tests the configured binding or explicit -BaseUrl.

Failure recovery

The installer records whether this invocation created the target site or pool and snapshots the prior state of an existing valid target.

  • If target creation or smoke testing fails, it removes only the site/app pool created by this invocation.
  • If an existing target fails during cutover or smoke testing, it restores its previous physical path and previous site-location parent-path value, then restarts/recycles its pool.
  • It never removes or edits an unrelated site, pool, or binding.
  • Staging/release files may remain for diagnosis; releases are reported as retention candidates and are never deleted automatically.
  • Explicit database migrations cannot be undone by IIS rollback.

Rollback

.\scripts\deploy-iis-git.ps1 `
  -Rollback `
  -RollbackTo '20260914-171500-a1b2c3d4e5f6' `
  -RemoteTarget 'webserver-1'

Rollback requires an already valid dedicated target and an existing immutable release under the configured DeployRoot. It switches only that target's physical path and smoke tests; it does not rewrite the prior release. Failure restores the prior target state.

Database and writable data

Migrations are disabled by default. -RunMigrations is an explicit exception and requires a verified backup; path rollback cannot undo database changes. Keep production databases, logs, and other writable data outside immutable release directories and grant the dedicated app-pool identity only necessary permissions.

Windows verification gates

Before production use, validate both scripts with the Windows PowerShell 5.1 parser, run host preflight on the intended Windows/IIS host, deploy to an isolated test name/binding, verify HTTP and parent includes, induce a smoke failure to prove invocation-scoped cleanup/restoration, then prove rollback. Linux checks cannot validate WebAdministration behavior, installed IIS features/modules, binding semantics on the live host, elevation, ACLs, app-pool identity, Access/ACE, or an actual HTTP response.

Powered by TurnKey Linux.