coollabsio/coolify · error · Exception

Failed to write SSH key to filesystem. Check disk space and

Error message

Failed to write SSH key to filesystem. Check disk space and permissions for: {$keyLocation}

What it means

Thrown by PrivateKey::storeInFileSystem() (app/Models/PrivateKey.php:229). With the lock held, $disk->put("ssh_key@{uuid}", $this->private_key) on the 'ssh-keys' disk returned false — Laravel's local driver returns false when file_put_contents fails, i.e. the write never hit disk. Combined with the preceding ensureStorageDirectoryExists() test write, this points to disk space exhaustion or a permission/ownership change that happened between the test write and the real write.

Source

Thrown at app/Models/PrivateKey.php:229

        // Ensure the storage directory exists and is writable
        $this->ensureStorageDirectoryExists();

        // Use file locking to prevent concurrent writes from corrupting the key
        $lockHandle = fopen($lockFile, 'c');
        if ($lockHandle === false) {
            throw new \Exception("Failed to open lock file for SSH key: {$lockFile}");
        }

        try {
            if (! flock($lockHandle, LOCK_EX)) {
                throw new \Exception("Failed to acquire lock for SSH key: {$keyLocation}");
            }

            // Attempt to store the private key
            $success = $disk->put($filename, $this->private_key);

            if (! $success) {
                throw new \Exception("Failed to write SSH key to filesystem. Check disk space and permissions for: {$keyLocation}");
            }

            // Verify the file was actually created and has content
            if (! $disk->exists($filename)) {
                throw new \Exception("SSH key file was not created: {$keyLocation}");
            }

            $storedContent = $disk->get($filename);
            if (empty($storedContent) || $storedContent !== $this->private_key) {
                $disk->delete($filename); // Clean up the bad file
                throw new \Exception("SSH key file content verification failed: {$keyLocation}");
            }

            // Ensure correct permissions for SSH (0600 required)
            if (file_exists($keyLocation) && ! chmod($keyLocation, 0600)) {
                Log::warning('Failed to set SSH key file permissions to 0600', [
                    'key_uuid' => $this->uuid,
                    'path' => $keyLocation,

View on GitHub (pinned to 70b9acc424)

Solutions

  1. Free space on the host (docker system prune, log rotation) and retry — the transaction and lock cleanup leave no partial state.
  2. Re-apply the ownership fix: sudo chown -R 9999 /data/coolify/ssh && sudo chmod -R 700 /data/coolify/ssh && docker restart coolify.
  3. dmesg/df -h the host to rule out a read-only remount or quota.
  4. The earlier create/update that failed rolls back (createAndStore wraps this in DB::transaction()), so simply retry after fixing.
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight free space on the storage backing the ssh-keys disk
$path = Storage::disk('ssh-keys')->path('');
if (disk_free_space($path) === false || disk_free_space($path) < 1024) {
    throw new \RuntimeException('Insufficient disk space for SSH key storage.');
}

Try / catch

try {
    $privateKey->storeInFileSystem();
} catch (\Exception $e) {
    if (str_contains($e->getMessage(), 'Check disk space and permissions')) {
        // free space / fix ownership, then retry — no partial file is left
    }
    throw $e;
}

Prevention

When it happens

Trigger: Creating or updating an SSH key when the host volume holding /data/coolify/ssh is full (ENOSPC) or became unwritable mid-operation (ownership flipped, quota hit, read-only remount on IO error).

Common situations: Full host disk from Docker images/logs; LVM/quota limits on the data volume; filesystem auto-remounted read-only after an error; multi-worker writes racing a permissions fix.

Related errors


AI-assisted analysis of coollabsio/coolify@70b9acc424 (2026-08-17). Data as JSON: /api/errors/d2b952a39367b3a8. Report an issue: GitHub.