Keys & Certificates Inventory
Version: 1.0
Date: January 18, 2026
Status: Active
Overview
This document provides a comprehensive inventory of all API keys, secrets, and certificates used in Forma3D.Connect. Each entry includes lifespan, renewal location, and renewal procedures.
IMPORTANT: This document contains references to credentials. Never store actual credentials in version control. All secrets should be stored in:
- Azure DevOps Library (Variable Groups)
- .env files (local development only, never committed)
- DigitalOcean environment variables
Infrastructure
Key/Certificate
Purpose
Lifespan
Renewal Location
Renewal Procedure
Last Renewed
Droplet SSH Key
SSH access to server
No expiry (rotate annually)
DigitalOcean > Settings > Security > SSH Keys
Generate new keypair, add to DO, update ~/.ssh/authorized_keys on droplet
YYYY-MM-DD
Droplet Root Password
Emergency console access
No expiry (rotate annually)
DigitalOcean > Droplet > Access > Reset Root Password
Reset via DO console, store in password manager
YYYY-MM-DD
TLS Certificate (Let's Encrypt)
HTTPS for API/Web
90 days
Let's Encrypt via Traefik ACME
Auto-renewed by Traefik (see below)
Auto
Database
Key/Certificate
Purpose
Lifespan
Renewal Location
Renewal Procedure
Last Renewed
Database CA Certificate
SSL connection to managed DB
1-5 years (provider-managed)
DigitalOcean > Databases > Your DB > Connection Details > Download CA
Download new CA cert, update deployment config
YYYY-MM-DD
Database Password
PostgreSQL access
No expiry (rotate quarterly)
DigitalOcean > Databases > Your DB > Users
Reset via provider, update DATABASE_URL in Azure DevOps
YYYY-MM-DD
Container Registry
Key/Certificate
Purpose
Lifespan
Renewal Location
Renewal Procedure
Last Renewed
Container Registry Token
Push/pull Docker images
No expiry
DigitalOcean > Container Registry > API
Generate new token, update CI/CD variables
YYYY-MM-DD
Cosign Signing Key
Container image signing
No expiry
Self-generated (cosign.key)
cosign generate-key-pair, update CI/CD secrets
YYYY-MM-DD
External Services
Shopify
Key/Certificate
Purpose
Lifespan
Renewal Location
Renewal Procedure
Last Renewed
SHOPIFY_API_KEY
App identification
No expiry
Shopify Admin > Apps > Your App > API credentials
Regenerate in Shopify admin, update Azure DevOps
YYYY-MM-DD
SHOPIFY_API_SECRET
App authentication
No expiry
Shopify Admin > Apps > Your App > API credentials
Regenerate in Shopify admin, update Azure DevOps
YYYY-MM-DD
SHOPIFY_ACCESS_TOKEN
Store-specific access
No expiry (unless revoked)
Shopify Admin > Apps > Your App
Reinstall app or regenerate
YYYY-MM-DD
SHOPIFY_WEBHOOK_SECRET
HMAC verification
No expiry
Shopify Admin > Settings > Notifications > Webhooks
Regenerate in webhooks settings, update Azure DevOps
YYYY-MM-DD
SimplyPrint
Key/Certificate
Purpose
Lifespan
Renewal Location
Renewal Procedure
Last Renewed
SIMPLYPRINT_API_KEY
Print farm API access
No expiry
SimplyPrint Dashboard > Settings > API
Generate new key in dashboard, update Azure DevOps
YYYY-MM-DD
SIMPLYPRINT_COMPANY_ID
Company identification
No expiry
SimplyPrint Dashboard > Settings
Fixed value, only changes if company re-created
N/A
SIMPLYPRINT_WEBHOOK_SECRET
Webhook verification
No expiry
SimplyPrint Dashboard > Webhooks
Configure in webhook settings
YYYY-MM-DD
Sendcloud
Key/Certificate
Purpose
Lifespan
Renewal Location
Renewal Procedure
Last Renewed
SENDCLOUD_PUBLIC_KEY
Shipping API authentication
No expiry
Sendcloud Panel > Settings > Integrations > API
Generate new integration, update Azure DevOps
YYYY-MM-DD
SENDCLOUD_SECRET_KEY
Shipping API authentication
No expiry
Sendcloud Panel > Settings > Integrations > API
Generate new integration, update Azure DevOps
YYYY-MM-DD
Push Notifications (Web Push / VAPID)
Key/Certificate
Purpose
Lifespan
Renewal Location
Renewal Procedure
Last Renewed
VAPID_PUBLIC_KEY
Web Push subscription (shared with frontend)
No expiry
Self-generated
npx web-push generate-vapid-keys --json, update Azure DevOps (WARNING: regenerating invalidates all push subscriptions)
2026-01-19
VAPID_PRIVATE_KEY
Web Push sending (server-side secret)
No expiry
Self-generated
Generate with public key (same command), update Azure DevOps
2026-01-19
VAPID_SUBJECT
Contact email for push services
N/A
Configuration only
Update in Azure DevOps if contact email changes
2026-01-19
Initial VAPID key generation:
npx web-push generate-vapid-keys --json
# Output: { "publicKey": "...", "privateKey": "..." }
Warning: Do NOT regenerate VAPID keys unless absolutely necessary. Regenerating keys invalidates all existing push subscriptions across all users. Users will need to re-subscribe for push notifications.
Application
Key/Certificate
Purpose
Lifespan
Renewal Location
Renewal Procedure
Last Renewed
INTERNAL_API_KEY
Dashboard/Admin access
No expiry (rotate annually)
Self-generated
Generate with openssl rand -hex 32, update Azure DevOps
YYYY-MM-DD
SENTRY_DSN
Error tracking
No expiry
Sentry Dashboard > Project Settings > Client Keys
Create new DSN if needed, update Azure DevOps
YYYY-MM-DD
SMTP Credentials
Email notifications
Varies by provider
Email provider dashboard
Regenerate password/API key
YYYY-MM-DD
CI/CD (Azure DevOps)
Key/Certificate
Purpose
Lifespan
Renewal Location
Renewal Procedure
Last Renewed
Azure DevOps PAT
Pipeline authentication
1 year max
Azure DevOps > User Settings > Personal Access Tokens
Generate new PAT, update service connections
YYYY-MM-DD
SSH Service Connection
Deploy to droplet
Tied to SSH key
Azure DevOps > Project Settings > Service Connections
Update with new SSH private key
YYYY-MM-DD
Secure Files
Certificates and keys
N/A
Azure DevOps > Pipelines > Library > Secure Files
Upload new files as needed
YYYY-MM-DD
TLS Certificate Auto-Renewal
Traefik automatically handles Let's Encrypt certificate renewal:
Validity: 90 days per certificate
Auto-renewal: Traefik renews ~30 days before expiry
Storage: Certificates stored in Docker volume traefik-certs at /letsencrypt/acme.json
Challenge: HTTP-01 challenge via port 80 (must remain accessible)
Configuration: See deployment/staging/traefik.yml > certificatesResolvers.letsencrypt
Monitoring TLS auto-renewal:
# Check certificate expiry date
echo | openssl s_client -connect connect-api.forma3d.be:443 2 >/dev/null | openssl x509 -noout -dates
# Check Traefik logs for renewal activity
docker logs forma3d-traefik 2 >& 1 | grep -i "acme\|certificate\|renew"
# Verify ACME storage file exists
docker exec forma3d-traefik ls -la /letsencrypt/acme.json
Troubleshooting failed renewal:
1. Ensure port 80 is open and reachable from internet
2. Check DNS still points to correct IP
3. Verify Traefik container is running: docker ps | grep traefik
4. Check Traefik logs for ACME errors
5. If needed, remove acme.json and restart Traefik to re-issue certificates
Renewal Calendar
Frequency
Items
Weekly (automated)
TLS certificates checked by Traefik
Monthly
Verify TLS auto-renewal is working
Quarterly
Rotate database password, review API key usage
Annually
Rotate SSH keys, Azure DevOps PAT, INTERNAL_API_KEY, review all external API keys
Before Expiry
Database CA certificate (monitor provider notifications), Azure DevOps PAT
On Incident
Rotate any potentially compromised credentials immediately
Renewal Checklist
When renewing any credential:
Generate new credential in source system
Update .env files (staging and production)
Update secrets in Azure DevOps (Library > Variable Groups)
Deploy with new credentials
Verify system still works (health checks)
Revoke old credential (if applicable)
Update this inventory with new "Last Renewed" date
Secure Storage Locations
Location
What's Stored
Access
Azure DevOps Variable Groups
All production secrets
Project Administrators
Azure DevOps Secure Files
SSH keys, certificates, cosign.key
Pipeline only
Password Manager
Root passwords, recovery codes
Authorized personnel
.env files (local)
Development credentials
Individual developers
Revision History:
Version
Date
Author
Changes
1.0
2026-01-18
Phase 6 Implementation
Initial inventory
1.1
2026-01-19
Phase 7 Implementation
Added VAPID keys for Web Push notifications