> For the complete documentation index, see [llms.txt](https://docs.devolutions.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.devolutions.net/powershell-universal/it/config/hosting/azure.md).

# Azure

PowerShell Universal è un'applicazione web ASP.NET Core e può essere ospitata in Windows Azure Web Apps.

## Container Web App

Le container web app consentono di utilizzare immagini Docker come web app in Azure. All'interno del portale di Azure, può creare una web app Docker Container utilizzando la procedura guidata App Services \ Create Web App.

Dopo aver selezionato un gruppo di risorse, assegnato un nome e selezionato un piano di calcolo, potrà creare la web app.

![Container Web App](/files/ylji2pvFTpDkaB3LmTyS)

Successivamente, dovrà distribuire l'immagine nella sua web app. Per farlo, selezioni il Deployment Center e configuri l'immagine da scaricare. Può scaricare una versione con tag statico (come 2.7.3) oppure scaricare la latest e la sua web app rimarrà automaticamente aggiornata con le nuove release di PowerShell Universal. Utilizzi il tag con il suffisso `azure`. È preconfigurato per l'esecuzione in Azure.

{% hint style="info" %}
Per gli ambienti di produzione, suggeriamo di impostare una versione con tag per evitare aggiornamenti involontari del container al riavvio. Per impostazione predefinita, Azure aggiornerà automaticamente i container quando un tag, come latest, viene aggiornato. Questo le consentirà di controllare gli aggiornamenti della sua versione di PowerShell Universal.
{% endhint %}

<figure><img src="/files/c2PXoMPrjJUdP5gh5adz" alt=""><figcaption><p>Configurazione Docker</p></figcaption></figure>

### Persistenza locale

Per impostazione predefinita, il container scriverà nella directory `/home`.

Dovrà assicurarsi che la variabile d'ambiente `WEBSITES_ENABLE_APP_SERVICE_STORAGE` sia impostata su true. Questo configura il container in modo che la cartella `/home` sia persistente ed è qui che vengono archiviati i dati di configurazione di PowerShell Universal.

### Git e SQL

Se sceglie di utilizzare l'integrazione git in PowerShell Universal, consigliamo di configurare un server e un database SQL per l'archiviazione. Git verrà utilizzato per sincronizzare i file di configurazione all'avvio del container. SQL memorizzerà le impostazioni di configurazione di git insieme a risorse come job, app token e identità.

Per iniziare le servirà un database Azure SQL. Dopo aver creato la risorsa, dovrà copiare la stringa di connessione dal database per fornirla a PowerShell Universal.

<figure><img src="/files/IWJAgAPl1xrwOVYPc9E7" alt=""><figcaption></figcaption></figure>

Si assicuri di aver consentito ai servizi di Azure di accedere al database.

<figure><img src="/files/3XoAYI6Bt42TiGvxBhxp" alt=""><figcaption></figcaption></figure>

Per abilitare il supporto SQL, deve impostare i plugin all'interno di PowerShell Universal per utilizzare il plugin SQL nell'Application Configuration della sua web app.

Crei un'impostazione `Plugins__0` con il valore `SQL`. Successivamente, imposti il valore `Data__ConnectionString` sul database del suo server SQL.

<figure><img src="/files/h4peAzMdiW9o9TUk8vRI" alt=""><figcaption></figcaption></figure>

Una volta configurato SQL, può avviare il container. Lo schema del database verrà creato all'avvio del container. Successivamente, dovrà configurare git all'interno di PowerShell Universal facendo clic su Settings \ Git. Inserisca il remote, il branch, il nome utente, la password o il personal access token e la modalità di sincronizzazione. Push-only non è consigliato in questa configurazione perché lo stato del container viene perso tra un riavvio e l'altro. Si assicuri che la modalità di inizializzazione sia impostata su Clone.

{% hint style="info" %}
Le impostazioni di git sono memorizzate nel suo database SQL e verranno recuperate a ogni avvio del container.
{% endhint %}

<figure><img src="/files/6jBSNbsIg6FbUKkkZYt0" alt=""><figcaption></figcaption></figure>

### Header inoltrati

I container sono generalmente ospitati dietro un reverse proxy e non saranno a conoscenza dell'URL esterno effettivo senza una configurazione aggiuntiva. Per garantire che i sistemi che richiedono l'URL esterno, come OpenID Connect, ricevano le informazioni corrette, dovrà impostare la variabile d'ambiente `ASPNETCORE_FORWARDEDHEADERS_ENABLED` su `true`.

![](/files/DND7o46xsw3IrDXW3G70)

Per maggiori informazioni, può leggere questo articolo del blog di [Microsoft](https://devblogs.microsoft.com/dotnet/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6/).

### Bicep

Può utilizzare il seguente template Bicep per distribuire una container web app con archiviazione persistente.

```bicep
@description('Name of Azure Web App')
param siteName string = 'psu-${uniqueString(resourceGroup().id)}'

@description('The version of PowerShell Universal')
param version string = '5.4.4'

@description('App Service Plan Pricing Tier')
@allowed([
  'B1'
  'B2'
  'B3'
  'S1'
  'S2'
  'S3'
  'P1V2'
  'P2V2'
  'P2V3'
])
param servicePlanPricingTier string = 'S2'
var servicePlanName = '${siteName}-asp'

@description('Location for all the resources.')
param location string = resourceGroup().location

var servicePlanPricingTiers = {
  F1: {
    tier: 'Free'
  }
  B1: {
    tier: 'Basic'
  }
  B2: {
    tier: 'Basic'
  }
  B3: {
    tier: 'Basic'
  }
  S1: {
    tier: 'Standard'
  }
  S2: {
    tier: 'Standard'
  }
  S3: {
    tier: 'Standard'
  }
  P1V2: {
    tier: 'Standard'
  }
  P2V2: {
    tier: 'Standard'
  }
  P2V3: {
    tier: 'Standard'
  }
}

resource planResource 'Microsoft.Web/serverfarms@2024-04-01' = {
  name: servicePlanName
  location: location
  sku: {
    name: servicePlanPricingTier
    tier: servicePlanPricingTiers[servicePlanPricingTier].tier
    capacity: 1
  }
  kind: 'linux'
  properties: {
    reserved: true
  }
}

resource siteResource 'Microsoft.Web/sites@2024-04-01' = {
  name: siteName
  location: location
  properties: {
    serverFarmId: planResource.id
    siteConfig: {
      linuxFxVersion: 'DOCKER|ironmansoftware/universal:${version}-azure'
    }
  }
}

resource siteWebAppsettingsResource 'Microsoft.Web/sites/config@2024-04-01' = {
  parent: siteResource
  name: 'appsettings'
  properties: {
    WEBSITES_ENABLE_APP_SERVICE_STORAGE: 'true'
  }
}

```

### Container sidecar

Le container web app supportano anche i [container sidecar](https://learn.microsoft.com/en-us/azure/app-service/overview-sidecar), che le consentono di eseguire container aggiuntivi insieme al container di PowerShell Universal. Questo è utile per supportare servizi come proxy, agent, collector o altri processi complementari. Quando ospita PowerShell Universal in questa configurazione, si assicuri che il container web esponga la porta HTTP corretta. Per impostazione predefinita, PowerShell Universal è in ascolto sulla porta `5000`.

## Web app standard

### Creazione manuale di una web app

All'interno del portale di Azure, dovrà creare una nuova risorsa Web App. PowerShell Universal richiede attualmente lo stack di runtime .NET 10. Può utilizzare Linux o Windows.

{% hint style="info" %}
Se durante la configurazione della sua WebApp sceglie un piano di hosting Windows anziché un piano di hosting Linux in Azure, deve scegliere un Basic Plan (B1) o superiore per poter utilizzare app a 64 bit. Deve inoltre andare in Settings > Configuration > General setting > Platform e selezionare 64-bit prima di eseguire il comando `Publish-AzWebApp`, altrimenti l'installazione non riuscirà.
{% endhint %}

<figure><img src="/files/8BvzzutomcOQppAhXRy6" alt=""><figcaption></figcaption></figure>

**Comando di avvio (solo Linux)**

Quando ospita in un ambiente Linux, dovrà impostare il comando di avvio in Settings \ Configuration \ General Settings \ Startup Command come segue.

```
dotnet Universal.Server.dll
```

Nell'esempio seguente, utilizzeremo il modulo Azure PowerShell per distribuire manualmente la Web App.

Innanzitutto dovrà installare Azure PowerShell.

```powershell
Install-Module Az
```

Una volta installato, dovrà connettersi alla sua sottoscrizione.

```powershell
Connect-AzAccount
```

### Distribuire i file Windows

Se utilizza Windows, dovrà scaricare il file ZIP per Windows. Questo scaricherà l'ultima versione di PowerShell Universal.

```powershell
$LatestVersion = Invoke-RestMethod https://imsreleases.blob.core.windows.net/universal/production/v5-version.txt
Invoke-WebRequest "https://imsreleases.blob.core.windows.net/universal/production/$LatestVersion/Universal.win7-x64.$LatestVersion.zip" -OutFile .\Universal.zip
```

### Distribuire i file Linux

Se utilizza Linux, dovrà scaricare il file ZIP per Linux. Questo scaricherà l'ultima versione di PowerShell Universal.

```powershell
$LatestVersion = Invoke-RestMethod https://imsreleases.blob.core.windows.net/universal/production/v5-version.txt
Invoke-WebRequest "https://imsreleases.blob.core.windows.net/universal/production/$LatestVersion/Universal.linux-x64.$LatestVersion.zip" -OutFile .\Universal.zip
```

Ora che abbiamo configurato il modulo Az e scaricato lo ZIP di Universal, possiamo distribuire la Web App.

```powershell
$Parameters = @{
    Force = $true
    ResourceGroupName = 'psudemo2_group'
    Name = 'psudemo2'
    ArchivePath = '.\Universal.zip'
}
Publish-AzWebApp @Parameters
```

{% hint style="info" %}
Può verificare in Azure in Deployment Center > Logs lo stato Success (Active) per assicurarsi che i file siano stati distribuiti/installati correttamente.
{% endhint %}

### Modifiche alle impostazioni richieste

Queste impostazioni possono essere configurate nella scheda Configuration all'interno delle Application settings.

<figure><img src="/files/bhK79nAysGqXRYCntigE" alt=""><figcaption></figcaption></figure>

#### Chiave di firma JWT

La chiave di firma JWT predefinita non è di lunghezza sufficiente e dovrà essere aggiornata. Questo può essere fatto in `appsettings.json` oppure utilizzando le variabili d'ambiente.

#### appsettings.json

```
  "Jwt": {
    "SigningKey": "xXyt9UpJKB4Pb*4$hprd!JJoyOcK4ZOV**O7Hug9&@gYHc$",
    "Issuer": "IronmanSoftware",
    "Audience": "PowerShellUniversal"
  },
```

#### Variabile d'ambiente

```
$Env:Jwt__SigningKey = 'xXyt9UpJKB4Pb*4$hprd!JJoyOcK4ZOV**O7Hug9&@gYHc$'
```

#### URL dell'API

Le Azure Web App utilizzano un reverse proxy e PowerShell Universal non rileva correttamente l'URL esterno. Durante l'esecuzione dei job, Universal utilizza la Management API per cercare automaticamente le informazioni su job, script e pianificazioni. Ciò significa che l'operazione non riuscirà se non è in grado di indirizzare correttamente l'URL esterno dell'API.

L'URL dell'API deve essere l'indirizzo HTTP esterno della sua Web App. Può aggiornarlo in `appsettings.json` oppure utilizzando una variabile d'ambiente.

#### appsettings.json

```
"Api": {
 "Url": "https://psudemo.azurewebsites.net"
 },
```

#### Variabile d'ambiente

```
$Env:Api__Url = "https://psudemo.azurewebsites.net"
```

#### NodeName

Può impostare il nome dell'istanza di PowerShell Universal specificando il NodeName. Ciò garantirà che i riavvii non influiscano sul database di PowerShell Universal. Non è richiesto per le installazioni LiteDB.

```
$Env:NodeName = "psuazure"
```

#### PORT e WEBSITES\_PORT (solo Linux)

Per sovrascrivere la porta predefinita in una web app Linux, deve impostare le impostazioni PORT e WEBSITES\_PORT su 5000.

Dopo aver pubblicato la Web App, visualizzi la sua istanza di PowerShell Universal navigando all'URL della Web App.

#### Archiviazione persistente

Il file `appsettings.json` predefinito memorizzerà il database e i file di configurazione in una posizione non persistente. Può aggiungere variabili d'ambiente per spostarli in un'archiviazione persistente all'interno della sua web app.

**Data\_\_RepositoryPath**

La variabile d'ambiente `Data__RepositoryPath` imposta la posizione dei file di configurazione di Universal. Imposti il valore come segue.

```
D:\home\Data\PowerShellUniversal\Repository
```

### Aggiornare la sua Web App

Quando viene rilasciata una nuova versione di PowerShell Universal, dovrà aggiornare i file applicativi della sua Web App. Consigliamo di rimuovere la directory dell'applicazione e ridistribuire i file. Il database e i file di configurazione non sono memorizzati nella directory dell'applicazione.

Può eliminare i file della sua Web App utilizzando la command API di Kudu. Le sue credenziali Kudu utilizzano l'autenticazione Basic e sono le stesse delle sue [credenziali di distribuzione](https://github.com/projectkudu/kudu/wiki/Deployment-credentials).

Per eliminare tutti i file nella sua Web App, esegua il comando seguente.

```powershell
$Parameters = @{
   Uri = "https://psudemo2.scm.azurewebsites.net/api/command"
   Credential = (Get-Credential)
   Body = (@{
      command = "rd /s /q D:\home\site\wwwroot"
      dir = "D:\home\site\wwwroot"
   } | ConvertTo-Json)
}

Invoke-RestMethod @Parameters
```

Dopo aver eliminato i file applicativi, può ridistribuirli eseguendo nuovamente i passaggi di creazione manuale.

## Application Gateway

Può configurare PowerShell Universal per l'esecuzione dietro un Application Gateway in Azure. Questo è utile per fornire bilanciamento del carico e alta disponibilità a più istanze di PowerShell Universal.

Innanzitutto, configuri un backend pool che abbia come target una o più Azure Web App che eseguono PowerShell Universal.

<figure><img src="/files/j1I9wxLtuxWhRH8AL5Bf" alt=""><figcaption><p>Backend pool</p></figcaption></figure>

Per le impostazioni del backend, dovrà assicurarsi di utilizzare HTTPS con un certificato CA noto. L'affinità basata sui cookie è necessaria per garantire che le sessioni rimangano associate a un singolo nodo.

<figure><img src="/files/62Pe6J46JgKpdQQiEy2P" alt=""><figcaption><p>Impostazioni del backend pool</p></figcaption></figure>

Per consentire ad Azure di servire la web app corretta, dovrà assicurarsi che l'impostazione Override with new host name sia configurata. Utilizzi il nome host per il target di backend.

<figure><img src="/files/rsvLf0EUVDcpICrAY77o" alt=""><figcaption><p>Nome host delle impostazioni di backend</p></figcaption></figure>

Si assicuri che la regola del backend pool sia configurata come target e non come reindirizzamento.

<figure><img src="/files/nAyQgEK93xUv4q1e1ehY" alt=""><figcaption><p>Regola dell'Application Gateway</p></figcaption></figure>

Configuri una regola di riscrittura degli header per trasmettere il nome host pubblico come header `X-Forwarded-Host`. PowerShell Universal lo utilizzerà per costruire internamente gli URL.

<figure><img src="/files/FdyY95336UHkC77ldUms" alt=""><figcaption><p>Regola di riscrittura</p></figcaption></figure>

La regola di riscrittura sopra riportata è un requisito dei metodi di autenticazione OpenID Connect e SAML2.

Infine, può configurare l'IP pubblico del suo Application Gateway utilizzando un provider DNS con un nome host personalizzato. Crei un record A nella sua gestione DNS.

<figure><img src="/files/cjeRRqzMaOlm0GF2AAEY" alt=""><figcaption><p>Record DNS</p></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.devolutions.net/powershell-universal/it/config/hosting/azure.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
