hashicorp/vagrant · error · Vagrant::Errors::CopyPrivateKeyFailed
Vagrant failed to copy the default insecure private key…
Error message
Vagrant failed to copy the default insecure private key into your
home directory. This is usually caused by a permissions error.
Please make sure the permissions of the source is readable and
the destination is writable.
Source: %{source}
Destination: %{destination} What it means
Raised as Vagrant::Errors::CopyPrivateKeyFailed from copy_insecure_private_keys (lib/vagrant/environment.rb:1094) when FileUtils.cp of the bundled source keys/vagrant file into the default insecure private key path under the Vagrant home (~/.vagrant.d/...) raises Errno::EACCES — the destination (or source) is not writable/readable due to permissions.
Solutions
- Fix ownership of the destination tree: `sudo chown -R $(id -u):$(id -g) ~/.vagrant.d` and ensure it is writable (chmod u+w)
- Verify the source is readable (it ships inside the Vagrant install; a broken install re-install fixes it)
- If $HOME cannot be made writable, point Vagrant elsewhere: `export VAGRANT_HOME=/writable/path/vagrant.d`
- Avoid running vagrant as root/mismatched users in the same home
Example fix
# before $ sudo chown -R root:root ~/.vagrant.d # (or created by earlier sudo run) $ vagrant up # CopyPrivateKeyFailed # after $ sudo chown -R $(id -u):$(id -g) ~/.vagrant.d $ vagrant up
Defensive patterns
Strategy: validation
Validate before calling
home = ENV["VAGRANT_HOME"] || File.expand_path("~/.vagrant.d")
raise ArgumentError, "#{home} not writable — key copy will fail" unless File.writable?(home)
# source ships with the install; destination is home/insecure_private_key Try / catch
begin
env = Vagrant::Environment.new
rescue Vagrant::Errors::CopyPrivateKeyFailed => e
abort "Cannot copy key #{e.extra_data[:source]} -> #{e.extra_data[:destination]}: fix permissions"
end Prevention
- Keep ~/.vagrant.d owned and writable by the vagrant user
- Avoid sudo vagrant; if unavoidable, chown -R the home afterwards
- Redirect VAGRANT_HOME on hosts with read-only $HOME
When it happens
Trigger: First run on a machine where the home directory's key location is not writable by the current user — root-owned ~/.vagrant.d after earlier sudo use, hardened read-only home, or a VAGRANT_HOME path without write permission — so copying the default key fails during environment setup.
Common situations: sudo vagrant used once, then normal user; home directories on locked-down corporate images; running as a service account whose $HOME is not writable.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- The home directory you specified is not accessible. The…
- The directory Vagrant will use to store local…
- An error occurred while executing a PowerShell script. This…
- Failed to create the following shared folder on the host…
- Hyper-V access check has failed for the configured…
AI-assisted analysis of hashicorp/vagrant@35f3160f4a (2026-08-21).
Data as JSON: /api/errors/d89bf2f53a623c89.
Report an issue: GitHub.
Appendix: source
Thrown at lib/vagrant/environment.rb:1094
# `default_private_keys_directory` contains the list of valid private
# keys supported by Vagrant.
#
# NOTE: The keys are copied because `ssh` requires that the key is chmod
# 0600, but if Vagrant is installed as a separate user, then the
# effective uid won't be able to read the key. So the key is copied
# to the home directory and chmod 0600.
def copy_insecure_private_keys
# First setup the deprecated single key path
if !@default_private_key_path.exist?
@logger.info("Copying private key to home directory")
source = File.expand_path("keys/vagrant", Vagrant.source_root)
destination = @default_private_key_path
begin
FileUtils.cp(source, destination)
rescue Errno::EACCES
raise Errors::CopyPrivateKeyFailed,
source: source,
destination: destination
end
end
if !Util::Platform.windows?
# On Windows, permissions don't matter as much, so don't worry
# about doing chmod.
if Util::FileMode.from_octal(@default_private_key_path.stat.mode) != "600"
@logger.info("Changing permissions on private key to 0600")
@default_private_key_path.chmod(0600)
end
end
# Now setup the key directory
Dir.glob(File.expand_path("keys/vagrant.key.*", Vagrant.source_root)).each do |source|
destination = default_private_keys_directory.join(File.basename(source))
default_private_key_paths << destinationView on GitHub (pinned to 35f3160f4a)