Skip to content

Delegate certificate reneawl to certapi, other fixes#50

Merged
mesudip merged 4 commits into
masterfrom
chore/certapi-upgrade
Apr 29, 2026
Merged

Delegate certificate reneawl to certapi, other fixes#50
mesudip merged 4 commits into
masterfrom
chore/certapi-upgrade

Conversation

@mesudip
Copy link
Copy Markdown
Owner

@mesudip mesudip commented Apr 28, 2026

No description provided.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the SSL certificate management system by replacing the internal SSL class with a RenewalManager from the certapi package and introducing a centralized certificate_backend factory. It also enhances the handling of injected Nginx directives by tracking them per backend, enabling precise cleanup when containers are removed. The VIRTUAL_HOST parsing logic was updated to support key=value syntax. Key feedback points include a missing reload mechanism in the background renewal process, the brittle use of protected internal methods, potential parsing conflicts with complex Nginx directives containing equal signs, and the use of Python 3.10+ type hint syntax which may break compatibility with older versions.

Comment on lines +33 to +38
self.renewal_manager = RenewalManager(
self.backend,
sync_watch_domains=self.sync_watch_domains,
renew_threshold_days=max(1, int(self.update_threshold_secs // (24 * 3600))),
batch_domains=self.certapi_batch_domains,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The RenewalManager is initialized without a reload callback. In the previous implementation (SSL.py), the background thread explicitly called server.reload() after renewing certificates. Without a similar mechanism here (e.g., passing a reload callback to RenewalManager if supported by the certapi client), Nginx will not pick up renewed or newly issued certificates until an unrelated event triggers a reload. This could lead to expired certificates being served even after successful background renewal.

Comment on lines +69 to +72
register_self_signed = getattr(self.renewal_manager, "_register_self_signed", None)
if register_self_signed is None:
return
register_self_signed(domain)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Accessing the protected method _register_self_signed of RenewalManager via getattr is brittle and violates encapsulation. If certapi is an external dependency, this code may break if the internal implementation of RenewalManager changes. It is recommended to use a public API if available, or expose this functionality properly in the RenewalManager class.

Comment on lines +26 to +31
if "=" in directive:
key, value = directive.split("=", 1)
key = key.strip()
value = value.strip()
if key:
return key, value if value else None
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Splitting directives by = in _parse_extra_directive can mangle complex Nginx directives that contain equal signs within their values (e.g., in set, map, or complex proxy_set_header directives). While this supports a convenient key=value syntax for simple cases, it risks breaking valid Nginx configurations. Consider a more robust parser or restricting this behavior to known safe keys.

Comment on lines +19 to +21
cert_manager: AcmeCertManager | None = None
certapi_client: CertManagerClient | None = None
challenge_store: NginxChallengeSolver | None = None
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of the | operator for type unions (e.g., AcmeCertManager | None) requires Python 3.10+. The rest of the codebase (e.g., Location.py) uses typing.Union, suggesting compatibility with older Python versions is intended. If support for Python < 3.10 is required, these type hints should be updated to use Optional or Union from the typing module.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 28, 2026

Codecov Report

❌ Patch coverage is 81.92771% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.32%. Comparing base (4a6d437) to head (8bd78b8).
⚠️ Report is 5 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
nginx_proxy/certificate_backend.py 69.38% 10 Missing and 5 partials ⚠️
...proxy/post_processors/ssl_certificate_processor.py 88.33% 6 Missing and 1 partial ⚠️
nginx_proxy/Location.py 84.37% 2 Missing and 3 partials ⚠️
...inx_proxy/pre_processors/virtual_host_processor.py 86.95% 1 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #50      +/-   ##
==========================================
+ Coverage   59.87%   61.32%   +1.45%     
==========================================
  Files          31       30       -1     
  Lines        2557     2384     -173     
  Branches      417      382      -35     
==========================================
- Hits         1531     1462      -69     
+ Misses        920      829      -91     
+ Partials      106       93      -13     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mesudip mesudip merged commit e8cc849 into master Apr 29, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant