diff --git a/README.rst b/README.rst index 0a5577e..c9b0917 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -modoboa-installer -================= +**modoboa-installer** +===================== |workflow| |codecov| @@ -76,7 +76,7 @@ If you want more information about the installation process, add the ``--debug`` option to your command line. Upgrade mode ------------- +============ An experimental upgrade mode is available. @@ -92,7 +92,7 @@ You can activate it as follows:: It will automatically install latest versions of modoboa and its plugins. Backup mode ------------ +=========== An experimental backup mode is available. @@ -129,7 +129,7 @@ configuration file (set enabled to False). This can be useful for larger instance. Restore mode ------------- +============ An experimental restore mode is available. @@ -140,7 +140,7 @@ You can start the process as follows:: Then wait for the process to finish. Change the generated hostname ------------------------------ +============================= By default, the installer will setup your email server using the following hostname: ``mail.``. If you want a different @@ -159,14 +159,26 @@ modifications. Finally, run the installer without the ``--stop-after-configfile-check`` option. -Let's Encrypt certificate -------------------------- +Certificate +=========== + +Self-signed +----------- + +It is the default type of certificate the installer will generate, it +is however not recommended for production use. + +Letsencrypt +----------- .. warning:: - Please note this option requires the hostname you're using to be - valid (ie. it can be resolved with a DNS query) and to match the - server you're installing Modoboa on. + Please note that by using this option, you agree to the `ToS + `_ of + letsencrypt and that your IP will be logged (see ToS). + Please also note this option requires the hostname you're using to be + valid (ie. it can be resolved with a DNS query) and to match the + server you're installing Modoboa on. If you want to generate a valid certificate using `Let's Encrypt `_, edit the ``installer.cfg`` file and @@ -175,6 +187,8 @@ modify the following settings:: [certificate] generate = true type = letsencrypt + tls_cert_file_path = + tls_key_file_path = [letsencrypt] email = admin@example.com @@ -182,6 +196,27 @@ modify the following settings:: Change the ``email`` setting to a valid value since it will be used for account recovery. +Manual +------ + +.. warning:: + + It is not possible to configure manual certs interactively, so + you'll have to do it in 2 steps. Please run ``run.py`` with + `--stop-after-configfile-check` first, configure your file as + desired and apply the configuration as written bellow. Then run + ``run.py`` again but without `--stop-after-configfile-check` or + `--interactive`. + +If you want to use already generated certs, simply edit the +``installer.cfg`` file and modify the following settings:: + + [certificate] + generate = true + type = manual + tls_cert_file_path = *path to tls key file* + tls_key_file_path = * path to tls fullchain file* + .. |workflow| image:: https://github.com/modoboa/modoboa-installer/workflows/Modoboa%20installer/badge.svg .. |codecov| image:: http://codecov.io/github/modoboa/modoboa-installer/coverage.svg?branch=master :target: http://codecov.io/github/modoboa/modoboa-installer?branch=master diff --git a/modoboa_installer/config_dict_template.py b/modoboa_installer/config_dict_template.py index bfd8f72..bb7325d 100644 --- a/modoboa_installer/config_dict_template.py +++ b/modoboa_installer/config_dict_template.py @@ -39,7 +39,16 @@ ConfigDictTemplate = [ "default": "self-signed", "customizable": True, "question": "Please choose your certificate type", - "values": ["self-signed", "letsencrypt"], + "values": ["self-signed", "letsencrypt", "manual"], + "non_interactive_values": ["manual"], + }, + { + "option": "tls_cert_file_path", + "default": "" + }, + { + "option": "tls_key_file_path", + "default": "" } ], }, diff --git a/modoboa_installer/ssl.py b/modoboa_installer/ssl.py index a76ef67..4dd7357 100644 --- a/modoboa_installer/ssl.py +++ b/modoboa_installer/ssl.py @@ -7,7 +7,7 @@ from . import package from . import utils -class CertificateBackend(object): +class CertificateBackend: """Base class.""" def __init__(self, config): @@ -24,13 +24,44 @@ class CertificateBackend(object): return False return True + def generate_cert(self): + """Create a certificate.""" + pass + + +class ManualCertificate(CertificateBackend): + """Use certificate provided.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + path_correct = True + self.tls_cert_file_path = self.config.get("certificate", + "tls_key_file_path") + self.tls_key_file_path = self.config.get("certificate", + "tls_cert_file_path") + + if not os.path.exists(self.tls_key_file_path): + utils.error("'tls_key_file_path' path is not accessible") + path_correct = False + if not os.path.exists(self.tls_cert_file_path): + utils.error("'tls_cert_file_path' path is not accessible") + path_correct = False + + if not path_correct: + sys.exit(1) + + self.config.set("general", "tls_key_file", + self.tls_key_file_path) + self.config.set("general", "tls_cert_file", + self.tls_cert_file_path) + class SelfSignedCertificate(CertificateBackend): """Create a self signed certificate.""" def __init__(self, *args, **kwargs): """Sanity checks.""" - super(SelfSignedCertificate, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.config.has_option("general", "tls_key_file"): # Compatibility return @@ -65,7 +96,7 @@ class LetsEncryptCertificate(CertificateBackend): def __init__(self, *args, **kwargs): """Update config.""" - super(LetsEncryptCertificate, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.hostname = self.config.get("general", "hostname") self.config.set("general", "tls_cert_file", ( "/etc/letsencrypt/live/{}/fullchain.pem".format(self.hostname))) @@ -119,8 +150,13 @@ class LetsEncryptCertificate(CertificateBackend): def get_backend(config): """Return the appropriate backend.""" - if not config.getboolean("certificate", "generate"): + cert_type = config.get("certificate", "type") + condition = (not config.getboolean("certificate", "generate") and + cert_type != "manual") + if condition: return None - if config.get("certificate", "type") == "letsencrypt": + if cert_type == "letsencrypt": return LetsEncryptCertificate(config) + if cert_type == "manual": + return ManualCertificate(config) return SelfSignedCertificate(config) diff --git a/modoboa_installer/utils.py b/modoboa_installer/utils.py index 2332273..18725c1 100644 --- a/modoboa_installer/utils.py +++ b/modoboa_installer/utils.py @@ -316,6 +316,17 @@ def get_entry_value(entry, interactive): if entry.get("values") and user_value != "": user_value = values[int(user_value)] + + non_interactive_values = entry.get("non_interactive_values", []) + if user_value in non_interactive_values: + error( + f"{user_value} cannot be set interactively. " + "Please configure installer.cfg manually by running " + "'python3 run.py --stop-after-configfile-check domain'. " + "Check modoboa-installer README for more information." + ) + sys.exit(1) + return user_value if user_value else default_value diff --git a/run.py b/run.py index bdc7b5a..78b9877 100755 --- a/run.py +++ b/run.py @@ -203,7 +203,7 @@ def main(input_args): if not args.skip_checks: utils.printcolor("Checking the installer...", utils.BLUE) checks.handle() - utils.success("Checks complete") + utils.success("Checks complete\n") is_config_file_available, outdate_config = utils.check_config_file( args.configfile, args.interactive, args.upgrade, args.backup, is_restoring)