import { Callout } from "zudoku/ui/Callout";

# OnPrem module

**Module:** `businessdev.ALbuild.OnPrem` &nbsp;•&nbsp; **Tier:** Licensed &nbsp;•&nbsp; **Cmdlets:** 8

The **OnPrem** module publishes, installs, synchronizes and upgrades apps on Business Central On-Premises environments, and publishes Per-Tenant Extensions (PTE) and Dev extensions. This is a **licensed** feature.

<Callout type="caution" title="Licensing">
Cmdlets in this module are part of a licensed tier and call `Assert-ALbuildLicensed` on entry. Without a valid ALbuild license they fail with clear remediation guidance. See [Licensing & tiers](../concepts/licensing).
</Callout>

<Callout type="caution" title="Business Central v29 requires PowerShell 7 on the agent">
Through v28 a Business Central server ships a Windows PowerShell 5 compatibility module, so the management cmdlets (`Publish-NAVApp`, `Sync-NAVApp`, ...) load directly into the Windows PowerShell 5.1 session that Azure DevOps runs tasks under.

**Business Central v29 removed it.** Only the .NET 8 modules (`Microsoft.BusinessCentral.*` under `...\Service\Admin`) remain, and Windows PowerShell 5.1 cannot load those. ALbuild handles this by delegating each management call to a PowerShell 7 child process, so the cmdlets on this page keep working unchanged — but **PowerShell 7 must be installed on the agent** (`winget install --id Microsoft.PowerShell`). Without it the release fails on entry with an explicit message instead of an unrecognised-cmdlet error.
</Callout>

## Cmdlets in this module

