Bladeren bron

ci: update docs/deployment-guide.md

ci-iis-release-pipeline
Clawdbot 8 uur geleden
bovenliggende
commit
3d28a2f132
1 gewijzigde bestanden met toevoegingen van 224 en 26 verwijderingen
  1. +224
    -26
      docs/deployment-guide.md

+ 224
- 26
docs/deployment-guide.md Bestand weergeven

@@ -1,37 +1,235 @@
# MVC-Starter - Deployment Guide
# IIS Deployment Guide

**Date:** 2026-03-11T11:59:39Z
## Deployment model

## Deployment Model
Production uses immutable release directories on the Windows host:

Single-site Windows IIS deployment with `public/` as the web root.
```text
C:\inetpub\deployments\<site>\
releases\
<release-id>\
app\
core\
db\
public\ <- IIS physicalPath points here
scripts\
...
shared\
public.web.config <- machine-owned configuration
deployment-state.json
```

## Deployment Steps
The complete repository is copied into each release. This is required because
`public/Default.asp` includes files above `public/`, including `../core` and
`../app`. IIS exposes only `<release>\public`; sibling source, scripts, tests,
and database files are not web-root content.

1. Copy the repository to the target Windows host.
2. Configure the IIS site to point to `public/`.
3. Ensure Classic ASP is enabled.
4. Ensure URL Rewrite is installed.
5. Update `public/web.config` for the target environment.
6. Ensure the Access DB file path is valid and accessible.
Switching `physicalPath` from one release's `public` directory to another is the
atomic-ish cutover. The app pool is recycled after the switch. If the smoke test
fails, the installer restores the previous physical path and recycles again.
The script does not stop the site for the normal copy/staging phase.

## Key Runtime Config
## Why Gitea is not the runner

- `ConnectionString`
- `Environment`
- `EnableErrorLogging`
- `ErrorLogPath`
- cache and UI timing settings
The repository server is Gitea 1.11.4, which predates Gitea Actions. Treat
Gitea as the Git source only. Run `scripts/deploy-iis-git.ps1` from one of:

## Deployment Risks
- a trusted external CI worker that checks out this repository;
- a controlled operator workstation;
- a separately managed scheduled task.

- Incorrect `ConnectionString` path for `.accdb`
- Missing IIS URL Rewrite module
- Missing Classic ASP support
- File permission issues for logs or database access
The worker must have Tailscale reachability and OpenSSH key-based access to
`webserver-1`. No password, private key, database path, or connection string
belongs in this repository.

## What Was Not Found
## Files

- No Docker, Kubernetes, or container deployment setup
- No CI/CD pipeline config
- No infrastructure-as-code deployment definition
- `scripts/deploy-iis-git.ps1`: controller/CI entry point. Validates branch and
worktree state, packages the full source tree, hashes it, transfers it with
`scp`, and invokes the host installer with `ssh`.
- `scripts/install-iis-release.ps1`: elevated host-side installer. Performs
preflight, preserves machine configuration, stages/releases, configures
Classic ASP parent paths, switches IIS, smoke tests, and rolls back.

Both scripts target Windows PowerShell 5.1 syntax.

## One-time host preparation

Complete these steps on `webserver-1` before the first live deployment:

1. Join the host and CI worker to the intended Tailscale tailnet. Confirm ACLs
allow SSH only from the intended deploy identity.
2. Install and configure Windows OpenSSH Server for key-based authentication.
The deploy identity must be able to run an elevated, non-interactive
PowerShell process; choose and audit the elevation mechanism locally.
3. Install IIS, Classic ASP (`IIS-ASP` / `Web-ASP`), and IIS URL Rewrite.
4. Create the IIS site and application pool. The scripts require an existing
site and do not change its bindings, authentication, app-pool identity, or
managed runtime.
5. Ensure the site currently points at a valid `public` directory containing
its machine-specific `web.config`. On first deployment this file is copied
to `shared\public.web.config` and becomes the deployment-owned preserved
copy.
6. Put the production Access database and logs outside release directories.
Grant the existing app-pool identity only the required permissions. The
deployment scripts deliberately do not change app-pool identity or ACLs.
7. Grant the deploy identity modify permission on the chosen deployment root
and permission to update this IIS site's configuration.
8. Back up IIS configuration and production data using the host's normal backup
system before enabling unattended deployment.

Default deployment root:

```text
C:\inetpub\deployments\<IIS site name>
```

Classic ASP parent paths are set explicitly at the site's location in
`applicationHost.config` by `install-iis-release.ps1`:

```text
system.webServer/asp enableParentPaths = true
```

This is intentional. The ASP section is commonly locked against `web.config`
overrides, so the setting is applied at the host/site level rather than added to
repository `public/web.config`.

## Safe validation sequence

From a standalone checkout on a Windows worker, first validate without making a
network connection:

```powershell
.\scripts\deploy-iis-git.ps1 `
-SiteName 'ttasp' `
-RemoteTarget 'webserver-1' `
-ExpectedBranch 'master' `
-DryRun
```

`-DryRun` validates the local source, branch, dirty state, XML, package creation,
and argument construction. It prints remote operations but does not run `ssh`
or `scp`.

Next run a remote read-only preflight. This does connect to `webserver-1`, copies
only the installer to a temporary directory, and checks the existing site,
app pool, Classic ASP feature (when its feature cmdlet is available), URL
Rewrite module, and availability of a preservable `web.config`:

```powershell
.\scripts\deploy-iis-git.ps1 `
-SiteName 'ttasp' `
-RemoteTarget 'webserver-1' `
-RemotePreflightOnly
```

For a normal deployment:

```powershell
.\scripts\deploy-iis-git.ps1 `
-SiteName 'ttasp' `
-RemoteTarget 'webserver-1' `
-ExpectedBranch 'master' `
-BaseUrl 'http://127.0.0.1/'
```

Use a host header or HTTPS URL in `-BaseUrl` when the site's binding requires
one. If no URL is supplied, the installer uses the first HTTP binding's port on
`127.0.0.1`. `-SkipSmokeTest` is an explicit exception and should not be used in
unattended production CI.

## Branch and artifact policy

The controller defaults to `-ExpectedBranch master`, matching the repository's
actual default branch. It refuses a different branch or dirty worktree. External CI should:

1. fetch from Gitea over its configured authenticated channel;
2. check out the exact approved commit on `master`;
3. run repository tests/static checks;
4. call the deployment script from that standalone checkout;
5. retain the commit ID, release ID, package SHA-256, and deployment output.

Use `-AllowAnyBranch` or `-AllowDirty` only for an intentional, reviewed manual
exception. If `SourcePath` is not itself a Git root, `-AllowAnyBranch` is
required because branch provenance cannot be proved.

A webhook receiver is not included. Gitea 1.11.4 can emit webhooks, but accepting
and authenticating them safely is infrastructure-specific. Polling or a manually
approved CI job is simpler unless an existing secured webhook runner is
available.

## Configuration preservation

The installer copies the current site's entire `public\web.config` to:

```text
<DeployRoot>\shared\public.web.config
```

It then overwrites each staged release's repository version with that preserved
file before cutover. This preserves all machine-specific values, especially:

- `ConnectionString` and its Access `Data Source` path;
- `Environment`;
- `ErrorLogPath` and logging flags;
- site-specific rewrite or app settings already present on the host.

The shared file is never automatically refreshed from repository content. To
change production settings, edit the shared file under the host's normal change
control, validate its XML, and deploy or roll back. Keep a protected backup.
Do not commit production values.

## Database migration policy

Deployments do **not** run migrations by default. The sample `db` directory is
part of the complete release but the production connection string should point
to data outside the release tree.

`-RunMigrations` is available only as an explicit operator choice. Before using
it:

1. take and verify a database backup;
2. review every pending migration against the target schema;
3. schedule downtime if the Access database requires exclusive access;
4. understand that switching IIS back does not undo a database migration.

The old script's automatic legacy `migrate_isbusiness_to_households.vbs` path has
been removed from deployment. Run one-off data repair scripts only under a
separate reviewed procedure.

## Rollback

List release IDs on the host under `<DeployRoot>\releases`, or use the value in
`deployment-state.json`. Then run from the worker:

```powershell
.\scripts\deploy-iis-git.ps1 `
-SiteName 'ttasp' `
-RemoteTarget 'webserver-1' `
-Rollback `
-RollbackTo '20260914-171500-a1b2c3d4e5f6' `
-BaseUrl 'http://127.0.0.1/'
```

Rollback refreshes the target release's `public\web.config` from the preserved
shared copy, switches `physicalPath`, recycles the app pool, and smoke tests. If
that smoke test fails, it restores the pre-rollback path.

The installer reports releases older than `-KeepReleases` as retention
candidates but does not delete them automatically. Delete only after confirming
they are neither current nor required for rollback and that backups exist.

## Failure and recovery behavior

- Package extraction occurs in `<release-id>.staging`.
- Layout and `web.config` XML are validated before promotion.
- Promotion is a directory rename within the release volume.
- IIS changes only after the final release directory exists.
- Failed smoke tests restore the prior `physicalPath`.
- Incomplete staging directories are retained for diagnosis.
- Database changes, external file writes, and machine configuration outside the
IIS path switch cannot be undone by release rollback.

Review Windows Event Log, IIS logs, app logs, the script transcript, and
`deployment-state.json` after any failure.

Laden…
Annuleren
Opslaan

Powered by TurnKey Linux.