﻿# ASP.NET Core 所有可能用到的 ASPNETCORE_* 環境變數總整理

我們在撰寫 .NET 的時候，有許多「組態設定」可以輕易的透過「環境變數」來進行調整或變更，這裡同時也包含了 ASP.NET Core 內建的許多 `ASPNETCORE_` 開頭的內建環境變數名稱，可以幫忙調整許多 .NET 與 ASP.NET Core 的預設行為。今天這篇文章我就來整理一下有哪些可以用！

![aspnetcore-environment-variables](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/264d533885ae6fa56133-864fe3b2-9a43-4356-b661-47c4a7e288bd.webp)

### 認識 ASP.NET Core 的宿主環境 (Host)

ASP.NET Core 有兩種宿主環境，不同的宿主環境通常會定義一些環境變數來幫助你調整環境的參數，而環境變數區分成兩個不同的名稱前綴 (Prefix)：分別為：

1.  [.NET Generic Host](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host)
    
    通常用來提供 .NET 應用程式一些重要的基礎設定，例如 Dependency injection (DI)、Logging、Configuration、IHostedService implementations 等等，通常用在背景服務類型的應用程式中。
    
    你在執行 `CreateDefaultBuilder()` 的時候，會載入 `DOTNET_` 開頭的環境變數。
    
    > 參見: [介紹幾個 .NET SDK、.NET CLI 與 .NET runtime 執行時的好用環境變數](/post/2021/09/21/Environment-variables-used-by-NET-SDK-NET-CLI-and-NET-runtime)
    
2.  [ASP.NET Core Web Host](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host)
    
    除了 .NET 應用程式重要的基礎設定外，執行 AAS.NET Core 網站還需要一些額外的設定，例如網站伺服器相關的設定，像是 [Kestrel](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel) 或 [IISIntegration](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/) 之類的。
    
    在載入 `WebHostBuilder` 的時候，會載入 `ASPNETCORE_` 開頭的環境變數。
    
    > 參見: [ASP.NET Core Web Host](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host)
    

### ASP.NET Core Web Host 常見的環境變數

大家應該都知道 ASP.NET Core 內建一套效率極高的 [Kestrel](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel) 網站伺服器，所有 ASP.NET Core 在執行的時候都少不了它，然而我們在啟動 Kestrel 的時候，就有許多可以設定的地方，以下我列出幾個相對常用的環境變數設定。

1.  `ASPNETCORE_ENVIRONMENT`
    
    我想這個應該是每位 ASP.NET Core 開發人員都該知道的環境變數，非常實用！
    
    這個 `ASPNETCORE_ENVIRONMENT` 環境變數會用來幫你切換不同的**環境**(Environment)，透過「環境」的管理，可以幫助你在執行時識別不同環境下的資訊，甚至於可以指定不同環境下的組態或應用程式邏輯。
    
    > 參見: [Use multiple environments in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/environments)
    
2.  `ASPNETCORE_URLS`
    
    我們在用 `dotnet run` 啟動 ASP.NET Core 在啟動的時候，會先去查找一個 `Properties/launchSettings.json` 檔案，找到裡面的 `profiles.設定檔名稱.applicationUrl` 屬性，並以這個屬性指定的 `host` 與 `port` 來啟動網站，其設定的格式為 `https://localhost:7087;http://localhost:5046`。如下範例：
    
    ```json
    {
      "profiles": {
        "w1": {
          "commandName": "Project",
          "dotnetRunMessages": true,
          "launchBrowser": true,
          "applicationUrl": "https://localhost:7087;http://localhost:5046",
          "environmentVariables": {
            "ASPNETCORE_ENVIRONMENT": "Development"
          }
        }
      }
    }
    ```
    
    然而，在你透過 `dotnet publish` 發行網站後，就不會再去讀取 `Properties/launchSettings.json` 檔案，取而代之的，就是去讀取 `ASPNETCORE_URLS` 環境變數，而且設定值的格式是一樣的，以下是設定範例：
    
    ```ini
    ASPNETCORE_URLS=https://+:443;http://+:80
    ```
    
    這裡的 `+` (加號) 用來綁定本機的所有網路介面 (network interface)，而 `https://` 預設會自動載入 ASP.NET Core 內建的**自簽憑證**。
    
    > 注意: 早期的 ASP.NET Core 版本使用 `ASPNETCORE_SERVER.URLS` 環境變數，不過已經棄用，使用上要注意，建議改用 `ASPNETCORE_URLS` 環境變數。
    
