Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions DNS_ANALYSIS_INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,19 @@ DNS_ANALYSIS_INDEX.md (You are here)

## Supported Providers Summary

**Total:** 21 DNS Providers
**Total:** 23 DNS Providers

### By Category
- **Major Cloud:** Cloudflare, AWS Route53, Google Cloud, Azure (4)
- **Enterprise:** PowerDNS, DNS Made Easy, NS1 (3)
- **Cloud Infrastructure:** DigitalOcean, Linode, Vultr, Hetzner (4)
- **Registrars:** Gandi, Namecheap, Porkbun, GoDaddy (4)
- **Web Hosting:** Hostinger (1)
- **Regional:** OVH, ArvanCloud (2)
- **Specialized:** RFC2136, ACME-DNS, Hurricane Electric, Dynu (4)
- **Specialized:** RFC2136, ACME-DNS, Hurricane Electric, Dynu, Infomaniak (5)

### By Features
- **Single-field credentials:** Cloudflare, DigitalOcean, Linode, Gandi, Vultr, Hetzner, NS1, ArvanCloud
- **Single-field credentials:** Cloudflare, DigitalOcean, Linode, Gandi, Vultr, Hetzner, NS1, ArvanCloud, Hostinger
- **Multi-field credentials:** Route53, Azure, Google Cloud, PowerDNS, OVH, Namecheap, RFC2136, ACME-DNS, etc.
- **Environment variables:** Route53 (AWS_*), Azure (AZURE_*), Google (GOOGLE_*)
- **Environment-only:** PowerDNS (POWERDNS_*), Cloudflare (CLOUDFLARE_TOKEN)
Expand Down
24 changes: 19 additions & 5 deletions DNS_PROVIDERS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DNS Providers Support

CertMate now supports **22 DNS providers** for Let's Encrypt DNS challenges through individual certbot plugins that provide reliable, well-tested DNS challenge support.
CertMate now supports **23 DNS providers** for Let's Encrypt DNS challenges through individual certbot plugins that provide reliable, well-tested DNS challenge support.

## 🎯 Supported Providers

Expand Down Expand Up @@ -30,6 +30,7 @@ All providers are supported through individual, well-maintained certbot plugins:
| **Dynu** | `certbot-dns-dynudns` | API Token | Dynamic DNS service |
| **ArvanCloud** | `certbot-dns-arvancloud` | API Key | Iranian cloud provider |
| **ACME-DNS** | `certbot-acme-dns` | API URL, Username, Password, Subdomain | Generic ACME-DNS server |
| **Hostinger** | `certbot-dns-hostinger` | API Token | Web hosting provider |

## 🛠 Configuration

