253 lines
5.5 KiB
Markdown
253 lines
5.5 KiB
Markdown
# myca-tools
|
||
|
||
Bash helpers for running a simple local root CA, issuing TLS certificates with SANs, and generating Nginx HTTPS reverse-proxy vhosts for internal services.
|
||
|
||
Do not use `.local`. Use `.lan` or a domain you control.
|
||
|
||
## Placeholders used in this README
|
||
|
||
- `NAME`
|
||
The service hostname you want to secure. Example: `app.lan`.
|
||
|
||
- `HOST_IP`
|
||
The local IP address of the server that presents the certificate. In a typical setup this is the machine running Nginx and hosting the service. Example: `192.168.1.50`.
|
||
|
||
- `BACKEND_HOST:PORT`
|
||
Where Nginx should proxy. Example: `127.0.0.1:8080`.
|
||
|
||
Replace these with your values before running commands.
|
||
|
||
## Features
|
||
|
||
- Initialise a root CA in `/etc/ssl/myca`
|
||
- Issue server certificates with DNS and IP SANs
|
||
- Sign existing CSRs
|
||
- Show and verify certificates
|
||
- Deploy certs to `/etc/nginx/ssl` and reload Nginx
|
||
- Generate a standard HTTPS reverse proxy vhost
|
||
|
||
## Requirements
|
||
|
||
- Debian or Ubuntu
|
||
- `openssl`
|
||
- `nginx` if you want reverse proxying
|
||
- Root access
|
||
|
||
## Install
|
||
|
||
```bash
|
||
git clone <your-repo-url> myca-tools
|
||
cd myca-tools
|
||
./install.sh
|
||
```
|
||
|
||
Installs:
|
||
|
||
/usr/local/sbin/myca.sh
|
||
|
||
/usr/local/sbin/mknginx-sni.sh
|
||
|
||
/usr/local/sbin/init-ca.sh
|
||
|
||
Prepares /etc/ssl/myca with certs, csrs, exts, and private.
|
||
|
||
## Quick start
|
||
|
||
1. Initialise a root CA if you do not already have one.
|
||
|
||
```bash
|
||
sudo init-ca.sh "/CN=My Local Root CA"
|
||
```
|
||
|
||
2. Trust the CA on this host.
|
||
|
||
```bash
|
||
sudo myca.sh trust-ca
|
||
```
|
||
|
||
3. Issue a cert for your internal service and deploy it to Nginx.
|
||
```bash
|
||
# Replace NAME and HOST_IP
|
||
sudo myca.sh issue NAME \
|
||
--dns NAME --ip HOST_IP --deploy-nginx
|
||
```
|
||
|
||
4. Create an Nginx vhost that uses the cert and proxies to your backend.
|
||
```bash
|
||
# Replace NAME and BACKEND_HOST:PORT
|
||
sudo mknginx-sni.sh NAME BACKEND_HOST:PORT
|
||
```
|
||
|
||
5. Ensure clients resolve the name.
|
||
```bash
|
||
HOST_IP NAME
|
||
```
|
||
|
||
6. Test.
|
||
```bash
|
||
myca.sh show NAME
|
||
myca.sh verify NAME
|
||
curl -Ik https://NAME
|
||
```
|
||
|
||
## Notes on SANs
|
||
|
||
You can omit --ip HOST_IP if clients always connect by DNS name and do not pin the IP.
|
||
|
||
If clients connect by IP, include that IP in SANs with --ip.
|
||
|
||
You can supply multiple --dns and --ip flags.
|
||
|
||
Scripts
|
||
myca.sh
|
||
|
||
Helper for issuing, signing, showing, verifying, and deploying certificates.
|
||
```bash
|
||
myca.sh COMMAND [args]
|
||
|
||
Commands:
|
||
issue NAME [--dns foo --ip 1.2.3.4 ...] [--days N] [--reuse-key] [--deploy-nginx]
|
||
sign NAME --csr /path/to/file.csr [--dns ... --ip ...] [--days N]
|
||
show NAME | /path/to/cert.crt
|
||
verify NAME | /path/to/cert.crt
|
||
list
|
||
trust-ca
|
||
|
||
Environment:
|
||
MYCA_DIR default /etc/ssl/myca
|
||
NGINX_SSL_DIR default /etc/nginx/ssl
|
||
```
|
||
|
||
Examples:
|
||
```bash
|
||
# Issue new key and cert with SANs
|
||
sudo myca.sh issue internal-api.lan --dns internal-api.lan --ip HOST_IP
|
||
|
||
# Reissue keeping the same key and deploy to Nginx
|
||
sudo myca.sh issue wiki.lan --dns wiki.lan --reuse-key --deploy-nginx
|
||
|
||
# Sign an existing CSR
|
||
sudo myca.sh sign portal.lan --csr /tmp/portal.csr --dns portal.lan --ip 10.0.0.5
|
||
|
||
# Show and verify
|
||
myca.sh show wiki.lan
|
||
myca.sh verify wiki.lan
|
||
|
||
# List issued certs
|
||
myca.sh list
|
||
```
|
||
|
||
Files are written to:
|
||
|
||
Keys /etc/ssl/myca/private/NAME.key
|
||
|
||
CSRs /etc/ssl/myca/csrs/NAME.csr
|
||
|
||
Certs /etc/ssl/myca/certs/NAME.crt
|
||
|
||
SAN /etc/ssl/myca/exts/NAME.ext
|
||
|
||
CA files expected:
|
||
|
||
/etc/ssl/myca/myCA.pem
|
||
|
||
/etc/ssl/myca/myCA.key
|
||
|
||
/etc/ssl/myca/myCA.srl created on first issuance
|
||
|
||
mknginx-sni.sh
|
||
|
||
Generate a standard HTTPS reverse proxy server block for a given name and backend.
|
||
```bash
|
||
sudo mknginx-sni.sh NAME [BACKEND_HOST:PORT]
|
||
# writes /etc/nginx/conf.d/NAME.conf
|
||
# proxies to BACKEND, default 127.0.0.1:8000
|
||
# uses /etc/nginx/ssl/NAME.crt and /etc/nginx/ssl/NAME.key
|
||
```
|
||
|
||
Example:
|
||
```bash
|
||
sudo mknginx-sni.sh internal-api.lan 127.0.0.1:9000
|
||
```
|
||
|
||
init-ca.sh
|
||
|
||
Initialise a new root CA in /etc/ssl/myca.
|
||
```bash
|
||
sudo init-ca.sh "/CN=My Local Root CA"
|
||
```
|
||
|
||
Creates:
|
||
|
||
Root key /etc/ssl/myca/myCA.key 4096 bit
|
||
|
||
Root cert /etc/ssl/myca/myCA.pem valid 10 years
|
||
|
||
Trusting your CA on clients
|
||
|
||
Linux Debian or Ubuntu:
|
||
```bash
|
||
sudo cp /etc/ssl/myca/myCA.pem /usr/local/share/ca-certificates/myCA.crt
|
||
sudo update-ca-certificates
|
||
```
|
||
|
||
ndows:
|
||
|
||
Import myCA.pem into Local Computer, Trusted Root Certification Authorities.
|
||
|
||
macOS:
|
||
|
||
Import myCA.pem into the System keychain in Keychain Access. Set Always Trust.
|
||
|
||
Browsers must trust the CA or you will see warnings.
|
||
|
||
Directory layout
|
||
```vbnet
|
||
/etc/ssl/myca/
|
||
├── myCA.key root key
|
||
├── myCA.pem root certificate
|
||
├── myCA.srl serial file
|
||
├── certs/ issued certificates
|
||
├── csrs/ certificate signing requests
|
||
├── exts/ SAN extension files
|
||
└── private/ server private keys
|
||
```
|
||
|
||
Nginx deploy target:
|
||
```swift
|
||
/etc/nginx/ssl/NAME.crt
|
||
/etc/nginx/ssl/NAME.key
|
||
```
|
||
|
||
Environment variables
|
||
|
||
Override defaults if needed:
|
||
```bash
|
||
export MYCA_DIR=/srv/pki
|
||
export NGINX_SSL_DIR=/etc/nginx/ssl
|
||
```
|
||
|
||
Security
|
||
|
||
Back up /etc/ssl/myca/myCA.key offline. Losing it prevents renewal under the same root.
|
||
|
||
Keep /etc/ssl/myca/private permissions intact. Keys are mode 600.
|
||
|
||
Keep this root CA for internal use only. Do not use it on the public internet.
|
||
|
||
Use shorter lifetimes for anything exposed beyond your LAN.
|
||
|
||
Troubleshooting
|
||
|
||
Missing CA: ensure myCA.pem and myCA.key exist under /etc/ssl/myca.
|
||
|
||
verify error:num=20: the client does not trust your CA. Install the CA to the client trust store.
|
||
|
||
Browser still warns after trusting CA: clear the site’s cached cert or restart the browser.
|
||
|
||
Nginx reload fails: run nginx -t and fix the reported error.
|
||
|
||
Licence
|
||
|
||
MIT.
|