Deploying from DevOps the right way: enabling External Deployment in OnPrem Business Central environments

It seems that lately, I’m only able to blog about something when I have a tool to share.. . That needs to change .. :-/. But not today. Today, I’m going to share yet another tool that we at the ALOps-team have been working on to serve many of our customers. And we decided to share it with the community. The tool is free, it will stay free … but, there is a …

Disclaimer

The tool is a hack, nothing more than that. We simulate the behavior of what we think happens on the SaaS environment when you upload an Extension through the Automation API. So, the tool is “as is”, there is no official support other than me not want you to suffer problems with it ;-). There is a github where you can share your feedback.
The tool is dependent on how Business Central will evolve in this matter – and we hope this will “just work” for many updates to come. It will work on an decent install of Business Central. Not on any kind of Copy/Paste or other non-standard installation.

Deploying extensions from DevOps, without a build agent at the customer site

The official statement from Microsoft for deploying apps from DevOps to your OnPrem Customers is: install a DevOps build agent. As you might know, build agents sometimes act not the way you want – and having to maintain a bunch on infrastructure that is not 100% under your control, isn’t something that you want either. Customers might install a windows update, or .. do whatever that makes your release pipeline not run anymore…

But what if…

.. we could just enable the Automation API (because, as you know, there is an ability to publish extensions with it) for OnPrem customers, and use that in our DevOps for our CD pipelines?
Well .. using the Automation API to publish an extension, is quite the same as using the “Upload Extension” action on the “Extension Management” page in Business Central:

Thing is – that doesn’t work OnPrem. So in a way – the “Upload Extension” functionality in the Automation API doesn’t work OnPrem either. The action simply isn’t available. And if you would run page 2507 (which is the upload wizard page) manually, it would simply show you the following message when you would try to upload an extension:

So – the question is .. How do we enable “External Deployment”.
Well, it’s just a setting on the Server Instance, by pointing to some kind of API Endpoint that the NST will call when anyone would upload an extension.

ALOps.ExternalDeployer

So, we created a PowerShell module, that makes it pretty easy to enable the External Deployer on any OnPrem environment. In fact, with 4 lines of PowerShell, you’ll have it up-and-running! Run this PowerShell on the environment that is running your NST where you would like to deploy to.

1. Install ALOps.ExternalDeployer: this will install the PowerShell module on the machine

install-module ALOps.ExternalDeployer -Force

2. Load the module: this will simply load the necessary commandlets in memory:

import-module ALOps.ExternalDeployer 

3. Install the External Deployer: this will install an agent that will take care of the app-publish and install whenever you upload an app through the Automation API, or the upload page.

Install-ALOpsExternalDeployer 

4. Link the ExternalDeployer to right NST: it will update and restart the NST with the settings needed for the External Deployer.

New-ALOpsExternalDeployer -ServerInstance BC

Done!

The easiest way to test it is to simply upload an extension through the Upload Extension wizard in Business Central. Thing is, in Business Central, the page isn’t accessible, but you can easily run any page by using the parameter “?page=2507” in the Webclient URL.
So – just run page 2507 to upload an Extension. Now, you’ll get this message:

That’s looking much better, isn’t it?
Next, since the “Deployment Status” isn’t available either from the “Tell Me”, you can also run that page by providing this parameter in the url: “?page=2508“.
Even if the upload would have failed, you get information in the page, just like you would in Business Central SaaS:

AND you can even drill down:

So .. It works! And this also means it will work through the Automation API. You can find all info on how to do that here: https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/itpro-introduction-to-automation-apis

And if you would like to do that with ALOps …

Well, pretty easy. There is an ALOps step “ALOps Extension API“, which has all necessary parameters to deploy. Just provide the right parameters, like:

  • API Interaction: Batch Publish (if you’d like to publish more than one extension at the same time)
  • API Endpoint
  • API Authentication

And you’re good to go! Here’s an example of one of our pipelines:

In our company, it’s all we use today. All deployments to all customers are using this external deployer. So rest assured – it’s well tested and very much approved ;-).
Enjoy!

4.20 avg. rating (85% score) - 5 votes

Permanent link to this article: https://www.waldo.be/2020/06/15/deploying-from-devops-the-right-way-enabling-external-deployment-in-onprem-business-central-environments/