Expand Down Expand Up @@ -224,6 +225,19 @@ curl -X POST http://localhost:5000/api/settings \
}
```

### Hostinger
```bash
# Get API token from Hostinger Control Panel
{
"dns_provider": "hostinger",
"dns_providers": {
"hostinger": {
"api_token": "your_hostinger_api_token"
}
}
}
```

## Creating Certificates

### Using Default Provider
Expand All @@ -247,7 +261,7 @@ curl -X POST http://localhost:5000/api/certificates/create \

## 🚀 How Provider Support Works

CertMate uses individual, well-maintained certbot plugins for maximum reliability. All 19 supported providers use dedicated certbot plugins, ensuring stability and consistent behavior across all DNS providers.
CertMate uses individual certbot plugins for maximum reliability. All 23 supported providers use certbot plugins (either provider-specific or protocol-based like RFC2136), ensuring stability and consistent behavior across all DNS providers.

## 🔍 Provider Detection Logic

Expand All @@ -258,7 +272,7 @@ supported_providers = [
'digitalocean', 'linode', 'gandi', 'ovh', 'namecheap',
'vultr', 'dnsmadeeasy', 'nsone', 'rfc2136',
'hetzner', 'porkbun', 'godaddy', 'he-ddns', 'dynudns',
'arvancloud', 'acme-dns'
'arvancloud', 'acme-dns', 'hostinger'
]

if dns_provider in supported_providers:
Expand Down Expand Up @@ -343,11 +357,11 @@ curl -X GET http://localhost:5000/api/settings/dns-providers \

## 📊 Provider Statistics

- **Total Supported**: 21 providers
- **Total Supported**: 23 providers
- **Geographic Coverage**: Global (all continents)
- **Enterprise Providers**: AWS, Azure, GCP, Cloudflare, PowerDNS, DNS Made Easy, NS1
- **European Providers**: OVH, Gandi, Hetzner
- **Budget Providers**: Namecheap, DigitalOcean, Linode, Vultr, Porkbun
- **Budget Providers**: Namecheap, DigitalOcean, Linode, Vultr, Porkbun, Hostinger
- **Free Providers**: Hurricane Electric, Dynu, ACME-DNS

---
Expand Down
6 changes: 6 additions & 0 deletions DNS_PROVIDERS_QUICK_REFERENCE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ DOMAIN REGISTRARS:
14. Porkbun certbot-dns-porkbun
15. GoDaddy certbot-dns-godaddy

WEB HOSTING PROVIDERS:
16. Hostinger certbot-dns-hostinger

REGIONAL PROVIDERS:
16. OVH certbot-dns-ovh
17. ArvanCloud certbot-dns-arvancloud
Expand Down Expand Up @@ -70,6 +73,9 @@ Single-field providers:
• nsone: api_key
• arvancloud: api_key

Single-field providers (continued):
• hostinger: api_token

Two-field providers:
• route53: access_key_id, secret_access_key (+ region)
• dnsmadeeasy: api_key, secret_key
Expand Down
16 changes: 10 additions & 6 deletions DNS_PROVIDER_ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,18 @@ CertMate implements a **modular, extensible DNS provider architecture** supporti
14. **Porkbun** - `certbot-dns-porkbun` - Domain registrar with DNS
15. **GoDaddy** - `certbot-dns-godaddy` - Domain registrar

### Web Hosting Providers
16. **Hostinger** - `certbot-dns-hostinger` - Web hosting provider

### Regional Providers
16. **OVH** - `certbot-dns-ovh` - European hosting
17. **ArvanCloud** - `certbot-dns-arvancloud` - Iranian cloud provider
17. **OVH** - `certbot-dns-ovh` - European hosting
18. **ArvanCloud** - `certbot-dns-arvancloud` - Iranian cloud provider

### Specialized Providers
18. **RFC2136** - `certbot-dns-rfc2136` - Standard DNS update protocol (BIND-compatible)
19. **ACME-DNS** - `certbot-acme-dns` - Generic ACME-DNS server
20. **Hurricane Electric** - `certbot-dns-he-ddns` - Free DNS hosting
21. **Dynu** - `certbot-dns-dynudns` - Dynamic DNS service
19. **RFC2136** - `certbot-dns-rfc2136` - Standard DNS update protocol (BIND-compatible)
20. **ACME-DNS** - `certbot-acme-dns` - Generic ACME-DNS server
21. **Hurricane Electric** - `certbot-dns-he-ddns` - Free DNS hosting
22. **Dynu** - `certbot-dns-dynudns` - Dynamic DNS service

---

Expand Down Expand Up @@ -202,6 +205,7 @@ POWERDNS_API_KEY=your_key
| **dynudns** | `token` |
| **arvancloud** | `api_key` |
| **acme-dns** | `api_url`, `username`, `password`, `subdomain` |
| **hostinger** | `api_token` |

---

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
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)
- **🌐 Multi-Cloud Support** - Works with 23 DNS providers (Cloudflare, AWS, Azure, GCP, Hetzner, Porkbun, GoDaddy, Hostinger, 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
Expand Down Expand Up @@ -118,6 +118,7 @@ CertMate supports **19 DNS providers** through Let's Encrypt DNS-01 challenge vi
| ** 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** |
| **🟣 Hostinger** | API Token | ➖ Single | Web hosting provider | ✅ **Stable** |
| **🔵 Hurricane Electric** | Username, Password | ➖ Single | Free DNS hosting | ✅ **Stable** |
| **🔶 Dynu** | API Token | ➖ Single | Dynamic DNS service | ✅ **Stable** |

Expand All @@ -126,7 +127,8 @@ CertMate supports **19 DNS providers** through Let's Encrypt DNS-01 challenge vi
- **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
- **Domain Registrars**: Gandi, OVH, Namecheap, Porkbun, GoDaddy
- **Web Hosting**: Hostinger
- **European Providers**: OVH, Gandi, Hetzner
- **Free Services**: Hurricane Electric, Dynu
- **Standard Protocols**: RFC2136 (for BIND and compatible servers)
Expand Down
10 changes: 8 additions & 2 deletions modules/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ def create_api_models(api):
'api_key': fields.String(description='ArvanCloud API key')
})

hostinger_model = api.model('HostingerConfig', {
'api_token': fields.String(description='Hostinger API token')
})

acme_dns_model = api.model('ACMEDNSConfig', {
'api_url': fields.String(description='ACME-DNS server URL'),
'username': fields.String(description='ACME-DNS username'),
Expand Down Expand Up @@ -124,6 +128,7 @@ def create_api_models(api):
'he-ddns': fields.Nested(he_ddns_model),
'dynudns': fields.Nested(dynudns_model),
'arvancloud': fields.Nested(arvancloud_model),
'hostinger': fields.Nested(hostinger_model),
'acme-dns': fields.Nested(acme_dns_model),
# Support for any other provider via certbot-dns-multi
'multi': fields.Raw(description='Configuration for any DNS provider via certbot-dns-multi')
Expand All @@ -145,13 +150,13 @@ def create_api_models(api):
'email': fields.String(description='Email for Let\'s Encrypt'),
'auto_renew': fields.Boolean(description='Enable auto-renewal'),
'api_bearer_token': fields.String(description='API bearer token for authentication'),
'dns_provider': fields.String(description='Active DNS provider', enum=['cloudflare', 'route53', 'azure', 'google', 'powerdns', 'digitalocean', 'linode', 'gandi', 'ovh', 'namecheap', 'vultr', 'dnsmadeeasy', 'nsone', 'rfc2136', 'hetzner', 'porkbun', 'godaddy', 'he-ddns', 'dynudns', 'arvancloud', 'acme-dns']),
'dns_provider': fields.String(description='Active DNS provider', enum=['cloudflare', 'route53', 'azure', 'google', 'powerdns', 'digitalocean', 'linode', 'gandi', 'ovh', 'namecheap', 'vultr', 'dnsmadeeasy', 'nsone', 'rfc2136', 'hetzner', 'porkbun', 'godaddy', 'he-ddns', 'dynudns', 'arvancloud', 'acme-dns', 'hostinger']),
'dns_providers': fields.Nested(dns_providers_model, description='DNS provider configurations')
})

create_cert_model = api.model('CreateCertificate', {
'domain': fields.String(required=True, description='Domain name to create certificate for'),
'dns_provider': fields.String(description='DNS provider to use (optional, uses default from settings)', enum=['cloudflare', 'route53', 'azure', 'google', 'powerdns', 'digitalocean', 'linode', 'gandi', 'ovh', 'namecheap', 'vultr', 'dnsmadeeasy', 'nsone', 'rfc2136', 'hetzner', 'porkbun', 'godaddy', 'he-ddns', 'dynudns', 'arvancloud', 'acme-dns']),
'dns_provider': fields.String(description='DNS provider to use (optional, uses default from settings)', enum=['cloudflare', 'route53', 'azure', 'google', 'powerdns', 'digitalocean', 'linode', 'gandi', 'ovh', 'namecheap', 'vultr', 'dnsmadeeasy', 'nsone', 'rfc2136', 'hetzner', 'porkbun', 'godaddy', 'he-ddns', 'dynudns', 'arvancloud', 'acme-dns', 'hostinger']),
'account_id': fields.String(description='DNS provider account ID to use (optional, uses default account if not specified)'),
'ca_provider': fields.String(description='Certificate Authority provider to use (optional, uses default from settings)', enum=['letsencrypt', 'digicert', 'private_ca'])
})
Expand Down Expand Up @@ -299,6 +304,7 @@ def create_api_models(api):
'he_ddns_model': he_ddns_model,
'dynudns_model': dynudns_model,
'arvancloud_model': arvancloud_model,
'hostinger_model': hostinger_model,
'acme_dns_model': acme_dns_model,
'multi_provider_model': multi_provider_model,
# Storage backend models
Expand Down
14 changes: 10 additions & 4 deletions modules/core/certificates.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
create_powerdns_config, create_digitalocean_config, create_linode_config,
create_gandi_config, create_ovh_config, create_namecheap_config,
create_arvancloud_config, create_infomaniak_config, create_acme_dns_config,
create_multi_provider_config
create_hostinger_config, create_multi_provider_config
)

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -83,7 +83,8 @@ def _create_dns_config_compat(self, dns_provider, dns_config):
'namecheap': 'create_namecheap_config',
'arvancloud': 'create_arvancloud_config',
'infomaniak': 'create_infomaniak_config',
'acme-dns': 'create_acme_dns_config'
'acme-dns': 'create_acme_dns_config',
'hostinger': 'create_hostinger_config'
}

# Try to get function from app module for test compatibility
Expand Down Expand Up @@ -144,6 +145,8 @@ def _create_dns_config_compat(self, dns_provider, dns_config):
dns_config.get('password', ''),
dns_config.get('subdomain', ''),
)
elif dns_provider == 'hostinger':
return config_func(dns_config.get('api_token', ''))
else:
# Multi-provider config: (provider, config_dict)
return config_func(dns_provider, dns_config)
Expand Down Expand Up @@ -201,6 +204,8 @@ def _create_dns_config_compat(self, dns_provider, dns_config):
dns_config.get('password', ''),
dns_config.get('subdomain', ''),
)
elif dns_provider == 'hostinger':
return create_hostinger_config(dns_config.get('api_token', ''))
else:
return create_multi_provider_config(dns_provider, dns_config)

Expand Down Expand Up @@ -446,7 +451,7 @@ def create_certificate(self, domain, email, dns_provider=None, dns_config=None,
route53_env_set = True
plugin_name = 'dns-route53'

elif dns_provider in ['azure', 'google', 'powerdns', 'digitalocean', 'linode', 'gandi', 'ovh', 'namecheap', 'arvancloud', 'infomaniak', 'acme-dns']:
elif dns_provider in ['azure', 'google', 'powerdns', 'digitalocean', 'linode', 'gandi', 'ovh', 'namecheap', 'arvancloud', 'infomaniak', 'acme-dns', 'hostinger']:
# Use compatibility function for config creation
credentials_file = self._create_dns_config_compat(dns_provider, dns_config)
plugin_name = f'dns-{dns_provider}'
Expand Down Expand Up @@ -501,7 +506,8 @@ def create_certificate(self, domain, email, dns_provider=None, dns_config=None,
'namecheap': 300,
'arvancloud': 120,
'infomaniak': 300,
'acme-dns': 30
'acme-dns': 30,
'hostinger': 120
}
propagation_time = int(propagation_map.get(dns_provider, default_map.get(dns_provider, 120)))
certbot_cmd.extend([f'--{plugin_name}-propagation-seconds', str(propagation_time)])
Expand Down
8 changes: 5 additions & 3 deletions modules/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def save_settings(self, settings, backup_reason="auto_save"):
return False

# Validate dns_provider against supported set
supported_providers = {'cloudflare','route53','azure','google','powerdns','digitalocean','linode','gandi','ovh','namecheap','vultr','dnsmadeeasy','nsone','rfc2136','hetzner','porkbun','godaddy','he-ddns','dynudns','arvancloud','infomaniak','acme-dns'}
supported_providers = {'cloudflare','route53','azure','google','powerdns','digitalocean','linode','gandi','ovh','namecheap','vultr','dnsmadeeasy','nsone','rfc2136','hetzner','porkbun','godaddy','he-ddns','dynudns','arvancloud','infomaniak','acme-dns','hostinger'}
if 'dns_provider' in settings and settings['dns_provider'] not in supported_providers:
logger.error(f"Invalid dns_provider: {settings['dns_provider']}")
return False
Expand Down Expand Up @@ -323,7 +323,8 @@ def save_settings(self, settings, backup_reason="auto_save"):
'namecheap': 300,
'arvancloud': 120,
'infomaniak': 300,
'acme-dns': 30
'acme-dns': 30,
'hostinger': 120
}
if 'dns_propagation_seconds' not in settings or not isinstance(settings['dns_propagation_seconds'], dict):
settings['dns_propagation_seconds'] = defaults
Expand Down Expand Up @@ -418,7 +419,8 @@ def migrate_dns_providers_to_multi_account(self, settings):
'he-ddns': ['username', 'password'],
'arvancloud': ['api_key'],
'infomaniak': ['api_token'],
'acme-dns': ['api_url', 'username', 'password', 'subdomain']
'acme-dns': ['api_url', 'username', 'password', 'subdomain'],
'hostinger': ['api_token']
}

# Check if migration is needed
Expand Down
11 changes: 9 additions & 2 deletions modules/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@
'porkbun': ['api_key', 'secret_key'],
'godaddy': ['api_key', 'secret'],
'he-ddns': ['username', 'password'],
'dynudns': ['token']
'dynudns': ['token'],
'hostinger': ['api_token']
}

# A mapping of multi-provider names to their certbot plugin .ini filename.
_MULTI_PROVIDER_PLUGIN_FILES = {
'vultr': 'vultr.ini', 'dnsmadeeasy': 'dnsmadeeasy.ini', 'nsone': 'nsone.ini',
'rfc2136': 'rfc2136.ini', 'hetzner': 'hetzner.ini', 'porkbun': 'porkbun.ini',
'godaddy': 'godaddy.ini', 'he-ddns': 'he-ddns.ini', 'dynudns': 'dynudns.ini'
'godaddy': 'godaddy.ini', 'he-ddns': 'he-ddns.ini', 'dynudns': 'dynudns.ini',
'hostinger': 'hostinger.ini'
}

# A data-driven template for building multi-provider config files.
Expand All @@ -80,6 +82,7 @@
'godaddy': {'dns_godaddy_key': 'api_key', 'dns_godaddy_secret': 'secret'},
'he-ddns': {'dns_he_ddns_username': 'username', 'dns_he_ddns_password': 'password'},
'dynudns': {'dns_dynudns_token': 'token'},
'hostinger': {'dns_hostinger_api_token': 'api_token'},
}


Expand Down Expand Up @@ -359,6 +362,10 @@ def create_acme_dns_config(api_url: str, username: str, password: str, subdomain
}}"""
return _create_config_file("acme-dns", content)

def create_hostinger_config(api_token: str) -> Path:
"""Create Hostinger DNS credentials file."""
return _create_config_file("hostinger", f"dns_hostinger_api_token = {api_token}\n")

def create_multi_provider_config(provider: str, config_data: Dict[str, Any]) -> Optional[Path]:
"""
Creates a certbot DNS plugin configuration file from a provider and data.
Expand Down
3 changes: 3 additions & 0 deletions requirements-extended.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ certbot-dns-namecheap==2.11.0
certbot-dns-porkbun==2.11.0
certbot-dns-godaddy==2.11.0

# Web hosting providers
certbot-dns-hostinger

# Specialized DNS services
certbot-dns-dnsmadeeasy==2.11.0
certbot-dns-nsone==2.11.0
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ certbot-dns-porkbun
certbot-dns-godaddy
certbot-dns-arvancloud
certbot-acme-dns
certbot-dns-hostinger

# Cloud SDK dependencies
boto3==1.34.144 # AWS support
Expand Down
4 changes: 4 additions & 0 deletions templates/help.html
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,10 @@ <h4 class="font-medium text-gray-900 dark:text-white mb-4">
<i class="fas fa-globe text-green-600 text-lg mb-1"></i>
<div class="text-xs font-medium text-gray-900 dark:text-white">GoDaddy</div>
</div>
<div class="text-center p-3 bg-gray-50 dark:bg-gray-700 rounded-lg border border-gray-200 dark:border-gray-600">
<i class="fas fa-server text-purple-500 text-lg mb-1"></i>
<div class="text-xs font-medium text-gray-900 dark:text-white">Hostinger</div>
</div>
<div class="text-center p-3 bg-gray-50 dark:bg-gray-700 rounded-lg border border-gray-200 dark:border-gray-600">
<i class="fas fa-cogs text-green-600 text-lg mb-1"></i>
<div class="text-xs font-medium text-gray-900 dark:text-white">DNS Made Easy</div>
Expand Down
Loading