From Fedora Project Wiki
This page is a draft only
It is still under construction and content may change. Do not rely on the information on this page.

Vagrant plugins are esentially RubyGems that are installed to a specific Vagrant plugin directory and that need to be registered in Vagrant plugin configuration file upon installation. As most of the RubyGems guidelines apply to them, this guide discusses only specifics in which Vagrant plugins differ.


Vagrant plugins are essentially RubyGems so they require Ruby and RubyGems. They also require Vagrant to be present as well for both runtime and buildtime. Specify:

Requires: ruby(release)
Requires: ruby(rubygems)
Requires: vagrant
BuildRequires: ruby(release)
BuildRequires: rubygems
BuildRequires: vagrant

Vagrant and its plugins current does not work with alternative Ruby interpreters, but you do not need to specify the requirement on ruby package in plugins spec files though.

Naming Guidelines

Plugins should follow upstream name that usually starts with vagrant-. Do not add the rubygem- prefix.


Vagrant plugins must be installed to certain standard locations. The vagrant package contains usuful macros that should be used to achieve that.

Macro Expanded path Usage
From vagrant; intended for Vagrant plugin packages.
%{vagrant_dir} %{_datadir}/vagrant Vagrant installation directory.
%{vagrant_plugin_conf_dir} %{_sharedstatedir}/vagrant Plugin configuration files.
%{vagrant_plugin_conf} %{vagrant_plugin_conf_dir}/plugins.json Configuration file for system-wide plugins.
%{vagrant_plugin_dir} %{vagrant_dir}/gems Common locations for Vagrant plugin gems.
%{vagrant_plugin_instdir} %{vagrant_plugin_dir}/gems/%{vagrant_plugin_name}-%{version} Directory with the actual content of the plugin.
%{vagrant_plugin_libdir} %{vagrant_plugin_instdir}/lib The lib folder of the plugin.
%{vagrant_plugin_cache} %{vagrant_plugin_dir}/cache/%{vagrant_plugin_name}-%{version}.gem The cached plugin.
%{vagrant_plugin_spec} %{vagrant_plugin_dir}/specifications/%{vagrant_plugin_name}-%{version}.gemspec The plugin's specification file.
%{vagrant_plugin_docdir} %{vagrant_plugin_dir}/doc/%{vagrant_plugin_name}-%{version} The rdoc documentation of the plugin.
%{vagrant_plugin_extdir} %{_libdir}/vagrant/gems/ruby/%{vagrant_plugin_name}-%{version} The directory for MRI Ruby plugin extensions. Currently unused.

Building Vagrant plugins

A sample spec for building a Vagrant plugin would look like this:

%global vagrant_plugin_name vagrant-registration

Name: %{vagrant_plugin_name}
Version: 0.0.19
Release: 2%{?dist}
Summary: Automatic guest registration for Vagrant
Group: Development/Languages
License: GPLv2
Requires(pre): shadow-utils
Requires(posttrans): vagrant
Requires(preun): vagrant
Requires: ruby(release)
Requires: ruby(rubygems) >= 1.3.6
Requires: vagrant
BuildRequires: ruby(release)
BuildRequires: rubygems-devel >= 1.3.6
BuildRequires: ruby 
BuildRequires: vagrant
BuildArch: noarch
Provides: vagrant(%{vagrant_plugin_name}) = %{version}

Enables guests to be registered automatically which is especially useful
for RHEL or SLES guests.

%package doc
Summary: Documentation for %{name}
Group: Documentation
Requires: %{name} = %{version}-%{release}
BuildArch: noarch

%description doc
Documentation for %{name}.

gem unpack %{SOURCE0}

%setup -q -D -T -n  %{vagrant_plugin_name}-%{version}

gem spec %{SOURCE0} -l --ruby > %{vagrant_plugin_name}.gemspec

# Create the gem as gem install only works on a gem file
gem build %{vagrant_plugin_name}.gemspec

mkdir -p %{buildroot}%{vagrant_plugin_dir}
cp -a .%{vagrant_plugin_dir}/* \

# We can't run test suite because it requires virtualization
pushd .%{vagrant_plugin_instdir}


getent group vagrant >/dev/null || groupadd -r vagrant

%vagrant_plugin_register %{vagrant_plugin_name}

%vagrant_plugin_unregister %{vagrant_plugin_name}

%license %{vagrant_plugin_instdir}/
%exclude %{vagrant_plugin_cache}

%files doc
%doc %{vagrant_plugin_instdir}/
%doc %{vagrant_plugin_instdir}/
%doc %{vagrant_plugin_docdir}



Since gems aren't an archive format that RPM recognizes, the first thing we have to do is explicitly use gem unpack to extract the source from the gem. Then we call %setup -n %{vagrant_plugin_name}-%{version} to tell RPM what the directory the gem has unpacked into. The -T and -D flags tell %setup that we've already unpacked the code

We then run gem spec to output the metadata from the gem into a file. This .gemspec file will be used to rebuild the gem later. If we need to modify the .gemspec (for instance, if the version of dependencies is wrong for Fedora or the .gemspec is using old, no longer supported fields) we would do it here. Patches to the code itself can also be done here.


Next we build the gem. Because %vagrant_plugin_install only operates on gem archives, we next recreate the gem with gem build. The gem file that is created is then used by %vagrant_plugin_install to build and install the code into the temporary directory, which is ./%{vagrant_plugin_dir} by default. We do this because the %vagrant_plugin_install command both builds and installs the code in one step so we need to have a temporary directory to place the built sources before installing them in %install section.

%vagrant_plugin_install macro accepts two additional options:

-n <gem_file>
Allows to override gem used for installation. This might get useful for converting legacy spec, so you might specify %{SOURCE0} as a gem for installation.
-d <install_dir>
Might override the gem installation destination. However we do not suggest to use this option.
The %vagrant_plugin_install macro must not be used to install into the %{buildroot}


Here we actually install the plugin files into the %{buildroot}. We create the directories that we need and then copy what was installed into the temporary directories into the %{buildroot} hierarchy.


In check section we execute the test suite if we can. This is often not possible because Vagrant requires virtualization to run.


In the %pre section we must check that vargant group exists. If not, we create it. This is why we required shadow-utils package earlier.

To do so, we write:

getent group vagrant >/dev/null || groupadd -r vagrant


After the files are installed we still need to tell Vagrant about the new plugin that has been installed and register it. There is %vagrant_plugin_register macro that must be used.

%vagrant_plugin_register %{vagrant_plugin_name}


After the files are uninstalled we still need to tell Vagrant about the plugin being removed and unregister it. There is %vagrant_plugin_unregister macro that must be used.

%vagrant_plugin_unregister %{vagrant_plugin_name}