選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

197 行
5.3 KiB

  1. # imports - standard imports
  2. import os
  3. # imports - third party imports
  4. import click
  5. # imports - module imports
  6. import bench
  7. from bench.config.nginx import make_nginx_conf
  8. from bench.config.production_setup import service
  9. from bench.config.site_config import get_domains, remove_domain, update_site_config
  10. from bench.bench import Bench
  11. from bench.utils import exec_cmd, which
  12. from bench.utils.bench import update_common_site_config
  13. from bench.exceptions import CommandFailedError
  14. def setup_letsencrypt(site, custom_domain, bench_path, interactive):
  15. site_path = os.path.join(bench_path, "sites", site, "site_config.json")
  16. if not os.path.exists(os.path.dirname(site_path)):
  17. print("No site named " + site)
  18. return
  19. if custom_domain:
  20. domains = get_domains(site, bench_path)
  21. for d in domains:
  22. if isinstance(d, dict) and d["domain"] == custom_domain:
  23. print(f"SSL for Domain {custom_domain} already exists")
  24. return
  25. if custom_domain not in domains:
  26. print(f"No custom domain named {custom_domain} set for site")
  27. return
  28. if interactive:
  29. click.confirm(
  30. "Running this will stop the nginx service temporarily causing your sites to go offline\n"
  31. "Do you want to continue?",
  32. abort=True,
  33. )
  34. if not Bench(bench_path).conf.get("dns_multitenant"):
  35. print("You cannot setup SSL without DNS Multitenancy")
  36. return
  37. create_config(site, custom_domain)
  38. run_certbot_and_setup_ssl(site, custom_domain, bench_path, interactive)
  39. setup_crontab()
  40. def create_config(site, custom_domain):
  41. config = (
  42. bench.config.env()
  43. .get_template("letsencrypt.cfg")
  44. .render(domain=custom_domain or site)
  45. )
  46. config_path = f"/etc/letsencrypt/configs/{custom_domain or site}.cfg"
  47. create_dir_if_missing(config_path)
  48. with open(config_path, "w") as f:
  49. f.write(config)
  50. def run_certbot_and_setup_ssl(site, custom_domain, bench_path, interactive=True):
  51. service("nginx", "stop")
  52. try:
  53. interactive = "" if interactive else "-n"
  54. exec_cmd(
  55. f"{get_certbot_path()} {interactive} --config /etc/letsencrypt/configs/{custom_domain or site}.cfg certonly"
  56. )
  57. except CommandFailedError:
  58. service("nginx", "start")
  59. print("There was a problem trying to setup SSL for your site")
  60. return
  61. ssl_path = f"/etc/letsencrypt/live/{custom_domain or site}/"
  62. ssl_config = {
  63. "ssl_certificate": os.path.join(ssl_path, "fullchain.pem"),
  64. "ssl_certificate_key": os.path.join(ssl_path, "privkey.pem"),
  65. }
  66. if custom_domain:
  67. remove_domain(site, custom_domain, bench_path)
  68. domains = get_domains(site, bench_path)
  69. ssl_config["domain"] = custom_domain
  70. domains.append(ssl_config)
  71. update_site_config(site, {"domains": domains}, bench_path=bench_path)
  72. else:
  73. update_site_config(site, ssl_config, bench_path=bench_path)
  74. make_nginx_conf(bench_path)
  75. service("nginx", "start")
  76. def setup_crontab():
  77. from crontab import CronTab
  78. job_command = (
  79. f'{get_certbot_path()} renew -a nginx --post-hook "systemctl reload nginx"'
  80. )
  81. job_comment = "Renew lets-encrypt every month"
  82. print(f"Setting Up cron job to {job_comment}")
  83. system_crontab = CronTab(user="root")
  84. for job in system_crontab.find_comment(comment=job_comment): # Removes older entries
  85. system_crontab.remove(job)
  86. job = system_crontab.new(command=job_command, comment=job_comment)
  87. job.setall("0 0 */1 * *") # Run at 00:00 every day-of-month
  88. system_crontab.write()
  89. def create_dir_if_missing(path):
  90. if not os.path.exists(os.path.dirname(path)):
  91. os.makedirs(os.path.dirname(path))
  92. def get_certbot_path():
  93. try:
  94. return which("certbot", raise_err=True)
  95. except FileNotFoundError:
  96. raise CommandFailedError(
  97. "Certbot is not installed on your system. Please visit https://certbot.eff.org/instructions for installation instructions, then try again."
  98. )
  99. def renew_certs():
  100. # Needs to be run with sudo
  101. click.confirm(
  102. "Running this will stop the nginx service temporarily causing your sites to go offline\n"
  103. "Do you want to continue?",
  104. abort=True,
  105. )
  106. setup_crontab()
  107. service("nginx", "stop")
  108. exec_cmd(f"{get_certbot_path()} renew")
  109. service("nginx", "start")
  110. def setup_wildcard_ssl(domain, email, bench_path, exclude_base_domain):
  111. def _get_domains(domain):
  112. domain_list = [domain]
  113. if not domain.startswith("*."):
  114. # add wildcard caracter to domain if missing
  115. domain_list.append(f"*.{domain}")
  116. else:
  117. # include base domain based on flag
  118. domain_list.append(domain.replace("*.", ""))
  119. if exclude_base_domain:
  120. domain_list.remove(domain.replace("*.", ""))
  121. return domain_list
  122. if not Bench(bench_path).conf.get("dns_multitenant"):
  123. print("You cannot setup SSL without DNS Multitenancy")
  124. return
  125. domain_list = _get_domains(domain.strip())
  126. email_param = ""
  127. if email:
  128. email_param = f"--email {email}"
  129. try:
  130. exec_cmd(
  131. f"{get_certbot_path()} certonly --manual --preferred-challenges=dns {email_param} \
  132. --server https://acme-v02.api.letsencrypt.org/directory \
  133. --agree-tos -d {' -d '.join(domain_list)}"
  134. )
  135. except CommandFailedError:
  136. print("There was a problem trying to setup SSL")
  137. return
  138. ssl_path = f"/etc/letsencrypt/live/{domain}/"
  139. ssl_config = {
  140. "wildcard": {
  141. "domain": domain,
  142. "ssl_certificate": os.path.join(ssl_path, "fullchain.pem"),
  143. "ssl_certificate_key": os.path.join(ssl_path, "privkey.pem"),
  144. }
  145. }
  146. update_common_site_config(ssl_config)
  147. setup_crontab()
  148. make_nginx_conf(bench_path)
  149. print("Restrting Nginx service")
  150. service("nginx", "restart")