-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathgetssl
More file actions
executable file
·97 lines (82 loc) · 3.42 KB
/
getssl
File metadata and controls
executable file
·97 lines (82 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env python3
import argparse
import sys
import os
from nginx import Nginx
from nginx_proxy.certificate_backend import build_certificate_backend
from urllib.parse import urlparse
def parse_args():
parser = argparse.ArgumentParser(
description="Obtain Let's Encrypt SSL certificate for one or more domains.",
epilog="This script respects environment variables: CERTAPI_URL, SSL_DIR, CHALLENGE_DIR, etc.",
)
parser.add_argument(
"--force",
action="store_true",
help="Skip certapi/nginx-proxy self-verification before requesting the certificate.",
)
parser.add_argument("domains", nargs="+", help="Domain(s) to include in the certificate.")
return parser.parse_args()
def flatten_2d_array(two_d_array):
return [item for sublist in two_d_array for item in sublist]
if __name__ == "__main__":
args = parse_args()
# Load configuration from environment variables (consistent with NginxProxyApp)
def _strip_end(s: str, char="/") -> str:
return s[:-1] if s.endswith(char) else s
ssl_dir = _strip_end(os.getenv("SSL_DIR", "/etc/ssl").strip())
conf_dir = _strip_end(os.getenv("NGINX_CONF_DIR", "/etc/nginx").strip())
challenge_dir = _strip_end(os.getenv("CHALLENGE_DIR", "/etc/nginx/challenges").strip()) + "/"
cert_renew_threshold_days = int(os.getenv("CERT_RENEW_THRESHOLD_DAYS", "30").strip())
# CertAPI Configuration
certapi_url = os.getenv("CERTAPI_URL", "").strip()
mock_server_config = {}
if certapi_url:
parsed = urlparse(certapi_url)
port = parsed.port
if port is None:
port = 443 if parsed.scheme == "https" else 80
mock_server_config["certapi"] = {"url": certapi_url, "host": parsed.hostname, "scheme": parsed.scheme, "port": port}
config_path = os.path.join(conf_dir, "conf.d/gen-ssl-direct.conf")
# Make sure challenge dir exists for local mode
if not os.path.exists(challenge_dir):
try:
os.makedirs(challenge_dir, exist_ok=True)
except OSError:
pass # Might fail if readonly, but then Nginx might scream
nginx = Nginx.Nginx(config_path, challenge_dir=challenge_dir)
backend_info = build_certificate_backend(
ssl_dir,
nginx,
config=mock_server_config,
renew_threshold_days=max(10, cert_renew_threshold_days),
)
try:
result = backend_info.backend.obtain(
args.domains,
key_type="ecdsa",
batch_domains=backend_info.batch_domains,
self_verify=not args.force,
)
if len(result.issued):
print(
"[ New Certificates ] : ",
", ".join(flatten_2d_array(sorted([x.domains for x in result.issued]))),
)
if len(result.existing):
print(
"[ Reuse Existing ] : ",
", ".join(flatten_2d_array(sorted([x.domains for x in result.existing]))),
)
# Attempt to reload nginx to pick up changes (if running)
print("Reloading nginx...")
if not nginx.reload():
print("Warning: Failed to reload nginx. Changes may not apply immediately.")
except Exception as e:
print(f"Error obtaining certificate: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
finally:
if os.path.exists(config_path):
os.remove(config_path)