{"record":{"id":"9eae4b619be0ebc0","repo":"goharbor/harbor","slug":"error-the-protocol-is-https-but-attribute-ssl-cer","errorCode":null,"errorMessage":"Error: The protocol is https but attribute ssl_cert is not set","messagePattern":"Error: The protocol is https but attribute ssl_cert is not set","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"make/photon/prepare/utils/configs.py","lineNumber":31,"sourceCode":"default_db_max_open_conns = 0\ndefault_https_cert_path = '/your/certificate/path'\ndefault_https_key_path = '/your/certificate/path'\n\nREGISTRY_USER_NAME = 'harbor_registry_user'\n\n\ndef validate(conf: dict, **kwargs):\n    # hostname validate\n    if conf.get('hostname') == '127.0.0.1':\n        raise Exception(\"127.0.0.1 can not be the hostname\")\n    if conf.get('hostname') == 'reg.mydomain.com':\n        raise Exception(\"Please specify hostname\")\n\n    # protocol validate\n    protocol = conf.get(\"protocol\")\n    if protocol == \"https\":\n        if not conf.get(\"cert_path\") or conf[\"cert_path\"] == default_https_cert_path:\n            raise Exception(\"Error: The protocol is https but attribute ssl_cert is not set\")\n        if not conf.get(\"cert_key_path\") or conf['cert_key_path'] == default_https_key_path:\n            raise Exception(\"Error: The protocol is https but attribute ssl_cert_key is not set\")\n    if protocol == \"http\":\n        logging.warning(\"WARNING: HTTP protocol is insecure. Harbor will deprecate http protocol in the future. Please make sure to upgrade to https\")\n\n    # log endpoint validate\n    if ('log_ep_host' in conf) and not conf['log_ep_host']:\n        raise Exception('Error: must set log endpoint host to enable external host')\n    if ('log_ep_port' in conf) and not conf['log_ep_port']:\n        raise Exception('Error: must set log endpoint port to enable external host')\n    if ('log_ep_protocol' in conf) and (conf['log_ep_protocol'] not in ['udp', 'tcp']):\n        raise Exception(\"Protocol in external log endpoint must be one of 'udp' or 'tcp' \")\n\n    # Storage validate\n    valid_storage_drivers = [\"filesystem\", \"azure\", \"gcs\", \"s3\", \"swift\", \"oss\"]\n    storage_provider_name = conf.get(\"storage_provider_name\")\n    if storage_provider_name not in valid_storage_drivers:\n        raise Exception(\"Error: storage driver %s is not supported, only the following ones are supported: %s\" % (","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/make/photon/prepare/utils/configs.py#L13-L49","documentation":"Thrown by validate() in make/photon/prepare/utils/configs.py when harbor.yml declares 'protocol: https' but the certificate path is empty or still the placeholder '/your/certificate/path' (default_https_cert_path). Harbor needs a real server certificate to configure the nginx proxy and derive internal TLS material, so HTTPS cannot proceed without it. The message says ssl_cert because it mirrors the old harbor.cfg attribute name.","triggerScenarios":"harbor.yml has the 'https:' block uncommented and 'certificate:' left as '/your/certificate/path' (or an empty value) when the config dict reaches validate(). The check is: not conf.get('cert_path') or conf['cert_path'] == '/your/certificate/path'.","commonSituations":"Users uncomment https but never replace the sample paths; someone comments out only the certificate line while keeping the key line; upgrades from http to https where the placeholder was never touched.","solutions":["Set 'https.certificate:' in harbor.yml to the absolute path of an existing PEM certificate on the Docker host, e.g. /data/cert/server.crt","Verify the file exists on the host: ls -l /data/cert/server.crt","If you do not have certificates yet, generate self-signed ones with openssl or keep the whole 'https:' block commented out to install over http (insecure, warned)","Re-run ./install.sh"],"exampleFix":"# harbor.yml (before)\nhttps:\n  port: 443\n  certificate: /your/certificate/path\n  private_key: /your/certificate/path\n\n# harbor.yml (after)\nhttps:\n  port: 443\n  certificate: /data/cert/harbor.example.com.crt\n  private_key: /data/cert/harbor.example.com.key","handlingStrategy":"validation","validationCode":"PLACEHOLDER = '/your/certificate/path'\nhttps_cfg = cfg.get('https') or {}\ncert = https_cfg.get('certificate', '')\nif https_cfg and (not cert or cert == PLACEHOLDER):\n    raise SystemExit('https.certificate is unset or still the placeholder')\nimport os\nif https_cfg and not os.path.isfile(cert):\n    raise SystemExit('https.certificate does not exist on the host: %s' % cert)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Replace every '/your/certificate/path' placeholder when enabling https","Use absolute host paths; prepare resolves them inside its container against the host filesystem","Prepare certificates before flipping Harbor to https"],"tags":["harbor","https","tls","certificate","configuration"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}