{"record":{"id":"ad884fc5803ceb05","repo":"goharbor/harbor","slug":"error-the-protocol-is-https-but-attribute-ssl-cer-ad884f","errorCode":null,"errorMessage":"Error: The protocol is https but attribute ssl_cert_key is not set","messagePattern":"Error: The protocol is https but attribute ssl_cert_key is not set","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"make/photon/prepare/utils/configs.py","lineNumber":33,"sourceCode":"default_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\" % (\n            storage_provider_name, \",\".join(valid_storage_drivers)))\n","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/make/photon/prepare/utils/configs.py#L15-L51","documentation":"Thrown by validate() in make/photon/prepare/utils/configs.py when harbor.yml declares 'protocol: https' but the private key path is empty or still the placeholder '/your/certificate/path' (default_https_key_path). The TLS key is required alongside the certificate to terminate HTTPS in the nginx proxy; one without the other is a fatal configuration error.","triggerScenarios":"harbor.yml has 'https:' enabled and 'private_key:' left as '/your/certificate/path' or an empty value. Fires only after the certificate check (error 21) already passed, i.e. the certificate was fixed but the key was not.","commonSituations":"Half-finished edits: users replace the certificate path but leave the key placeholder; copy-paste configs where both paths still point at the sample; certificate renewed via script that only updates cert path.","solutions":["Set 'https.private_key:' to the absolute path of the matching PEM private key on the Docker host, e.g. /data/cert/harbor.example.com.key","Confirm the key matches the certificate: openssl x509 -noout -modulus -in server.crt | openssl md5 vs openssl rsa -noout -modulus -in server.key | openssl md5","Re-run ./install.sh"],"exampleFix":"# harbor.yml (before)\nhttps:\n  certificate: /data/cert/harbor.example.com.crt\n  private_key: /your/certificate/path\n\n# harbor.yml (after)\nhttps:\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 {}\nkey = https_cfg.get('private_key', '')\nif https_cfg and (not key or key == PLACEHOLDER):\n    raise SystemExit('https.private_key is unset or still the placeholder')\nif https_cfg and not os.path.isfile(key):\n    raise SystemExit('https.private_key does not exist on the host: %s' % key)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always edit certificate and private_key together when enabling https","Verify cert/key pair match before running install","Automate cert rotation to update both harbor.yml entries"],"tags":["harbor","https","tls","private-key","configuration"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}