https://github.com/fabriziosalmi/certmate
SSL Certificate Management System (API + UI)
https://github.com/fabriziosalmi/certmate
ssl-api ssl-certificates ssl-management
Last synced: 11 days ago
JSON representation
SSL Certificate Management System (API + UI)
- Host: GitHub
- URL: https://github.com/fabriziosalmi/certmate
- Owner: fabriziosalmi
- License: mit
- Created: 2025-06-24T07:16:05.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2025-07-01T16:42:24.000Z (8 months ago)
- Last Synced: 2025-07-01T17:41:17.290Z (8 months ago)
- Topics: ssl-api, ssl-certificates, ssl-management
- Language: HTML
- Homepage: https://www.certmate.org/
- Size: 2.51 MB
- Stars: 264
- Watchers: 0
- Forks: 5
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
- awesome-starts - fabriziosalmi/certmate - SSL Certificate Management System (API + UI) (automation)
README
# ๐ CertMate - SSL Certificate Management System
**CertMate** is a powerful SSL certificate management system designed for modern infrastructure. Built with multi-DNS provider support, Docker containerization, and comprehensive REST API, it's the perfect solution for managing certificates across multiple datacenters and cloud environments.
[](https://opensource.org/licenses/MIT)
[](https://www.python.org/downloads/)
[](https://hub.docker.com/)
[](http://localhost:8000/docs/)


[๐ Quick Start](#-quick-start-with-docker) โข [๐ Documentation](#-documentation) โข [๐ง Installation](#-installation-methods) โข [๐ DNS Providers](#-supported-dns-providers) โข [๏ฟฝ Backup & Recovery](#-backup--recovery) โข [๏ฟฝ๐ API Reference](#-api-usage)
---
## ๐ Why CertMate?
CertMate solves the complexity of SSL certificate management in modern distributed architectures. Whether you're running a single application or managing certificates across multiple datacenters, CertMate provides:
- **๐ Zero-Downtime Automation** - Certificates renew automatically 30 days before expiry
- **๐ Multi-Cloud Support** - Works with 19 DNS providers (Cloudflare, AWS, Azure, GCP, Hetzner, Porkbun, GoDaddy, and more)
- **๐ Enterprise-Ready** - Docker, Kubernetes, REST API, and monitoring built-in
- **๐ฆ Simple Integration** - One-URL certificate downloads for easy automation
- **๐ Security-First** - Bearer token authentication, secure file permissions, audit logging
- **๐พ Automatic Backup** - Built-in backup and restore for settings and certificates
## โจ Key Features
### ๐ **Certificate Management**
- **Let's Encrypt Integration** - Free, automated SSL certificates
- **Wildcard Support** - Single certificate for `*.example.com` and `example.com`
- **Multi-Domain Certificates** - SAN certificates for multiple domains
- **Automatic Renewal** - Smart renewal 30 days before expiry
- **Certificate Validation** - Real-time SSL certificate status checking
### ๐ **Multi-DNS Provider Support**
- **Multi-Account Support** - Manage multiple accounts per provider for enterprise environments
- **Cloudflare** - Global CDN with edge locations worldwide (โจ Multi-Account)
- **AWS Route53** - Amazon's scalable DNS service (โจ Multi-Account)
- **Azure DNS** - Microsoft's cloud DNS solution (โจ Multi-Account)
- **Google Cloud DNS** - Google's high-performance DNS (โจ Multi-Account)
- **DigitalOcean** - Cloud infrastructure DNS (โจ Multi-Account)
- **PowerDNS** - Open-source DNS server with REST API (โจ Multi-Account)
### ๐ **Enterprise Features**
- **Multi-Account Management** - Support multiple accounts per DNS provider for enterprise workflows
- **REST API** - Complete programmatic control with Swagger/OpenAPI docs
- **Web Dashboard** - Modern, responsive UI built with Tailwind CSS
- **Docker Ready** - Full containerization with Docker Compose
- **Kubernetes Compatible** - Deploy in any Kubernetes cluster
- **High Availability** - Stateless design for horizontal scaling
- **Monitoring Integration** - Health checks and structured logging
### ๐พ **Backup & Recovery**
- **Automatic Backups** - Settings and certificates backed up automatically on changes
- **Manual Backup Creation** - On-demand backup creation via web UI or API
- **Comprehensive Coverage** - Backs up DNS configurations, certificates, and application settings
- **Retention Management** - Configurable retention policies with automatic cleanup
- **Easy Restore** - Simple restore process from any backup point
- **Download Support** - Export backups for external storage and disaster recovery
### ๐ **Security & Compliance**
- **Bearer Token Authentication** - Secure API access control
- **File Permissions** - Proper certificate file security (600/700)
- **Audit Logging** - Complete certificate lifecycle tracking
- **Environment Variables** - Secure credential management
- **Rate Limit Handling** - Let's Encrypt rate limit awareness
### ๐ป **Developer Experience**
- **One-URL Downloads** - Simple certificate retrieval for automation
- **Multiple Output Formats** - PEM, ZIP, individual files
- **SDK Examples** - Python, Bash, Ansible, Terraform examples
- **Webhook Support** - Certificate renewal notifications
- **Backup API** - Programmatic backup creation and restoration
- **Extensive Documentation** - API docs, guides, and examples
## ๐ Supported DNS Providers
CertMate supports **19 DNS providers** through Let's Encrypt DNS-01 challenge via individual certbot plugins that provide reliable, well-tested DNS challenge support. **Multi-account support** is available for major providers, enabling enterprise-grade deployments with separate accounts for production, staging, and disaster recovery.
| Provider | Credentials Required | Multi-Account | Use Case | Status |
|----------|---------------------|---------------|----------|---------|
| **๐ถ Cloudflare** | API Token | โ
**Yes** | Global CDN, Free tier available | โ
**Stable** |
| **๐ AWS Route53** | Access Key, Secret Key | โ
**Yes** | AWS infrastructure, Enterprise | โ
**Stable** |
| **๐ต Azure DNS** | Service Principal credentials | โ
**Yes** | Microsoft ecosystem | โ
**Stable** |
| **๐ข Google Cloud DNS** | Service Account JSON | โ
**Yes** | Google Cloud Platform | โ
**Stable** |
| **๐ท DigitalOcean** | API Token | โ
**Yes** | Cloud infrastructure | โ
**Stable** |
| **โซ PowerDNS** | API URL, API Key | โ
**Yes** | Self-hosted, On-premises | โ
**Stable** |
| **๐ท RFC2136** | Nameserver, TSIG Key/Secret | โ
**Yes** | Standard DNS update protocol | โ
**Stable** |
| **๐ฃ Linode** | API Key | โ Single | Cloud hosting | โ
**Stable** |
| **๐ก Gandi** | API Token | โ Single | Domain registrar | โ
**Stable** |
| **๐ด OVH** | API Credentials | โ Single | European hosting | โ
**Stable** |
| **๐ข Namecheap** | Username, API Key | โ Single | Domain registrar | โ
**Stable** |
| **๐ฆ Vultr** | API Key | โ Single | Global cloud infrastructure | โ
**Stable** |
| **๐บ DNS Made Easy** | API Key, Secret Key | โ Single | Enterprise DNS management | โ
**Stable** |
| **๐ฃ NS1** | API Key | โ Single | Intelligent DNS platform | โ
**Stable** |
| ** Hetzner** | API Token | โ Single | European cloud hosting | โ
**Stable** |
| **๐ก Porkbun** | API Key, Secret Key | โ Single | Domain registrar with DNS | โ
**Stable** |
| **๐ข GoDaddy** | API Key, Secret | โ Single | Popular domain registrar | โ
**Stable** |
| **๐ต Hurricane Electric** | Username, Password | โ Single | Free DNS hosting | โ
**Stable** |
| **๐ถ Dynu** | API Token | โ Single | Dynamic DNS service | โ
**Stable** |
### ๐ Provider Categories
- **Enterprise Multi-Account**: Cloudflare, AWS Route53, Azure DNS, Google Cloud DNS, DigitalOcean, PowerDNS, RFC2136
- **Cloud Providers**: AWS Route53, Azure DNS, Google Cloud DNS, DigitalOcean, Linode, Vultr, Hetzner
- **Enterprise DNS**: Cloudflare, DNS Made Easy, NS1, PowerDNS
- **Domain Registrars**: Gandi, OVH, Namecheap, Porkbun, GoDaddy
- **European Providers**: OVH, Gandi, Hetzner
- **Free Services**: Hurricane Electric, Dynu
- **Standard Protocols**: RFC2136 (for BIND and compatible servers)
### ๐ข Multi-Account Benefits
For supported providers, you can configure multiple accounts to enable:
- **Environment Separation**: Different accounts for production, staging, and development
- **Multi-Region Management**: Separate accounts for different geographical regions
- **Team Isolation**: Department-specific accounts with tailored permissions
- **Disaster Recovery**: Backup accounts for high-availability scenarios
- **Permission Scoping**: Accounts with minimal required permissions for security
> ๐ **Detailed Setup Instructions**: See [DNS_PROVIDERS.md](DNS_PROVIDERS.md) for provider-specific configuration.
> ๐ง **Step-by-Step Installation**: See [INSTALLATION.md](INSTALLATION.md) for complete setup guide.
> ๐ข **Multi-Account Examples**: See [MULTI_ACCOUNT_EXAMPLES.md](MULTI_ACCOUNT_EXAMPLES.md) for enterprise configuration examples.
## ๐ Quick Start with Docker
Get CertMate running in under 5 minutes with Docker Compose:
### Prerequisites
- Docker 20.10+
- Docker Compose 2.0+
- Domain with DNS managed by supported provider
### 1. Clone and Setup
```bash
# Clone the repository
git clone https://github.com/fabriziosalmi/certmate.git
cd certmate
# Copy environment template
cp .env.example .env
```
### 2. Configure Environment
Edit `.env` file with your credentials:
```bash
# ๐ Required: API Security
API_BEARER_TOKEN=your_super_secure_api_token_here_change_this
# ๐ DNS Provider Configuration (choose one or multiple)
# Option 1: Cloudflare (Recommended for beginners)
CLOUDFLARE_TOKEN=your_cloudflare_api_token_here
# Option 2: AWS Route53
# AWS_ACCESS_KEY_ID=your_aws_access_key
# AWS_SECRET_ACCESS_KEY=your_aws_secret_key
# AWS_DEFAULT_REGION=us-east-1
# Option 3: Azure DNS
# AZURE_SUBSCRIPTION_ID=your_azure_subscription_id
# AZURE_RESOURCE_GROUP=your_resource_group
# AZURE_TENANT_ID=your_tenant_id
# AZURE_CLIENT_ID=your_client_id
# AZURE_CLIENT_SECRET=your_client_secret
# Option 4: Google Cloud DNS
# GOOGLE_PROJECT_ID=your_gcp_project_id
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
# Option 5: PowerDNS
# POWERDNS_API_URL=https://your-powerdns-server:8081
# POWERDNS_API_KEY=your_powerdns_api_key
# โ๏ธ Optional: Application Settings
SECRET_KEY=your_flask_secret_key_here
FLASK_ENV=production
HOST=0.0.0.0
PORT=8000
```
### 3. Deploy
```bash
# Start all services
docker-compose up -d
# Check status
docker-compose ps
# View logs
docker-compose logs -f certmate
```
### 4. Access CertMate
| Service | URL | Description |
|---------|-----|-------------|
| **Web Dashboard** | http://localhost:8000 | Main certificate management interface |
| **API Documentation** | http://localhost:8000/docs/ | Interactive Swagger/OpenAPI docs |
| **Alternative API Docs** | http://localhost:8000/redoc/ | ReDoc documentation |
| **Health Check** | http://localhost:8000/health | Service health monitoring |
### 5. Create Your First Certificate
Using the Web Interface:
1. Navigate to http://localhost:8000
2. Go to Settings and configure your DNS provider
3. Add your domain (e.g. `example.com`)
4. Click "Create Certificate"
Using the API:
```bash
curl -X POST "http://localhost:8000/api/certificates/create" \
-H "Authorization: Bearer your_api_token_here" \
-H "Content-Type: application/json" \
-d '{"domain": "example.com"}'
```
## ๐ Installation Methods
Choose the installation method that best fits your environment:
### ๐ณ Docker (Recommended)
Perfect for production deployments with isolation and easy scaling. **Supports multiple architectures**: AMD64 (Intel/AMD), ARM64 (Apple Silicon, ARM servers), and ARM v7 (Raspberry Pi).
```bash
# Quick start with Docker Compose
git clone https://github.com/fabriziosalmi/certmate.git
cd certmate
cp .env.example .env
# Edit .env with your configuration
docker-compose up -d
```
**Multi-Platform Support:**
```bash
# Build for multiple architectures (ARM64 + AMD64)
./build-multiplatform.sh
# Build and push to Docker Hub for all platforms
./build-multiplatform.sh -r YOUR_DOCKERHUB_USERNAME -p
# Use pre-built multi-platform image
docker run --platform linux/arm64 -d --name certmate --env-file .env -p 8000:8000 USERNAME/certmate:latest
```
> ๐ **Multi-Platform Guide**: See [DOCKER_MULTIPLATFORM.md](DOCKER_MULTIPLATFORM.md) for comprehensive multi-architecture setup instructions.
### ๐ Python Virtual Environment
Ideal for development and testing environments.
```bash
# Create and activate virtual environment
python3 -m venv certmate-env
source certmate-env/bin/activate # On Windows: certmate-env\Scripts\activate
# Install dependencies
git clone https://github.com/fabriziosalmi/certmate.git
cd certmate
pip install -r requirements.txt
# Set environment variables
export API_BEARER_TOKEN="your_token_here"
export CLOUDFLARE_TOKEN="your_cloudflare_token"
# Run the application
python app.py
```
### โธ๏ธ Kubernetes
For container orchestration and high availability deployments.
```yaml
# Example Kubernetes deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: certmate
spec:
replicas: 2
selector:
matchLabels:
app: certmate
template:
metadata:
labels:
app: certmate
spec:
containers:
- name: certmate
image: certmate:latest
ports:
- containerPort: 8000
env:
- name: API_BEARER_TOKEN
valueFrom:
secretKeyRef:
name: certmate-secrets
key: api-token
volumeMounts:
- name: certificates
mountPath: /app/certificates
volumes:
- name: certificates
persistentVolumeClaim:
claimName: certmate-certificates
```
### ๐ฆ System Package Installation
For system-wide installation on Linux distributions.
```bash
# Install system dependencies (Ubuntu/Debian)
sudo apt update
sudo apt install python3 python3-pip python3-venv certbot openssl
# Clone and install
git clone https://github.com/fabriziosalmi/certmate.git
sudo mv certmate /opt/
cd /opt/certmate
sudo pip3 install -r requirements.txt
# Create systemd service (see Service Setup section below for detailed instructions)
sudo cp certmate.service /etc/systemd/system/
sudo systemctl enable certmate
sudo systemctl start certmate
```
> ๐ **Detailed Instructions**: See [INSTALLATION.md](INSTALLATION.md) for complete setup guides for each method.
## ๐ ๏ธ Service Setup
For production deployments, CertMate should run as a system service. This section provides comprehensive instructions for setting up CertMate with systemd on Linux distributions.
### Prerequisites
- Linux system with systemd
- Python 3.9 or higher
- Root/sudo access
### 1. Create Dedicated System User
Create a dedicated user for running CertMate:
```bash
# Create system user and group
sudo useradd --system --shell /bin/false --home-dir /opt/certmate --create-home certmate
# Set proper ownership
sudo chown -R certmate:certmate /opt/certmate
```
### 2. Prepare Application Directory
Set up the application in `/opt/certmate`:
```bash
# If not already done, clone the repository
git clone https://github.com/fabriziosalmi/certmate.git
sudo mv certmate /opt/
cd /opt/certmate
# Create Python virtual environment
sudo -u certmate python3 -m venv venv
sudo -u certmate ./venv/bin/pip install -r requirements.txt
# Create necessary directories
sudo -u certmate mkdir -p certificates data
```
### 3. Configure Environment Variables
Create environment file for the service:
```bash
# Create environment file
sudo tee /opt/certmate/.env > /dev/null <&2
}
create_backup() {
if [[ -d "$CERT_DIR" ]]; then
log "Creating backup of existing certificates"
mkdir -p "$BACKUP_DIR"
cp -r "$CERT_DIR"/* "$BACKUP_DIR/" || true
fi
}
download_certificate() {
log "Downloading certificate for ${DOMAIN}"
# Download with retry logic
for i in {1..3}; do
if curl -f -H "Authorization: Bearer $API_TOKEN" \
-o "${DOMAIN}-tls.zip" \
"$CERTMATE_URL/$DOMAIN/tls"; then
log "Certificate downloaded successfully"
return 0
else
log "Download attempt $i failed, retrying..."
sleep 5
fi
done
log "Failed to download certificate after 3 attempts"
return 1
}
extract_certificate() {
log "Extracting certificate to ${CERT_DIR}"
mkdir -p "$CERT_DIR"
unzip -o "${DOMAIN}-tls.zip" -d "$CERT_DIR"
# Set proper permissions
chmod 600 "$CERT_DIR"/*.pem
chown root:ssl-cert "$CERT_DIR"/*.pem
}
reload_services() {
log "Reloading web services"
systemctl reload nginx || log "Failed to reload nginx"
systemctl reload apache2 || log "Failed to reload apache2"
systemctl reload haproxy || log "Failed to reload haproxy"
}
cleanup() {
rm -f "${DOMAIN}-tls.zip"
}
# Main execution
main() {
log "Starting certificate update for ${DOMAIN}"
create_backup
download_certificate
extract_certificate
reload_services
cleanup
log "Certificate update completed for ${DOMAIN}"
}
# Trap cleanup on exit
trap cleanup EXIT
# Run main function
main "$@"
```
**Advanced Ansible Playbook:**
```yaml
---
- name: Manage SSL certificates with CertMate multi-account support
hosts: web_servers
vars:
certmate_url: "https://certmate.company.com"
certmate_token: "{{ vault_certmate_token }}"
tasks:
- name: Configure Cloudflare accounts
uri:
url: "{{ certmate_url }}/api/settings/dns-providers/cloudflare/accounts"
method: POST
headers:
Authorization: "Bearer {{ certmate_token }}"
Content-Type: "application/json"
body_format: json
body:
account_id: "{{ item.account_id }}"
config:
name: "{{ item.name }}"
description: "{{ item.description }}"
api_token: "{{ item.api_token }}"
loop:
- account_id: "production"
name: "Production Environment"
description: "Main production Cloudflare account"
api_token: "{{ vault_cloudflare_prod_token }}"
- account_id: "staging"
name: "Staging Environment"
description: "Development and testing account"
api_token: "{{ vault_cloudflare_staging_token }}"
- name: Create certificates with specific accounts
uri:
url: "{{ certmate_url }}/api/certificates/create"
method: POST
headers:
Authorization: "Bearer {{ certmate_token }}"
Content-Type: "application/json"
body_format: json
body:
domain: "{{ item.domain }}"
dns_provider: "{{ item.provider }}"
account_id: "{{ item.account_id }}"
loop:
- domain: "api.company.com"
provider: "cloudflare"
account_id: "production"
- domain: "staging.company.com"
provider: "cloudflare"
account_id: "staging"
- domain: "test.company.com"
provider: "route53"
account_id: "backup-aws"
- name: Download and deploy certificates
block:
- name: Download certificate
uri:
url: "{{ certmate_url }}/{{ item }}/tls"
headers:
Authorization: "Bearer {{ certmate_token }}"
dest: "/tmp/{{ item }}-tls.zip"
- name: Extract certificate
unarchive:
src: "/tmp/{{ item }}-tls.zip"
dest: "/etc/ssl/certs/{{ item }}/"
remote_src: yes
owner: root
group: ssl-cert
mode: '0640'
loop:
- "api.company.com"
- "staging.company.com"
- "test.company.com"
```
become: yes
vars:
certmate_url: "https://certmate.company.com"
api_token: "{{ vault_certmate_token }}"
certificate_domains:
- name: "api.company.com"
dns_provider: "cloudflare"
nginx_sites: ["api"]
services_to_reload: ["nginx"]
- name: "web.company.com"
dns_provider: "route53"
nginx_sites: ["web", "admin"]
services_to_reload: ["nginx", "haproxy"]
tasks:
- name: Create certificate directories
file:
path: "/etc/ssl/certs/{{ item.name }}"
state: directory
owner: root
group: ssl-cert
mode: '0750'
loop: "{{ certificate_domains }}"
- name: Check certificate expiry
uri:
url: "{{ certmate_url }}/api/certificates/{{ item.name }}/deployment-status"
method: GET
headers:
Authorization: "Bearer {{ api_token }}"
register: cert_status
loop: "{{ certificate_domains }}"
- name: Create new certificates if needed
uri:
url: "{{ certmate_url }}/api/certificates/create"
method: POST
headers:
Authorization: "Bearer {{ api_token }}"
Content-Type: "application/json"
body_format: json
body:
domain: "{{ item.name }}"
dns_provider: "{{ item.dns_provider }}"
loop: "{{ certificate_domains }}"
when: cert_status.results[ansible_loop.index0].json.needs_renewal | default(false)
- name: Download certificates
uri:
url: "{{ certmate_url }}/{{ item.name }}/tls"
method: GET
headers:
Authorization: "Bearer {{ api_token }}"
dest: "/tmp/{{ item.name }}-tls.zip"
creates: "/tmp/{{ item.name }}-tls.zip"
loop: "{{ certificate_domains }}"
- name: Extract certificates
unarchive:
src: "/tmp/{{ item.name }}-tls.zip"
dest: "/etc/ssl/certs/{{ item.name }}/"
owner: root
group: ssl-cert
mode: '0640'
remote_src: yes
loop: "{{ certificate_domains }}"
notify:
- reload nginx
- reload haproxy
- restart services
- name: Verify certificate installation
openssl_certificate:
path: "/etc/ssl/certs/{{ item.name }}/fullchain.pem"
provider: assertonly
has_expired: no
valid_in: 86400 # Valid for at least 1 day
loop: "{{ certificate_domains }}"
- name: Update nginx SSL configuration
template:
src: "nginx-ssl.conf.j2"
dest: "/etc/nginx/sites-available/{{ item.1 }}"
backup: yes
loop: "{{ certificate_domains | subelements('nginx_sites') }}"
notify: reload nginx
- name: Cleanup temporary files
file:
path: "/tmp/{{ item.name }}-tls.zip"
state: absent
loop: "{{ certificate_domains }}"
handlers:
- name: reload nginx
systemd:
name: nginx
state: reloaded
- name: reload haproxy
systemd:
name: haproxy
state: reloaded
- name: restart services
systemd:
name: "{{ item }}"
state: restarted
loop: "{{ services_to_restart | default([]) }}"
```
## โ๏ธ Configuration Guide
### ๐ง Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `API_BEARER_TOKEN` | โ
| - | Bearer token for API authentication |
| `SECRET_KEY` | โ | auto-generated | Flask secret key for sessions |
| `HOST` | โ | `127.0.0.1` | Server bind address |
| `PORT` | โ | `8000` | Server port |
| `FLASK_ENV` | โ | `production` | Flask environment |
| `FLASK_DEBUG` | โ | `false` | Enable debug mode |
### ๐ DNS Provider Configuration
#### Cloudflare Setup
1. Go to [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens)
2. Click "Create Token" โ "Custom token"
3. Set permissions:
- **Zone**: `DNS:Edit` + `Zone:Read`
- **Zone Resources**: Include specific zones or all zones
4. Copy the generated token
```bash
# Environment variable
CLOUDFLARE_TOKEN=your_cloudflare_api_token_here
```
#### AWS Route53 Setup
1. Create IAM user with Route53 permissions
2. Attach policy: `Route53FullAccess` or custom policy:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:GetChange",
"route53:ChangeResourceRecordSets"
],
"Resource": "*"
}
]
}
```
```bash
# Environment variables
AWS_ACCESS_KEY_ID=your_access_key_id
AWS_SECRET_ACCESS_KEY=your_secret_access_key
AWS_DEFAULT_REGION=us-east-1
```
#### Azure DNS Setup
1. Create Service Principal:
```bash
az ad sp create-for-rbac --name "CertMate" --role "DNS Zone Contributor" --scopes "/subscriptions/{subscription-id}/resourceGroups/{resource-group}"
```
```bash
# Environment variables
AZURE_SUBSCRIPTION_ID=your_subscription_id
AZURE_RESOURCE_GROUP=your_resource_group_name
AZURE_TENANT_ID=your_tenant_id
AZURE_CLIENT_ID=your_client_id
AZURE_CLIENT_SECRET=your_client_secret
```
#### Google Cloud DNS Setup
1. Create service account with DNS Administrator role
2. Download JSON key file
```bash
# Environment variables
GOOGLE_PROJECT_ID=your_project_id
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
```
#### PowerDNS Setup
```bash
# Environment variables
POWERDNS_API_URL=https://your-powerdns-server:8081
POWERDNS_API_KEY=your_api_key
```
### ๐ Directory Structure
```
certmate/
โโโ ๐ app.py # Main Flask application
โโโ ๐ requirements.txt # Python dependencies
โโโ ๐ docker-compose.yml # Docker Compose configuration
โโโ ๐ Dockerfile # Container build instructions
โโโ ๐ nginx.conf # Nginx reverse proxy config
โโโ ๐ .env.example # Environment template
โโโ ๐ README.md # This documentation
โโโ ๐ INSTALLATION.md # Detailed installation guide
โโโ ๐ DNS_PROVIDERS.md # DNS provider configuration
โโโ ๐ CONTRIBUTING.md # Contribution guidelines
โโโ ๐ certificates/ # Certificate storage
โ โโโ ๐ {domain}/
โ โโโ ๐ cert.pem # Server certificate
โ โโโ ๐ chain.pem # Certificate chain
โ โโโ ๐ fullchain.pem # Full chain
โ โโโ ๐ privkey.pem # Private key
โโโ ๐ data/ # Application data
โ โโโ โ๏ธ settings.json # Persistent settings
โโโ ๐ logs/ # Application logs
โโโ ๐ letsencrypt/ # Let's Encrypt working directory
โ โโโ ๐ config/ # Certbot configuration
โ โโโ ๐ work/ # Certbot working files
โ โโโ ๐ logs/ # Certbot logs
โโโ ๐ templates/ # Web interface templates
โโโ ๐ index.html # Main dashboard
โโโ โ๏ธ settings.html # Settings page
```
## ๐ Security & Best Practices
### ๐ก๏ธ Security Considerations
#### Authentication & Authorization
- **Strong Bearer Tokens**: Use cryptographically secure tokens (32+ characters)
- **Token Rotation**: Regularly rotate API tokens
- **Environment Variables**: Never commit tokens to version control
- **HTTPS Only**: Always use HTTPS in production environments
- **IP Restrictions**: Implement firewall rules to restrict access
#### Certificate Security
- **File Permissions**: Private keys stored with `600` permissions
- **Directory Permissions**: Certificate directories with `700` permissions
- **Backup Encryption**: Encrypt certificate backups
- **Access Logging**: Monitor certificate access patterns
#### Network Security
```bash
# Example firewall rules (iptables)
# Allow only specific IPs to access CertMate
iptables -A INPUT -p tcp --dport 8000 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 8000 -s 192.168.0.0/16 -j ACCEPT
iptables -A INPUT -p tcp --dport 8000 -j DROP
```
### โก Performance Optimization
#### Production Deployment
```yaml
# docker-compose.prod.yml
version: '3.8'
services:
certmate:
image: certmate:latest
deploy:
replicas: 2
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
environment:
- FLASK_ENV=production
- GUNICORN_WORKERS=4
- GUNICORN_THREADS=2
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
```
#### Load Balancing with Nginx
```nginx
upstream certmate_backend {
server certmate1:8000;
server certmate2:8000;
server certmate3:8000;
}
server {
listen 443 ssl http2;
server_name certmate.company.com;
ssl_certificate /etc/ssl/certs/certmate.company.com/fullchain.pem;
ssl_certificate_key /etc/ssl/certs/certmate.company.com/privkey.pem;
location / {
proxy_pass http://certmate_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# API rate limiting
limit_req zone=api burst=10 nodelay;
}
}
```
### ๐ Backup & Recovery
CertMate provides comprehensive backup and recovery capabilities built directly into the application, ensuring your certificates and configuration data are always protected.
#### Built-in Backup System
**Automatic Backups:**
- **Settings Backup** - Automatically created when DNS providers, domains, or application settings are modified
- **Certificate Backup** - Automatically created when new certificates are generated or renewed
- **Retention Management** - Configurable retention policy (default: 10 most recent backups)
- **Automatic Cleanup** - Old backups are automatically removed based on retention settings
**Manual Backups:**
- **On-Demand Creation** - Create backups anytime via the web interface or API
- **Selective Backup** - Choose to backup settings, certificates, or both
- **Download Support** - Export backups for external storage and disaster recovery
#### Web Interface Backup Management
Access backup features from the Settings page:
```html
Create Settings Backup
Create Certificate Backup
- Download backups for external storage
- Restore from any backup point
- View backup contents and metadata
- Delete specific backups manually
```
#### API Backup Operations
**Create Backups:**
```bash
# Create settings backup
curl -X POST "http://localhost:8000/api/backup/settings" \
-H "Authorization: Bearer your_token"
# Create certificate backup
curl -X POST "http://localhost:8000/api/backup/certificates" \
-H "Authorization: Bearer your_token"
```
**List and Download Backups:**
```bash
# List all backups
curl -H "Authorization: Bearer your_token" \
"http://localhost:8000/api/backups"
# Download specific backup
curl -H "Authorization: Bearer your_token" \
"http://localhost:8000/api/backup/download/settings_20241225_120000.json" \
-o backup.json
```
#### Backup File Structure
**Settings Backup (JSON):**
```json
{
"timestamp": "2024-12-25T12:00:00Z",
"version": "1.0",
"dns_providers": {...},
"domains": [...],
"settings": {...}
}
```
**Certificate Backup (ZIP):**
```
certificates_20241225_120000.zip
โโโ domain1.com/
โ โโโ cert.pem
โ โโโ chain.pem
โ โโโ fullchain.pem
โ โโโ privkey.pem
โโโ domain2.com/
โโโ cert.pem
โโโ chain.pem
โโโ fullchain.pem
โโโ privkey.pem
```
#### External Backup Integration
For additional protection, integrate with external backup systems:
**Automated External Backup Script:**
```bash
#!/bin/bash
# /opt/scripts/backup-certmate-external.sh
BACKUP_DIR="/backup/certmate/$(date +%Y%m%d_%H%M%S)"
CERT_DIR="/opt/certmate/certificates"
DATA_DIR="/opt/certmate/data"
BACKUP_STORAGE="/backup/certmate/backups"
RETENTION_DAYS=30
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Download latest backups via API
curl -H "Authorization: Bearer $API_TOKEN" \
"http://localhost:8000/api/backups/latest/settings" \
-o "$BACKUP_DIR/settings_backup.json"
curl -H "Authorization: Bearer $API_TOKEN" \
"http://localhost:8000/api/backups/latest/certificates" \
-o "$BACKUP_DIR/certificates_backup.zip"
# Backup certificates directory
tar -czf "$BACKUP_DIR/certificates.tar.gz" "$CERT_DIR"
# Backup application data
tar -czf "$BACKUP_DIR/data.tar.gz" "$DATA_DIR"
# Copy built-in backups
cp -r "$BACKUP_STORAGE"/* "$BACKUP_DIR/"
# Encrypt backups (optional)
gpg --cipher-algo AES256 --compress-algo 1 --symmetric \
--output "$BACKUP_DIR/certificates.tar.gz.gpg" \
"$BACKUP_DIR/certificates.tar.gz"
# Cleanup old backups
find /backup/certmate -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;
echo "External backup completed: $BACKUP_DIR"
```
#### Recovery Procedures
**Web Interface Recovery:**
1. Navigate to Settings โ Backup Management
2. Select the backup to restore from
3. Choose restore type (settings, certificates, or both)
4. Confirm restoration
5. Application will restart if settings are restored
**API Recovery:**
```bash
# Restore settings from backup
curl -X POST "http://localhost:8000/api/backup/restore/settings" \
-H "Authorization: Bearer your_token" \
-H "Content-Type: application/json" \
-d '{"backup_id": "settings_20241225_120000"}'
# Restore certificates from backup
curl -X POST "http://localhost:8000/api/backup/restore/certificates" \
-H "Authorization: Bearer your_token" \
-H "Content-Type: application/json" \
-d '{"backup_id": "certificates_20241225_120000"}'
```
**Manual Recovery from External Backup:**
```bash
#!/bin/bash
# /opt/scripts/backup-certmate.sh
BACKUP_DIR="/backup/certmate/$(date +%Y%m%d_%H%M%S)"
CERT_DIR="/opt/certmate/certificates"
DATA_DIR="/opt/certmate/data"
RETENTION_DAYS=30
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Backup certificates
tar -czf "$BACKUP_DIR/certificates.tar.gz" "$CERT_DIR"
# Backup application data
tar -czf "$BACKUP_DIR/data.tar.gz" "$DATA_DIR"
# Backup database if using external DB
# mysqldump certmate > "$BACKUP_DIR/database.sql"
# Encrypt backups
gpg --cipher-algo AES256 --compress-algo 1 --symmetric \
--output "$BACKUP_DIR/certificates.tar.gz.gpg" \
"$BACKUP_DIR/certificates.tar.gz"
# Cleanup old backups
find /backup/certmate -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;
echo "Backup completed: $BACKUP_DIR"
```
#### Recovery Procedure
```bash
#!/bin/bash
# Recovery from backup
BACKUP_DATE="20241225_120000"
BACKUP_DIR="/backup/certmate/$BACKUP_DATE"
# Stop services
docker-compose down
# Restore certificates
gpg --decrypt "$BACKUP_DIR/certificates.tar.gz.gpg" | \
tar -xzf - -C /opt/certmate/
# Restore data
tar -xzf "$BACKUP_DIR/data.tar.gz" -C /opt/certmate/
# Set permissions
chown -R 1000:1000 /opt/certmate/certificates
chmod -R 700 /opt/certmate/certificates
# Start services
docker-compose up -d
echo "Recovery completed from backup: $BACKUP_DATE"
```
## ๐ Monitoring & Observability
### ๐ Health Monitoring
#### Built-in Health Checks
```bash
# Basic health check
curl -f http://localhost:8000/health
# Detailed health with auth
curl -H "Authorization: Bearer your_token" \
http://localhost:8000/api/certificates
```
#### Prometheus Metrics Integration
```python
# Add to app.py for Prometheus monitoring
from prometheus_client import Counter, Histogram, generate_latest
# Metrics
certificate_requests = Counter('certmate_certificate_requests_total',
'Total certificate requests', ['domain', 'status'])
certificate_expiry = Histogram('certmate_certificate_expiry_days',
'Days until certificate expiry', ['domain'])
@app.route('/metrics')
def metrics():
return generate_latest()
```
#### Log Aggregation
```yaml
# docker-compose.logging.yml
version: '3.8'
services:
certmate:
logging:
driver: "fluentd"
options:
fluentd-address: localhost:24224
tag: certmate
fluentd-async-connect: "true"
fluentd:
image: fluent/fluentd:v1.14
volumes:
- ./fluentd/conf:/fluentd/etc
- ./logs:/var/log/fluentd
ports:
- "24224:24224"
- "24224:24224/udp"
```
### ๐ Grafana Dashboard Example
```json
{
"dashboard": {
"title": "CertMate SSL Certificate Monitoring",
"panels": [
{
"title": "Certificate Expiry Status",
"targets": [
{
"expr": "certmate_certificate_expiry_days < 30",
"legendFormat": "Expiring Soon ({{domain}})"
}
],
"alert": {
"conditions": [
{
"query": {"queryType": "", "refId": "A"},
"reducer": {"type": "last", "params": []},
"evaluator": {"params": [30], "type": "lt"}
}
],
"executionErrorState": "alerting",
"frequency": "1h",
"handler": 1,
"name": "Certificate Expiring",
"noDataState": "no_data",
"notifications": []
}
}
]
}
}
```
### ๐จ Alerting Configuration
#### Webhook Notifications
```python
# Add webhook notification support
import requests
def send_webhook_notification(domain, event_type, details):
webhook_url = os.getenv('WEBHOOK_URL')
if not webhook_url:
return
payload = {
'domain': domain,
'event': event_type,
'timestamp': datetime.now().isoformat(),
'details': details
}
try:
requests.post(webhook_url, json=payload, timeout=10)
except Exception as e:
logger.error(f"Failed to send webhook: {e}")
```
#### Slack Integration Example
```bash
# Slack notification script
#!/bin/bash
SLACK_WEBHOOK="your_slack_webhook_url"
DOMAIN="$1"
STATUS="$2"
MESSAGE="Certificate for $DOMAIN: $STATUS"
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"๐ $MESSAGE\"}" \
"$SLACK_WEBHOOK"
```
## ๐ง Troubleshooting Guide
### ๐จ Common Issues & Solutions
#### Certificate Creation Failures
**Issue**: `DNS validation failed`
```bash
# Check DNS propagation
dig TXT _acme-challenge.example.com @8.8.8.8
# Verify DNS provider credentials
curl -H "Authorization: Bearer cf_token" \
"https://api.cloudflare.com/client/v4/user/tokens/verify"
```
**Issue**: `Rate limit exceeded`
```bash
# Let's Encrypt rate limits:
# - 50 certificates per registered domain per week
# - 5 duplicate certificates per week
# - 300 new orders per account per 3 hours
# Check rate limit status
curl "https://crt.sh/?q=example.com&output=json" | jq length
```
**Issue**: `Permission denied accessing certificate files`
```bash
# Fix file permissions
sudo chown -R certmate:certmate /opt/certmate/certificates
sudo chmod -R 700 /opt/certmate/certificates
sudo chmod 600 /opt/certmate/certificates/*/privkey.pem
```
#### API Authentication Issues
**Issue**: `401 Unauthorized`
```bash
# Verify token format
curl -H "Authorization: Bearer your_token_here" \
http://localhost:8000/api/certificates
# Check token in settings
docker exec certmate cat /app/data/settings.json | jq .api_bearer_token
```
**Issue**: `Token not found`
```bash
# Reset API token
docker exec -it certmate python -c "
import json
with open('/app/data/settings.json', 'r+') as f:
data = json.load(f)
data['api_bearer_token'] = 'new_secure_token_here'
f.seek(0)
json.dump(data, f, indent=2)
f.truncate()
"
```
#### Docker & Container Issues
**Issue**: `Container won't start`
```bash
# Check logs
docker-compose logs certmate
# Verify environment variables
docker-compose config
# Check port conflicts
netstat -tulpn | grep :8000
```
**Issue**: `Volume mount issues`
```bash
# Fix volume permissions
sudo chown -R 1000:1000 ./certificates ./data ./logs
# Check volume mounts
docker inspect certmate | jq '.[0].Mounts'
```
#### DNS Provider Specific Issues
**Cloudflare**:
```bash
# Verify API token permissions
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer your_token_here"
# Check zone access
curl -X GET "https://api.cloudflare.com/client/v4/zones" \
-H "Authorization: Bearer your_token_here"
```
**AWS Route53**:
```bash
# Test AWS credentials
aws sts get-caller-identity
# Check Route53 permissions
aws route53 list-hosted-zones
```
**Azure DNS**:
```bash
# Verify service principal
az login --service-principal \
-u $AZURE_CLIENT_ID \
-p $AZURE_CLIENT_SECRET \
--tenant $AZURE_TENANT_ID
# Check DNS zone access
az network dns zone list
```
### ๐ Debug Mode
Enable debug logging for troubleshooting:
```bash
# Environment variable
FLASK_DEBUG=true
FLASK_ENV=development
# Or in Docker Compose
docker-compose -f docker-compose.yml -f docker-compose.debug.yml up
```
### ๐ Support Checklist
Before seeking help, please provide:
- [ ] CertMate version/commit hash
- [ ] DNS provider being used
- [ ] Error messages from logs
- [ ] Steps to reproduce the issue
- [ ] Environment details (Docker, Python version, OS)
```bash
# Collect system information
echo "=== CertMate Debug Info ==="
echo "Version: $(docker exec certmate python -c 'import app; print(getattr(app, "__version__", "unknown"))')"
echo "Python: $(docker exec certmate python --version)"
echo "OS: $(docker exec certmate cat /etc/os-release | head -2)"
echo "Certbot: $(docker exec certmate certbot --version)"
echo "DNS Plugins: $(docker exec certmate pip list | grep certbot-dns)"
echo "Certificates: $(docker exec certmate ls -la /app/certificates)"
echo "Settings: $(docker exec certmate cat /app/data/settings.json | jq .)"
```
## ๐ Documentation
### ๐ Complete Documentation Set
| Document | Description | Target Audience |
|----------|-------------|-----------------|
| **[README.md](README.md)** | Main documentation and quick start | All users |
| **[INSTALLATION.md](INSTALLATION.md)** | Detailed installation instructions | System administrators |
| **[DNS_PROVIDERS.md](DNS_PROVIDERS.md)** | DNS provider setup guides | DevOps engineers |
| **[CONTRIBUTING.md](CONTRIBUTING.md)** | Development and contribution guide | Developers |
| **[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)** | Community guidelines | Contributors |
### ๐ Online Resources
- **API Documentation**: http://your-server:8000/docs/ (Swagger UI)
- **Alternative API Docs**: http://your-server:8000/redoc/ (ReDoc)
- **GitHub Repository**: https://github.com/fabriziosalmi/certmate
- **Docker Hub**: https://hub.docker.com/r/certmate/certmate
- **Issue Tracker**: https://github.com/fabriziosalmi/certmate/issues
### ๐ Examples Repository
Check out our examples repository for:
- Production deployment configurations
- Integration scripts for popular tools
- Terraform modules
- Kubernetes manifests
- CI/CD pipeline examples
## ๐ Roadmap & Future Features
### ๐ฎ Planned Features
- **๐ Certificate Templates** - Predefined certificate configurations
- **๐ Advanced Analytics** - Certificate usage and performance metrics
- **๐ ACME v2 Features** - External account binding, certificate transparency
- **๐ Multi-Region Support** - Geographic certificate distribution
- **๐ฑ Mobile App** - iOS/Android certificate monitoring
- **๐ค AI-Powered Renewal** - Intelligent renewal scheduling
- **๐ Plugin System** - Custom DNS provider plugins
- **๐ Enterprise Dashboard** - Multi-tenant certificate management
### ๐๏ธ Version History
| Version | Release Date | Key Features |
|---------|--------------|--------------|
| **v2.0.0** | 2024-12-25 | Multi-DNS provider support, enhanced API |
| **v1.5.0** | 2024-11-15 | Docker improvements, monitoring features |
| **v1.0.0** | 2024-10-01 | Initial release with Cloudflare support |
### ๐ค Community Contributions
We welcome contributions! Areas where we need help:
- **Documentation** - Tutorials, use cases, translations
- **Testing** - DNS provider testing, edge cases
- **Integrations** - New DNS providers, monitoring tools
- **Features** - UI improvements, API enhancements
## ๐ค Contributing
We love contributions! CertMate is an open-source project and we welcome:
### ๐ ๏ธ Types of Contributions
- **๐ Bug Reports** - Help us identify and fix issues
- **๐ก Feature Requests** - Suggest new functionality
- **๐ Documentation** - Improve guides and examples
- **๐งช Testing** - Test new features and edge cases
- **๐ป Code** - Submit pull requests with improvements
### ๐ Quick Start for Contributors
```bash
# Fork and clone the repository
git clone https://github.com/fabriziosalmi/certmate.git
cd certmate
# Create development environment
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install -r requirements-dev.txt
# Set up pre-commit hooks
pre-commit install
# Run tests
pytest
# Start development server
python app.py
```
### ๐ Contribution Guidelines
1. **Fork** the repository
2. **Create** a feature branch (`git checkout -b feature/amazing-feature`)
3. **Commit** your changes (`git commit -m 'Add amazing feature'`)
4. **Push** to the branch (`git push origin feature/amazing-feature`)
5. **Open** a Pull Request
### ๐ Contributors
Thanks to all contributors who make CertMate better!
[](https://github.com/fabriziosalmi/certmate/graphs/contributors)
## ๐ License
This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details.
### ๐ฏ MIT License Summary
- โ
**Commercial Use** - Use in commercial projects
- โ
**Modification** - Modify and distribute changes
- โ
**Distribution** - Distribute the software
- โ
**Private Use** - Use privately
- โ **Liability** - No warranty or liability
- โ **Patent Grant** - No patent rights granted
---
**Made with โค๏ธ by the CertMate Team**
[โญ Star us on GitHub](https://github.com/fabriziosalmi/certmate) โข [๐ Report Bug](https://github.com/fabriziosalmi/certmate/issues) โข [๐ก Request Feature](https://github.com/fabriziosalmi/certmate/issues/new?template=feature_request.md)