myca-tools/README.md
2025-08-20 16:14:31 +01:00

253 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 sites cached cert or restart the browser.
Nginx reload fails: run nginx -t and fix the reported error.
Licence
MIT.