You can host PowerShell Universal as a Windows Service, in IIS, as a Azure Web App or just as a stand alone application. If you are running on Windows, we suggest either a Windows Service or IIS.
To host as a Windows Service, you can download and install the PowerShell Universal MSI. The MSI will automatically install the PowerShell Universal service and start it. Jobs will run under the system account by default but you can configure the service to run under another account after installation.
After the MSI has finished setup, your default web browser will open to http://localhost:5000 for login. The default login credentials are set to Admin and any password.
You do not need to use the MSI to configure Universal as a Windows Service. You can also do it manually with the following PowerShell script.
Read our Azure hosting guide.
You can also host the Universal server as a stand alone application. Simply run the Universal.Server.exe
from the binary directory to utilize the Kestrel web server implementation in ASP.NET Core to start the web server.
This section applies to Universal when it is hosted outside of IIS.
You can set the port of the Universal server by modifying the appsettings.json
file. We recommend that you create an appsettings.json
file in the default configuration folder.
Windows
%ProgramData%\PowerShellUniversal
Linux
%HOME%/.PowerShellUniversal
To set the port, change the Kestrel endpoints section of the appsettings.json
. By default, the configuration is defined to listen on port 5000 and on any address.
To configure HTTPS, you can adjust the appsettings.json
file to use a particular certificate and port. The below configuration uses the testCert.pfx
file and testPassword
and listens on port 5463.
To configure a certificate in a particular location and store, you can use a configuration such as this.
When selecting the certificate by subject name, ensure you use the common name with out CN=
prefix.
Location can be either CurrentUser
or LocalMachine
.
You can use thumbprint rather than subject in version 3.4 and later.
Some providers, like Let's Encrypt and GoDaddy, will issue certificates as PEM and key text files. You can use these types of certificates directly with the Kestrel web server. You will need to specify the HttpsFromPem
section within the Endpoints
for Kestrel.
By default, Universal will listen on HTTP1 and HTTP2. You can adjust the protocols that the server listens to by setting the Protocols property. For example, you can specifically set HTTP1 and HTTP2 support with the following setting.
Some versions of Windows Server (like 2012R2), do not support HTTP2. To disable HTTP2 support, set the listener to only listen on HTTP1.
For a full set of listening options, you can refer to the ASP.NET Core Documentation.
In this example, we'll show how to create a self-signed certificated and use it with PowerShell Universal.
First, create a self-signed certificate and store it into your local machine store. You will need to run PowerShell as administrator. The local machine store is required because PowerShell Universal may be running as service and not as your account.
Next, you'll need to configure PowerShell Universal to use the certificate. This can be accomplished by editing or creating the appsettings.json
file in %ProgramData%\PowerShellUniversal
. This file should already exist if you installed with the MSI installer. The contents of the file should include the DNS name of your certificate and the location.
For self-signed certificates, you will need to include the AllowInvalid
option.
Once you have updated the appsettings.json
file, restart the PowerShell Universal service. You should now be able to access your PowerShell Universal web site at https://localhost
.
PowerShell Universal high availability configuration.
PowerShell Universal can be configured for high availability ("HA") by using a combination of SQL server persistence and a load balancer to ensure that both the front end tools, such as dashboards are accessible and back-end tools, such as jobs, continue to run.
We recommend taking advantage of SQL persistence to ensure that all nodes within your cluster share the same data in regards to job queues, app tokens and identities within your system. Each node should be configured with the same SQL server connection string.
As jobs run, users login and app tokens are created, the SQL server will be used to store this information and will be shared across nodes.
We recommend using git synchronization to store and version control the PowerShell configuration scripts used to manage the PowerShell Universal nodes. One-way git sync may be preferred as the nodes will then be read-only and pull configurations after they have been merged to your production branch. Each node pulls the configuration files on a configurable interval (defaults to 1 minute). Storing git configuration settings in the database is desired as it requires less configuration per node.
PowerShell Universal supports the use of load balancers such as F5 and nginx. There are some requirements that must be met when using load balancers.
Persistent (sticky) sessions are required by dashboards
Web socket support is required by the admin console and dashboards
To aid with load balancing; you can use the /api/v1/status
endpoint for your nodes. The endpoint will return status codes based on the current state of the node. 200
means the node is online and ready to receive requests. Servers running in maintenance mode will return 503
. Servers that failed to start due to a configuration error, will return 500
. Servers with dashboards that failed to start will also return 500
.
You can set your nodes into Maintenance Mode by clicking Platform \ Computers and checking the maintenance mode option. Once maintenance mode is enabled, the /api/v1/status
endpoint will begin returning 503
. This should be configured to disable traffic being routed to the node while maintenance is performed.
There currently are some limitations to highly available PowerShell Universal clusters.
Caching performed using $Cache
or Set-PSUCache
is currently limited to the single node that is performing these operations as they are stored in memory on the system. We recommend an external cache, such as Redis, if you wish to cache data across nodes.
Multi-Node dashboard broadcast messages are currently not supported. Using cmdlets like Show-UDToast -Broadcast
will cause a toast modal to be shown to all connected users of the current node but will not be broadcast to the dashboards across all nodes.
Information about hosting PowerShell Universal in IIS.
PowerShell Universal supports being hosted in IIS (Internet Information Services (IIS) for Windows® Server). Please note that a series of host prerequisites and specific configuration steps are required to facilitate running PowerShell universal on IIS. Please review each section carefully as IIS requires many specific configuration settings applied to work with modern .NET Core applications such as PowerShell Universal.
The following components are required in order to host PowerShell Universal on IIS.
Internet Information Services (IIS) Version 10.0
Including: WebSocket Protocol
The following Windows Server IIS features are also required to be enabled on the IIS Host:
Feature Display Name | Requirement | Installation Script |
---|---|---|
First make sure to enable the IIS feature on Windows Server and then install the ASP.NET Core hosting bundle.
NOTE: IIS often requires a host reboot after installing the .NET Core Hosting bundle! It is strongly recommended that you REBOOT the IIS host after installing the .NET Core Hosting bundle.
Once these prerequisites are met, you are ready to begin configuration of PowerShell Universal on IIS.
Enabling the IIS WebDav Publishing feature will cause issues with Universal. WebDav Publishing filters HTTP requests and prevents PUT and DELETE verbs by default. If you have WebDav Publishing enabled, please ensure you have it configured properly to allow these verbs.
Download the Latest copy of PowerShell Universal. You will need to download the ZIP Archive version of PowerShell Universal. This archive is specifically built for those wishing to configure PowerShell Universal for IIS or other third party web servers. Extract the contents of the Zip to the intended web host folder location on your IIS Host.
You must ensure that the PowerShell Universal application files are unblocked after extracting them. You can unblock them with the Unblock-File
cmdlet.
This location is very important and will be referenced throughout this document. Most importantly this location must be accessible by the Identity used by the IIS Application Pool.
Now that our Host is ready and we have downloaded PowerShell Universal, we can begin configuring IIS.
The First step in the IIS configuration process is to create a new Application Pool in IIS. Before we begin the configuration we should ensure that we select a valid identity for the IIS Application Pool.
The Application Pool Identity is crucial for PowerShell Universal as this will be the "default user" that jobs and dashboards will run as. It will also be the user that will perform read/write operations to the Universal Automation database and will be used by IIS to read the web content directory and execute the application.
It is suggested to use "LocalSystem" or a Service Account of your choosing.
Due to limitations in IIS, the Application Pool Identity settings have MAJOR consequences on the behavior for "Run As" options when using Universal Automation.
IIS Limitations with Universal Automation
App Service configured as Local System - Scripts will execute as the System Account by default and a Run as Accounts CAN be specified when executing a Script in Universal Automation
App Service configured as a Service Account - Scripts can ONLY be executed with the Service Account and a **Run as Account _**_CANNOT** be specified when executing scripts.
Service Account Identity Requirements
The Default Database location can be customized via the PowerShell Universal appsettings.json
file if desired.
Once we have selected a valid identity we are ready to create the Application Pool in IIS.
Now that we have chosen an App Pool identity that has read/write access to the PowerShell Universal Application and Database folders we can create the Application Pool in IIS.
In IIs Manager, Choose the option to Add Application Pool...
Name: Use any Name you would like for the Application Pool
.NET CLR Version: No managed code
Click OK create the Application Pool.
Now that the Application Pool has been created, we will need to configure the Advanced Settings
Open the "Advanced Settings" for the Application Pool and apply the following Configurations:
General / Enable 32-Bit Applications: False
Process Model / Identity: Use the Identity we selected for our Application Pool in the "Choosing an App Pool Identity" section above.
Process Model / Load User Profile: True
Once the Advanced Settings have been applied, our Application Pool is ready, our next step will be to configure the IIS Web Site that will utilize this Application Pool.
Now that we have a valid Application Pool we need to create an IIS website to expose the application. Before we do this we will want to review the PowerShell Universal web.config
file for our website. Within the extracted PowerShell Universal Application folder, we will find a web.config file. This configuration file has been specifically designed for IIS and has a number of configurations we need to review prior to creating the IIS Website.
Most Importantly we will need to update "processPath" argument value of this configuration file. This value will provide IIS with the exact path of the application binary so that it can properly launch the application.
Open the web.config file in the PowerShell Universal Application Folder
Locate the <aspNetCore processPath section of the configuration file
Update the arguments="PATH" value to be the exact location of the Universal.Server.exe path.
Save the file to apply the configuration
There are a variety of additional configurations in this file. We'll be reviewing these in more detail in the "Advanced Configuration" Section but you can refer to the "Additional web.config configurations" on this page for more details
Now that an Application Pool has been created for PowerShell Universal with a valid Identity and we have configured the web.config file, we are finally ready to create the IIS Website. The Website component of IIS loads the application artifacts and exposes the application on the configured web endpoint.
In the IIS Manager: Click "Add Website.."
Configure the new website options :
Site Name: Use any name you would like, ex: PowerShell Universal.
Application Pool: DO NOT use the DefaultAppPool - Select the Application Pool we created in our previous step.
Physical Path: This must be the physical path to the PowerShell Universal Content we extracted from our download .zip file. NOTE: The AppPool identity must have access to the location.
Binding Settings: Note, for initial configuration is suggested to use the base defaults, we'll update these later in our advanced configuration
Type http - For Initial Configuration
IP Address: All Unassigned
Port: 80
Host Name: Name of the Host
At this point, all the required configurations should be in place, and the IIS website hosting PowerShell Universal should be up and running. With a web browser - browse to the configured website location to validate that PowerShell Universal has started. From here you can follow the "Getting Started" guide to validate base functionality. Once you are sure that the Application is working properly with a Basic IIS configuration you can proceed to the "Advanced Configuration" to secure and finalize your desired IIS Configuration.
You are are still experiencing issues with the basic IIS Configuration try checking the "Logs" path specified in the web.config for common issues. If you are still experiencing issues reach out on the forums or support for assistance.
It is possible to nest multiple PowerShell Universal instances under a single application pool and website, but it does require some additional configuration.
You will need have two folders for your application files: one for each application. You will also need to setup two data folders: one for each application.
Once you have setup your folder structure configured, you will need to create two appsettings.json files and update your web.config files for each application.
Within the appsettings.json files, you will need to set the proper paths to the data files for each instance. You will also need to configure the correct base URL for the nested site.
Next, you'll need to update the web.config files for each site to use the proper appsettings.json file and use OutOfProcess hosting.
Now, within the IIS Manager, right click on the psu1 and psu2 folders to convert them to applications.
You should now be able to access the PowerShell Universal admin console at both of the following URLs.
Misconfigured app pool settings can cause jobs to fail to run. The primary cause is app pool recycling or a failure to start the web app when the server is started. This is not an issue for features like APIs or Dashboards but due to the background processing of jobs, you will need to ensure the server starts the website and keeps it running. You can learn more here.
If you are going to be running scheduled jobs within your PowerShell Universal instance hosted in IIS, you must make sure to configure IIS appropriately. There are several settings to validate when configuring your application pool.
Install the Application Initialization feature of the Web Server Role.
You will want to configure the following settings:
General: .NET CLR version = No Managed Code.
General: Start Mode = AlwaysRunning
Process Model: Idle Time-out setting = 0 (disabled)
Recycling: Regular Time Interval = 0.
Within the IIS Site that is hosting Universal, you will need to ensure that Preload is enabled.
While we attempt to detect that PSU is running within IIS, you may run into problems with the negotiate authentication handler being enabled when it's not supported in IIS. To ensure this is not a problem, you can completed disabled it by setting the below environment variable on your IIS machine.
If you are still having issues with IIS and jobs, you should consider turning on IIS recycle logging to ensure that IIS is keeping your site running.
As of PowerShell Universal 3.3, you can via the uptime of the system on the home page of the admin console to get a good indicator of the last time the service was started.
Prior to version 3.3, you can view the server uptime by visiting the Hangfire dashboard and clicking the Servers tab.
PowerShell Universal can use anonymous authentication and Windows Authentication in IIS.
To enable Windows Authentication, you will first need to enable it for your Web Server and then for your website. You can find the authentication settings under the Authentication section in IIS Manager.
For the website, set the same settings.
Once authentication is enabled in IIS, you will have to ensure that Windows Authentication is enabled for PowerShell Universal.
First, adjust the web.config
file to forward the Windows authentication token.
Next, enable Windows Authentication in the appsettings.json
file for PowerShell Universal.
Restart your Application Pool and now you should be able to login with Windows credentials.
When enabling Windows Authentication but not Anonymous Authentication, you will no longer be able to use PowerShell Universal AppTokens. You will need to enable both authentication methods to support Windows Credentials as well as App Tokens.
Anonymous Authentication can be enabled to allow for app tokens and other requests to be transmitted through the IIS proxy. You will need to enable Anonymous Authentication on both the Server and Web site levels. There is no additional configuration to do within PowerShell Universal.
The settings within the Universal web.config can be adjusted as you see fit. Below you will find a description of each setting.
This setting is used for Windows Authentication. If you wish to use Windows Authentication with IIS, ensure that you disable Anonymous Authentication and enable Windows Authentication within your IIS site and then set this setting to true.
This setting is used for debugging start up issues with your Universal setup. It's recommended to enable this when first configuring IIS integration. You can disable it once everything is configured. You need to ensure that your AppPool identity has write access to the StdOutLogFile location.
The hosting model sets how the Universal server will run. When set to InProcess, the Universal Server will run from within the IIS agent. This provides better performance than using OutOfProcess hosting. InProcess hosting does not work with StdOutLogEnabled. It's recommended to use OutOfProcess hosting only while configuring Universal and, InProcess when your configuration steps have been completed.
When upgrading, ensure that you do not copy files over the top of your existing install. Instead, delete the current application files and copy the new ones into the directory. Copying over the top of the files can result in binaries being present in the installation directory that are not expected and can issues with the system.
Learn how to host PowerShell Universal in Azure.
PowerShell Universal is an ASP.NET Core web application and can be hosted in Windows Azure Web Apps.
Container web apps allow for using Docker images as web apps in Azure. Within the Azure portal, you can create a Docker Container web app by using the App Services \ Create Web App wizard.
Once you have selected a resource group, assigned a name and selected a compute plan, you will be able to create the web app.
Next, you'll need to deploy the image to your web app. To do so, select the Deployment Center and configure the image to pull. You can either pull a static tagged version (like 2.7.3) or pull the latest and your web app will automatically stay up to date with new PowerShell Universal releases.
For production environments, we suggest setting a tagged version to avoid unintentional updates to your container when it restarts. By default, Azure will automatically update containers when a tag, such as latest, is updated. This will allow you to control updates to your PowerShell Universal version.
For single instance systems, you can use an Azure Storage Account with a File Share to store the configuration and database.
Do not use an Azure Storage Account if you chose to use git integration. PowerShell Universal performance will be severely degraded if you use this configuration due to the performance of Azure File Shares.
We'll need to configure the Azure Storage Account for file shares to store the data for this web app. Within your storage account, create a new File Share that is transaction optimized.
Back in your App Service, you can setup a Path mapping to the file share we just created. In my example, I've set the mount path to /Data
. This is where the configuration and database will be stored.
Finally, we need to configure PowerShell Universal to store data on our file share. On the Application settings tab, set the Data__ConnectionString
and Data__RepositoryPath
to store data on the file share.
Restart the App Service and login to your new PowerShell Universal instance. You'll see that data generated by PowerShell Universal is being stored on the share.
If you choose to use git integration in PowerShell Universal, we recommend setting up a SQL server and database for storage. Git will be used to synchronize configuration files when the container is started. SQL will store the git configuration settings alongside resources like jobs, app tokens and identities.
You'll need an Azure SQL database to get started. Once you create the resource, you will need to copy the connection string from the database to provide to PowerShell Universal.
Ensure that you have allowed Azure services to access the database.
To enable SQL support, you should set the plugins within PowerShell Universal to use the SQL plugin in the Application Configuration for your web app.
Create a Plugins__0
setting with the value SQL
. Next, set the Data__ConnectionString
value to your SQL server database.
Once you have SQL configured, you can start your container. The database schema will be created as the container starts. Next, you'll need to configure git within PowerShell Universal by clicking Settings \ Git. Enter your remote, branch, username, password or personal access token, and synchronization mode. Push-only is not recommended in this configuration because container state is lost between restarts. Ensure that the initialization mode is set to Clone.
Git settings are stored in your SQL database and will be retrieved each time the container is started.
Containers are typically hosted behind a reverse proxy and will not be aware of the actual external URL without additional configuration. In order to ensure that systems that require the external URL, like OpenID Connect, receive the proper information, you will need to set the ASPNETCORE_FORWARDEDHEADERS_ENABLED
environment variable to true
.
For more information, you can read this blog post from the Microsoft.
Within the Azure Portal, you will need to create a new Web App resource. PowerShell Universal currently requires the .NET 6 runtime stack. You can use either Linux or Windows.
If you choose a Windows hosting plan rather than a Linux hosting plan in Azure when configuring your WebApp then you need to choose a Basic Plan (B1) or higher to be able to use 64-bit apps. You also have to go to Settings > Configuration > General setting > Platform and select 64-bit before you run the Publish-AzWebApp
command, or it will fail to install.
Startup Command (Linux Only)
When hosting in a Linux environment, you will need to set the startup command under Settings \ Configuration \ General Settings \ Startup Command to the following.
In the below example, we'll use the Azure PowerShell module to deploy the Web App manually.
You'll first need to install Azure PowerShell.
Once installed, you'll need to connect to your subscription.
If you are using Windows, you will need to download the Windows ZIP file. This will download the latest version of PowerShell Universal.
If you are using Linux, you will need to download the Linux ZIP file. This will download the latest version fo PowerShell Universal.
Now that we have the Az module configured and the Universal ZIP downloaded, we can deploy the Web App.
You can check in Azure under Deployment Center > Logs for Status Success (Active) to ensure files deployed / installed successfully.
These settings can be set within the Configuration tab within the Application settings.
The default JWT signing key is not of a sufficient length and will need to be updated. This can be done in appsettings.json
or by using environment variables.
Azure Web Apps use a reverse proxy and PowerShell Universal does not detect the external URL appropriately. When running jobs, Universal uses the Management API to automatically look up job, script and schedule information. This means that this will fail if it cannot correctly address the external API URL.
The API URL should be the external HTTP address of your Web App. You can update this in appsettings.json
or by using an environment variable.
You can set the name of the PowerShell Universal instance by specifying the NodeName. This will ensure that restarts will not affect the PowerShell Universal database. This is not required for LiteDB installations.
To override the default port in a Linux web app, you need to set the PORT and WEBSITES_PORT setting to 5000.
After publishing the Web App, view your PowerShell Universal instance by navigating to the Web App's URL.
The default appsettings.json
file will store the database and configuration files in a non-persistent location. You can add environment variables to move them to persistent storage within your web app.
Data__ConnectionString
The Data__ConnectionString
environment variable sets the location of the database. You will have to ensure that you enable a "shared" connection for LiteDB to function properly in Azure. Set the value to the following.
Data__RepositoryPath
The Data__RepositoryPath
environment variable sets the location of the configuration files for Universal. Set the value to the following.
When a new version of PowerShell Universal is released, you will need to update the application files for your Web App. We recommend removing the application directory and redeploying the files. The database and configuration files are not stored in the application directory.
You can delete the files for your Web App by using the Kudu command API. Your Kudu credentials use Basic authentication and are the same as your deployment credentials.
To delete all the files in your Web App, issue the following command.
Once you've delete the application files, you can redeploy them by running the manual creation steps again.
WebSocket Protocol
Required to run PowerShell Universal
Install-WindowsFeature Web-WebSockets
Windows Authentication
Required for using Windows Authentication
Install-WindowsFeature Web-Windows-Auth