皆さんこんにちは。
我が家では2025年春からProxmox VEの仮想環境を使っています。
ASUS NUC 14 Proを採用し、この小ささにメモリ64GB、ストレージ3TBと強力なスペックになっています。
仮想サーバやLinuxコンテナを立て放題なので、便利に活用しています。
さてProxmox VEを使い始めた方が最初にはまるのは、管理画面にアクセスすると証明書エラーが出る という件ではないでしょうか。
これはProxmox VE内で自己署名のルートCA証明書(/etc/pve/pve-root-ca.pem)を用いて管理画面のサーバ証明書を発行しているためで、ブラウザから見ると「知らないCAが発行した証明書」に見えるのが原因です。エラーを消すには、商用(公的CA)の証明書に取り替えるか、このルートCA証明書を各デバイスにインポートして信頼させる必要があります。
私も、自分が使う各デバイスにこのルートCA証明書をインストールしました。さて、せっかくルートCAを信頼させたのなら、理屈上は このCAで署名した自己発行の証明書も同じように「信頼された証明書」として使えるはず です。仮想サーバごとにこのCAで証明書を発行してやれば、管理画面だけでなく、自宅環境の各サービスもブラウザの証明書エラーなしでHTTPSアクセスできるようになります。
この記事では、Proxmoxの内部CAを使って 仮想サーバ用の証明書をFQDN入力だけで自動発行するスクリプト を作ったので、その手順を解説します。
概要
Proxmoxに標準で用意されている内部CA( /etc/pve/pve-root-ca.pem と秘密鍵 /etc/pve/priv/pve-root-ca.key )を使って、仮想サーバ用のサーバ証明書を発行したい。手動で行う場合は毎回 opensslコマンドを4回叩き、CSRの入力項目を対話で答えるのが面倒となるので、FQDNだけ入力すれば秘密鍵・CSR・証明書まで一気に作る ようにしました。
手動の手順
手動で行う場合の手順はこんな感じで、定期的に行うのはそれなりに面倒です。
- 秘密鍵の作成
openssl genrsa -out server.key 2048 - CSRの作成
openssl req -new -key server.key -out server.csr(Country/State/Org…を対話入力) - SAN定義ファイルの作成
subjectAltName = DNS:... - Proxmox CAで署名
openssl x509 -req -CA pve-root-ca.pem -CAkey pve-root-ca.key ...
スクリプト
上記の手順を自動化するシェルスクリプトです。
#!/usr/bin/env bash
#
# issue-vm-cert.sh
# Proxmox の CA(/etc/pve/pve-root-ca.pem, /etc/pve/priv/pve-root-ca.key)を使って
# 仮想サーバ用の証明書を発行する。
# ユーザが入力する FQDN だけを変数にし、秘密鍵・CSR・証明書を自動生成する。
#
# 実行例:
# sudo ./issue-vm-cert.sh
# sudo ./issue-vm-cert.sh your-vm.example.com
# sudo ./issue-vm-cert.sh your-vm.example.com --days 825
#
# ※ CA秘密鍵を読むため root 権限(sudo)が必要です。
#
set -euo pipefail
# ---- 固定設定(手順書のCSR入力項目に対応) ---------------------------------
COUNTRY="JP"
STATE="Tokyo"
LOCALITY="Chiyoda-ku"
ORG="Example Inc."
ORG_UNIT="" # 手順書では空欄
EMAIL="" # 手順書では空欄
# CA のパス(Proxmox 既定)
CA_CERT="/etc/pve/pve-root-ca.pem"
CA_KEY="/etc/pve/priv/pve-root-ca.key"
# 証明書の有効日数
# ブラウザの上限に注意: Chrome は 398 日超、Apple(macOS/iOS/Safari) は 825 日超の
# サーバ証明書を信頼しない(ERR_CERT_VALIDITY_TOO_LONG 等)。
# どのブラウザでも通る安全値として 398 日を既定にする。
# (手順書は 3650 日だが、それだと証明書エラーになるため変更)
DAYS=398
# 出力先ディレクトリ(既定はカレント)
OUTDIR="."
# ---- 引数パース -----------------------------------------------------------
FQDN=""
while [[ $# -gt 0 ]]; do
case "$1" in
--days) DAYS="$2"; shift 2 ;;
--outdir) OUTDIR="$2"; shift 2 ;;
-h|--help)
grep -E '^#( |$)' "$0" | sed 's/^# \{0,1\}//'
exit 0 ;;
-*)
echo "不明なオプション: $1" >&2; exit 1 ;;
*)
FQDN="$1"; shift ;;
esac
done
# ---- FQDN の取得(未指定なら対話入力) ------------------------------------
if [[ -z "$FQDN" ]]; then
read -rp "仮想サーバの FQDN を入力してください (例: your-vm.example.com): " FQDN
fi
# 前後空白除去
FQDN="$(echo "$FQDN" | tr -d '[:space:]')"
if [[ -z "$FQDN" ]]; then
echo "エラー: FQDN が空です。" >&2
exit 1
fi
# 簡易バリデーション(英数字・ハイフン・ドットのみ許可)
if ! [[ "$FQDN" =~ ^[A-Za-z0-9.-]+$ ]]; then
echo "エラー: FQDN に使用できない文字が含まれています: $FQDN" >&2
exit 1
fi
# ---- 事前チェック ---------------------------------------------------------
for f in "$CA_CERT" "$CA_KEY"; do
if [[ ! -r "$f" ]]; then
echo "エラー: CA ファイルを読めません: $f" >&2
echo " root 権限(sudo)で実行しているか、Proxmox ホスト上で実行しているか確認してください。" >&2
exit 1
fi
done
mkdir -p "$OUTDIR"
# 出力ファイル名は FQDN ベースにして複数VMでも衝突しないようにする
KEY="$OUTDIR/$FQDN.key"
CSR="$OUTDIR/$FQDN.csr"
CRT="$OUTDIR/$FQDN.crt"
EXT="$OUTDIR/$FQDN.ext.cnf"
# 既存ファイルがあれば確認
for f in "$KEY" "$CSR" "$CRT"; do
if [[ -e "$f" ]]; then
read -rp "既存ファイル $f を上書きしますか? [y/N]: " ans
[[ "$ans" =~ ^[Yy]$ ]] || { echo "中止しました。"; exit 1; }
fi
done
echo "=========================================="
echo " FQDN : $FQDN"
echo " 出力先 : $OUTDIR"
echo " CA cert : $CA_CERT"
echo " 有効日数 : $DAYS"
echo "=========================================="
# ---- ① 秘密鍵の作成 -------------------------------------------------------
echo "[1/4] 秘密鍵を作成: $KEY"
openssl genrsa -out "$KEY" 2048
chmod 600 "$KEY"
# ---- ② CSR の作成(-subj で入力項目を非対話で指定、CN=FQDN) --------------
echo "[2/4] CSR を作成: $CSR"
SUBJ="/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORG"
[[ -n "$ORG_UNIT" ]] && SUBJ="$SUBJ/OU=$ORG_UNIT"
SUBJ="$SUBJ/CN=$FQDN"
[[ -n "$EMAIL" ]] && SUBJ="$SUBJ/emailAddress=$EMAIL"
openssl req -new -key "$KEY" -out "$CSR" -subj "$SUBJ"
# ---- ③ SAN 定義ファイルの作成(DNS=FQDN) ---------------------------------
echo "[3/4] SAN 定義ファイルを作成: $EXT"
cat > "$EXT" <
使い方はこんな感じです。
chmod +x issue-vm-cert.sh sudo ./issue-vm-cert.sh
FQDNを聞かれますので、証明書を作成したいFQDNを入れてください。
カレントディレクトリに 秘密鍵(.key)、証明書署名要求(.csr)、証明書(.crt)が出力されます。
これらを利用したいサーバに転送して活用してください
Topics サーバ証明書の期限について
最近、サーバ証明書の期限はどんどん短くなる傾向にあります。
今年、CA/Browser Forumがサーバ証明書の有効期間を段階的に短縮する決議をしておりますが、段階的に証明書の期限が短くなっており、2029年3月以降は47日以下の証明書しか利用できない(それ以上はエラーになる)予定です。
但し あくまで現時点においては、上記手順で発行した自己サーバ証明書は制約の影響を受けないようです。
- 47日ルールはCA/Browser Forumのパブリックルートプログラム向け規則で、ブラウザ/OSのルートストアに載る公的CA(DigiCert、Let’s Encrypt等)が対象
- Proxmoxの内部CAはどのルートストアにも載っていないプライベートCAなので規制対象外
- 期間上限を強制するブラウザ検証も公的チェーンにのみ適用され、端末に手動インストールした内部CAには効かない
上記のスクリプトも活用いただければと思います。


コメント