Coverage for frappe_manager / ssl_manager / vhost_config_manager.py: 36%

22 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-07-02 18:35 +0530

1""" 

2Manages nginx-proxy vhost.d configuration files for per-domain HTTPS redirect control. 

3 

4This module handles creation and removal of vhost.d configuration files that 

5enable HTTPS redirects only for domains that have SSL certificates. 

6""" 

7 

8from pathlib import Path 

9 

10 

11class VhostConfigManager: 

12 """ 

13 Manages per-domain nginx-proxy vhost.d configuration files. 

14 

15 This class creates and manages vhost.d files that control HTTPS redirect 

16 behavior on a per-domain basis. When a domain has a certificate, we create 

17 a vhost.d file to enable HTTP→HTTPS redirects for that domain only. 

18 

19 This solves the nginx-proxy behavior where ALL domains in VIRTUAL_HOST get 

20 redirected to HTTPS when ANY certificate exists. 

21 

22 Attributes: 

23 vhostd_dir: Path to the nginx-proxy vhost.d directory (host filesystem) 

24 """ 

25 

26 # Default HTTPS redirect configuration 

27 HTTPS_REDIRECT_CONFIG = """# Enable HTTPS redirect for this domain only 

28# This domain has a valid SSL certificate 

29if ($scheme = http) { 

30 return 301 https://$host$request_uri; 

31} 

32""" 

33 

34 def __init__(self, vhostd_dir: Path): 

35 """ 

36 Initialize the vhost config manager. 

37 

38 Args: 

39 vhostd_dir: Path to the nginx-proxy vhost.d directory 

40 

41 Raises: 

42 ValueError: If vhostd_dir doesn't exist 

43 """ 

44 self.vhostd_dir = vhostd_dir 

45 

46 if not self.vhostd_dir.exists(): 

47 raise ValueError( 

48 f"vhost.d directory does not exist: {self.vhostd_dir}. " 

49 "Ensure nginx-proxy is running and volumes are mounted correctly.", 

50 ) 

51 

52 def enable_https_redirect(self, domain: str) -> Path: 

53 """ 

54 Enable HTTPS redirect for a specific domain. 

55 

56 Creates a vhost.d configuration file that redirects HTTP traffic to HTTPS 

57 for this domain only. This should be called after a certificate is successfully 

58 generated for the domain. 

59 

60 Args: 

61 domain: Domain name to enable HTTPS redirect for 

62 

63 Returns: 

64 Path to the created vhost.d config file 

65 

66 Example: 

67 >>> manager.enable_https_redirect("example.com") 

68 Path("/path/to/vhostd/example.com") 

69 """ 

70 vhost_file = self.vhostd_dir / domain 

71 

72 # Write the redirect configuration 

73 vhost_file.write_text(self.HTTPS_REDIRECT_CONFIG) 

74 

75 return vhost_file 

76 

77 def disable_https_redirect(self, domain: str) -> bool: 

78 """ 

79 Disable HTTPS redirect for a specific domain. 

80 

81 Removes the vhost.d configuration file for this domain, allowing it to 

82 serve HTTP traffic without redirecting to HTTPS. This should be called 

83 when a certificate is removed. 

84 

85 Args: 

86 domain: Domain name to disable HTTPS redirect for 

87 

88 Returns: 

89 True if the file was removed, False if it didn't exist 

90 

91 Example: 

92 >>> manager.disable_https_redirect("example.com") 

93 True 

94 """ 

95 vhost_file = self.vhostd_dir / domain 

96 

97 if vhost_file.exists(): 

98 vhost_file.unlink() 

99 return True 

100 return False 

101 

102 def has_redirect_config(self, domain: str) -> bool: 

103 """ 

104 Check if a domain has a redirect configuration file. 

105 

106 Args: 

107 domain: Domain name to check 

108 

109 Returns: 

110 True if vhost.d file exists for this domain, False otherwise 

111 """ 

112 vhost_file = self.vhostd_dir / domain 

113 return vhost_file.exists() 

114 

115 def get_config_path(self, domain: str) -> Path: 

116 """ 

117 Get the path to the vhost.d config file for a domain. 

118 

119 Args: 

120 domain: Domain name 

121 

122 Returns: 

123 Path to the vhost.d config file (may not exist) 

124 """ 

125 return self.vhostd_dir / domain