{"record":{"id":"ce05a6ff613b0f19","repo":"coollabsio/coolify","slug":"ssh-keys-storage-directory-is-not-writable-run-on","errorCode":null,"errorMessage":"SSH keys storage directory is not writable. Run on the host: sudo chown -R 9999 /data/coolify/ssh && sudo chmod -R 700 /data/coolify/ssh && docker restart coolify","messagePattern":"SSH keys storage directory is not writable\\. Run on the host: sudo chown -R 9999 /data/coolify/ssh && sudo chmod -R 700 /data/coolify/ssh && docker restart coolify","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"app/Models/PrivateKey.php","lineNumber":285,"sourceCode":"\n    protected function ensureStorageDirectoryExists()\n    {\n        $disk = Storage::disk('ssh-keys');\n        $directoryPath = '';\n\n        if (! $disk->exists($directoryPath)) {\n            $success = $disk->makeDirectory($directoryPath);\n            if (! $success) {\n                throw new \\Exception('Failed to create SSH keys storage directory');\n            }\n        }\n\n        // Check if directory is writable by attempting a test file\n        $testFilename = '.test_write_'.uniqid();\n        $testSuccess = $disk->put($testFilename, 'test');\n\n        if (! $testSuccess) {\n            throw new \\Exception('SSH keys storage directory is not writable. Run on the host: sudo chown -R 9999 /data/coolify/ssh && sudo chmod -R 700 /data/coolify/ssh && docker restart coolify');\n        }\n\n        // Clean up test file\n        $disk->delete($testFilename);\n    }\n\n    public function getKeyLocation()\n    {\n        return Storage::disk('ssh-keys')->path(\"ssh_key@{$this->uuid}\");\n    }\n\n    public function updatePrivateKey(array $data)\n    {\n        return DB::transaction(function () use ($data) {\n            $this->update($data);\n\n            return $this;\n        });","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/coollabsio/coolify/blob/70b9acc42467278373e00de77abb40684e25b395/app/Models/PrivateKey.php#L267-L303","documentation":"Thrown by PrivateKey::ensureStorageDirectoryExists() (app/Models/PrivateKey.php:285). After ensuring the directory exists, the routine proves writability by writing a probe file .test_write_{uniqid} into the ssh-keys disk; if put() returns false, storage is unusable and the exception embeds the exact host-side remediation command. This is the most common SSH-key storage failure on self-hosted installs: the Coolify container runs as uid 9999 and the host directory is owned by root.","triggerScenarios":"Any PrivateKey create/update/delete that hits the filesystem when /data/coolify/ssh exists but uid 9999 cannot write into it (root-owned dir, 755 perms, wrong volume bind) — the probe write fails before any key operation starts.","commonSituations":"Post-install first key upload; permission drift after restoring a backup or moving the host; bind-mounting the wrong directory over /data/coolify/ssh.","solutions":["Run exactly what the message says on the host: sudo chown -R 9999 /data/coolify/ssh && sudo chmod -R 700 /data/coolify/ssh && docker restart coolify.","Verify with: docker exec coolify touch /data/coolify/ssh/.probe (should succeed silently).","Retry the SSH key operation in the UI/API."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Same pre-flight as callers can run\n$root = Storage::disk('ssh-keys')->path('');\n$probe = $root.'/.probe_'.uniqid();\nif (@file_put_contents($probe, 'x') === false) {\n    throw new \\RuntimeException('Run on the host: sudo chown -R 9999 /data/coolify/ssh && sudo chmod -R 700 /data/coolify/ssh && docker restart coolify');\n}\n@unlink($probe);","typeGuard":null,"tryCatchPattern":"try {\n    $privateKey->storeInFileSystem();\n} catch (\\Exception $e) {\n    if (str_contains($e->getMessage(), 'storage directory is not writable')) {\n        // apply the exact host command from the message, restart coolify, retry\n    }\n    throw $e;\n}","preventionTips":["After install, restore, or host migration, proactively run the chown 9999 / chmod 700 command before uploading keys.","The container user is fixed at uid 9999 — any volume bind for /data/coolify/ssh must honor that."],"tags":["coolify","ssh-key","permissions","file-storage","installation"],"backgroundTag":"file-write-permission-denied","analyzedSha":"70b9acc42467278373e00de77abb40684e25b395","analyzedAt":"2026-08-17T01:41:01.313Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}