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

5.5 KiB
Raw Blame History

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

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.
sudo init-ca.sh "/CN=My Local Root CA"
  1. Trust the CA on this host.
sudo myca.sh trust-ca
  1. Issue a cert for your internal service and deploy it to Nginx.
# Replace NAME and HOST_IP
sudo myca.sh issue NAME \
  --dns NAME --ip HOST_IP --deploy-nginx
  1. Create an Nginx vhost that uses the cert and proxies to your backend.
# Replace NAME and BACKEND_HOST:PORT
sudo mknginx-sni.sh NAME BACKEND_HOST:PORT
  1. Ensure clients resolve the name.
HOST_IP  NAME
  1. Test.
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.

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:

# 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.

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:

sudo mknginx-sni.sh internal-api.lan 127.0.0.1:9000

init-ca.sh

Initialise a new root CA in /etc/ssl/myca.

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:

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

/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:

/etc/nginx/ssl/NAME.crt
/etc/nginx/ssl/NAME.key

Environment variables

Override defaults if needed:

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.