Expiration date: {{expires_at.isoformat()}}
8 | 9 | Affected domains: 10 | 11 |Expiration date: {{expires_at.isoformat()}} (in {{expires_in_days}} days)
9 | 10 | Affected domains: 11 | 12 |43 | | Serial Number | 44 |Created At | 45 |Valid Until | 46 |Age (Days) | 47 |Revoked At | 48 |Domains | 49 |
---|---|---|---|---|---|---|
55 | | {{cert.serial_number}} |
56 | {{cert.not_valid_before.strftime('%Y-%m-%d')}} | 57 |{{cert.not_valid_after.strftime('%Y-%m-%d')}} | 58 |59 | {% if cert.is_valid %} 60 | {{cert.age.days}} / {{cert.lifetime.days}} 61 | {% else %} 62 | - 63 | {% endif %} 64 | | 65 |66 | {% if cert.revoked_at %} 67 | {{cert.revoked_at.strftime('%Y-%m-%d')}} 68 | {% else %} 69 | - 70 | {% endif %} 71 | | 72 |
73 |
|
81 |
73 | | Domain | 74 |First requested at | 75 |Newest certificate valid until | 76 |
---|---|---|---|
82 | | {{domain.domain_name}} | 84 |{{domain.first_requested_at.strftime('%Y-%m-%d')}} | 85 |{{domain.expires_at.strftime('%Y-%m-%d')}} | 86 |
ACME Entrypoint: {{acme_url}}
23 | 24 | {% endblock %} -------------------------------------------------------------------------------- /app/web/www/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knrdl/acme-ca-server/4371f3d0931c77863d15d7623d4c876b58eeab6d/app/web/www/favicon.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "acme-ca-server" 3 | description = "ACME CA Server" 4 | readme = "README.md" 5 | license = {file = "LICENSE"} 6 | dynamic = ["dependencies"] 7 | requires-python = ">=3.10" 8 | classifiers = [ 9 | "License :: OSI Approved :: MIT License", 10 | "Programming Language :: Python :: 3", 11 | ] 12 | 13 | [project.urls] 14 | Homepage = "https://github.com/knrdl/acme-ca-server" 15 | Documentation = "https://github.com/knrdl/acme-ca-server" 16 | Repository = "https://github.com/knrdl/acme-ca-server.git" 17 | Issues = "https://github.com/knrdl/acme-ca-server/issues" 18 | 19 | [tool.setuptools.dynamic] 20 | dependencies = {file = ["requirements.txt"]} 21 | 22 | 23 | [tool.pylint] 24 | max-line-length = 179 25 | recursive = 'yes' 26 | disable = 'too-many-branches,no-else-return,broad-exception-caught,missing-module-docstring,missing-class-docstring,missing-function-docstring' 27 | 28 | [tool.pytest.ini_options] 29 | pythonpath = "app" 30 | testpaths = [ 31 | "tests/pytest/", 32 | ] 33 | addopts = [ 34 | "--import-mode=importlib", 35 | ] 36 | 37 | [tool.ruff] 38 | line-length = 179 39 | 40 | [tool.ruff.format] 41 | quote-style = "single" -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiosmtplib==4.0.1 2 | asyncpg==0.30.0 3 | cryptography==45.0.3 4 | fastapi==0.115.12 5 | httpx==0.28.1 6 | jinja2==3.1.6 7 | jwcrypto==1.5.6 8 | pydantic[email]==2.11.5 9 | pydantic-settings==2.9.1 10 | uvicorn[standard]==0.34.3 11 | -------------------------------------------------------------------------------- /tests/e2e/.gitignore: -------------------------------------------------------------------------------- 1 | certbot/ 2 | traefikdata/ 3 | caddydata/ 4 | uacmedata/ 5 | acmeshdata/ 6 | 7 | ca.key 8 | ca.pem 9 | *.xdb -------------------------------------------------------------------------------- /tests/e2e/Caddyfile: -------------------------------------------------------------------------------- 1 | { 2 | acme_ca http://localhost:8080/acme/directory 3 | email caddy@example.org 4 | ocsp_stapling off 5 | } 6 | 7 | http://localhost:8080 { 8 | reverse_proxy acme.example.org:8080 9 | 10 | } 11 | 12 | host10.example.org { 13 | header Content-Type text/html 14 | respond "