# Bước 1 — Khởi tạo dịch vụ máy chủ (đã thực hiện)

Môi trường triển khai thử:

| Mục | Giá trị |
|-----|---------|
| Domain | `https://cert.nhovn.com` |
| IP nội bộ | `192.168.99.3` |
| Document root | `/phpsvr/chungthuc` |
| Luồng MVP | Office → PDF → **ký server nội bộ** → bản cuối *(chưa làm USB token)* |

---

## 1. Đã cài đặt

| Thành phần | Đường dẫn / phiên bản | Vai trò |
|------------|----------------------|---------|
| LibreOffice | 24.2.7 (`soffice`) | Convert Office → PDF |
| poppler-utils | `pdfinfo` | Kiểm tra PDF |
| qpdf | 11.9 | Tiện ích PDF |
| Python venv + pyHanko | `/opt/chungthuc-venv` | Ký số PDF (PAdES) |
| CLI helpers | `/opt/chungthuc/bin/` | Convert / ký từ shell |
| Apache vhost | `cert.nhovn.com` (+ SSL tạm snakeoil) | Phục vụ app |

Font đã cài: DejaVu, Liberation, Noto (hỗ trợ tiếng Việt cơ bản).

---

## 2. Thư mục dữ liệu

```
/phpsvr/chungthuc/uploads/
├── goc/      # Office gốc
├── pdf/      # Sau convert
└── signed/   # Sau ký server
```

Quyền: `www:www`, mode `775`. Apache **deny** truy cập trực tiếp `uploads/` (tải file qua app sau này).

---

## 3. Chứng thư ký nội bộ

```
/etc/chungthuc/
├── ca/
│   ├── ca.cert.pem          # Root CA nội bộ (công khai)
│   └── openssl.cnf
├── certs/
│   ├── signer.cert.pem      # Cert máy chủ ký PDF
│   └── signer-chain.pem
└── private/                 # mode 700 — không đưa vào git / web
    ├── ca.key.pem           # Root CA private (root only)
    ├── signer.key.pem       # root:www 640
    ├── signer.p12           # PKCS#12 cho pyHanko
    └── signer.pass          # passphrase PKCS#12
```

| Cert | CN | Hiệu lực |
|------|-----|----------|
| Root CA | NHOVN Internal Root CA | ~10 năm (đến 2036) |
| Signer | NHOVN PDF Signing Server | ~825 ngày (đến 2028-10) |

SAN signer: `cert.nhovn.com`, `localhost`, `192.168.99.3`.

**Bản Root CA để cài máy client nội bộ:**  
`/phpsvr/chungthuc/docs/NHOVN_Internal_Root_CA.crt`

Máy đã tin Root CA này sẽ thấy chữ ký **TRUSTED**. Máy chưa tin vẫn thấy chữ ký **INTACT** nhưng **UNTRUSTED** (đúng kỳ vọng nội bộ).

---

## 4. Lệnh vận hành (smoke / thủ công)

```bash
# Convert
convert-office-to-pdf /phpsvr/chungthuc/uploads/goc/file.docx /phpsvr/chungthuc/uploads/pdf

# Ký server
sign-pdf-server /phpsvr/chungthuc/uploads/pdf/file.pdf /phpsvr/chungthuc/uploads/signed/file_signed.pdf

# Kiểm tra (tin CA nội bộ)
pyhanko sign validate --trust /etc/chungthuc/ca/ca.cert.pem /phpsvr/chungthuc/uploads/signed/file_signed.pdf
```

Smoke đã chạy thành công: `uploads/signed/smoke_mau_signed.pdf` → `INTACT:TRUSTED,UNTOUCHED` khi validate kèm Root CA.

---

## 5. Apache / HTTPS

- Site HTTP: `/etc/apache2/sites-available/cert.nhovn.com.conf` → DocumentRoot `/phpsvr/chungthuc`
- Site HTTPS: `cert.nhovn.com-ssl.conf` đang dùng **snakeoil** (tự ký) để mở sẵn cổng 443
- DNS công khai `cert.nhovn.com` hiện trỏ `14.241.182.144` — nếu TLS terminate ở proxy/firewall phía trước, cần trỏ/proxy về `192.168.99.3` và gắn cert TLS web thật (khác với CA ký PDF)

**Lưu ý:** Chứng thư **TLS web** (HTTPS) và chứng thư **ký PDF** là hai việc khác nhau. CA nội bộ ở `/etc/chungthuc` chỉ dùng để ký PDF.

Truy cập nội bộ tạm: `http://192.168.99.3/` (vhost ServerName) hoặc qua DocumentRoot cũ `http://192.168.99.3/chungthuc/` nếu vẫn dùng `phpsvr.conf`.

---

## 6. Bước 2 — App PHP (đã có MVP)

UI thủ công từng nút tại DocumentRoot:

- `http://192.168.99.3/` (Host `cert.nhovn.com`) hoặc `http://192.168.99.3/chungthuc/`
- Luồng: **Chọn goc → Convert → Preview → Ký server → signed + audit** (không tự chạy nối tiếp)

| Mục | Chi tiết |
|-----|----------|
| User mẫu | `kythu` / `Kythu@123` |
| Tạo user | `register.php` |
| DB audit | SQLite `data/chungthuc.sqlite` |
| File mẫu | `uploads/goc/huongdan_sudung_online.docx`, `KL_KQNB_YC151816015.xlsx` |

## 7. Việc còn lại

1. **Máy nội bộ:** cài Root CA để Adobe hiện bút xanh — xem [`trust_root_ca.md`](trust_root_ca.md).
2. Gắn **TLS thật** cho `https://cert.nhovn.com`.
3. (Sau) USB token, TSA, upload UI đầy đủ.

**Kiểm tra toàn vẹn trên server (đã OK):** `INTACT:TRUSTED,UNTOUCHED` với CA NHOVN.  
Adobe đỏ = máy chưa tin CA (đúng với phía ngoài).
