Proxmox上のUbuntuにローカルCAを構築してNginxでHTTPS通信するまでの手順まとめ


## 1. はじめに

Proxmox上に立てたUbuntuサーバ上で、自前の認証局（CA）を構築し、HTTPSサーバ（Nginx）を立ち上げる手順をまとめました。社内開発やローカル環境で自己署名CAを使いたい方向けです。

---

## 2. 環境構成

| 役割      | ホスト名          | IPアドレス           | OS           |
| ------- | ------------- | ---------------- | ------------ |
| 認証局（CA） | `ca01`        | `192.168.10.100`   | Ubuntu 20.04 |
| Webサーバ  | `test-nodejs` | `192.168.10.233` | Ubuntu 20.04 |

---

## 3. OpenSSLでローカル認証局（CA）を構築

### 3.1 必要なディレクトリ作成

```bash
mkdir -p ~/myCA/{certs,crl,newcerts,private,server}
chmod 700 ~/myCA/private
touch ~/myCA/index.txt
echo 1000 > ~/myCA/serial
```

### 3.2 CA秘密鍵と自己署名証明書を作成

```bash
cd ~/myCA
openssl genrsa -aes256 -out private/cakey.pem 4096
openssl req -x509 -new -key private/cakey.pem -days 3650 -sha256 -out certs/ca.cert.pem
```

※ パスフレーズを求められます。

---

## 4. サーバ用証明書の発行（SAN対応）

### 4.1 サーバで秘密鍵とSAN付きCSRを作成

```bash
mkdir ~/ssl && cd ~/ssl
openssl genrsa -out server.key.pem 2048
```

`san.cnf` を作成：

```ini
[ req ]
default_bits        = 2048
distinguished_name  = req_distinguished_name
req_extensions      = req_ext
prompt              = no

[ req_distinguished_name ]
CN = 192.168.10.233

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
IP.1 = 192.168.10.233
DNS.1 = test-nodejs.nvrin
```

```bash
openssl req -new -key server.key.pem -out server.csr.pem -config san.cnf
```

### 4.2 CSRをCAに転送して署名

```bash
scp server.csr.pem root@ca01:/root/myCA/server/
```

CA側で署名：

```bash
# openssl.cnfの[ server_cert ]セクションに以下を追加（SANをコピーする）
# subjectAltName = copy

openssl ca -config openssl.cnf \
  -extensions server_cert \
  -days 825 \
  -notext \
  -md sha256 \
  -in server/server.csr.pem \
  -out server/server.cert.pem
```

---

## 5. NginxにHTTPSを設定する

### 5.1 証明書・鍵ファイルを配置

```bash
sudo mkdir -p /etc/nginx/ssl
sudo cp ~/ssl/server.cert.pem /etc/nginx/ssl/
sudo cp ~/ssl/server.key.pem /etc/nginx/ssl/
sudo cp ~/ssl/ca.cert.pem /etc/nginx/ssl/
sudo chmod 644 /etc/nginx/ssl/*.pem
```

### 5.2 サーバブロックを作成（HTTPSのみ）

```bash
sudo nano /etc/nginx/sites-available/my-ssl-site
```

以下の内容を記述：

```nginx
server {
    listen 443 ssl;
    server_name 192.168.10.233;

    ssl_certificate     /etc/nginx/ssl/server.cert.pem;
    ssl_certificate_key /etc/nginx/ssl/server.key.pem;
    ssl_trusted_certificate /etc/nginx/ssl/ca.cert.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    location / {
        root /var/www/html;
        index index.html;
    }
}
```

シンボリックリンクを張って有効化：

```bash
sudo ln -s /etc/nginx/sites-available/my-ssl-site /etc/nginx/sites-enabled/
```

### 5.3 設定テストとリロード

```bash
sudo nginx -t
sudo systemctl reload nginx
```

---

## 6. 動作確認とトラブル対応

### 6.1 curlで接続テスト

```bash
curl -v https://192.168.10.233 --cacert /etc/nginx/ssl/ca.cert.pem
```

成功すれば、TLS 1.3で接続されて証明書情報も確認できます。

### 6.2 `subjectAltName` エラー対策

もし以下のようなエラーが出る場合：

```
curl: (60) SSL: no alternative certificate subject name matches target host name
```

これは証明書に `subjectAltName (SAN)` が正しく含まれていないためです。

#### 対処法：

- `CN = 192.168.10.233` に加えて、`subjectAltName = IP:192.168.10.233` を含むCSRを再作成する（前章参照）
- Nginx用の証明書署名時に、OpenSSL設定で `subjectAltName = copy` を有効にしておく

また、ローカル環境であれば `/etc/hosts` に次のように追加し、FQDNでアクセスするのも有効です：

```
192.168.10.233 test-nodejs.local
```

そして：

```bash
curl -v https://test-nodejs.local --cacert ca.cert.pem
```

---

## 7. おわりに

ローカル開発環境でも、正式なCAと同じ仕組みでHTTPS通信を実現できると、\
セキュリティ強化や本番環境の疑似体験がしやすくなります。

また、自己署名CAは、以下のような応用にも使えます：

- クライアント証明書によるアクセス制限（双方向SSL）
- 社内サービスの簡易PKI運用
- IoTやオンプレ環境の証明書管理

引き続き、証明書の失効処理やクライアント証明書の発行なども試してみてください！

---

## 📌 参考
- [curl SSL証明書のエラー解説](https://curl.se/docs/sslcerts.html)