Orchard Core Deployments
Use deployment plans to export configuration or content as a recipe package, then import that package into another tenant. A plan is an ordered collection of deployment steps. Enable the feature that owns each selected step on the source and target tenant before creating, exporting, or importing the plan.
Create and run a deployment plan
- Enable
OrchardCore.Deployment and the features that contribute the required steps.
- In Configuration → Deployment Plans, create a plan, add steps, and configure each step.
- Use the plan's Export action to download a deployment package. It is a recipe which the target imports through the Recipes administration UI or setup flow.
- Use the plan's Execute action only when a configured deployment target is available. The Recipes feature supplies the normal recipe deployment target.
Order steps deliberately. For example, enable features first, define content types before content, configure indexes before requesting a rebuild, and create workflow definitions only after their activity-providing features are enabled.
Create a plan with a recipe
The deployment recipe step is named lowercase deployment. Its Type must be the registered deployment-step factory name, normally the class name, and Step must serialize the corresponding DeploymentStep. The plan creation fails without changes if any type is unavailable because its feature is disabled.
{
"steps": [
{
"name": "Feature",
"enable": [
"OrchardCore.Deployment",
"OrchardCore.ContentTypes",
"OrchardCore.Contents"
],
"disable": []
},
{
"name": "deployment",
"Plans": [
{
"Name": "Configuration",
"Steps": [
{
"Type": "ContentDefinitionDeploymentStep",
"Step": {
"Id": "[js: uuid()]",
"Name": "ContentDefinition"
}
},
{
"Type": "AllContentDeploymentStep",
"Step": {
"Id": "[js: uuid()]",
"Name": "AllContent"
}
}
]
}
]
}
]
}
The deployment recipe step creates or updates plans; it does not export their package. Export or execute the resulting plan from the Deployment Plans UI.
Built-in deployment steps in release/3.0
Only steps whose owning feature is enabled appear in the picker. The complete set registered by framework modules is below. Steps that rebuild, reset, or export to a target are operational steps rather than configuration export steps.
| Area |
Registered step types |
| Deployment |
CustomFileDeploymentStep, RecipeFileDeploymentStep, DeploymentPlanDeploymentStep, JsonRecipeDeploymentStep |
| Content |
AllContentDeploymentStep, ContentDeploymentStep, ContentItemDeploymentStep, ExportContentToDeploymentTargetDeploymentStep |
| Content definitions |
ContentDefinitionDeploymentStep, ReplaceContentDefinitionDeploymentStep, DeleteContentDefinitionDeploymentStep |
| Core configuration |
AllFeaturesDeploymentStep, SiteSettingsDeploymentStep, ThemesDeploymentStep, PlacementsDeploymentStep, AllLayersDeploymentStep, AllRolesDeploymentStep, AllQueriesDeploymentStep, CustomSettingsDeploymentStep |
| Media and templates |
MediaDeploymentStep, AllMediaProfilesDeploymentStep, AllTemplatesDeploymentStep, AllAdminTemplatesDeploymentStep, AllShortcodeTemplatesDeploymentStep |
| Localization, users, tenants |
TranslationsDeploymentStep, AllDataTranslationsDeploymentStep, AllUsersDeploymentStep, CustomUserSettingsDeploymentStep, AllFeatureProfilesDeploymentStep |
| Workflow, menus, maps, search settings |
AllWorkflowTypeDeploymentStep, AdminMenuDeploymentStep, AllSitemapsDeploymentStep, SearchSettingsDeploymentStep |
| Indexing |
IndexProfileDeploymentStep, RebuildIndexDeploymentStep, ResetIndexDeploymentStep |
| Lucene |
LuceneIndexDeploymentStep, LuceneIndexRebuildDeploymentStep, LuceneIndexResetDeploymentStep |
| Elasticsearch |
ElasticsearchIndexDeploymentStep, ElasticsearchIndexRebuildDeploymentStep, ElasticsearchIndexResetDeploymentStep |
| Azure AI Search |
AzureAISearchIndexDeploymentStep, AzureAISearchIndexRebuildDeploymentStep, AzureAISearchIndexResetDeploymentStep |
| Authentication |
FacebookLoginDeploymentStep, AzureADDeploymentStep, MicrosoftAccountDeploymentStep, OpenIdServerDeploymentStep, OpenIdValidationDeploymentStep |
Do not guess step JSON. Create the plan in the admin UI and use its export as the authoritative payload, especially for steps with feature-specific options.
Remote deployment
Enable OrchardCore.Deployment.Remote on the source and target along with OrchardCore.Deployment. In Configuration → Remote Instances, register the remote endpoint; in Remote Clients, configure the client credentials/permissions used to call it. The remote UI supports exporting a local plan to a remote instance and importing a remote plan/package locally. Treat the endpoint and its credentials as production secrets, use HTTPS, and ensure the target has every feature required by the imported steps.
{
"steps": [
{
"name": "Feature",
"enable": [
"OrchardCore.Deployment",
"OrchardCore.Deployment.Remote",
"OrchardCore.Recipes"
],
"disable": []
}
]
}
Write a custom deployment step
Implement all three pieces in the module that owns the data.
- Derive a serializable model from
DeploymentStep, set a stable Name, and add only settings that the editor needs.
- Implement
IDeploymentSource, preferably by deriving from DeploymentSourceBase<TStep>, and append valid recipe JSON to DeploymentPlanResult.Steps or files through result.FileBuilder.
- Add a
DisplayDriver<DeploymentStep, TStep> and the corresponding summary, thumbnail, and edit Razor shapes when the step is configurable.
- Register the source, step factory, JSON derived type, and driver with the exact
AddDeployment<TSource, TStep, TDisplayDriver>() overload.
- If implementing a destination for executing packages rather than a source step, implement
IDeploymentTargetHandler and register it separately with AddDeploymentTargetHandler<TImplementation>().
Every object added to DeploymentPlanResult.Steps is a recipe step consumed on import. Emit an existing recipe step or ship and enable a matching custom IRecipeStepHandler on the target tenant. The example emits MySettings, so its companion recipe handler must be available there.
using System.Text.Json.Nodes;
using Microsoft.Extensions.Localization;
using OrchardCore.Deployment;
namespace MyModule.Deployment;
public sealed class MySettingsDeploymentStep : DeploymentStep
{
public MySettingsDeploymentStep()
{
Name = nameof(MySettingsDeploymentStep);
}
public MySettingsDeploymentStep(IStringLocalizer<MySettingsDeploymentStep> localizer)
: this()
{
Category = localizer["Settings"];
}
}
public sealed class MySettingsDeploymentSource
: DeploymentSourceBase<MySettingsDeploymentStep>
{
protected override Task ProcessAsync(
MySettingsDeploymentStep step,
DeploymentPlanResult result)
{
result.Steps.Add(new JsonObject
{
["name"] = "MySettings",
["Enabled"] = true,
});
return Task.CompletedTask;
}
}
using OrchardCore.Deployment;
using OrchardCore.DisplayManagement.Handlers;
using OrchardCore.DisplayManagement.Views;
namespace MyModule.Deployment;
public sealed class MySettingsDeploymentStepDriver
: DisplayDriver<DeploymentStep, MySettingsDeploymentStep>
{
public override Task<IDisplayResult> DisplayAsync(
MySettingsDeploymentStep step,
BuildDisplayContext context)
=> CombineAsync(
View("MySettingsDeploymentStep_Fields_Summary", step)
.Location("Summary", "Content"),
View("MySettingsDeploymentStep_Fields_Thumbnail", step)
.Location("Thumbnail", "Content"));
}
Add Views/Items/MySettingsDeploymentStep.Fields.Summary.cshtml and Views/Items/MySettingsDeploymentStep.Fields.Thumbnail.cshtml. Add an edit view and override Edit/UpdateAsync when the step has editable properties.
using Microsoft.Extensions.DependencyInjection;
using OrchardCore.Deployment;
using OrchardCore.Modules;
namespace MyModule;
public sealed class Startup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddDeployment<
MySettingsDeploymentSource,
MySettingsDeploymentStep,
MySettingsDeploymentStepDriver>();
}
}
AddDeployment<TSource, TStep, TDisplayDriver>() registers the source transiently, a deployment-step factory, derived JSON metadata, and the display driver. Use AddDeploymentWithoutSource<TStep, TDisplayDriver>() only for a step that has no source, such as RecipeFileDeploymentStep.
Deployment target handlers
An IDeploymentTargetHandler consumes a generated DeploymentPlanResult for a specific target. It is not a replacement for IDeploymentSource. Register it independently:
services.AddDeploymentTargetHandler<MyDeploymentTargetHandler>();
The framework Recipes module demonstrates this split by registering RecipeDeploymentTargetHandler, while the Deployment module registers plan sources and steps.
1---2name: orchardcore-deployments3description: Skill for authoring Orchard Core deployment plans and custom deployment steps. Covers plan creation, plan recipes, export targets, remote deployment, built-in step selection, and end-to-end extensibility. Use this skill when requests mention Orchard Core Deployments, Create a Deployment Plan, Deployment Step Types, Export or Import a Deployment Package, Remote Deployment, Deployment Plan Recipe Export, or Creating Deployment Steps in Code. Strong matches include work with OrchardCore.Deployment, OrchardCore.Deployment.Remote, IDeploymentSource, IDeploymentTargetHandler, DeploymentStep, AddDeployment, AddDeploymentTargetHandler, DeploymentPlansRecipeStep, and DeploymentPlanResult. It also helps with Deployment Plan Recipe Export, custom step display drivers, and the code patterns, admin flows, recipe steps, and referenced examples captured in this skill.4license: Apache-2.05metadata:6 author: CrestApps Team7 version: "1.0"8---910# Orchard Core Deployments1112Use deployment plans to export configuration or content as a recipe package, then import that package into another tenant. A plan is an ordered collection of deployment steps. Enable the feature that owns each selected step on the source and target tenant before creating, exporting, or importing the plan.1314## Create and run a deployment plan15161. Enable `OrchardCore.Deployment` and the features that contribute the required steps.172. In **Configuration → Deployment Plans**, create a plan, add steps, and configure each step.183. Use the plan's **Export** action to download a deployment package. It is a recipe which the target imports through the Recipes administration UI or setup flow.194. Use the plan's **Execute** action only when a configured deployment target is available. The Recipes feature supplies the normal recipe deployment target.2021Order steps deliberately. For example, enable features first, define content types before content, configure indexes before requesting a rebuild, and create workflow definitions only after their activity-providing features are enabled.2223## Create a plan with a recipe2425The deployment recipe step is named lowercase `deployment`. Its `Type` must be the registered deployment-step factory name, normally the class name, and `Step` must serialize the corresponding `DeploymentStep`. The plan creation fails without changes if any type is unavailable because its feature is disabled.2627```json28{29 "steps": [30 {31 "name": "Feature",32 "enable": [33 "OrchardCore.Deployment",34 "OrchardCore.ContentTypes",35 "OrchardCore.Contents"36 ],37 "disable": []38 },39 {40 "name": "deployment",41 "Plans": [42 {43 "Name": "Configuration",44 "Steps": [45 {46 "Type": "ContentDefinitionDeploymentStep",47 "Step": {48 "Id": "[js: uuid()]",49 "Name": "ContentDefinition"50 }51 },52 {53 "Type": "AllContentDeploymentStep",54 "Step": {55 "Id": "[js: uuid()]",56 "Name": "AllContent"57 }58 }59 ]60 }61 ]62 }63 ]64}65```6667The `deployment` recipe step creates or updates plans; it does **not** export their package. Export or execute the resulting plan from the Deployment Plans UI.6869## Built-in deployment steps in release/3.07071Only steps whose owning feature is enabled appear in the picker. The complete set registered by framework modules is below. Steps that rebuild, reset, or export to a target are operational steps rather than configuration export steps.7273| Area | Registered step types |74|---|---|75| Deployment | `CustomFileDeploymentStep`, `RecipeFileDeploymentStep`, `DeploymentPlanDeploymentStep`, `JsonRecipeDeploymentStep` |76| Content | `AllContentDeploymentStep`, `ContentDeploymentStep`, `ContentItemDeploymentStep`, `ExportContentToDeploymentTargetDeploymentStep` |77| Content definitions | `ContentDefinitionDeploymentStep`, `ReplaceContentDefinitionDeploymentStep`, `DeleteContentDefinitionDeploymentStep` |78| Core configuration | `AllFeaturesDeploymentStep`, `SiteSettingsDeploymentStep`, `ThemesDeploymentStep`, `PlacementsDeploymentStep`, `AllLayersDeploymentStep`, `AllRolesDeploymentStep`, `AllQueriesDeploymentStep`, `CustomSettingsDeploymentStep` |79| Media and templates | `MediaDeploymentStep`, `AllMediaProfilesDeploymentStep`, `AllTemplatesDeploymentStep`, `AllAdminTemplatesDeploymentStep`, `AllShortcodeTemplatesDeploymentStep` |80| Localization, users, tenants | `TranslationsDeploymentStep`, `AllDataTranslationsDeploymentStep`, `AllUsersDeploymentStep`, `CustomUserSettingsDeploymentStep`, `AllFeatureProfilesDeploymentStep` |81| Workflow, menus, maps, search settings | `AllWorkflowTypeDeploymentStep`, `AdminMenuDeploymentStep`, `AllSitemapsDeploymentStep`, `SearchSettingsDeploymentStep` |82| Indexing | `IndexProfileDeploymentStep`, `RebuildIndexDeploymentStep`, `ResetIndexDeploymentStep` |83| Lucene | `LuceneIndexDeploymentStep`, `LuceneIndexRebuildDeploymentStep`, `LuceneIndexResetDeploymentStep` |84| Elasticsearch | `ElasticsearchIndexDeploymentStep`, `ElasticsearchIndexRebuildDeploymentStep`, `ElasticsearchIndexResetDeploymentStep` |85| Azure AI Search | `AzureAISearchIndexDeploymentStep`, `AzureAISearchIndexRebuildDeploymentStep`, `AzureAISearchIndexResetDeploymentStep` |86| Authentication | `FacebookLoginDeploymentStep`, `AzureADDeploymentStep`, `MicrosoftAccountDeploymentStep`, `OpenIdServerDeploymentStep`, `OpenIdValidationDeploymentStep` |8788Do not guess step JSON. Create the plan in the admin UI and use its export as the authoritative payload, especially for steps with feature-specific options.8990## Remote deployment9192Enable `OrchardCore.Deployment.Remote` on the source and target along with `OrchardCore.Deployment`. In **Configuration → Remote Instances**, register the remote endpoint; in **Remote Clients**, configure the client credentials/permissions used to call it. The remote UI supports exporting a local plan to a remote instance and importing a remote plan/package locally. Treat the endpoint and its credentials as production secrets, use HTTPS, and ensure the target has every feature required by the imported steps.9394```json95{96 "steps": [97 {98 "name": "Feature",99 "enable": [100 "OrchardCore.Deployment",101 "OrchardCore.Deployment.Remote",102 "OrchardCore.Recipes"103 ],104 "disable": []105 }106 ]107}108```109110## Write a custom deployment step111112Implement all three pieces in the module that owns the data.1131141. Derive a serializable model from `DeploymentStep`, set a stable `Name`, and add only settings that the editor needs.1152. Implement `IDeploymentSource`, preferably by deriving from `DeploymentSourceBase<TStep>`, and append valid recipe JSON to `DeploymentPlanResult.Steps` or files through `result.FileBuilder`.1163. Add a `DisplayDriver<DeploymentStep, TStep>` and the corresponding summary, thumbnail, and edit Razor shapes when the step is configurable.1174. Register the source, step factory, JSON derived type, and driver with the exact `AddDeployment<TSource, TStep, TDisplayDriver>()` overload.1185. If implementing a destination for executing packages rather than a source step, implement `IDeploymentTargetHandler` and register it separately with `AddDeploymentTargetHandler<TImplementation>()`.119120Every object added to `DeploymentPlanResult.Steps` is a recipe step consumed on import. Emit an existing recipe step or ship and enable a matching custom `IRecipeStepHandler` on the target tenant. The example emits `MySettings`, so its companion recipe handler must be available there.121122```csharp123using System.Text.Json.Nodes;124using Microsoft.Extensions.Localization;125using OrchardCore.Deployment;126127namespace MyModule.Deployment;128129public sealed class MySettingsDeploymentStep : DeploymentStep130{131 public MySettingsDeploymentStep()132 {133 Name = nameof(MySettingsDeploymentStep);134 }135136 public MySettingsDeploymentStep(IStringLocalizer<MySettingsDeploymentStep> localizer)137 : this()138 {139 Category = localizer["Settings"];140 }141}142143public sealed class MySettingsDeploymentSource144 : DeploymentSourceBase<MySettingsDeploymentStep>145{146 protected override Task ProcessAsync(147 MySettingsDeploymentStep step,148 DeploymentPlanResult result)149 {150 result.Steps.Add(new JsonObject151 {152 ["name"] = "MySettings",153 ["Enabled"] = true,154 });155156 return Task.CompletedTask;157 }158}159```160161```csharp162using OrchardCore.Deployment;163using OrchardCore.DisplayManagement.Handlers;164using OrchardCore.DisplayManagement.Views;165166namespace MyModule.Deployment;167168public sealed class MySettingsDeploymentStepDriver169 : DisplayDriver<DeploymentStep, MySettingsDeploymentStep>170{171 public override Task<IDisplayResult> DisplayAsync(172 MySettingsDeploymentStep step,173 BuildDisplayContext context)174 => CombineAsync(175 View("MySettingsDeploymentStep_Fields_Summary", step)176 .Location("Summary", "Content"),177 View("MySettingsDeploymentStep_Fields_Thumbnail", step)178 .Location("Thumbnail", "Content"));179}180```181182Add `Views/Items/MySettingsDeploymentStep.Fields.Summary.cshtml` and `Views/Items/MySettingsDeploymentStep.Fields.Thumbnail.cshtml`. Add an edit view and override `Edit`/`UpdateAsync` when the step has editable properties.183184```csharp185using Microsoft.Extensions.DependencyInjection;186using OrchardCore.Deployment;187using OrchardCore.Modules;188189namespace MyModule;190191public sealed class Startup : StartupBase192{193 public override void ConfigureServices(IServiceCollection services)194 {195 services.AddDeployment<196 MySettingsDeploymentSource,197 MySettingsDeploymentStep,198 MySettingsDeploymentStepDriver>();199 }200}201```202203`AddDeployment<TSource, TStep, TDisplayDriver>()` registers the source transiently, a deployment-step factory, derived JSON metadata, and the display driver. Use `AddDeploymentWithoutSource<TStep, TDisplayDriver>()` only for a step that has no source, such as `RecipeFileDeploymentStep`.204205## Deployment target handlers206207An `IDeploymentTargetHandler` consumes a generated `DeploymentPlanResult` for a specific target. It is not a replacement for `IDeploymentSource`. Register it independently:208209```csharp210services.AddDeploymentTargetHandler<MyDeploymentTargetHandler>();211```212213The framework Recipes module demonstrates this split by registering `RecipeDeploymentTargetHandler`, while the Deployment module registers plan sources and steps.