{"record":{"id":"3a869602834f2c69","repo":"kubernetes/kops","slug":"exactly-one-admin-ssh-public-key-can-be-specifie-3a8696","errorCode":null,"errorMessage":"exactly one 'admin' SSH public key can be specified when running with Scaleway; please delete a key using `kops delete secret`","messagePattern":"exactly one 'admin' SSH public key can be specified when running with Scaleway; please delete a key using `kops delete secret`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/apply_cluster.go","lineNumber":495,"sourceCode":"\t\t\t\treturn nil, fmt.Errorf(\"SSH public key must be specified when running with Openstack (create with `kops create secret --name %s sshpublickey admin -i ~/.ssh/id_rsa.pub`)\", cluster.ObjectMeta.Name)\n\t\t\t}\n\n\t\t\tif len(sshPublicKeys) != 1 {\n\t\t\t\treturn nil, fmt.Errorf(\"exactly one 'admin' SSH public key can be specified when running with Openstack; please delete a key using `kops delete secret`\")\n\t\t\t}\n\t\t}\n\n\tcase kops.CloudProviderScaleway:\n\t\t{\n\t\t\tif !featureflag.Scaleway.Enabled() {\n\t\t\t\treturn nil, fmt.Errorf(\"Scaleway support is currently alpha, and is feature-gated.  export KOPS_FEATURE_FLAGS=Scaleway\")\n\t\t\t}\n\n\t\t\tif len(sshPublicKeys) == 0 {\n\t\t\t\treturn nil, fmt.Errorf(\"SSH public key must be specified when running with Scaleway (create with `kops create secret --name %s sshpublickey admin -i ~/.ssh/id_rsa.pub`)\", cluster.ObjectMeta.Name)\n\t\t\t}\n\t\t\tif len(sshPublicKeys) != 1 {\n\t\t\t\treturn nil, fmt.Errorf(\"exactly one 'admin' SSH public key can be specified when running with Scaleway; please delete a key using `kops delete secret`\")\n\t\t\t}\n\n\t\t\tscwCloud := cloud.(scaleway.ScwCloud)\n\t\t\tscwZone = scwCloud.Zone()\n\t\t}\n\n\tcase kops.CloudProviderLinode:\n\t\t{\n\t\t\tif !featureflag.Linode.Enabled() {\n\t\t\t\treturn nil, fmt.Errorf(\"Akamai (Linode) support is currently alpha, and is feature-gated. Please export KOPS_FEATURE_FLAGS=Linode\")\n\t\t\t}\n\t\t}\n\n\tcase kops.CloudProviderMetal:\n\t\t// Metal is a special case, we don't need to do anything here (yet)\n\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknown CloudProvider %q\", cluster.GetCloudProvider())","sourceCodeStart":477,"sourceCodeEnd":513,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/apply_cluster.go#L477-L513","documentation":"For Scaleway clusters kOps enforces exactly one 'admin' SSH public key. In apply_cluster.go Run, if more than one sshpublickey secret exists the apply is rejected, mirroring the OpenStack rule, because the Scaleway path provisions a single admin keypair.","triggerScenarios":"`kops update cluster` on a scaleway cluster whose secret store contains two or more sshpublickey entries.","commonSituations":"Accumulated keys from repeated `kops create secret sshpublickey` runs with different names, or migrating keys from another provider's cluster.","solutions":["Delete surplus keys: `kops delete secret sshpublickey <extra-name> --name <cluster>`","Keep exactly one (typically 'admin'): verify with `kops get secrets`","Rerun `kops update cluster`"],"exampleFix":"// before: admin + laptop keys exist\nkops delete secret sshpublickey laptop --name scw.example.com\n// after: only 'admin'; update succeeds","handlingStrategy":"validation","validationCode":"count=$(kops get secrets --name \"$CLUSTER\" | grep -c sshpublickey); [ \"$count\" -le 1 ] || kops delete secret sshpublickey <extra> --name \"$CLUSTER\"","typeGuard":null,"tryCatchPattern":"if err := updateCluster(); err != nil { if strings.Contains(err.Error(), \"exactly one 'admin' SSH public key\") { listAndPruneKeys(); retry() } return err }","preventionTips":["Treat 'admin' as the only sshpublickey; never add additional named keys on scaleway","Periodically audit secrets for duplicates","Wrap key rotation so old keys are deleted in the same step new ones are added"],"tags":["scaleway","ssh","configuration","precondition"],"backgroundTag":"invalid-ssh-key-configuration","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}