v0.24.5
This commit is contained in:
commit
5e23e9af02
240 files changed
+99957
No files matched your search
@@ -0,0 +1,157 @@
|
||||
# Basic Let's Encrypt / RFC2136 integration (0.5.0)
|
||||
|
||||
For the multi-provider UI, HTTP-01, Cloudflare and OVH, see ACME_PROVIDERS.md.
|
||||
Managed automatic renewal added in 0.7 is documented in RENEWAL.md.
|
||||
The RFC2136 fields and private account paths below remain supported.
|
||||
|
||||
## Scope and prerequisites
|
||||
|
||||
This is an integrated control-plane adapter for **Certbot + certbot-dns-rfc2136**,
|
||||
not a newly written ACME or DNS-update protocol client. The plugin creates and
|
||||
cleans up DNS-01 TXT records through TSIG-signed RFC2136 updates. It must be
|
||||
installed separately. No real CA issuance or authoritative-DNS update has been
|
||||
performed in the packaging environment.
|
||||
Rust compilation, process integration and actual certificate deployment remain
|
||||
acceptance work (TEST_REPORT.md).
|
||||
|
||||
Use Linux/Unix with Python 3.10+, a current compatible Certbot/plugin installation,
|
||||
and `python3` and `certbot` available in the RustProxy service's PATH. Check:
|
||||
|
||||
```bash
|
||||
bash dev.sh acme --doctor
|
||||
certbot --version
|
||||
certbot plugins --authenticators
|
||||
```
|
||||
|
||||
The doctor command reports executable discovery and the required plugin's name;
|
||||
it does NOT verify the plugin, DNS permissions or network connectivity. Nothing
|
||||
is installed automatically, and RustProxy never invokes sudo. A service hardening
|
||||
policy must allow child processes, the cert directory, DNS updates/queries to the
|
||||
chosen server and outbound HTTPS to the CA. Do not run the proxy as root just to
|
||||
make Certbot available. Use a private, service-owned cert directory (0700).
|
||||
|
||||
The operator must control publicly valid DNS names and an authoritative DNS
|
||||
server that permits the configured TSIG identity to change **only the necessary
|
||||
_acme-challenge TXT names**. Do not grant zone-wide update authority merely for
|
||||
certificates. A private update-server IP is acceptable when the resulting TXT
|
||||
records are visible to the public validation resolvers. Split DNS/views, CAA,
|
||||
replication delays and delegation must be checked on the operator's DNS setup.
|
||||
DNS-01 does not require opening the application's HTTP listener for a challenge.
|
||||
|
||||
## Panel workflow
|
||||
|
||||
Open **Certificates > Let's Encrypt / RFC2136**. Enter a certificate library ID,
|
||||
contact email, comma-separated DNS names (including optional `*.example.org`),
|
||||
DNS update server IP/port, TSIG name, base64 secret, algorithm and propagation
|
||||
wait. ASCII/punycode DNS names only; up to 16 names. SHA256 is the default TSIG
|
||||
algorithm; SHA384/SHA512 are also allowed. SHA1/MD5 are not exposed. A TSIG key
|
||||
name may be a single label such as `keyname.`. Optional signed SOA queries support
|
||||
DNS servers/views that require them. Port defaults to 53; propagation defaults
|
||||
to 60 seconds (allowed 10..900).
|
||||
|
||||
Start with **staging**. Its certificates are not publicly trusted. Production
|
||||
requires a separate explicit confirmation, in addition to agreement with the
|
||||
Let's Encrypt subscriber agreement. The CA directory is fixed for each mode;
|
||||
arbitrary directory URLs, shell hooks and arbitrary extra Certbot options are
|
||||
not accepted by this interface.
|
||||
|
||||
Requesting starts one bounded asynchronous job, not a proxy-path operation. Refresh
|
||||
shows running, failed, or ready. At ready, the Rust control plane has checked PEM
|
||||
parsing, matching key and every requested DNS name before exposing only metadata.
|
||||
Click **Add issued certificate to library**, then select its ID in the vhost SSL
|
||||
tab and save. Replacing an existing ID requires confirmation and retains its
|
||||
legacy SNI host assignments; the whole current configuration is revalidated with
|
||||
revision CAS. Failed issuance/validation/import leaves active configuration alone.
|
||||
Certificates are loaded for new handshakes; changing listener protocols still
|
||||
requires restart. Existing connections retain their negotiated certificate.
|
||||
|
||||
## Renewal and operator responsibilities
|
||||
|
||||
Configured RFC2136 managed profiles participate in the 0.7 renewal scheduler.
|
||||
Validated changed certificate material is published automatically; there is a
|
||||
per-certificate opt-out, explicit Check now and Dry run. Initial issuance/import
|
||||
remains explicit. The old 0.5 helper alone was issuance-only; do not confuse
|
||||
retained files or an unrelated OS Certbot timer with RustProxy publication.
|
||||
See RENEWAL.md for prerequisites, timing, rollback boundaries and legacy profiles.
|
||||
No external expiry notification, revocation UI or account manager is included.
|
||||
|
||||
Account state and TSIG credentials are kept privately under:
|
||||
|
||||
```text
|
||||
data/certs/acme/<staging-or-production>-<certificate-id>/
|
||||
rfc2136.ini # SECRET, mode 0600
|
||||
profile.json # non-secret parameters, mode 0600
|
||||
config/ # Certbot account, renewal, live and archive data
|
||||
work/
|
||||
logs/ # private Certbot diagnostics
|
||||
```
|
||||
|
||||
The location follows the configured certificate directory, not always `data/certs`.
|
||||
There is one job per RustProxy process and a filesystem lock per profile. Bounds:
|
||||
16 KiB request, 128 profiles, 128 staged ACME pairs and 128 KiB per PEM file. The
|
||||
provider timeout is 1200 seconds plus propagation wait; the Rust worker has a
|
||||
2160-second outer deadline and stops its process group on cancellation/shutdown.
|
||||
Normal TXT cleanup belongs to the plugin. A hard kill, machine crash or DNS error
|
||||
can leave challenge TXT records: inspect DNS and clean only the failed challenge
|
||||
values, not unrelated records. Only the latest job status lives in memory; restart
|
||||
loses that status, not the private Certbot files.
|
||||
|
||||
TSIG is supplied through stdin to the helper, never argv, SQLite, exports or job
|
||||
responses. The browser clears the secret field after submission and does not put
|
||||
it in local/session storage. Private credentials/account files are deliberately
|
||||
retained for renewal; protect them and private logs as secrets. Keep unused staged
|
||||
pairs under operator control; active files are never silently deleted.
|
||||
|
||||
The existing `dev.sh backup` includes SQLite and configured PEM files, **not the
|
||||
ACME account/profile directory**. Back up `certs/acme` separately while no issuance
|
||||
is active, preserving ownership/modes and encryption appropriate to private keys.
|
||||
Source upgrade leaves the data directory alone. Do not ship profiles in source ZIPs.
|
||||
|
||||
## API and local helper
|
||||
|
||||
`GET /api/acme` returns the latest sanitized job, provider name and
|
||||
`automatic_renewal: false`. `POST /api/acme/issue` requires the normal authenticated
|
||||
session, Origin/CSRF protections and an explicit bounded JSON request:
|
||||
|
||||
```json
|
||||
{
|
||||
"certificate_id": "example",
|
||||
"email": "operator@example.org",
|
||||
"domains": ["example.org", "*.example.org"],
|
||||
"environment": "staging",
|
||||
"agree_tos": true,
|
||||
"confirm_production": false,
|
||||
"dns_server": "192.0.2.53",
|
||||
"dns_port": 53,
|
||||
"key_name": "rustproxy.example.org.",
|
||||
"key_secret": "REPLACE_WITH_YOUR_PRIVATE_BASE64_TSIG_SECRET",
|
||||
"key_algorithm": "HMAC-SHA256",
|
||||
"sign_query": false,
|
||||
"propagation_seconds": 60
|
||||
}
|
||||
```
|
||||
|
||||
This documentation example is intentionally not an executable credential. A
|
||||
successful job submission returns 202; busy returns 429. Invalid input, consent
|
||||
and provider failures use fixed `acme.*` diagnostics rather than returning
|
||||
provider stderr or credentials. Look in the private profile logs for DNS/plugin
|
||||
errors. A 202 response means accepted, not issued.
|
||||
|
||||
Advanced local staging without the running API:
|
||||
|
||||
```bash
|
||||
# request.json must be private (0600), with real operator-owned parameters.
|
||||
bash dev.sh acme --cert-dir /absolute/private/cert-directory < request.json
|
||||
```
|
||||
|
||||
This CLI only stages files and prints metadata. Unlike the integrated API, it
|
||||
cannot run Rust's key/SAN validation on its own and never activates a certificate.
|
||||
Import through the normal validated library/config workflow. Do not post secret
|
||||
JSON into shell arguments, source examples, tickets or logs.
|
||||
|
||||
## Primary references
|
||||
|
||||
- Plugin: https://certbot-dns-rfc2136.readthedocs.io/en/stable/
|
||||
- Certbot CLI: https://eff-certbot.readthedocs.io/en/stable/man/certbot.html
|
||||
- Staging: https://letsencrypt.org/docs/staging-environment/
|
||||
- Challenge background: https://letsencrypt.org/docs/challenge-types/
|
||||
Reference in new issue
Block a user