44 comments

5 pings

Skip to comment form

    • rovelgoenne on June 18, 2020 at 9:54 am
    • Reply

    Great post! One question: is this also possible within a docker container?

      • waldo on June 18, 2020 at 12:20 pm
        Author

      Absolutely – we mainly use it within containers 😉

  1. Hi Waldo. This is a great feature – and tested it on my local where it did the job, However wee have a multitenant demo environment where it seams to try and publish to “default” tenant – is there any way you can use this in a multitenant environment. Thx.. Richard

      • waldo on June 22, 2020 at 3:25 pm
        Author

      It should work for tenants – we are using it for MT .. . How are you uploading your apps?

  2. Using the page 2507 as you describe directly from the role center (added as action in our demo role center).

    The funny part is that if I look at the error message that i get I can see that the tenant Id is “default” and that is why it fails.

      • waldo on June 26, 2020 at 12:18 pm
        Author

      At this point, BC doesn’t allow this, I’m afraid. So it’s also not possible in this version.. . We might have a workaround, but we’re not sure it will work. . .

  3. This is a great feature I must say. Thanks for the update.

    • Todd Scott on July 20, 2020 at 2:18 pm
    • Reply

    Is there a way to tell what BC Server Instances have been configured using New-ALOpsExternalDeployer -ServerInstance BC? I have a few customers on our server and would like to know which ones have been configured.

    • Todd Scott on July 20, 2020 at 2:50 pm
    • Reply

    Don’t suppose there is an API to import a FOB file?

      • waldo on July 20, 2020 at 4:04 pm
        Author

      Nope, sorry 😉

    • Catalin on July 29, 2020 at 1:10 pm
    • Reply

    I know you’ve been working with API’s and deploying to saas. I can deploy apps to saas using API calls but not an app that has been registered on the market place.
    I get the “Extension with app ID *** has been submitted to AppSource, please install it from AppSource marketplace instead.

    Is there a way around this? How do you deploy beta versions to a saas QA environment?

    • Robert on December 7, 2020 at 1:54 pm
    • Reply

    Okay, when you run New-ALOpsExternalDeployer it modifies the customsettings.config of the service tier to point at your service. This is okay, but I’m a little worried about the value of the “APIkey” you set. It’s obviously a pointer to the service tier, but there appears to be no actual authentication in it to prove that the connection as come from that service tier. This wouldn’t bother me too much if the port (7040) for deployment service were bound to localhost. However, it appears to be bound to 0.0.0.0 and so will accept a connection from anywhere the firewalls allow.

    Is this correct, or does it have a way of configuring at least a simple magic-cookie into the configuration?

    • Mr. Dee on April 19, 2021 at 1:11 pm
    • Reply

    Hi there. If it’s free and as-is, why not release the code so others may learn / contribute in case we find something that doesn’t wor?

      • waldo on April 19, 2021 at 2:21 pm
        Author

      Because the code is not mine, and is based on a framework we don’t want to share.

      • Mr. Dee on April 19, 2021 at 4:24 pm

      OK, I understand. So if the deployer happened to happily deploy one app, but fails with HTTP500 on a second app, I have no real option to find out why?

      • waldo on April 19, 2021 at 7:00 pm
        Author

      Did you get that?
      The only thing it does it upload it in the Extension Management – which also happens in SaaS. So check the deployment status. Or your API endpoint.
      That should be all that can go wrong.

      Though, there is one more important part: the script that is installed when you install the module. The location, you can find with the command:
      cd (get-module alops.externaldeployer -ListAvailable).ModuleBase

      In de subdir “bin\PSScripts”, you’ll find the “deploy apps”. Changing the script changes the behavior of the externaldeployer, of course. Use at your own risk ;-). The deployapps will never result in an http-error, I guess. You just upload an app to an api, where the external deployer executes the PS script mentioned above.

      So .. basically, you have all code now :p

  4. Hi Waldo,

    does the server have to be reachable from the internet to make that work?

      • waldo on November 15, 2021 at 11:15 am
        Author

      Yes, since the app needs to be uploaded to the automation-API

    • mbomhof on February 22, 2022 at 7:01 pm
    • Reply

    Hi Waldo, also here i’m trying this in a single-tenant environment and it is working great. However, in my multi-tenant environment it is publishing my app with scope to the ‘default’ instance. When it is going to the next step, syncing in one of the tenants, the app cannot be found.

    Log:

    *** Add NAV-DeploymentRequestId [4f51715b-7804-4e64-988d-4d5c2f78ffc0]
    *** [POST] => [/v1.0/DeployPackage]
    *** PowershellDeploy
    >>PowershellDeploy
    Deploy Script: [C:\Program Files\WindowsPowerShell\Modules\ALOps.ExternalDeployer\1.38\bin\PSScripts\_Deploy-ALOpsNAVApp.ps1]
    >>*** Package Data File => [C:\Windows\TEMP\tmpDEC3.tmp.app]
    >>*** ServerInstance = [BC180NL]
    >>*** ContainerId = []
    >>*** Tenant = [default]
    >>Use [Install-ALOpsExternalDeployer] to install [ALOps External Deployer] service.
    >>*** Loading assemblies from: [C:\program files\microsoft dynamics 365 business central\180\service]
    >> * App.ID = ***myId***
    >> * App.Name = ***myName***
    >> * App.Publisher = ***myPublisher***
    >> * App.Version = ***myVersion***
    >> => Publishing App ‘***myName*** ***myVersion***’
    >>*** Publish per Tenant
    >>*** Get Tenants
    >>*** Sync Tenant **tenant1**
    >>*** Sync App [***myName***] on tenant [**tenant1**]
    Exception Occured: The running command stopped because the preference variable “ErrorActionPreference” or common parameter is set to Stop: Er is geen gepubliceerde extensie die overeenkomt met de opgegeven parameterwaarden.
    *** Operation Response: {“JobId”:”f16af1c4-8af1-4b6c-b086-f954f6af1f2f”,”Details”:”The running command stopped because the preference variable \”ErrorActionPreference\” or common parameter is set to Stop: Er is geen gepubliceerde extensie die overeenkomt met de opgegeven parameterwaarden.”,”Status”:1,”ErrorCode”:100}

    It seems like it is publishing in tenant ‘default’, then it is trying to sync tenant ‘**tenant1**’.
    However, i uploaded the file using ?page=2507 in tenant ‘**tenant2**’.
    Am i doing something wrong?

      • waldo on March 28, 2022 at 7:17 pm
        Author

      Yeah, publishing to MT environment is not implemented. but as you can see in the output – you have access to the scripts – so you would be able to change them as well 😉

    • Mathias on April 28, 2022 at 7:39 am
    • Reply

    Perhaps a stupid question, but where do you find this nice log? 🙂

      • waldo on April 28, 2022 at 8:49 am
        Author

      What Log do you mean?

  5. The Write-Host output from your PS scripts.

      • waldo on April 28, 2022 at 12:45 pm
        Author

      Sorry Mathias, but I have no idea what you mean :(. There is no log in this article, is there? But we do tend to deliberately “write-host” all output explicitly to show in pipelines outputs, yes …

  6. No worries 🙂

    I mean this output that mbomhof pasted into his post

    Log:

    *** Add NAV-DeploymentRequestId [4f51715b-7804-4e64-988d-4d5c2f78ffc0]
    *** [POST] => [/v1.0/DeployPackage]
    *** PowershellDeploy
    >>PowershellDeploy
    Deploy Script: [C:\Program Files\WindowsPowerShell\Modules\ALOps.ExternalDeployer\1.38\bin\PSScripts\_Deploy-ALOpsNAVApp.ps1]
    >>*** Package Data File => [C:\Windows\TEMP\tmpDEC3.tmp.app]
    >>*** ServerInstance = [BC180NL]
    >>*** ContainerId = []
    >>*** Tenant = [default]
    >>Use [Install-ALOpsExternalDeployer] to install [ALOps External Deployer] service.
    >>*** Loading assemblies from: [C:\program files\microsoft dynamics 365 business central\180\service]
    >> * App.ID = ***myId***
    >> * App.Name = ***myName***
    >> * App.Publisher = ***myPublisher***
    >> * App.Version = ***myVersion***
    >> => Publishing App ‘***myName*** ***myVersion***’
    >>*** Publish per Tenant
    >>*** Get Tenants
    >>*** Sync Tenant **tenant1**
    >>*** Sync App [***myName***] on tenant [**tenant1**]

  7. Neve mind, found it in the event viewer on the server (Dooh) 🙂 great post thanks Waldo!

      • waldo on April 28, 2022 at 2:04 pm
        Author

      👍Awesome!

    • Kevin Zündorf on August 8, 2022 at 12:36 pm
    • Reply

    Hi Waldo, this is a great tool and i have been using it for a while now. 🙂 But i upgraded a customer to BC20 OnPrem recently, and now the service returns “Upload of per-tenant extensions is not supported for your system configuration. For more information, see https://docs.microsoft.com/en-us/dynamics365/business-central/ui-extensions“. I already tried to update the Deployer and reinstalled it for the service. Is this a known Issue oder am i missing something?

    Greetings from Germany, Kevin 🙂

      • waldo on August 8, 2022 at 12:38 pm
        Author

      This is a known issue when you didn’t correctly install the nst , but basically copy/pasted the files.
      Can you try to re-install (and really install) the nst?

      • Kevin Zündorf on August 8, 2022 at 12:45 pm

      Thank you for the fast reply, i will try to reinstall ist. Thank you!

      • Kevin Zundorf on August 8, 2022 at 2:13 pm

      It works now, thx 🙂

    • Fabio Cipriani on November 16, 2022 at 10:58 am
    • Reply

    Hi Waldo! Thank you for sharing your knowledge in your blog and in the sessions online and at the events!
    I used this tool to release the apps in this months and everything worked without problems with Azure DevOps Release pipelines with PowerShell.
    But now, after installing BC21 unfortunately it doesn’t work anymore. The trick works, so I can view and use P2507 & P2508, but the powershell give an error on Invoke-RestMethod Patch (extensionUpload): “(500) Internal Server Error” (before doing this I commented the call to Invoke-RestMethod Get (extensions) because it doesn’t exists anymore).
    In another case everything looked ok in Powershell, but in P2508 I see the app in status “Unknown” and of course not uploaded
    I noticed that calling the baseURL “…/API/microsoft/automation/beta” the response is different between BC20 and BC21 (I can send you the screenshot if you need it). Do you have any hints…?
    Thank you so much
    Fabio

      • waldo on November 16, 2022 at 11:50 am
        Author

      Yep, I know – we’re working on a fix for V21 (MS broke how they deploy the apps :(). We’re close, and the install should be the same as before (but you’ll have to re-install). i’ll probably blog about it, and if not, please watch the powershellgallery for the alops.externaldeployer.

      Hopefully this week …

      • Fabio Cipriani on November 16, 2022 at 12:44 pm

      Perfect! Thanks a lot, I’ll monitor the powershellgallery for alops.externaldeployer 🙂

      • waldo on November 16, 2022 at 2:57 pm
        Author

      Just that you know – we do have a new working version on the gallery – please feel free to test 😉

      • Fabio Cipriani on November 16, 2022 at 4:24 pm

      Thank you for the advice!
      I disinstalled 1.38 and installed new version 1.41
      I tried to publish again, but unfortunately I get another error, this time everything seems ok in Powershell, the release pipeline terminate with ok.
      But the status in P2508 is “Failed”, and the error says “ServiceTier [bc] not found.”. I checked the Event Viewer on Service Server, and there is one information line about AlOpsExternalDeployer with the following log:

      *** [POST] => [/v1.0/DeployPackage]
      *** PowershellDeploy
      >>PowershellDeploy
      Deploy Script: [C:\Program Files\WindowsPowerShell\Modules\ALOps.ExternalDeployer\1.41\bin\PSScripts\_Deploy-ALOpsNAVApp.ps1]
      >>*** Package Data File => [C:\Windows\TEMP\tmpC826.tmp.app]
      >>*** ServerInstance = [bc]
      >>*** ContainerId = []
      >>*** Tenant = [default]
      >>Use [Install-ALOpsExternalDeployer] to install [ALOps External Deployer] service.
      Exception Occured: ServiceTier [bc] not found.
      Exception Inner: ServiceTier [bc] not found.
      *** Operation Response: {“JobId”:”dbcef9cd-98a7-4190-979c-abe41d10b588″,”Details”:”ServiceTier [bc] not found.”,”Status”:1,”ErrorCode”:100}
      *** Save Session: dbcef9cd-98a7-4190-979c-abe41d10b588

      My ServerInstance is named BC210, and of course I configured AlOps External Deployer with this PowerShell line:
      New-ALOpsExternalDeployer -ServerInstance BC210 (and everything seemed ok, with also the restart of BC210 service)

      • waldo on November 16, 2022 at 4:54 pm
        Author

      Could you please make an issue on: https://github.com/HodorNV/ALOps-External-Deployer/issues

      • Fabio Cipriani on November 16, 2022 at 5:39 pm

      Yes, of course
      Thank you

      Fabio

    • Francesco on November 28, 2022 at 12:13 pm
    • Reply

    Hello, I have some issue activating the external deployer on a BC 21.1 on-premises

    When I launch the command

    New-ALOpsExternalDeployer -ServerInstance [InstanceName]

    I got this:

    Set-NAVServerConfiguration : The configuration setting ‘LocalServiceApiKey’ is not valid for Microsoft Dynamics 365 Business Central Server.
    At C:\Program Files\WindowsPowerShell\Modules\ALOps.ExternalDeployer\1.38\New-ALOpsExternalDeployer.ps1:22 char:5
    + Set-NAVServerConfiguration -ServerInstance $ServerInstance -KeyNa …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (0:Int32) [Set-NAVServerConfiguration], NavConfigurationException
    + FullyQualifiedErrorId : MicrosoftDynamicsNavServer$BC21-1_SOLIME,Microsoft.Dynamics.Nav.Management.Cmdlets.SetNavServerConfiguration

    How can I get this right?

      • waldo on November 28, 2022 at 1:09 pm
        Author

      We are working on an update for v21. Did you already upgrade to the new version of ALOPs.ExternalDeployer?
      After that – re-do the install-process. If all is pretty standard, it should work. It’s the “non-standard” bc-installs we’re still struggling with…

      • waldo on November 30, 2022 at 2:18 pm
        Author

      Since today, we have a new version. Can you try again?

      When installing for multiple instances, you need to specify a different port for each instance ..

      • Francesco on January 23, 2023 at 3:08 pm

      Hello, thank you, I’ll try right away.
      Question: I have a server with multiple instances, different versions. From BC 18 to BC 21. Do I have to uninstall the old version of the externaldeployer? I that case, there is a command before install the new version or the new versioni overwrites the old one? Do I have to specify a different port for every single BC service, right?

    • Simon on December 14, 2022 at 6:25 pm
    • Reply

    Thanks – great utility …

    In case helpful – to succeed with updated version for BC210 required me to :-
    1) specify instance parameters for Install-ALOpsExternalDeployer -ServerInstance ‘BC210’ -ListenPort 7210
    2) remove PowerShell module folders from previously installed versions (otherwise got error from $CERFilePath in Install-ALOpsCertificate() returning array rather than single value file as required…) (for me older versions located in C:\Program Files\WindowsPowerShell\Modules\ALOps.ExternalDeployer)
    3) to tidy – remove unwanted services e.g. Remove-ALOpsExternalDeployer -ServiceName ‘ALOpsExternalDeployer$BC’

      • waldo on December 14, 2022 at 6:33 pm
        Author

      That’s good feedback – thanks so much!

      We put everything in a container – so we rebuild container, and done. Wasn’t aware we needed so much cleaning up!

  1. […] Source : Waldo’s Blog Read more… […]

  2. […] might have read my previous blogpost on how to enable the “external deployment” in an OnPrem Business Central environment. Well, that post deserved an “extension” as I didn’t provide examples on how to […]

  3. […] might have read my previous blogpost on how to enable the “external deployment” in an OnPrem Business Central environment. Well, that post deserved an “extension” as I didn’t provide examples on how to […]

  4. […] might have read my previous blogpost on how to enable the “external deployment” in an OnPrem Business Central environment. Well, that post deserved an “extension” as I didn’t provide examples on how to […]

  5. […] Use Waldo's workaround and install straight from DevOps https://www.waldo.be/2020/06/15/deploying-from-devops-the-right-way-enabling-external-deployment-in-… This is the approach I recommend to everyone, if it is possible. In our cases it unfortunately […]

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.