11 KiB
11 KiB
Local Certificate Authority Setup
This document describes the setup of a local Certificate Authority (CA) for issuing HTTPS certificates to internal services.
Overview
Problem: Internal services (Home Assistant, AD5M printer, Dockge, etc.) use HTTP, causing:
- Browser security warnings
- Some services refuse to work without HTTPS
- Insecure credential transmission
Solution: Local CA using step-ca that issues trusted certificates for .nianticbooks.home domain.
Architecture
CA Server Location
- Host: main-pve (10.0.10.3) - most reliable server
- Container: LXC container for isolation
- IP: 10.0.10.15 (reserved for ca-server)
- Domain: ca.nianticbooks.home
Services Requiring Certificates
| Service | Current IP | Domain | Port |
|---|---|---|---|
| Home Assistant | 10.0.10.24 | bob.nianticbooks.home | 8123 |
| AD5M Printer | 10.0.10.30 | ad5m.nianticbooks.home | 80 |
| Dockge | 10.0.10.27 | dockge.nianticbooks.home | 5001 |
| Proxmox (main-pve) | 10.0.10.3 | freddesk.nianticbooks.home | 8006 |
| Proxmox (pve-router) | 10.0.10.2 | pve-router.nianticbooks.home | 8006 |
| OMV | 10.0.10.5 | omv.nianticbooks.home | 80 |
Implementation Plan
Phase 1: CA Server Setup
- Create LXC container on main-pve
- Install step-ca
- Initialize CA with:
- CA name: "Homelab Internal CA"
- Domain: nianticbooks.home
- Validity: 10 years (root), 1 year (leaf certificates)
Phase 2: Certificate Generation
For each service, generate:
- Server certificate
- Private key
- Auto-renewal script
Phase 3: Service Configuration
Configure each service to:
- Use generated certificate
- Listen on HTTPS port
- Optionally redirect HTTP → HTTPS
Phase 4: Client Trust
Distribute root CA certificate to:
- Linux clients (this computer, servers)
- Windows clients
- macOS clients
- Mobile devices (iOS/Android)
Step-by-Step Implementation
1. Create CA Server Container
# On main-pve (10.0.10.3)
pct create 115 local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst \
--hostname ca-server \
--cores 1 \
--memory 512 \
--swap 512 \
--storage local-lvm \
--rootfs 8 \
--net0 name=eth0,bridge=vmbr0,ip=10.0.10.15/24,gw=10.0.10.1 \
--unprivileged 1 \
--features nesting=1 \
--onboot 1
# Start container
pct start 115
# Enter container
pct enter 115
2. Install step-ca
# Inside container
apt update && apt install -y wget
# Download step-ca
wget https://dl.smallstep.com/gh-release/cli/gh-release-header/v0.25.0/step-cli_0.25.0_amd64.deb
wget https://dl.smallstep.com/gh-release/certificates/gh-release-header/v0.25.0/step-ca_0.25.0_amd64.deb
# Install
dpkg -i step-cli_0.25.0_amd64.deb step-ca_0.25.0_amd64.deb
# Verify
step version
step-ca version
3. Initialize CA
# Create CA user
useradd -r -s /bin/bash -m -d /etc/step-ca step
# Initialize CA (as step user)
su - step
step ca init
# Configuration prompts:
# Name: Homelab Internal CA
# DNS: ca.nianticbooks.home
# Address: :443
# Provisioner: admin@nianticbooks.home
# Password: [generate strong password, save to password manager]
4. Configure CA Service
# Create systemd service
cat > /etc/systemd/system/step-ca.service <<'EOF'
[Unit]
Description=step-ca Certificate Authority
After=network.target
[Service]
Type=simple
User=step
Group=step
WorkingDirectory=/etc/step-ca
ExecStart=/usr/bin/step-ca /etc/step-ca/config/ca.json --password-file=/etc/step-ca/password.txt
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Store CA password securely
echo "YOUR_CA_PASSWORD" > /etc/step-ca/password.txt
chown step:step /etc/step-ca/password.txt
chmod 600 /etc/step-ca/password.txt
# Enable and start
systemctl daemon-reload
systemctl enable step-ca
systemctl start step-ca
systemctl status step-ca
5. Issue Certificates for Services
Home Assistant (bob.nianticbooks.home)
# Generate certificate
step certificate create bob.nianticbooks.home \
bob.crt bob.key \
--profile leaf \
--not-after 8760h \
--ca /etc/step-ca/certs/intermediate_ca.crt \
--ca-key /etc/step-ca/secrets/intermediate_ca_key \
--bundle
# Copy to Home Assistant
scp bob.crt bob.key homeassistant.local:/ssl/
Configure Home Assistant (configuration.yaml):
http:
ssl_certificate: /ssl/bob.crt
ssl_key: /ssl/bob.key
server_port: 8123
AD5M Printer (Fluidd/Klipper)
step certificate create ad5m.nianticbooks.home \
ad5m.crt ad5m.key \
--profile leaf \
--not-after 8760h \
--ca /etc/step-ca/certs/intermediate_ca.crt \
--ca-key /etc/step-ca/secrets/intermediate_ca_key \
--bundle
# Copy to printer
scp ad5m.crt ad5m.key root@10.0.10.30:/etc/nginx/ssl/
Configure nginx for Fluidd:
server {
listen 443 ssl;
server_name ad5m.nianticbooks.home;
ssl_certificate /etc/nginx/ssl/ad5m.crt;
ssl_certificate_key /etc/nginx/ssl/ad5m.key;
location / {
proxy_pass http://localhost:80;
}
}
Dockge
step certificate create dockge.nianticbooks.home \
dockge.crt dockge.key \
--profile leaf \
--not-after 8760h \
--ca /etc/step-ca/certs/intermediate_ca.crt \
--ca-key /etc/step-ca/secrets/intermediate_ca_key \
--bundle
# Copy to Dockge host
Proxmox
# Main PVE
step certificate create freddesk.nianticbooks.home \
freddesk.crt freddesk.key \
--profile leaf \
--not-after 8760h \
--ca /etc/step-ca/certs/intermediate_ca.crt \
--ca-key /etc/step-ca/secrets/intermediate_ca_key \
--bundle
# Copy to Proxmox
scp freddesk.crt freddesk.key root@10.0.10.3:/etc/pve/local/pveproxy-ssl.pem
scp freddesk.key root@10.0.10.3:/etc/pve/local/pveproxy-ssl.key
# Restart Proxmox web service
ssh root@10.0.10.3 "systemctl restart pveproxy"
6. Certificate Auto-Renewal
Create renewal script on CA server:
cat > /usr/local/bin/renew-certs.sh <<'EOF'
#!/bin/bash
# Auto-renew certificates for homelab services
SERVICES=(
"bob.nianticbooks.home:10.0.10.24:/ssl/"
"ad5m.nianticbooks.home:10.0.10.30:/etc/nginx/ssl/"
"dockge.nianticbooks.home:10.0.10.27:/etc/ssl/"
"freddesk.nianticbooks.home:10.0.10.3:/etc/pve/local/"
)
for service in "${SERVICES[@]}"; do
IFS=':' read -r domain ip path <<< "$service"
echo "Renewing certificate for $domain..."
# Check if certificate expires in < 30 days
if step certificate needs-renewal "${domain}.crt"; then
# Generate new certificate
step certificate create "$domain" \
"${domain}.crt" "${domain}.key" \
--profile leaf \
--not-after 8760h \
--ca /etc/step-ca/certs/intermediate_ca.crt \
--ca-key /etc/step-ca/secrets/intermediate_ca_key \
--bundle --force
# Deploy to service
scp "${domain}.crt" "${domain}.key" "root@${ip}:${path}"
# Restart service
case "$domain" in
bob.*)
ssh root@${ip} "systemctl restart home-assistant@homeassistant"
;;
ad5m.*)
ssh root@${ip} "systemctl restart nginx"
;;
freddesk.*)
ssh root@${ip} "systemctl restart pveproxy"
;;
esac
echo "✓ Renewed $domain"
fi
done
EOF
chmod +x /usr/local/bin/renew-certs.sh
# Add to crontab (weekly check)
echo "0 2 * * 0 /usr/local/bin/renew-certs.sh" >> /etc/crontab
7. Client Trust Configuration
Linux (Ubuntu/Debian)
# Copy root CA certificate
scp root@10.0.10.15:/etc/step-ca/certs/root_ca.crt /usr/local/share/ca-certificates/homelab-ca.crt
# Update trust store
update-ca-certificates
# Verify
curl https://bob.nianticbooks.home:8123
Windows
- Copy
root_ca.crtto Windows machine - Right-click → Install Certificate
- Store Location: Local Machine
- Certificate Store: Trusted Root Certification Authorities
- Click Next → Finish
macOS
# Copy certificate
scp root@10.0.10.15:/etc/step-ca/certs/root_ca.crt ~/Downloads/
# Import to keychain
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ~/Downloads/root_ca.crt
iOS/Android
- Email
root_ca.crtto device or host on web server - Open certificate file on device
- Install profile
- iOS: Settings → General → About → Certificate Trust Settings → Enable
- Android: Settings → Security → Install from storage
DNS Configuration
Ensure UCG Ultra has DNS entries for all services:
bob.nianticbooks.home → 10.0.10.24
ad5m.nianticbooks.home → 10.0.10.30
dockge.nianticbooks.home → 10.0.10.27
freddesk.nianticbooks.home → 10.0.10.3
pve-router.nianticbooks.home → 10.0.10.2
omv.nianticbooks.home → 10.0.10.5
ca.nianticbooks.home → 10.0.10.15
Verification
Test each service:
# Home Assistant
curl -I https://bob.nianticbooks.home:8123
# AD5M
curl -I https://ad5m.nianticbooks.home
# Dockge
curl -I https://dockge.nianticbooks.home:5001
# Proxmox
curl -I https://freddesk.nianticbooks.home:8006
Troubleshooting
Certificate Not Trusted
# Check if CA is in trust store
ls /usr/local/share/ca-certificates/
# Verify certificate chain
openssl s_client -connect bob.nianticbooks.home:8123 -showcerts
# Check certificate validity
openssl x509 -in bob.crt -text -noout
Service Won't Start with HTTPS
# Check certificate permissions
ls -la /ssl/
# Check service logs
journalctl -u home-assistant@homeassistant -f
# Verify certificate matches key
openssl x509 -noout -modulus -in cert.crt | openssl md5
openssl rsa -noout -modulus -in cert.key | openssl md5
# Should match
Maintenance
Certificate Expiry Monitoring
# Check certificate expiration
for cert in *.crt; do
echo "$cert:"
openssl x509 -in "$cert" -noout -dates
done
Renewing Root CA
Root CA expires in 10 years. To renew:
- Generate new root CA
- Issue new intermediate CA
- Re-issue all service certificates
- Update all client trust stores
Security Considerations
- CA private key stored encrypted on CA server
- CA server only accessible from local network
- Certificate validity limited to 1 year
- Auto-renewal prevents expiry
- Root CA backed up to OMV storage
Backup
# Backup CA configuration
rsync -av /etc/step-ca/ /mnt/omv-backup/ca-backup/$(date +%Y%m%d)/
# Store root CA password in password manager
Next Steps
- Create CA server LXC container
- Install and configure step-ca
- Generate certificates for all services
- Configure services to use HTTPS
- Distribute root CA to all devices
- Set up auto-renewal
- Test all services with HTTPS
- Update Pangolin routes to use HTTPS backend