You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+50-21Lines changed: 50 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
4
4
5
5
## Overview
6
6
7
-
MikoPBX extension module for automated SSL certificate management via Let's Encrypt (ACME v2). Uses the `getssl` bash script as the ACME client with HTTP-01 validation, and provides real-time certificate request progress via nchan Pub/Sub or polling fallback.
7
+
MikoPBX extension module for automated SSL certificate management via Let's Encrypt (ACME v2). Uses `acme.sh` as the primary ACME client with support for both **HTTP-01** and **DNS-01** validation methods. Provides real-time certificate request progress via nchan Pub/Sub or polling fallback.
8
+
9
+
**DNS-01 support** enables certificate issuance without opening port 80, using DNS provider APIs (Cloudflare, AWS Route53, Hetzner, Yandex Cloud, and 150+ others). Also supports wildcard certificates (`*.domain.com`).
10
+
11
+
Legacy `getssl` client files are retained for one transition release cycle.
8
12
9
13
## Build Commands
10
14
@@ -23,59 +27,84 @@ Repeat for each source file (`module-get-ssl-index.js`, `module-get-ssl-status-w
23
27
```bash
24
28
phpstan analyse
25
29
```
26
-
Config in `phpstan.neon`: level 0, scans `Lib/`, `Models/`, `bin/`, `App/`, `Setup/`. Requires MikoPBX Core sources at `../../Core/src` for class resolution. Ignores Phalcon 4/5 compatibility class-not-found errors.
30
+
Config in `phpstan.neon`: level 0, scans `Lib/`, `Models/`, `bin/`, `App/`, `Setup/`. Requires MikoPBX Core sources at `../../Core/src` for class resolution. Ignores Phalcon 4/5 compatibility class-not-found errors. The `bin/` scripts report `Globals.php` not found — this is expected (runtime file from MikoPBX DI container).
27
31
28
32
## Architecture
29
33
30
34
### PSR-4 Namespace
31
35
Root namespace `Modules\ModuleGetSsl\` maps to repository root (see `composer.json`).
32
36
33
37
### Module Lifecycle
34
-
1.**Installation** (`Setup/PbxExtensionSetup.php`): Creates DB table `m_ModuleGetSsl`, sets defaults, detects domain from internet interface
38
+
1.**Installation** (`Setup/PbxExtensionSetup.php`): Creates DB table `m_ModuleGetSsl`, sets defaults (including `challengeType='http'` for migration), detects domain from internet interface
35
39
2.**Runtime** (`Lib/GetSslConf.php`): Registers REST API callbacks, cron tasks, reacts to model changes and PBX lifecycle events
4.**Port 80 Management** (`Lib/AcmeHttpPort.php`): Temporarily opens port 80 for ACME HTTP-01 validation — creates nginx server block at `/etc/nginx/mikopbx/modules_servers/ModuleGetSsl_acme80.conf`, adds iptables rules when firewall is active, uses a lock file at `/var/run/custom_modules/ModuleGetSsl/acme_port80.lock` with 300s max open time and automatic stale cleanup
3.**Certificate Request** (`Lib/GetSslMain.php`): Prepares acme.sh environment, launches async certificate request (HTTP-01 via `--webroot` or DNS-01 via `--dns`), streams progress to browser
41
+
4.**Port 80 Management** (`Lib/AcmeHttpPort.php`): Temporarily opens port 80 for ACME HTTP-01 validation only — creates nginx server block at `/etc/nginx/mikopbx/modules_servers/ModuleGetSsl_acme80.conf`, adds iptables rules when firewall is active, uses a lock file at `/var/run/custom_modules/ModuleGetSsl/acme_port80.lock` with 300s max open time and automatic stale cleanup. **Skipped entirely for DNS-01.**
-**`Lib/GetSslConf.php`** — Module configuration hook (extends `ConfigClass`). Handles REST API routing (`GET-CERT`, `CHECK-RESULT`), cron task registration, and PBX lifecycle events (`onAfterPbxStarted`, `onAfterModuleEnable`). Wraps cert requests in `AcmeHttpPort::openPort()`/`closePort()` via try/finally
43
-
-**`Lib/GetSslMain.php`** — Core orchestrator. Manages directories, generates getssl config file, launches certificate requests, monitors process completion (120s timeout), pushes real-time updates via nchan, updates SSL keys in PbxSettings DB
44
-
-**`Lib/AcmeHttpPort.php`** — Port 80 lifecycle manager. Opens/closes nginx + iptables for ACME validation. Includes stale lock cleanup (cron watchdog + PBX startup)
46
+
-**`Lib/GetSslMain.php`** — Core orchestrator. Manages directories, prepares acme.sh environment (`prepareAcmeEnvironment()`), builds acme.sh commands for HTTP-01 or DNS-01, launches certificate requests, monitors process completion (120s for HTTP-01 / 300s for DNS-01), pushes real-time updates via nchan, updates SSL keys in PbxSettings DB. Finds certificates in acme.sh paths first, falls back to legacy getssl paths
47
+
-**`Lib/GetSslConf.php`** — Module configuration hook (extends `ConfigClass`). Handles REST API routing (`GET-CERT`, `CHECK-RESULT`), cron task registration, and PBX lifecycle events (`onAfterPbxStarted`, `onAfterModuleEnable`). Conditionally wraps cert requests in `AcmeHttpPort::openPort()`/`closePort()` only for HTTP-01
48
+
-**`Lib/AcmeHttpPort.php`** — Port 80 lifecycle manager. Opens/closes nginx + iptables for ACME HTTP-01 validation. Includes stale lock cleanup (cron watchdog + PBX startup)
49
+
-**`Lib/DnsProviderRegistry.php`** — Static registry of 23 popular DNS providers with env variable definitions. Single source of truth for backend (form select options) and frontend (dynamic credential fields). Methods: `getProviders()`, `getProviderById()`, `getProviderSelectOptions()`
45
50
-**`Lib/MikoPBXVersion.php`** — Compatibility layer for Phalcon 4 vs 5 class names. Version cutoff at PBX 2024.2.30
46
-
-**`Models/ModuleGetSsl.php`** — Phalcon ORM model for `m_ModuleGetSsl` table (fields: `id`, `domainName`, `autoUpdate`). Source table: `m_ModuleGetSsl`
47
-
-**`App/Controllers/ModuleGetSslController.php`** — Web UI controller: renders form, handles save, triggers certificate request on save
48
-
-**`App/Forms/ModuleGetSslForm.php`** — Phalcon form definition. Note: `addCheckBox()` helper exists for backward compat and can be removed when `min_pbx_version` ≥ 2024.3.0
51
+
-**`Models/ModuleGetSsl.php`** — Phalcon ORM model for `m_ModuleGetSsl` table. Fields: `id`, `domainName`, `autoUpdate`, `challengeType` ('http'|'dns'), `dnsProvider` (e.g. 'dns_cf'), `dnsCredentials` (base64-encoded JSON)
52
+
-**`App/Controllers/ModuleGetSslController.php`** — Web UI controller: renders form with DNS provider options, passes `dnsProvidersJson` to view for JS, handles save including `dnsCredentials`
53
+
-**`App/Forms/ModuleGetSslForm.php`** — Phalcon form definition with Select for `challengeType`, Select for `dnsProvider` (with search), Hidden for `dnsCredentials`. Note: `addCheckBox()` helper exists for backward compat and can be removed when `min_pbx_version` ≥ 2024.3.0
-**`bin/acme/dnsapi/`** — 168 DNS provider hook scripts for DNS-01 validation
59
+
-**`bin/getssl`** — Legacy getssl client (retained for transition)
60
+
-**`bin/utils/`** — Legacy getssl utilities (retained for transition)
49
61
50
62
### CLI Scripts (`bin/`)
51
63
52
64
All scripts bootstrap via `require_once('Globals.php')` which loads the MikoPBX DI container.
53
65
54
-
-**`cronRenewCert.php`** — Cron entry point: opens port 80, runs `getssl -a -U -q`, installs cert, closes port 80
55
-
-**`reloadCmd.php`** — Called by getssl after successful cert issuance; installs cert/key into PbxSettings
66
+
-**`cronRenewCert.php`** — Cron entry point: conditionally opens port 80 (HTTP-01 only), runs `acme.sh --cron`, installs cert, closes port 80
67
+
-**`reloadCmd.php`** — Called by acme.sh `--reloadcmd` after successful cert issuance; installs cert/key into PbxSettings
56
68
-**`reloadCron.php`** — Reloads cron configuration when module settings change
57
69
-**`cleanupPort80.php`** — Cron watchdog (runs every minute): calls `AcmeHttpPort::cleanupStale()`
58
70
-**`updateCert.php`** — Manual cert request without nchan (runs synchronously)
59
71
60
72
### Frontend (ES6 → Babel → ES5)
61
73
62
-
-**`public/assets/js/src/module-get-ssl-index.js`** — Form controller: validation, module status toggle, triggers API call to start certificate request, handles async response channel
74
+
-**`public/assets/js/src/module-get-ssl-index.js`** — Form controller: validation, module status toggle, challenge type switching (HTTP-01/DNS-01), dynamic DNS provider credential fields based on `dnsProvidersMeta`, credential collection/restoration (base64 JSON), triggers API call to start certificate request
63
75
-**`public/assets/js/src/module-get-ssl-status-worker.js`** — Real-time progress: EventSource (PBX ≥2024.2.30) or polling fallback, Ace editor for log display, 4-stage processing pipeline (STAGE_1–4)
64
76
65
77
### Real-time Updates Flow
66
78
67
79
1. Browser sends `POST /pbxcore/api/modules/ModuleGetSsl/get-cert` with `X-Async-Response-Channel-Id: module-get-ssl-pub`
68
-
2. Backend opens port 80, generates config, launches getssl, monitors process (120s timeout)
80
+
2. Backend conditionally opens port 80 (HTTP-01 only), prepares acme.sh environment, launches acme.sh, monitors process (120s HTTP-01 / 300s DNS-01)
69
81
3. Progress pushed to nchan channel `module-get-ssl-pub` as JSON with `moduleUniqueId`, `stage`, `stageDetails`, `pid`
70
82
4. Browser subscribes via EventSource (PBX ≥2024.2.30) or polls `check-result` endpoint
71
-
5. Backend closes port 80 in `finally` block
83
+
5. Backend closes port 80 in `finally` block (HTTP-01 only)
84
+
85
+
### DNS-01 Challenge Flow
86
+
87
+
1. User selects DNS-01 in the UI, picks a DNS provider, enters API credentials
88
+
2. Credentials stored as base64-encoded JSON in `dnsCredentials` model field
89
+
3. On cert request: credentials decoded to `export VAR='val'; ...` prefix before acme.sh command
90
+
4. acme.sh creates `_acme-challenge` TXT record via DNS provider API, validates, cleans up
91
+
5. No port 80 required — works behind firewalls and NAT
acme.sh stores certificates in `{moduleDir}/db/acme/{domain}/`:
103
+
-`fullchain.cer` — full certificate chain
104
+
-`{domain}.key` — private key
105
+
106
+
Legacy getssl paths (`{moduleDir}/db/getssl/{domain}/`) are checked as fallback.
107
+
79
108
## Phalcon Version Compatibility
80
109
81
110
Always use `MikoPBXVersion` for version-dependent class imports (Di, Validation, Uniqueness, Text, Logger). PBX versions ≥2024.2.30 use Phalcon 5; older versions use Phalcon 4. Do not hardcode Phalcon namespace paths.
@@ -89,5 +118,5 @@ Language files in `Messages/`. Translation keys prefixed with `module_getssl_`.
Copy file name to clipboardExpand all lines: README.md
+29-6Lines changed: 29 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,20 +6,43 @@
6
6
7
7
This module automates obtaining and renewing free SSL certificates from [Let's Encrypt](https://letsencrypt.org/) for your MikoPBX web interface. After setup, the HTTPS certificate is issued automatically and renewed on schedule — no manual steps required.
8
8
9
+
## Verification Methods
10
+
11
+
The module supports two verification methods:
12
+
13
+
### HTTP-01 (default)
14
+
The classic method — Let's Encrypt verifies domain ownership by making an HTTP request to your server on port 80. Simple setup: just enter your domain name and click save.
15
+
16
+
**Requirements:** port 80 accessible from the internet. The module opens it temporarily during verification and closes it immediately after.
17
+
18
+
### DNS-01
19
+
Certificate issuance via your DNS provider's API. No need to open port 80 — works behind firewalls, NAT, and in private networks. Also supports **wildcard certificates** (`*.domain.com`).
**Setup:** select DNS-01 in the verification method dropdown, choose your DNS provider, enter API credentials, and click save.
24
+
9
25
## How It Works
10
26
11
-
1. You install the module from the MikoPBX module marketplace
12
-
2. Enter your domain name in the module settings and click save
13
-
3. The module requests a certificate from Let's Encrypt, and the progress is shown in real time
14
-
4. Once issued, the certificate is automatically applied to the MikoPBX web interface
27
+
1. Install the module from the MikoPBX module marketplace
28
+
2. Enter your domain name in the module settings
29
+
3. Choose a verification method (HTTP-01 or DNS-01)
30
+
4. For DNS-01 — select your DNS provider and enter API credentials
31
+
5. Click save — the module requests a certificate from Let's Encrypt, progress is shown in real time
32
+
6. Once issued, the certificate is automatically applied to the MikoPBX web interface
15
33
16
34
Auto-renewal runs on the 1st and 15th of each month. If the certificate is due for renewal, it will be updated automatically.
17
35
18
36
## Requirements
19
37
20
38
- MikoPBX **2024.1.114** or newer
21
-
- A domain name pointing to your PBX public IP address (A record)
22
-
- Port **80** accessible from the internet (required for Let's Encrypt HTTP-01 validation)
39
+
- A domain name pointing to your PBX (A record)
40
+
-**For HTTP-01:** port **80** accessible from the internet
41
+
-**For DNS-01:** API credentials from your DNS provider (no open ports required)
42
+
43
+
## Technical Details
44
+
45
+
The module uses [acme.sh](https://github.com/acmesh-official/acme.sh) as the ACME client — a widely used, zero-dependency bash script supporting the full ACME v2 protocol and 150+ DNS providers.
Copy file name to clipboardExpand all lines: readme.ru.md
+28-5Lines changed: 28 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,20 +6,43 @@
6
6
7
7
Модуль автоматически получает и обновляет бесплатные SSL-сертификаты от [Let's Encrypt](https://letsencrypt.org/) для веб-интерфейса MikoPBX. После настройки HTTPS-сертификат выпускается автоматически и продлевается по расписанию — никаких ручных действий не требуется.
8
8
9
+
## Способы проверки
10
+
11
+
Модуль поддерживает два способа проверки владения доменом:
12
+
13
+
### HTTP-01 (по умолчанию)
14
+
Классический способ — Let's Encrypt проверяет владение доменом, отправляя HTTP-запрос на ваш сервер на порт 80. Простая настройка: достаточно указать доменное имя и нажать сохранить.
15
+
16
+
**Требование:** порт 80 должен быть доступен из интернета. Модуль открывает его временно на время проверки и закрывает сразу после.
17
+
18
+
### DNS-01
19
+
Выпуск сертификата через API вашего DNS-провайдера. Не нужно открывать порт 80 — работает за файрволами, NAT и в закрытых сетях. Также поддерживает **wildcard-сертификаты** (`*.domain.com`).
20
+
21
+
**Поддерживаемые провайдеры (20+):** Cloudflare, Amazon Route53, GoDaddy, DigitalOcean, Hetzner, Yandex Cloud, OVH, Selectel, reg.ru, Beget, Namecheap, Azure DNS, Vultr, DuckDNS, Linode, INWX, DreamHost, deSEC, PowerDNS, ISPConfig, Google Cloud DNS и любой пользовательский провайдер.
22
+
23
+
**Настройка:** выберите DNS-01 в выпадающем списке способа проверки, выберите DNS-провайдера, введите API-ключи и нажмите сохранить.
24
+
9
25
## Как это работает
10
26
11
27
1. Установите модуль из маркетплейса модулей MikoPBX
12
-
2. Укажите доменное имя в настройках модуля и нажмите сохранить
13
-
3. Модуль запросит сертификат у Let's Encrypt, прогресс отображается в реальном времени
14
-
4. После выпуска сертификат автоматически применяется к веб-интерфейсу MikoPBX
28
+
2. Укажите доменное имя в настройках модуля
29
+
3. Выберите способ проверки (HTTP-01 или DNS-01)
30
+
4. Для DNS-01 — выберите DNS-провайдера и введите API-ключи
31
+
5. Нажмите сохранить — модуль запросит сертификат у Let's Encrypt, прогресс отображается в реальном времени
32
+
6. После выпуска сертификат автоматически применяется к веб-интерфейсу MikoPBX
15
33
16
34
Автоматическое продление запускается 1-го и 15-го числа каждого месяца. Если сертификат подлежит обновлению, он будет продлён автоматически.
17
35
18
36
## Требования
19
37
20
38
- MikoPBX версии **2024.1.114** или новее
21
-
- Доменное имя, указывающее на публичный IP-адрес АТС (A-запись)
22
-
- Порт **80**, доступный из интернета (необходим для HTTP-01 валидации Let's Encrypt)
39
+
- Доменное имя, указывающее на вашу АТС (A-запись)
40
+
-**Для HTTP-01:** порт **80**, доступный из интернета
41
+
-**Для DNS-01:** API-ключи от вашего DNS-провайдера (открытые порты не нужны)
42
+
43
+
## Технические детали
44
+
45
+
Модуль использует [acme.sh](https://github.com/acmesh-official/acme.sh) в качестве ACME-клиента — широко используемый bash-скрипт без зависимостей, поддерживающий полный протокол ACME v2 и более 150 DNS-провайдеров.
0 commit comments