| Cmdlet | Description |
| --- | --- |
| [`Install-BcOnPremApp`](#install-bconpremapp) | Installs a published AL app on an on-premises Business Central server instance (licensed). |
| [`New-BcApiAuthContext`](#new-bcapiauthcontext) | Acquires an OAuth2 access token for the Business Central API. |
| [`Publish-BcDevExtension`](#publish-bcdevextension) | Publishes an AL app to a Business Central server's development endpoint (licensed). |
| [`Publish-BcOnPremApp`](#publish-bconpremapp) | Publishes an AL app to an on-premises Business Central server instance (licensed). |
| [`Publish-BcOnPremContainerApp`](#publish-bconpremcontainerapp) | Publishes an AL app to a Business Central server instance running inside a Docker container (licensed). |
| [`Publish-BcPerTenantExtension`](#publish-bcpertenantextension) | Deploys a per-tenant extension to a Business Central environment via the automation API (licensed). |
| [`Start-BcOnPremUpgrade`](#start-bconpremupgrade) | Runs the data-upgrade for an AL app on an on-premises Business Central server instance (licensed). |
| [`Sync-BcOnPremApp`](#sync-bconpremapp) | Synchronises an AL app's schema on an on-premises Business Central server instance (licensed). |

---

## Install-BcOnPremApp

Installs a published AL app on an on-premises Business Central server instance (licensed).

### Syntax

```powershell
Install-BcOnPremApp
    -ServerInstance <String>
    -AppName <String>
    [-AppVersion <String>]
    [-Tenant <String>]
```

### Parameters

| Parameter | Type | Required | Description |
| --- | --- | :---: | --- |
| `-ServerInstance` | String | Yes | The BC server instance. |
| `-AppName` | String | Yes | The app name. |
| `-AppVersion` | String | No | Optional app version. |
| `-Tenant` | String | No | Tenant. Default 'default'. **Default:** `'default'`. |

---

## New-BcApiAuthContext

Acquires an OAuth2 access token for the Business Central API.

Acquires a bearer token for the Business Central REST / automation API from Azure AD using
one of three flows, selected by the parameters you pass:

 * ClientSecret - service-to-service (client_credentials) with an app-registration secret.
 * Certificate - service-to-service (client_credentials) with a signed client_assertion
 JWT. The signing certificate lives in Azure Key Vault and its private key
 never leaves the vault (a service principal reads the public certificate
 and performs the RS256 signature via the Key Vault key 'sign' operation).
 * RefreshToken - exchanges an OAuth2 refresh token (ALbuild V1 parity).

Returns an auth context whose AccessToken is passed to Publish-BcPerTenantExtension (or any
other Business Central API cmdlet).

### Syntax

```powershell
New-BcApiAuthContext
    [-TenantId <String>]
    -ClientId <String>
    -ClientSecret <Object>
    -RefreshToken <Object>
    -KeyVaultUrl <String>
    -CertificateName <String>
    [-KeyVaultTenantId <String>]
    -KeyVaultClientId <String>
    -KeyVaultClientSecret <Object>
    [-Scope <String>]
```

### Parameters

| Parameter | Type | Required | Description |
| --- | --- | :---: | --- |
| `-TenantId` | String | No | Azure AD tenant id (or verified domain) of the Business Central tenant. Default 'common'. **Default:** `'common'`. |
| `-ClientId` | String | Yes | Application (client) id to authenticate as. Required for the ClientSecret and Certificate flows. For the RefreshToken flow it defaults to the well-known Business Central PowerShell client id the V1 task used. |
| `-ClientSecret` | Object | Yes | App-registration client secret (SecureString or string). Selects the ClientSecret flow. |
| `-RefreshToken` | Object | Yes | OAuth2 refresh token (SecureString or string). Selects the RefreshToken flow. |
| `-KeyVaultUrl` | String | Yes | Key Vault base URL holding the client-assertion certificate. Selects the Certificate flow. |
| `-CertificateName` | String | Yes | Certificate name in Key Vault (Certificate flow). |
| `-KeyVaultTenantId` | String | No | Azure AD tenant of the service principal used to access Key Vault. Defaults to -TenantId. |
| `-KeyVaultClientId` | String | Yes | Application (client) id of the service principal used to access Key Vault (Certificate flow). |
| `-KeyVaultClientSecret` | Object | Yes | Client secret of the service principal used to access Key Vault (Certificate flow). |
| `-Scope` | String | No | OAuth2 scope. Default 'https://api.businesscentral.dynamics.com/.default'. The RefreshToken flow additionally requests 'offline_access'. **Default:** `'https://api.businesscentral.dynamics.com/.default'`. |

### Output

PSCustomObject with AccessToken, TokenType, ExpiresOn, TenantId, ClientId, Scope.

### Examples

**Example 1**

```powershell
$ctx = New-BcApiAuthContext -TenantId $t -ClientId $c -ClientSecret $s
Publish-BcPerTenantExtension -TenantId $t -Environment 'Production' -AccessToken $ctx.AccessToken -AppFile .\out\My.app
```

**Example 2**

```powershell
$ctx = New-BcApiAuthContext -TenantId $t -ClientId $appRegId -KeyVaultUrl $kv -CertificateName 'bc-deploy' `
    -KeyVaultClientId $sp -KeyVaultClientSecret $spSecret
```

---

## Publish-BcDevExtension

Publishes an AL app to a Business Central server's development endpoint (licensed).

Uploads the .app to the BC development service endpoint (the same endpoint VS Code uses for
'Publish'), which publishes, synchronises and installs the app in one call. Requires a valid
ALbuild license.

### Syntax

```powershell
Publish-BcDevExtension
    -DevServerUrl <String>
    -ServerInstance <String>
    -AppFile <String>
    -Credential <PSCredential>
    [-SchemaUpdateMode <String>]
    [-DependencyPublishingOption <String>]
```

### Parameters

| Parameter | Type | Required | Description |
| --- | --- | :---: | --- |
| `-DevServerUrl` | String | Yes | The development service base URL, e.g. https://bcserver:7049. |
| `-ServerInstance` | String | Yes | The server instance name (the URL path segment). |
| `-AppFile` | String | Yes | Path to the .app file. |
| `-Credential` | PSCredential | Yes | Credential for the dev endpoint (Windows or BC user). |
| `-SchemaUpdateMode` | String | No | Schema update mode: synchronize (default), recreate or forcesync. **Allowed values:** `synchronize`, `recreate`, `forcesync`. **Default:** `'synchronize'`. |
| `-DependencyPublishingOption` | String | No | ignore (default), default or strict. **Allowed values:** `ignore`, `default`, `strict`. **Default:** `'ignore'`. |

---

## Publish-BcOnPremApp

Publishes an AL app to an on-premises Business Central server instance (licensed).

Publishes the .app to the given server instance using the Business Central management
cmdlets, optionally synchronising and installing it. Run on a host where the BC management
module is available (the BC server or a deployment agent). Requires a valid ALbuild license.

### Syntax

```powershell
Publish-BcOnPremApp
    -ServerInstance <String>
    -AppFile <String>
    [-SkipVerification]
    [-Sync]
    [-Install]
    [-SyncMode <String>]
    [-Scope <String>]
    [-Tenant <String>]
    [-Development]
    [-Credential <PSCredential>]
    [-DevServerUrl <String>]
```

### Parameters

| Parameter | Type | Required | Description |
| --- | --- | :---: | --- |
| `-ServerInstance` | String | Yes | The BC server instance name. |
| `-AppFile` | String | Yes | Path to the .app file. |
| `-SkipVerification` | switch | No | Publish without signature verification. |
| `-Sync` | switch | No | Synchronise after publishing. |
| `-Install` | switch | No | Install after synchronising. |
| `-SyncMode` | String | No | Add (default), Clean, Development or ForceSync. **Allowed values:** `Add`, `Clean`, `Development`, `ForceSync`. **Default:** `'Add'`. |
| `-Scope` | String | No | Global (default) or Tenant. **Allowed values:** `Global`, `Tenant`. **Default:** `'Global'`. |
| `-Tenant` | String | No | Tenant. Default 'default'. **Default:** `'default'`. |
| `-Development` | switch | No | Publish via the server's development endpoint (like VS Code) as a replaceable development extension - re-publishable without a version bump, which is what test environments need. Publishes + syncs + installs in one call, so -Install/-SkipVerification/-Scope do not apply; -SyncMode maps to the dev schema-update mode. Requires -Credential. |
| `-Credential` | PSCredential | No | BC user credential to authenticate to the development endpoint (required with -Development). |
| `-DevServerUrl` | String | No | Development service base URL, e.g. https://bcserver:7049. Optional: when omitted (and -Development is set) the endpoint is resolved from the local server's CustomSettings.config as https/http://localhost: &lt;DeveloperServicesPort>. Provide it explicitly when the agent is not the BC server, or to target a specific hostname. |

---

## Publish-BcOnPremContainerApp

Publishes an AL app to a Business Central server instance running inside a Docker container (licensed).

The on-prem counterpart to Publish-BcOnPremApp for deployments where the target BC server runs
inside a Docker container on the deployment host (the ALbuild V1 "Release On-Prem" scenario with a
container name supplied). The .app is copied into the container and published, synchronised and
installed with the in-container BC management cmdlets. Requires Windows + Docker on the agent and a
valid ALbuild license.

Use Publish-BcOnPremApp when the BC server is installed directly on the host; use this cmdlet when
it runs in a container.

### Syntax

```powershell
Publish-BcOnPremContainerApp
    -ContainerName <String>
    -AppFile <String>
    [-SkipVerification]
    [-Sync]
    [-Install]
    [-SyncMode <String>]
    [-Scope <String>]
    [-ServerInstance <String>]
    [-Tenant <String>]
    [-OperationTimeoutSeconds <Int32>]
    [-Development]
    [-Credential <PSCredential>]
```

### Parameters

| Parameter | Type | Required | Description |
| --- | --- | :---: | --- |
| `-ContainerName` | String | Yes | Name of the Business Central Docker container the app is deployed into. |
| `-AppFile` | String | Yes | Path to the .app file on the host. |
| `-SkipVerification` | switch | No | Publish without signature verification. |
| `-Sync` | switch | No | Synchronise after publishing. |
| `-Install` | switch | No | Install after synchronising. |
| `-SyncMode` | String | No | Add (default), Clean, Development or ForceSync. **Allowed values:** `Add`, `Clean`, `Development`, `ForceSync`. **Default:** `'Add'`. |
| `-Scope` | String | No | Global (default) or Tenant. **Allowed values:** `Global`, `Tenant`. **Default:** `'Global'`. |
| `-ServerInstance` | String | No | BC server instance inside the container. Default 'BC'. **Default:** `'BC'`. |
| `-Tenant` | String | No | Tenant. Default 'default'. **Default:** `'default'`. |
| `-OperationTimeoutSeconds` | Int32 | No | Maximum seconds to allow each publish/sync/install step before abandoning it and throwing. Default 600. **Default:** `600`. |
| `-Development` | switch | No | Publish via the container's development endpoint (like VS Code / BcContainerHelper -useDevEndpoint): the app is published as a replaceable development extension - re-publishable without a version bump, which is what test environments need. Requires -Credential. Ignores -Scope/-Install (the dev endpoint publishes, syncs and installs in one call); -SyncMode maps to the dev schema-update mode. |
| `-Credential` | PSCredential | No | BC user credential to authenticate to the development endpoint (required with -Development). |

### Examples

**Example 1**

```powershell
Publish-BcOnPremContainerApp -ContainerName 'bcprod' -AppFile .\out\My.app -Sync -Install
```

**Example 2**

```powershell
Publish-BcOnPremContainerApp -ContainerName 'bc-test' -AppFile .\out\My.app -Development -Credential $cred
```

---

## Publish-BcPerTenantExtension

Deploys a per-tenant extension to a Business Central environment via the automation API (licensed).

Uploads and schedules one or more per-tenant extensions using the Business Central automation
API extensionUpload entity: create an upload record, PATCH the .app binary into it, then
trigger the upload action. A bearer access token for the environment is required (acquire one
with New-BcApiAuthContext, which supports S2S client-secret, certificate and refresh-token
authentication).

The target environment can be given either as a ready automation API base URL
(-AutomationBaseUrl) or, more conveniently, as -TenantId + -Environment (the URL is then
built for you). When -CompanyId is omitted the first company in the environment is used. One
or more .app files (or a folder of them) can be published in a single call.

### Syntax

```powershell
Publish-BcPerTenantExtension
    -TenantId <String>
    -Environment <String>
    -AutomationBaseUrl <String>
    [-CompanyId <String>]
    -AppFile <String[]>
    -AccessToken <String>
    [-SchemaSyncMode <String>]
    [-Schedule <String>]
    [-IncludeTestApp]
    [-NoWait]
    [-TimeoutMinutes <Int32>]
```

### Parameters

| Parameter | Type | Required | Description |
| --- | --- | :---: | --- |
| `-TenantId` | String | Yes | Azure AD tenant id of the environment. Used to build the automation API base URL. |
| `-Environment` | String | Yes | Business Central environment name (sandbox or production). Used to build the base URL. |
| `-AutomationBaseUrl` | String | Yes | The automation API base URL, e.g. https://api.businesscentral.dynamics.com/v2.0/&#123;tenant}/&#123;environment}/api/microsoft/automation/v2.0 Supply this instead of -TenantId/-Environment to target a non-default service URL. |
| `-CompanyId` | String | No | The company id (GUID) in the environment. When omitted, the first company is resolved and used. |
| `-AppFile` | String[] | Yes | One or more .app files (or folders/wildcards) to publish. Runtime packages (*.runtime.app) are skipped. Defaults to the $(bcAppFile) build variable when called from the task. |
| `-AccessToken` | String | Yes | OAuth2 bearer token for the environment (e.g. from New-BcApiAuthContext). |
| `-SchemaSyncMode` | String | No | Schema sync mode: Add (default) or ForceSync. **Allowed values:** `Add`, `ForceSync`. **Default:** `'Add'`. |
| `-Schedule` | String | No | WHEN the environment deploys the extension. The automation API never installs synchronously: the upload action queues the deployment, and this decides what it is queued for. Current (default) deploys against the environment's current version; NextMinor / NextMajor hold the app back until that upgrade runs. Maps to the API's "Current version" / "Next minor version" / "Next major version". **Allowed values:** `Current`, `NextMinor`, `NextMajor`. **Default:** `'Current'`. |
| `-IncludeTestApp` | switch | No | Publish test apps too. By default they are skipped: a test app belongs in a build container, not in a customer environment, and it drags in the Microsoft test framework. |
| `-NoWait` | switch | No | Return as soon as every upload is queued, without waiting for the environment to finish deploying. The task then reports what was QUEUED, not what succeeded. |
| `-TimeoutMinutes` | Int32 | No | How long to wait for the deployment to finish when -NoWait is not used. Default 15. **Default:** `15`. |

### Examples

**Example 1**

```powershell
$ctx = New-BcApiAuthContext -TenantId $t -ClientId $c -ClientSecret $s
Publish-BcPerTenantExtension -TenantId $t -Environment 'Production' -AccessToken $ctx.AccessToken -AppFile .\out
```

**Example 2**

```powershell
Publish-BcPerTenantExtension -AutomationBaseUrl $url -CompanyId $id -AppFile .\out\My.app -AccessToken $token
```

---

## Start-BcOnPremUpgrade

Runs the data-upgrade for an AL app on an on-premises Business Central server instance (licensed).

### Syntax

```powershell
Start-BcOnPremUpgrade
    -ServerInstance <String>
    -AppName <String>
    [-AppVersion <String>]
    [-Tenant <String>]
```

### Parameters

| Parameter | Type | Required | Description |
| --- | --- | :---: | --- |
| `-ServerInstance` | String | Yes | The BC server instance. |
| `-AppName` | String | Yes | The app name. |
| `-AppVersion` | String | No | Optional app version. |
| `-Tenant` | String | No | Tenant. Default 'default'. **Default:** `'default'`. |

---

## Sync-BcOnPremApp

Synchronises an AL app's schema on an on-premises Business Central server instance (licensed).

### Syntax

```powershell
Sync-BcOnPremApp
    -ServerInstance <String>
    -AppName <String>
    [-AppVersion <String>]
    [-Mode <String>]
    [-Tenant <String>]
```

### Parameters

| Parameter | Type | Required | Description |
| --- | --- | :---: | --- |
| `-ServerInstance` | String | Yes | The BC server instance. |
| `-AppName` | String | Yes | The app name. |
| `-AppVersion` | String | No | Optional app version. |
| `-Mode` | String | No | Add (default), Clean, Development or ForceSync. **Allowed values:** `Add`, `Clean`, `Development`, `ForceSync`. **Default:** `'Add'`. |
| `-Tenant` | String | No | Tenant. Default 'default'. **Default:** `'default'`. |

---
