dotnet-devcert-trust

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

.NET Dev Certificate Trust on Linux

Linux上的.NET开发证书信任配置

When to Use This Skill

何时使用本指南

Use this skill when:
  • Redis TLS connections fail with
    UntrustedRoot
    or
    RemoteCertificateNameMismatch
    in Aspire
  • dotnet dev-certs https --check --trust
    returns exit code 7
  • HTTPS localhost connections fail with certificate validation errors
  • After running
    dotnet dev-certs https --clean
    and needing to restore trust
  • Setting up a new Linux dev machine for .NET HTTPS development
  • Aspire dashboard or inter-service gRPC calls fail with TLS errors
  • Upgrading from Aspire < 13.1.0 (which didn't use TLS on Redis by default)
在以下场景中使用本指南:
  • Aspire中Redis TLS连接因
    UntrustedRoot
    RemoteCertificateNameMismatch
    错误失败
  • dotnet dev-certs https --check --trust
    返回退出码7
  • HTTPS本地连接因证书验证错误失败
  • 运行
    dotnet dev-certs https --clean
    后需要恢复证书信任
  • 为.NET HTTPS开发搭建新的Linux开发机器
  • Aspire仪表板或服务间gRPC调用因TLS错误失败
  • 从Aspire < 13.1.0版本升级(该版本默认不对Redis启用TLS)

The Problem

问题说明

On Windows and macOS,
dotnet dev-certs https --trust
handles everything automatically — it generates the certificate, installs it in the user store, and adds it to the system trust store. On Linux, it does almost nothing useful. The command generates the cert and places it in the user store, but:
  1. It does not export the certificate to the system CA directory
  2. It does not run
    update-ca-certificates
    to rebuild the CA bundle
  3. It does not add the cert to browser trust stores (NSS/NSSDB)
  4. The
    --trust
    flag silently succeeds but the cert remains untrusted
This means .NET applications, OpenSSL, curl, and browsers all reject the dev certificate — even though
dotnet dev-certs https --check
reports it exists.
在Windows和macOS系统上,
dotnet dev-certs https --trust
会自动处理所有操作——生成证书、安装到用户存储并添加到系统信任存储。但在Linux上,该命令几乎没有实际作用。它只会生成证书并存放到用户存储,但:
  1. 不会将证书导出到系统CA目录
  2. 不会运行
    update-ca-certificates
    来重建CA证书包
  3. 不会将证书添加到浏览器信任存储(NSS/NSSDB)
  4. --trust
    标记会静默执行成功,但证书仍处于未信任状态
这意味着.NET应用、OpenSSL、curl和浏览器都会拒绝该开发证书——即使
dotnet dev-certs https --check
报告证书已存在。

Why This Surfaces with Aspire 13.1.0+

为何Aspire 13.1.0+版本会出现此问题

Prior to Aspire 13.1.0, Redis connections used plaintext. Starting with 13.1.0, Aspire enables TLS on Redis by default. If your dev cert isn't trusted at the system level, Redis connections fail immediately with:
System.Security.Authentication.AuthenticationException:
  The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot
在Aspire 13.1.0之前,Redis连接使用明文传输。从13.1.0版本开始,Aspire默认对Redis启用TLS。如果你的开发证书未在系统级别被信任,Redis连接会立即失败,报错如下:
System.Security.Authentication.AuthenticationException:
  The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot

How Linux Certificate Trust Works

Linux证书信任机制

Understanding the architecture prevents cargo-cult debugging:
┌─────────────────────────────────────────────────────┐
│ Application (.NET, curl, OpenSSL)                   │
│   reads: /etc/ssl/certs/ca-certificates.crt         │
│          (consolidated CA bundle)                    │
└──────────────────────┬──────────────────────────────┘
                       │ built by
┌──────────────────────▼──────────────────────────────┐
│ update-ca-certificates                              │
│   reads from:                                        │
│     /usr/share/ca-certificates/      (distro CAs)   │
│     /usr/local/share/ca-certificates/ (local CAs)   │
│   writes to:                                         │
│     /etc/ssl/certs/ca-certificates.crt (bundle)     │
│     /etc/ssl/certs/*.pem (individual symlinks)      │
└─────────────────────────────────────────────────────┘
Key insight: Placing a
.crt
file in
/usr/local/share/ca-certificates/
is necessary but not sufficient. The consolidated bundle at
/etc/ssl/certs/ca-certificates.crt
must be rebuilt by running
update-ca-certificates
. Applications read the bundle, not the individual files.
理解其架构可避免盲目调试:
┌─────────────────────────────────────────────────────┐
│ 应用程序(.NET、curl、OpenSSL)                     │
│   读取:/etc/ssl/certs/ca-certificates.crt         │
│          (合并后的CA证书包)                        │
└──────────────────────┬──────────────────────────────┘
                       │ 由以下工具构建
┌──────────────────────▼──────────────────────────────┐
│ update-ca-certificates                              │
│   读取自:                                        │
│     /usr/share/ca-certificates/      (发行版CA证书)   │
│     /usr/local/share/ca-certificates/ (本地CA证书)   │
│   写入到:                                         │
│     /etc/ssl/certs/ca-certificates.crt (证书包)     │
│     /etc/ssl/certs/*.pem (单个证书符号链接)      │
└─────────────────────────────────────────────────────┘
核心要点:
.crt
文件放到
/usr/local/share/ca-certificates/
目录是必要的,但并不足够。必须运行
update-ca-certificates
来重建
/etc/ssl/certs/ca-certificates.crt
这个合并后的证书包。应用程序读取的是这个证书包,而非单个证书文件。

5-Point Diagnostic Procedure

五步诊断流程

Run these checks in order. Stop at the first FAIL and apply its fix before continuing.
按顺序执行以下检查。在第一个失败的检查步骤停止,应用对应的修复方案后再继续。

Check 1: Dev Cert Existence

检查1:开发证书是否存在

bash
dotnet dev-certs https --check
echo "Exit code: $?"
Exit CodeMeaningAction
0Cert exists in user storePASS — continue
Non-zeroNo valid dev certRun
dotnet dev-certs https
bash
dotnet dev-certs https --check
echo "Exit code: $?"
退出码含义操作
0证书存在于用户存储通过 — 继续
非零值无有效开发证书运行
dotnet dev-certs https

Check 2: System Trust Store — Single Cert, Correct Permissions

检查2:系统信任存储——单个证书,权限正确

bash
ls -la /usr/local/share/ca-certificates/ | grep -iE 'dotnet|aspnet'
ResultMeaning
Only
dotnet-dev-cert.crt
with
-rw-r--r--
(644)
PASS
Multiple cert files, wrong permissions, or stale
aspnet*
files
FAIL
Common stale files from previous sessions:
FileProblem
aspnetcore-dev.crt
Often created with
0600
permissions (unreadable by
update-ca-certificates
)
aspnet/https.crt
Old convention, may have a different fingerprint than current dev cert
dotnet-dev-cert.crt
with
0600
Correct name but wrong permissions
Fix:
bash
undefined
bash
ls -la /usr/local/share/ca-certificates/ | grep -iE 'dotnet|aspnet'
结果含义
仅存在
dotnet-dev-cert.crt
且权限为
-rw-r--r--
(644)
通过
存在多个证书文件、权限错误或过期的
aspnet*
文件
失败
常见的过期文件来源:
文件问题
aspnetcore-dev.crt
通常以
0600
权限创建(
update-ca-certificates
无法读取)
aspnet/https.crt
旧命名规范,其指纹可能与当前开发证书不匹配
权限为
0600
dotnet-dev-cert.crt
名称正确但权限错误
修复方案:
bash
undefined

Remove ALL stale cert files

删除所有过期证书文件

sudo rm -f /usr/local/share/ca-certificates/aspnetcore-dev.crt sudo rm -rf /usr/local/share/ca-certificates/aspnet/
sudo rm -f /usr/local/share/ca-certificates/aspnetcore-dev.crt sudo rm -rf /usr/local/share/ca-certificates/aspnet/

Ensure correct permissions on the dev cert (if it exists)

确保开发证书权限正确(如果已存在)

sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
undefined
sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
undefined

Check 3: CA Bundle Inclusion

检查3:CA证书包是否包含该证书

This is the most commonly failed check. The cert file exists but was never added to the bundle.
bash
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \
  /usr/local/share/ca-certificates/dotnet-dev-cert.crt
ResultMeaning
dotnet-dev-cert.crt: OK
PASS — cert is in the consolidated bundle
error 20 at 0 depth lookup: unable to get local issuer certificate
FAIL — bundle was never rebuilt
error 2 at 0 depth lookup: unable to get issuer certificate
FAIL — same issue, different OpenSSL version
Fix:
bash
sudo update-ca-certificates
这是最常失败的检查项。证书文件存在但从未被加入到证书包中。
bash
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \\
  /usr/local/share/ca-certificates/dotnet-dev-cert.crt
结果含义
dotnet-dev-cert.crt: OK
通过 — 证书已在合并后的证书包中
error 20 at 0 depth lookup: unable to get local issuer certificate
失败 — 证书包从未被重建
error 2 at 0 depth lookup: unable to get issuer certificate
失败 — 问题相同,仅OpenSSL版本不同
修复方案:
bash
sudo update-ca-certificates

Expected output includes "1 added" or similar

预期输出包含"1 added"或类似内容

Re-verify

重新验证

openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt
/usr/local/share/ca-certificates/dotnet-dev-cert.crt
undefined
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \ /usr/local/share/ca-certificates/dotnet-dev-cert.crt
undefined

Check 4: Environment Variable Overrides

检查4:环境变量覆盖

SSL environment variables can redirect certificate lookups away from the system bundle:
bash
echo "SSL_CERT_DIR=${SSL_CERT_DIR:-<unset>}"
echo "SSL_CERT_FILE=${SSL_CERT_FILE:-<unset>}"
echo "DOTNET_SSL_CERT_DIR=${DOTNET_SSL_CERT_DIR:-<unset>}"
echo "DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=${DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER:-<unset>}"
ResultMeaning
All
<unset>
PASS
Any variable setFAIL — may redirect cert lookups
Fix: Remove the offending variables from your shell profile (
~/.bashrc
,
~/.zshrc
,
~/.profile
) and start a new shell.
SSL环境变量可能会将证书查找路径从系统证书包重定向到其他位置:
bash
echo "SSL_CERT_DIR=${SSL_CERT_DIR:-<unset>}"
echo "SSL_CERT_FILE=${SSL_CERT_FILE:-<unset>}"
echo "DOTNET_SSL_CERT_DIR=${DOTNET_SSL_CERT_DIR:-<unset>}"
echo "DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=${DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER:-<unset>}"
结果含义
全部为
<unset>
通过
存在已设置的变量失败 — 可能会重定向证书查找路径
修复方案: 从你的Shell配置文件(
~/.bashrc
~/.zshrc
~/.profile
)中移除相关变量,然后重启Shell。

Check 5: Symlink Integrity

检查5:符号链接完整性

Stale symlinks from previously removed certificates can confuse OpenSSL:
bash
find /etc/ssl/certs/ -xtype l 2>/dev/null | head -5
ResultMeaning
No outputPASS
Broken symlinks listedFAIL
Fix:
bash
sudo update-ca-certificates --fresh
已删除证书对应的过期符号链接可能会导致OpenSSL混乱:
bash
find /etc/ssl/certs/ -xtype l 2>/dev/null | head -5
结果含义
无输出通过
列出了损坏的符号链接失败
修复方案:
bash
sudo update-ca-certificates --fresh

Rebuilds ALL symlinks from scratch

从头开始重建所有符号链接

undefined
undefined

Full Recovery Procedure

完整恢复流程

When multiple checks fail or you want a clean slate, run this complete sequence:
bash
#!/usr/bin/env bash
set -euo pipefail

echo "=== .NET Dev Certificate Trust Recovery ==="
当多个检查项失败或你需要彻底清理时,执行以下完整步骤:
bash
#!/usr/bin/env bash
set -euo pipefail

echo "=== .NET开发证书信任恢复 ==="

Step 1: Remove ALL stale certificate files

步骤1:删除所有过期证书文件

echo "--- Removing stale certificate files ---" sudo rm -f /usr/local/share/ca-certificates/aspnetcore-dev.crt sudo rm -rf /usr/local/share/ca-certificates/aspnet/ sudo rm -f /usr/local/share/ca-certificates/dotnet-dev-cert.crt
echo "--- 删除过期证书文件 ---" sudo rm -f /usr/local/share/ca-certificates/aspnetcore-dev.crt sudo rm -rf /usr/local/share/ca-certificates/aspnet/ sudo rm -f /usr/local/share/ca-certificates/dotnet-dev-cert.crt

Step 2: Clean and regenerate dev cert

步骤2:清理并重新生成开发证书

echo "--- Regenerating dev certificate ---" dotnet dev-certs https --clean dotnet dev-certs https
echo "--- 重新生成开发证书 ---" dotnet dev-certs https --clean dotnet dev-certs https

Step 3: Export as PEM and install to system trust store

步骤3:导出为PEM格式并安装到系统信任存储

echo "--- Installing to system trust store ---" dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt rm /tmp/dotnet-dev-cert.crt
echo "--- 安装到系统信任存储 ---" dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt rm /tmp/dotnet-dev-cert.crt

Step 4: Rebuild CA bundle (CRITICAL — most commonly missed step)

步骤4:重建CA证书包(关键步骤——最常被忽略)

echo "--- Rebuilding CA bundle ---" sudo update-ca-certificates
echo "--- 重建CA证书包 ---" sudo update-ca-certificates

Step 5: Verify

步骤5:验证

echo "--- Verifying ---" openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt
/usr/local/share/ca-certificates/dotnet-dev-cert.crt
echo "=== Done! Restart your .NET application. ==="

Save this as `~/fix-devcert.sh` and run with `bash ~/fix-devcert.sh` when needed.
echo "--- 验证 ---" openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \ /usr/local/share/ca-certificates/dotnet-dev-cert.crt
echo "=== 完成!请重启你的.NET应用程序。 ==="

将此脚本保存为`~/fix-devcert.sh`,需要时运行`bash ~/fix-devcert.sh`。

Distro-Specific Notes

发行版专属说明

Ubuntu / Debian

Ubuntu / Debian

The procedure above is written for Ubuntu/Debian and works as-is.
  • CA directory:
    /usr/local/share/ca-certificates/
  • Bundle command:
    sudo update-ca-certificates
  • Bundle output:
    /etc/ssl/certs/ca-certificates.crt
  • Cert format: PEM with
    .crt
    extension required
上述流程是为Ubuntu/Debian编写的,可直接使用。
  • CA目录:
    /usr/local/share/ca-certificates/
  • 重建证书包命令:
    sudo update-ca-certificates
  • 证书包输出路径:
    /etc/ssl/certs/ca-certificates.crt
  • 证书格式: 必须为PEM格式且扩展名为
    .crt

Fedora / RHEL / CentOS

Fedora / RHEL / CentOS

Fedora uses
update-ca-trust
instead of
update-ca-certificates
:
bash
undefined
Fedora使用
update-ca-trust
而非
update-ca-certificates
bash
undefined

Export cert

导出证书

dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.pem --format PEM --no-password
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.pem --format PEM --no-password

Install to Fedora trust store (different directory!)

安装到Fedora信任存储(目录不同!)

sudo cp /tmp/dotnet-dev-cert.pem /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem sudo chmod 644 /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem rm /tmp/dotnet-dev-cert.pem
sudo cp /tmp/dotnet-dev-cert.pem /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem sudo chmod 644 /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem rm /tmp/dotnet-dev-cert.pem

Rebuild trust bundle

重建信任证书包

sudo update-ca-trust
sudo update-ca-trust

Verify

验证

openssl verify /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem

**Key differences:**
| | Ubuntu/Debian | Fedora/RHEL |
|--|---------------|-------------|
| CA directory | `/usr/local/share/ca-certificates/` | `/etc/pki/ca-trust/source/anchors/` |
| Rebuild command | `update-ca-certificates` | `update-ca-trust` |
| Bundle path | `/etc/ssl/certs/ca-certificates.crt` | `/etc/pki/tls/certs/ca-bundle.crt` |
| Extension | `.crt` | `.pem` (any extension works) |
openssl verify /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem

**主要区别:**
| | Ubuntu/Debian | Fedora/RHEL |
|--|---------------|-------------|
| CA目录 | `/usr/local/share/ca-certificates/` | `/etc/pki/ca-trust/source/anchors/` |
| 重建命令 | `update-ca-certificates` | `update-ca-trust` |
| 证书包路径 | `/etc/ssl/certs/ca-certificates.crt` | `/etc/pki/tls/certs/ca-bundle.crt` |
| 扩展名 | `.crt` | `.pem`(任何扩展名均可) |

Arch Linux

Arch Linux

Arch uses the same
update-ca-trust
approach as Fedora:
bash
sudo cp /tmp/dotnet-dev-cert.pem /etc/ca-certificates/trust-source/anchors/dotnet-dev-cert.pem
sudo chmod 644 /etc/ca-certificates/trust-source/anchors/dotnet-dev-cert.pem
sudo update-ca-trust
Arch使用与Fedora相同的
update-ca-trust
方式:
bash
sudo cp /tmp/dotnet-dev-cert.pem /etc/ca-certificates/trust-source/anchors/dotnet-dev-cert.pem
sudo chmod 644 /etc/ca-certificates/trust-source/anchors/dotnet-dev-cert.pem
sudo update-ca-trust

WSL2

WSL2

WSL2 runs a real Linux kernel with its own certificate store — separate from the Windows host. The standard Ubuntu/Debian procedure works, but watch for:
  1. Shared filesystem (
    /mnt/c/
    )
    — cert files on the Windows filesystem have Windows permissions that may not be 644. Always copy to a native Linux path first.
  2. systemd not running — some older WSL2 setups don't have systemd, which
    update-ca-certificates
    hooks may depend on. If the command hangs, try
    sudo dpkg-reconfigure ca-certificates
    instead.
  3. Docker Desktop integration — If using Docker Desktop's WSL2 backend, containers inherit the WSL2 distro's CA bundle. Fixing trust in WSL2 fixes it for containers too.
WSL2运行真实的Linux内核,拥有独立于Windows主机的证书存储。标准的Ubuntu/Debian流程适用,但需注意以下几点:
  1. 共享文件系统(
    /mnt/c/
    — Windows文件系统上的证书文件权限可能不是644。请先复制到Linux原生路径。
  2. 未运行systemd — 部分旧版WSL2未启用systemd,而
    update-ca-certificates
    的某些钩子依赖它。如果命令挂起,尝试使用
    sudo dpkg-reconfigure ca-certificates
    替代。
  3. Docker Desktop集成 — 如果使用Docker Desktop的WSL2后端,容器会继承WSL2发行版的CA证书包。修复WSL2中的信任问题即可同步解决容器中的问题。

Aspire-Specific Considerations

Aspire专属注意事项

Redis TLS (Aspire 13.1.0+)

Redis TLS(Aspire 13.1.0+)

Aspire 13.1.0 enables TLS on Redis by default. If you see:
UntrustedRoot
in Redis connection errors, the dev cert isn't trusted at the system level. Run the full recovery procedure above.
Aspire 13.1.0默认对Redis启用TLS。如果你在Redis连接错误中看到:
UntrustedRoot
说明开发证书未在系统级别被信任。执行上述完整恢复流程即可解决。

Aspire Dashboard HTTPS

Aspire仪表板HTTPS

The Aspire dashboard uses the dev cert for HTTPS. If the dashboard shows certificate warnings in the browser, the cert isn't in the browser's trust store. For development, clicking through the warning is acceptable — the system-level trust (needed for Redis, gRPC, etc.) is the priority.
Aspire仪表板使用开发证书提供HTTPS服务。如果浏览器中打开仪表板时显示证书警告,说明证书未被浏览器信任存储收录。在开发环境中,点击跳过警告即可——系统级别的信任(Redis、gRPC等所需)才是重点。

ASPIRE_ALLOW_UNSECURED_TRANSPORT

ASPIRE_ALLOW_UNSECURED_TRANSPORT

Setting
ASPIRE_ALLOW_UNSECURED_TRANSPORT=true
is a workaround, not a fix. It disables TLS for inter-service communication, which:
  • Masks the underlying trust issue
  • Doesn't match production behavior
  • May cause different bugs than what you'd see in production
Fix the cert trust instead.
设置
ASPIRE_ALLOW_UNSECURED_TRANSPORT=true
是一种临时 workaround,而非修复方案。它会禁用服务间通信的TLS,这会:
  • 掩盖底层的信任问题
  • 与生产环境行为不符
  • 可能导致与生产环境不同的Bug
建议直接修复证书信任问题。

Certificate Lifecycle

证书生命周期

The dev cert is valid for 1 year from creation. When it expires:
  1. dotnet dev-certs https --check
    will report no valid cert
  2. Run the full recovery procedure to generate a new cert
  3. The old cert file in
    /usr/local/share/ca-certificates/
    will be replaced
  4. update-ca-certificates
    will swap the old cert for the new one in the bundle
No system reboot is required. Applications pick up the new bundle on next TLS handshake (restart your app).
开发证书自创建之日起有效期为1年。过期后:
  1. dotnet dev-certs https --check
    会报告无有效证书
  2. 执行完整恢复流程生成新证书
  3. /usr/local/share/ca-certificates/
    中的旧证书文件会被替换
  4. update-ca-certificates
    会将证书包中的旧证书替换为新证书
无需重启系统。应用程序会在下一次TLS握手时读取新的证书包(请重启你的应用)。

Automation: CI/CD Pipelines

自动化:CI/CD流水线

In CI/CD on Linux runners, dev certs are rarely needed (you typically test against real certificates or disable TLS validation in test harnesses). However, if your integration tests require trusted dev certs:
在Linux运行器的CI/CD环境中,开发证书很少用到(通常会针对真实证书测试或在测试工具中禁用TLS验证)。但如果你的集成测试需要受信任的开发证书:

GitHub Actions

GitHub Actions

yaml
- name: Trust .NET Dev Certificate
  run: |
    dotnet dev-certs https
    dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
    sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    rm /tmp/dotnet-dev-cert.crt
    sudo update-ca-certificates
yaml
- name: 信任.NET开发证书
  run: |
    dotnet dev-certs https
    dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
    sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    rm /tmp/dotnet-dev-cert.crt
    sudo update-ca-certificates

Azure DevOps

Azure DevOps

yaml
- script: |
    dotnet dev-certs https
    dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
    sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    rm /tmp/dotnet-dev-cert.crt
    sudo update-ca-certificates
  displayName: 'Trust .NET Dev Certificate'
yaml
- script: |
    dotnet dev-certs https
    dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
    sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    rm /tmp/dotnet-dev-cert.crt
    sudo update-ca-certificates
  displayName: '信任.NET开发证书'

Common Pitfalls

常见陷阱

1. Cert placed but bundle never rebuilt

1. 证书已放置但证书包从未重建

Symptom: Cert file exists in
/usr/local/share/ca-certificates/
but
openssl verify
fails.
Cause:
update-ca-certificates
was never run after placing the file.
Fix:
sudo update-ca-certificates
This is the single most common mistake. The CA directory is an input to the bundle generation process, not the bundle itself.
症状: 证书文件存在于
/usr/local/share/ca-certificates/
openssl verify
失败。
原因: 放置证书后从未运行
update-ca-certificates
修复方案:
sudo update-ca-certificates
这是最常见的错误。CA目录是证书包生成过程的输入源,而非证书包本身。

2. Stale cert files with wrong permissions

2. 过期证书文件权限错误

Symptom:
update-ca-certificates
runs but reports
0 added
.
Cause: Cert files with
0600
permissions are unreadable by
update-ca-certificates
(which runs as root but reads files through a process that may check world-readability). Files must be
644
.
Fix:
sudo chmod 644 /usr/local/share/ca-certificates/*.crt
症状:
update-ca-certificates
运行但报告
0 added
原因: 权限为
0600
的证书文件无法被
update-ca-certificates
读取(该命令以root身份运行,但读取文件时可能会检查全局可读性)。文件权限必须为
644
修复方案:
sudo chmod 644 /usr/local/share/ca-certificates/*.crt

3. Multiple cert files from different sessions

3. 存在多个不同会话的证书文件

Symptom:
update-ca-certificates
adds multiple certs, but applications still fail.
Cause: Old cert files from previous
dotnet dev-certs https --clean
/ regenerate cycles remain in the CA directory. The old cert's fingerprint doesn't match the current dev cert.
Fix: Remove all
dotnet*
and
aspnet*
files, then re-export the current cert.
症状:
update-ca-certificates
添加了多个证书,但应用程序仍然失败。
原因: 之前
dotnet dev-certs https --clean
/重新生成过程中的旧证书文件仍保留在CA目录中。旧证书的指纹与当前开发证书不匹配。
修复方案: 删除所有
dotnet*
aspnet*
文件,然后重新导出当前证书。

4. Fingerprint mismatch after clean/regenerate

4. 清理/重新生成后指纹不匹配

Symptom:
openssl verify
passes but .NET still reports
UntrustedRoot
.
Cause: The cert in
/usr/local/share/ca-certificates/
was exported from a previous dev cert. After
dotnet dev-certs https --clean && dotnet dev-certs https
, a new cert with a different fingerprint was generated. The system trusts the old cert, not the new one.
Fix: Re-export and reinstall:
bash
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
sudo update-ca-certificates
症状:
openssl verify
通过但.NET仍报告
UntrustedRoot
原因:
/usr/local/share/ca-certificates/
中的证书是从之前的开发证书导出的。执行
dotnet dev-certs https --clean && dotnet dev-certs https
后,生成了一个新的、指纹不同的证书。系统信任的是旧证书,而非新证书。
修复方案: 重新导出并安装:
bash
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
sudo update-ca-certificates

5. Using --trust and assuming it worked

5. 使用--trust并假设操作成功

Symptom:
dotnet dev-certs https --trust
returns exit code 0 but nothing is actually trusted.
Cause: On Linux,
--trust
attempts to add the cert to the OpenSSL trust store but does not call
update-ca-certificates
. The operation "succeeds" from dotnet's perspective but the bundle remains unchanged.
Fix: Don't rely on
--trust
on Linux. Follow the manual procedure in this skill.
症状:
dotnet dev-certs https --trust
返回退出码0但实际上没有任何内容被信任。
原因: 在Linux上,
--trust
尝试将证书添加到OpenSSL信任存储,但不会调用
update-ca-certificates
。从dotnet的角度看操作"成功",但证书包并未改变。
修复方案: 不要依赖Linux上的
--trust
标记,请遵循本指南中的手动流程。

Quick Reference

快速参考

bash
undefined
bash
undefined

Generate dev cert (if missing)

生成开发证书(如果缺失)

dotnet dev-certs https
dotnet dev-certs https

Export as PEM

导出为PEM格式

dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password

Install to system trust (Ubuntu/Debian)

安装到系统信任存储(Ubuntu/Debian)

sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt sudo update-ca-certificates
sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt sudo update-ca-certificates

Verify trust

验证信任状态

openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt
/usr/local/share/ca-certificates/dotnet-dev-cert.crt
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \ /usr/local/share/ca-certificates/dotnet-dev-cert.crt

Check cert details

查看证书详情

openssl x509 -in /usr/local/share/ca-certificates/dotnet-dev-cert.crt -noout -subject -dates -fingerprint
openssl x509 -in /usr/local/share/ca-certificates/dotnet-dev-cert.crt -noout -subject -dates -fingerprint

Nuclear option: full clean + rebuild

终极方案:彻底清理 + 重建

dotnet dev-certs https --clean && dotnet dev-certs https
undefined
dotnet dev-certs https --clean && dotnet dev-certs https
undefined

Related Skills

相关指南

  • dotnet-skills:aspire-configuration
    — Aspire AppHost configuration including TLS settings
  • dotnet-skills:aspire-service-defaults
    — Service defaults including HTTPS configuration
  • dotnet-skills:aspire-configuration
    — Aspire AppHost配置,包括TLS设置
  • dotnet-skills:aspire-service-defaults
    — 服务默认配置,包括HTTPS设置 ",