Documentation: - certs/README.md: Complete guide for managing nginx TLS certificates - Server cert generation (self-signed, CA-signed, Let's Encrypt) - Certificate expiry monitoring and renewal procedures - Agent certificate pinning configuration - Air-gapped deployment notes Tooling: - certs/regenerate-server-cert.sh: Bash script for cert regeneration - certs/regenerate-server-cert.ps1: PowerShell script for Windows - Both scripts backup old certs and display new thumbprint Config: - Updated .gitignore to allow cert management files (docs/scripts/config) - Private keys and actual certificates still excluded (security) Context: - User asked where to manage server-side certificate - Current cert: self-signed, CN=localhost, valid 1 year - Agents validate server cert via pinning or Windows trusted roots - Critical for mTLS client cert authentication (ADR-006) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
ShopDB Server Certificate Management
This directory contains the TLS certificates for ShopDB's nginx server.
Current Certificate
- File:
server.crt(certificate) andserver.key(private key) - Common Name: localhost
- Subject Alternative Names: localhost, 192.168.100.1
- Validity: 1 year from generation date
- Type: Self-signed (for development and air-gapped sites)
Certificate Location
The certs/ directory is mounted into the nginx container at /etc/nginx/certs/:
# docker-compose.yml
nginx:
volumes:
- ./certs:/etc/nginx/certs:ro
Referenced in nginx.conf:
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
Generating a New Server Certificate
Option 1: Self-Signed (Development/Air-Gapped)
Generate a new self-signed certificate valid for 1 year:
cd certs
# Generate new private key and certificate
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout server.key \
-out server.crt \
-days 365 \
-config openssl.cnf
# Restart nginx to pick up new certificate
docker-compose restart nginx
Option 2: Custom Certificate (Production)
If you have a certificate from a trusted CA or internal PKI:
- Copy your certificate to
certs/server.crt - Copy your private key to
certs/server.key - Update
certs/openssl.cnfwith the correct CN and SANs - Restart nginx:
docker-compose restart nginx
Option 3: Let's Encrypt (Public-Facing Sites)
For internet-accessible ShopDB instances, use Let's Encrypt:
# Install certbot
apt-get install certbot python3-certbot-nginx
# Generate certificate (interactive)
certbot --nginx -d your-domain.com
# Copy certificates to certs directory
cp /etc/letsencrypt/live/your-domain.com/fullchain.pem certs/server.crt
cp /etc/letsencrypt/live/your-domain.com/privkey.pem certs/server.key
# Restart nginx
docker-compose restart nginx
Certificate Expiry
Check current certificate expiry:
openssl x509 -in certs/server.crt -noout -dates
ShopDB agents validate the server certificate using:
- Pinning (if
ServerCertThumbprintconfigured in agent appsettings.json) - Windows trusted roots (if no pinning configured)
Agent Certificate Pinning
To enable server certificate pinning on agents:
-
Get the server certificate thumbprint:
# Windows certutil -hashfile certs\server.crt SHA256 # Or from certificate details openssl x509 -in certs/server.crt -fingerprint -sha256 -noout -
Update agent
appsettings.json:{ "ServerCertThumbprint": "AA:BB:CC:DD:EE:FF:..." } -
Restart the agent service
NOTE: When you renew the server certificate, you must update ServerCertThumbprint on all agents before the old certificate expires, or agents will reject the new certificate.
Air-Gapped Site Deployment
For air-gapped sites:
- Generate certificate on work PC (with correct hostname/IP)
- Include
certs/directory in bundle (already in git repo) - Deploy bundle to site
- Certificate deploys automatically with
docker-compose up
Certificate Files
server.crt- Server certificate (nginx HTTPS)server.key- Server private keyopenssl.cnf- OpenSSL configuration for certificate generationtest-client.crt,test-client.key,test-client.p12- Test client certificates (for development only)
Security Notes
- Private Key Protection:
server.keyshould be readable only by nginx (done via Docker volume mount) - Self-Signed Trust: Self-signed certificates are expected in air-gapped environments
- Agent Pinning: Use
ServerCertThumbprintto prevent MITM attacks with self-signed certs - Expiry Monitoring: Set calendar reminders to renew certificates before expiry
Related Documentation
- Agent certificate renewal:
plugins/endpoints/api/certificate_renewal.py - Client certificate authentication:
shopdb/core/auth/client_cert.py - Nginx configuration:
nginx.conf