3.  `ASPNETCORE_Kestrel__Certificates__Default__Path` 與 `ASPNETCORE_Kestrel__Certificates__Default__Password`
    
    如果 `ASPNETCORE_URLS` 環境變數指定了 `https://` 通訊協定，預設會自動載入 ASP.NET Core 內建的**自簽憑證**，不過在正式環境下，我們通常會使用**正式憑證**，而這兩個環境變數就是為此而生。
    
    我們可以練習透過 mkcert 快速建立一個 PKCS#12 格式的憑證 (PFX)：
    
    ```bash
    mkcert -pkcs12 localhost
    ```
    
    > 這個命令會產生 `localhost.p12` 檔案，預設密碼為 `changeit`
    
    然後我們就可以設定環境變數如下：
    
    ```ini
    ASPNETCORE_Kestrel__Certificates__Default__Path='localhost.p12'
    ASPNETCORE_Kestrel__Certificates__Default__Password='changeit'
    ```
    
4.  `ASPNETCORE_CONTENTROOT`
    
    ASP.NET Core 在啟動的時候，預設會找**主程式**當前的路徑作為**內容**(Content)的**根目錄**，這裡的 **Content** 指的是 ASP.NET Core 應用程式部署時所有的「內容」，也就是所有的 `*.dll` 所在的那些資料夾內容。
    
    當你想在啟動應用程式的時候，選用另一個資料夾當作載入**組件**(assembly)的依據，你才需要指定這個 `ASPNETCORE_CONTENTROOT` 環境變數。
    
    有個實際的案例是，當你的 ASP.NET Core 應用程式是部署在 Windows 服務時，預設 Windows Service 會以 `C:\Windows\System32` 為工作目錄，這也意謂著你的 ASP.NET Core 應用程式在執行的時候，會無法載入正確的 DLL 檔案，那就是因為 `CONTENTROOT` 路徑錯誤導致的。解決方法就是額外指定 `ASPNETCORE_CONTENTROOT` 環境變數即可。詳見: [Host ASP.NET Core in a Windows Service](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?tabs=visual-studio&WT.mc_id=DT-MVP-4015686)
    
5.  `ASPNETCORE_HOSTINGSTARTUPASSEMBLIES`
    
    這裡的 `ASPNETCORE_HOSTINGSTARTUPASSEMBLIES` 可以指定 ASP.NET Core 應用程式的**啟動組件**(startup assemblies)，他會在應用程式啟動時，自動找出指定組件中的 `HostingStartup` attribute，並在應用程式啟動時執行特定程式碼！
    
    ```ini
    ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
    ```
    
    > 多個組件請用 `;` (分號) 分隔不同組件！
    
    這是一種在 .NET 環境下動態載入程式碼的一種進階技巧，詳見 [Use hosting startup assemblies in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/platform-specific-configuration) 文章說明。
    
    > 參見: [啟用 Razor 執行階段編譯 (Enable Razor runtime compilation) 技術細節探索](/post/2021/10/02/Razor-runtime-compilation-in-detail)
    
6.  `ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES`
    
    由於 [hosting startup assemblies](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/platform-specific-configuration) 可以寫死在程式中：
    
    ```csharp
    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseSetting(
                        WebHostDefaults.HostingStartupExcludeAssembliesKey,
                        "{ASSEMBLY1;ASSEMBLY2; ...}")
                    .UseStartup<Startup>();
            });
    ```
    
    如果你想要在啟動時動態排除特定組件，就可以使用 `ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES` 這個環境變數。
    
7.  `ASPNETCORE_PREVENTHOSTINGSTARTUP`
    
    如果你想要在啟動時完全關閉 [hosting startup assemblies](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/platform-specific-configuration) 機制，就可以使用 `ASPNETCORE_PREVENTHOSTINGSTARTUP` 這個環境變數。
    
    ```ini
    ASPNETCORE_PREVENTHOSTINGSTARTUP=1
    ```
    
8.  `ASPNETCORE_HTTP_PORTS`
    
    這個環境變數可以讓你在啟動 ASP․NET Core 應用程式時，透過這個 `ASPNETCORE_HTTP_PORTS` 環境變數來指定預設的 `HTTP` 連接埠。
    
    如果有多個 Ports 可以用分號分隔，例如：`ASPNETCORE_HTTP_PORTS=80;8080`。
    
9.  `ASPNETCORE_HTTPS_PORTS`
    
    當你使用了 [HTTPS Redirection Middleware](https://learn.microsoft.com/en-us/aspnet/core/security/enforcing-ssl) (`UseHttpsRedirection`) 強迫將所有 HTTP 要求自動轉向到 HTTPS 通訊協定，預設會自動轉向到 Port `443`，如果不是這個 Port 的話，就要透過 `ASPNETCORE_HTTPS_PORTS` 環境變數來指定。
    
    ```
    ASPNETCORE_HTTPS_PORT=443;8443
    ```
    
    或是你也可以將 `https_port` 設定加在 `appsettings.json` 設定檔中：
    
    ```json
    {
      "https_port": 443,
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*"
    }
    ```
    
10.  `ASPNETCORE_SHUTDOWNTIMEOUTSECONDS`
     
     當 ASP.NET Core 應用程式呼叫 [IApplicationLifetime.ApplicationStopping](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.iapplicationlifetime.applicationstopping) 或在嘗試停止應用程式的過程，因為特定原因導致無法關閉時，可以設定等待幾秒就要強制關閉！(預設 `5` 秒)
     
     ```ini
     ASPNETCORE_SHUTDOWNTIMEOUTSECONDS=10
     ```
     
11.  `ASPNETCORE_STARTUPASSEMBLY`
     
     在 ASP.NET Core 5 之前都有個 `Startup` 類別，雖然在 ASP.NET Core 6 的 Minimal APIs 看不到了，但事實上你還是可以定義這個類別，並使用早期的 API 進行定義。如果你想將 `Startup` 類別寫在完全不同的另一個組件下，就可以利用 `ASPNETCORE_STARTUPASSEMBLY` 環境變數來動態指定**啟動類別** (Startup class)，非常方便！
     
12.  `ASPNETCORE_WEBROOT`
     
     在 ASP.NET Core 網站中，如果要載入靜態網站資源，預設都會放在 `wwwroot` 資料夾下，而這個資料夾名稱可以很簡單的透過 `ASPNETCORE_WEBROOT` 環境變數來改變，完全不用修改程式碼。
     
     ```ini
     ASPNETCORE_WEBROOT=public
     ```
     

### 一些相對罕見的環境變數

-   `ASPNETCORE_TEMP`
    
    在 ASP.NET Core 的核心程式中，所有會用到「暫存資料夾」的地方，都會優先判斷式否有這個 `ASPNETCORE_TEMP` 環境變數，如果有的話，就會以環境變數指定的資料夾路徑作為暫存檔案的存放地點。如果沒有，就會直接呼叫 `Path.GetTempPath()` 取得系統預設的暫存資料夾。
    
    ```ini
    ASPNETCORE_TEMP=G:\TEMP
    ```
    
-   `ASPNETCORE_FORWARDEDHEADERS_ENABLED`
    
    如果你想在 Kesntel 前面加上一個負載平衡器，而且負載平衡器不是用 IIS 的話，你就可能會用到這個環境變數。
    
    詳細的用法參見 [Forward the scheme for Linux and non-IIS reverse proxies](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-6.0&WT.mc_id=DT-MVP-4015686#forward-the-scheme-for-linux-and-non-iis-reverse-proxies) 文章說明。
    
    ```ini
    ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
    ```
    
    如果你的網站部署在 **Azure App Service on Linux** 或 **Web App for Containers** 上，也只要在「應用程式設定」的地方加入一個 `ASPNETCORE_FORWARDEDHEADERS_ENABLED=true` 設定到網站上即可，程式完全不用修改就可以啟用。參見: [Forwarded Headers Middleware Updates in .NET Core 3.0 preview 6](https://devblogs.microsoft.com/dotnet/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6/?WT.mc_id=DT-MVP-4015686)
    

### ASP.NET Core Module (ANCM) for IIS 相關環境變數

-   `ASPNETCORE_PORT`
    
    這個環境變數只會用在與 IIS 整合的時候，IIS 在啟動 Kestrel 的時候，會偷偷傳入這個環境變數，用來指定 Out of proccess 運作的 Kestrel 要跑在哪個 Port 上面。
    
    > 注意: 你幾乎不會自行設定這個環境變數！
    
-   `ASPNETCORE_APPL_PATH`
    
    這個環境變數只會用在與 IIS 整合的時候，IIS 在啟動 Kestrel 的時候，會偷偷傳入這個環境變數，用來指定應用程式所在路徑。
    
    > 注意: 你幾乎不會自行設定這個環境變數！
    
-   `ASPNETCORE_TOKEN`
    
    這個環境變數只會用在與 IIS 整合的時候，IIS 在啟動 Kestrel 的時候，會偷偷傳入這個環境變數，用來指定 IIS 與 Kestrel 之間的 Token。
    
    > 注意: 你幾乎不會自行設定這個環境變數！
    
-   `ASPNETCORE_IIS_HTTPAUTH`
    
    這個環境變數只會用在與 IIS 整合的時候，IIS 在啟動 Kestrel 的時候，會偷偷傳入這個環境變數，用來指定 Kestrel 該如何處理 AUTH 要求。
    
    > 注意: 你幾乎不會自行設定這個環境變數！
    
-   `ASPNETCORE_IIS_WEBSOCKETS_SUPPORTED`
    
    這個環境變數只會用在與 IIS 整合的時候，IIS 在啟動 Kestrel 的時候，會偷偷傳入這個環境變數，用來告訴 Kestrel 這台 IIS 是否支援 WebSockets 協定。
    
    > 注意: 你幾乎不會自行設定這個環境變數！
    
-   `ASPNETCORE_MODULE_DEBUG`
    
    當你在 Visual Studio 使用 IIS Express 開發時，這個環境變數可以讓你將 ASP.NET Core Module 的偵錯資訊輸出到 Console 畫面上。
    
    ```ini
    ASPNETCORE_MODULE_DEBUG=console
    ```
    

### 已經不再使用的環境變數

-   `ASPNETCORE_SERVER.URLS`
    
    這個環境變數已經被 `ASPNETCORE_URLS` 取代。
    
-   `ASPNET_ENV`
    
    這個環境變數已經被 `ASPNETCORE_ENVIRONMENT` 取代。
    
-   `Hosting:Environment`
    
    這個環境變數已經被 `ASPNETCORE_ENVIRONMENT` 取代。
    
-   `ASPNETCORE_MANAGEMENTPORT`
    
    在 ASP.NET Core 5.0 以前，有個 `ASPNETCORE_MANAGEMENTPORT` 環境變數，用來指定健康檢測端點的 Port 埠號要用哪一個，讓正式對外的 Port 與健康檢測的 Port 分開，增強安全性。不過從 ASP.NET Core 6.0 開始，就不太需要這個設定了，直接寫死在程式中就好，如下範例：
    
    ```csharp
    app.MapHealthChecks("/healthz").RequireHost("*:5001");
    ```
    
    > 想瞭解 ASP.NET Core 5.0 的設定方式，參見 [Health checks in ASP.NET Core | Microsoft Docs](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-5.0&WT.mc_id=DT-MVP-4015686#filter-by-port)
    

### 其他可能會用到的環境變數

-   強迫在 Console 顯示最完整的 Log 訊息
    
    ```ini
    ASPNETCORE_Logging__Console__LogLevel__Default=Trace
    ```
    

### 如果不想載入 ASPNETCORE\_ 環境變數

以下範例程式我從 [dotnet/aspnetcore](https://github.com/dotnet/aspnetcore/) Repo 的 [`src\Hosting\Hosting\test\GenericWebHostBuilderTests.cs`](https://github.com/dotnet/aspnetcore/blob/8c5a59ac18d0d2d1ced5e247f5d0880650ef1ad8/src/Hosting/Hosting/test/GenericWebHostBuilderTests.cs#L29-L40) 測試程式中擷取出來的，只要將 `webHostBulderOptions.SuppressEnvironmentConfiguration` 設定為 `true` 即可。

```csharp
[Fact]
public void CanSuppressAspNetCoreEnvironmentVariables()
{
    var randomEnvKey = Guid.NewGuid().ToString();
    Environment.SetEnvironmentVariable("ASPNETCORE_" + randomEnvKey, "true");

    using var host = new HostBuilder()
        .ConfigureWebHost(_ => { }, webHostBulderOptions =>
        {
            webHostBulderOptions.SuppressEnvironmentConfiguration = true;
        })
        .Build();

    var config = host.Services.GetRequiredService<IConfiguration>();

    Assert.Null(config[randomEnvKey]);

    Environment.SetEnvironmentVariable("ASPNETCORE_" + randomEnvKey, null);
}
```

### 2024-05-05: 補充說明 .NET CLI 的使用技巧

本篇文章介紹的雖然都是 ASP.NET Core 的環境變數，但其實在透過 .NET CLI 執行 ASP.NET Core 應用程式的時候，其實也可以透過命令列的方式直接取代這些環境變數，而且載入的優先權比環境變數高。以下是幾個常見的例子 (以 `dotnet run` 為例)：

-   啟動網站時指定環境名稱
    
    ```bash
    dotnet MyApp.dll --environment=Production
    ```
    
-   啟動網站時指定網站的網址與埠號
    
    ```bash
    dotnet MyApp.dll --urls="https://localhost:5001;http://localhost:5000"
    ```
    
-   啟動網站時顯示所有的記錄訊息
    
    ```bash
    dotnet MyApp.dll --Logging:Console:LogLevel:Default=Trace
    ```
    
-   啟動網站時載入 Kestrel 所需的 TLS 憑證
    
    ```bash
    dotnet MyApp.dll --Kestrel:Certificates:Default:Path='localhost.p12' --Kestrel:Certificates:Default:Password='changeit' --urls='https://*:5001'
    ```
    
-   啟動網站時變更 ContentRoot 路徑
    
    這個需求在 [Host ASP.NET Core in a Windows Service](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?tabs=visual-studio&WT.mc_id=DT-MVP-4015686) 的時候常見。
    
    ```powershell
    dotnet MyApp.dll --contentRoot=g:\publish
    ```
    
-   啟動網站時變更預設的 HTTPS 轉向埠號
    
    當你的 Kestrel 監聽多個 HTTPS Port 時，或是網站位於 Reverse Proxy 後面時，就有可能需要設定這個參數。
    
    ```powershell
    dotnet MyApp.dll --urls='https://*:5001;http://*:5000;https://*:5003' --https_port=5003
    ```
    

### 相關連結

-   [ASP.NET Core Web Host | Microsoft Docs](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host)
    -   [Override configuration](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host#override-configuration)
-   [.NET Generic Host in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host)
-   [Forwarded Headers Middleware Updates in .NET Core 3.0 preview 6](https://devblogs.microsoft.com/dotnet/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6/?WT.mc_id=DT-MVP-4015686)
