
Additionally, fixed most of the errors reported by rstcheck. Fixes https://github.com/saltstack/salt/issues/58668
40 KiB
Git Fileserver Backend Walkthrough
Note
This walkthrough assumes basic knowledge of Salt. To get up to speed,
check out the Salt Walkthrough <tutorial-salt-walk-through>
.
The gitfs backend allows Salt to serve files from git repositories.
It can be enabled by adding git
to the fileserver_backend
list, and configuring one or more repositories in gitfs_remotes
.
Branches and tags become Salt fileserver environments.
Note
Branching and tagging can result in a lot of potentially-conflicting
top files <states-top>
, for this reason it may
be useful to set top_file_merging_strategy
to same
in the minions' config files if the top files are being managed in a
GitFS repo.
Installing Dependencies
Both pygit2 and GitPython are supported Python interfaces to
git. If compatible versions of both are installed, pygit2 will be preferred. In these cases, GitPython can be forced using the gitfs_provider
parameter in the master config file.
Note
It is recommended to always run the most recent version of any the below dependencies. Certain features of GitFS may not be available without the most recent version of the chosen library.
pygit2
The minimum supported version of pygit2 is 0.20.3. Availability for this version of pygit2 is still limited, though the SaltStack team is working to get compatible versions available for as many platforms as possible.
For the Fedora/EPEL versions which have a new enough version packaged, the following command would be used to install pygit2:
# yum install python-pygit2
Provided a valid version is packaged for Debian/Ubuntu (which is not currently the case), the package name would be the same, and the following command would be used to install it:
# apt-get install python-pygit2
If pygit2 is not packaged for the platform on
which the Master is running, the pygit2 website
has installation instructions here. Keep in mind however that
following these instructions will install libgit2 and pygit2 without system packages. Additionally, keep
in mind that SSH authentication in pygit2
<pygit2-authentication-ssh>
requires libssh2 (not libssh)
development libraries to be present before libgit2 is built. On some Debian-based
distros pkg-config
is also required to link libgit2 with libssh2.
Note
If you are receiving the error "Unsupported URL Protocol" in the Salt Master log when making a connection using SSH, review the libssh2 details listed above.
Additionally, version 0.21.0 of pygit2 introduced a dependency on python-cffi, which in turn depends on newer releases of libffi. Upgrading libffi is not advisable as several other applications depend on it, so on older LTS linux releases pygit2 0.20.3 and libgit2 0.20.0 is the recommended combination.
Warning
pygit2 is actively developed and frequently makes non-backwards-compatible API changes, even in minor releases. It is not uncommon for pygit2 upgrades to result in errors in Salt. Please take care when upgrading pygit2, and pay close attention to the changelog, keeping an eye out for API changes. Errors can be reported on the SaltStack issue tracker.
RedHat Pygit2 Issues
The release of RedHat/CentOS 7.3 upgraded both
python-cffi
and http-parser
, both of which are
dependencies for pygit2/libgit2_. Both
pygit2
and libgit2
packages (which are from
the EPEL repository) should be upgraded to the most recent versions, at
least to 0.24.2
.
The below errors will show up in the master log if an incompatible
python-pygit2
package is installed:
2017-02-10 09:07:34,892 [salt.utils.gitfs ][ERROR ][11211] Import pygit2 failed: CompileError: command 'gcc' failed with exit status 1
2017-02-10 09:07:34,907 [salt.utils.gitfs ][ERROR ][11211] gitfs is configured but could not be loaded, are pygit2 and libgit2 installed?
2017-02-10 09:07:34,907 [salt.utils.gitfs ][CRITICAL][11211] No suitable gitfs provider module is installed.
2017-02-10 09:07:34,912 [salt.master ][CRITICAL][11211] Master failed pre flight checks, exiting
The below errors will show up in the master log if an incompatible
libgit2
package is installed:
2017-02-15 18:04:45,211 [salt.utils.gitfs ][ERROR ][6211] Error occurred fetching gitfs remote 'https://foo.com/bar.git': No Content-Type header in response
A restart of the salt-master
daemon and gitfs cache
directory clean up may be required to allow http(s) repositories to
continue to be fetched.
GitPython
GitPython 0.3.0 or newer is required to use GitPython for gitfs. For RHEL-based Linux distros, a compatible version is available in EPEL, and can be easily installed on the master using yum:
# yum install GitPython
Ubuntu 14.04 LTS and Debian Wheezy (7.x) also have a compatible version packaged:
# apt-get install python-git
GitPython requires the git
CLI utility to work. If installed from a system package, then git should
already be installed, but if installed via pip then it may still be
necessary to install git separately. For MacOS users, GitPython comes bundled in with the Salt
installer, but git must still be installed for it to work properly. Git
can be installed in several ways, including by installing XCode.
Warning
GitPython advises against the use of its library for long-running processes (such as a salt-master or salt-minion). Please see their warning on potential leaks of system resources: https://github.com/gitpython-developers/GitPython#leakage-of-system-resources.
Warning
Keep in mind that if GitPython has been previously installed on the
master using pip (even if it was subsequently uninstalled), then it may
still exist in the build cache (typically
/tmp/pip-build-root/GitPython
) if the cache is not cleared
after installation. The package in the build cache will override any
requirement specifiers, so if you try upgrading to version 0.3.2.RC1 by
running pip install 'GitPython==0.3.2.RC1'
then it will
ignore this and simply install the version from the cache directory.
Therefore, it may be necessary to delete the GitPython directory from
the build cache in order to ensure that the specified version is
installed.
Warning
GitPython 2.0.9 and newer is not
compatible with Python 2.6. If installing GitPython using pip on a machine running Python
2.6, make sure that a version earlier than 2.0.9 is installed. This can
be done on the CLI by running
pip install 'GitPython<2.0.9'
, or in a pip.installed
<salt.states.pip_state.installed>
state using the following
SLS:
GitPython:
pip.installed:
- name: 'GitPython < 2.0.9'
Simple Configuration
To use the gitfs backend, only two configuration changes are required on the master:
Include
gitfs
in thefileserver_backend
list in the master config file:fileserver_backend: - gitfs
Note
git
also works here. Prior to the 2018.3.0 release, onlygit
would work.Specify one or more
git://
,https://
,file://
, orssh://
URLs ingitfs_remotes
to configure which repositories to cache and search for requested files:gitfs_remotes: - https://github.com/saltstack-formulas/salt-formula.git
SSH remotes can also be configured using scp-like syntax:
gitfs_remotes: - git@github.com:user/repo.git - ssh://user@domain.tld/path/to/repo.git
Information on how to authenticate to SSH remotes can be found
here <gitfs-authentication>
.Restart the master to load the new configuration.
Note
In a master/minion setup, files from a gitfs remote are cached once by the master, so minions do not need direct access to the git repository.
Multiple Remotes
The gitfs_remotes
option accepts an ordered list of git
remotes to cache and search, in listed order, for requested files.
A simple scenario illustrates this cascading lookup behavior:
If the gitfs_remotes
option specifies three remotes:
gitfs_remotes:
- git://github.com/example/first.git
- https://github.com/example/second.git
- file:///root/third
And each repository contains some files:
first.git:
top.sls
edit/vim.sls
edit/vimrc
nginx/init.sls
second.git:
edit/dev_vimrc
haproxy/init.sls
third:
haproxy/haproxy.conf
edit/dev_vimrc
Salt will attempt to lookup the requested file from each gitfs remote repository in the order in which they are defined in the configuration. The git://github.com/example/first.git remote will be searched first. If the requested file is found, then it is served and no further searching is executed. For example:
- A request for the file salt://haproxy/init.sls will be served from the https://github.com/example/second.git git repo.
- A request for the file salt://haproxy/haproxy.conf will be served from the file:///root/third repo.
Note
This example is purposefully contrived to illustrate the behavior of the gitfs backend. This example should not be read as a recommended way to lay out files and git repos.
The file:// prefix denotes a git repository in a local directory. However, it will still use the given file:// URL as a remote, rather than copying the git repo to the salt cache. This means that any refs you want accessible must exist as local refs in the specified repo.
Warning
Salt versions prior to 2014.1.0 are not tolerant of changing the
order of remotes or modifying the URI of existing remotes. In those
versions, when modifying remotes it is a good idea to remove the gitfs
cache directory (/var/cache/salt/master/gitfs
) before
restarting the salt-master service.
Per-remote Configuration Parameters
2014.7.0
The following master config parameters are global (that is, they apply to all configured gitfs remotes):
gitfs_base
gitfs_root
gitfs_ssl_verify
gitfs_mountpoint
(new in 2014.7.0)gitfs_user
(pygit2 only, new in 2014.7.0)gitfs_password
(pygit2 only, new in 2014.7.0)gitfs_insecure_auth
(pygit2 only, new in 2014.7.0)gitfs_pubkey
(pygit2 only, new in 2014.7.0)gitfs_privkey
(pygit2 only, new in 2014.7.0)gitfs_passphrase
(pygit2 only, new in 2014.7.0)gitfs_refspecs
(new in 2017.7.0)gitfs_disable_saltenv_mapping
(new in 2018.3.0)gitfs_ref_types
(new in 2018.3.0)gitfs_update_interval
(new in 2018.3.0)
Note
pygit2 only supports disabling SSL verification in versions 0.23.2 and newer.
These parameters can now be overridden on a per-remote basis. This allows for a tremendous amount of customization. Here's some example usage:
gitfs_provider: pygit2
gitfs_base: develop
gitfs_remotes:
- https://foo.com/foo.git
- https://foo.com/bar.git:
- root: salt
- mountpoint: salt://bar
- base: salt-base
- ssl_verify: False
- update_interval: 120
- https://foo.com/bar.git:
- name: second_bar_repo
- root: other/salt
- mountpoint: salt://other/bar
- base: salt-base
- ref_types:
- branch
- http://foo.com/baz.git:
- root: salt/states
- user: joe
- password: mysupersecretpassword
- insecure_auth: True
- disable_saltenv_mapping: True
- saltenv:
- foo:
- ref: foo
- http://foo.com/quux.git:
- all_saltenvs: master
Important
There are two important distinctions which should be noted for per-remote configuration:
- The URL of a remote which has per-remote configuration must be suffixed with a colon.
- Per-remote configuration parameters are named like the global
versions, with the
gitfs_
removed from the beginning. The exception being thename
,saltenv
, andall_saltenvs
parameters, which are only available to per-remote configurations.
The all_saltenvs
parameter is new in the 2018.3.0
release.
In the example configuration above, the following is true:
The first and fourth gitfs remotes will use the
develop
branch/tag as thebase
environment, while the second and third will use thesalt-base
branch/tag as thebase
environment.The first remote will serve all files in the repository. The second remote will only serve files from the
salt
directory (and its subdirectories). The third remote will only server files from theother/salt
directory (and its subdirectories), while the fourth remote will only serve files from thesalt/states
directory (and its subdirectories).The third remote will only serve files from branches, and not from tags or SHAs.
The fourth remote will only have two saltenvs available:
base
(pointed atdevelop
), andfoo
(pointed atfoo
).The first and fourth remotes will have files located under the root of the Salt fileserver namespace (
salt://
). The files from the second remote will be located undersalt://bar
, while the files from the third remote will be located undersalt://other/bar
.The second and third remotes reference the same repository and unique names need to be declared for duplicate gitfs remotes.
The fourth remote overrides the default behavior of
not authenticating to insecure (non-HTTPS) remotes <gitfs-insecure-auth>
.Because
all_saltenvs
is configured for the fifth remote, files from the branch/tagmaster
will appear in every fileserver environment.Note
The use of
http://
(instead ofhttps://
) is permitted here only because authentication is not being used. Otherwise, theinsecure_auth
parameter must be used (as in the fourth remote) to force Salt to authenticate to anhttp://
remote.The first remote will wait 120 seconds between updates instead of 60.
Per-Saltenv Configuration Parameters
2016.11.0
For more granular control, Salt allows the following three things to be overridden for individual saltenvs within a given repo:
- The
mountpoint <gitfs-walkthrough-mountpoint>
- The
root <gitfs-walkthrough-root>
- The branch/tag to be used for a given saltenv
Here is an example:
gitfs_root: salt
gitfs_saltenv:
- dev:
- mountpoint: salt://gitfs-dev
- ref: develop
gitfs_remotes:
- https://foo.com/bar.git:
- saltenv:
- staging:
- ref: qa
- mountpoint: salt://bar-staging
- dev:
- ref: development
- https://foo.com/baz.git:
- saltenv:
- staging:
- mountpoint: salt://baz-staging
Given the above configuration, the following is true:
- For all gitfs remotes, files for the
dev
saltenv will be located undersalt://gitfs-dev
. - For the
dev
saltenv, files from the first remote will be sourced from thedevelopment
branch, while files from the second remote will be sourced from thedevelop
branch. - For the
staging
saltenv, files from the first remote will be located undersalt://bar-staging
, while files from the second remote will be located undersalt://baz-staging
. - For all gitfs remotes, and in all saltenvs, files will be served
from the
salt
directory (and its subdirectories).
Custom Refspecs
2017.7.0
GitFS will by default fetch remote branches and tags. However,
sometimes it can be useful to fetch custom refs (such as those created
for GitHub
pull requests). To change the refspecs GitFS fetches, use the gitfs_refspecs
config
option:
gitfs_refspecs:
- '+refs/heads/*:refs/remotes/origin/*'
- '+refs/tags/*:refs/tags/*'
- '+refs/pull/*/head:refs/remotes/origin/pr/*'
- '+refs/pull/*/merge:refs/remotes/origin/merge/*'
In the above example, in addition to fetching remote branches and
tags, GitHub's custom refs for pull requests and merged pull requests
will also be fetched. These special head
refs represent the
head of the branch which is requesting to be merged, and the
merge
refs represent the result of the base branch after
the merge.
Important
When using custom refspecs, the destination of the fetched refs
must be under refs/remotes/origin/
, preferably in
a subdirectory like in the example above. These custom refspecs will map
as environment names using their relative path underneath
refs/remotes/origin/
. For example, assuming the
configuration above, the head branch for pull request 12345 would map to
fileserver environment pr/12345
(slash included).
Refspecs can be configured on a per-remote basis
<gitfs-per-remote-config>
. For example, the below
configuration would only alter the default refspecs for the
second GitFS remote. The first remote would only fetch branches
and tags (the default).
gitfs_remotes:
- https://domain.tld/foo.git
- https://domain.tld/bar.git:
- refspecs:
- '+refs/heads/*:refs/remotes/origin/*'
- '+refs/tags/*:refs/tags/*'
- '+refs/pull/*/head:refs/remotes/origin/pr/*'
- '+refs/pull/*/merge:refs/remotes/origin/merge/*'
Global Remotes
2018.3.0 for all_saltenvs, 3001 for fallback
The all_saltenvs
per-remote configuration parameter
overrides the logic Salt uses to map branches/tags to fileserver
environments (i.e. saltenvs). This allows a single branch/tag to appear
in all GitFS saltenvs.
Note
all_saltenvs
only works within GitFS. That is,
files in a branch configured using all_saltenvs
will
not show up in a fileserver environment defined via some other
fileserver backend (e.g. file_roots
).
The fallback
global or per-remote configuration can also
be used.
This is very useful in particular when working with salt formulas
<conventions-formula>
. Prior to the addition of this
feature, it was necessary to push a branch/tag to the remote repo for
each saltenv in which that formula was to be used. If the formula needed
to be updated, this update would need to be reflected in all of the
other branches/tags. This is both inconvenient and not scalable.
With all_saltenvs
, it is now possible to define your
formula once, in a single branch.
gitfs_remotes:
- http://foo.com/quux.git:
- all_saltenvs: anything
If you want to also test working branches of the formula repository,
use fallback
:
gitfs_remotes:
- http://foo.com/quux.git:
- fallback: anything
Update Intervals
Prior to the 2018.3.0 release, GitFS would update its fileserver
backends as part of a dedicated "maintenance" process, in which various
routine maintenance tasks were performed. This tied the update interval
to the loop_interval
config option, and also forced
all fileservers to update at the same interval.
Now it is possible to make GitFS update at its own interval, using
gitfs_update_interval
:
gitfs_update_interval: 180
gitfs_remotes:
- https://foo.com/foo.git
- https://foo.com/bar.git:
- update_interval: 120
Using the above configuration, the first remote would update every three minutes, while the second remote would update every two minutes.
Configuration Order of Precedence
The order of precedence for GitFS configuration is as follows (each level overrides all levels below it):
Per-saltenv configuration (defined under a per-remote
saltenv
param)gitfs_remotes: - https://foo.com/bar.git: - saltenv: - dev: - mountpoint: salt://bar
Global per-saltenv configuration (defined in
gitfs_saltenv
)gitfs_saltenv: - dev: - mountpoint: salt://bar
Per-remote configuration parameter
gitfs_remotes: - https://foo.com/bar.git: - mountpoint: salt://bar
Global configuration parameter
gitfs_mountpoint: salt://bar
Note
The one exception to the above is when all_saltenvs
<gitfs-global-remotes>
is used. This value overrides all
logic for mapping branches/tags to fileserver environments. So, even if
gitfs_saltenv
is used to globally override the mapping for a given saltenv, all_saltenvs <gitfs-global-remotes>
would take
precedence for any remote which uses it.
It's important to note however that any root
and
mountpoint
values configured in gitfs_saltenv
(or
per-saltenv
configuration <gitfs-per-saltenv-config>
) would be
unaffected by this.
Serving from a Subdirectory
The gitfs_root
parameter allows files to be served
from a subdirectory within the repository. This allows for only part of
a repository to be exposed to the Salt fileserver.
Assume the below layout:
.gitignore
README.txt
foo/
foo/bar/
foo/bar/one.txt
foo/bar/two.txt
foo/bar/three.txt
foo/baz/
foo/baz/top.sls
foo/baz/edit/vim.sls
foo/baz/edit/vimrc
foo/baz/nginx/init.sls
The below configuration would serve only the files under
foo/baz
, ignoring the other files in the repository:
gitfs_remotes:
- git://mydomain.com/stuff.git
gitfs_root: foo/baz
The root can also be configured on a per-remote basis
<gitfs-per-remote-config>
.
Mountpoints
2014.7.0
The gitfs_mountpoint
parameter will prepend the
specified path to the files served from gitfs. This allows an existing
repository to be used, rather than needing to reorganize a repository or
design it around the layout of the Salt fileserver.
Before the addition of this feature, if a file being served up via
gitfs was deeply nested within the root directory (for example,
salt://webapps/foo/files/foo.conf
, it would be necessary to
ensure that the file was properly located in the remote repository, and
that all of the parent directories were present (for example, the
directories webapps/foo/files/
would need to exist at the
root of the repository).
The below example would allow for a file foo.conf
at the
root of the repository to be served up from the Salt fileserver path
salt://webapps/foo/files/foo.conf
.
gitfs_remotes:
- https://mydomain.com/stuff.git
gitfs_mountpoint: salt://webapps/foo/files
Mountpoints can also be configured on a per-remote basis
<gitfs-per-remote-config>
.
Using gitfs in Masterless Mode
Since 2014.7.0, gitfs can be used in masterless mode. To do so,
simply add the gitfs configuration parameters (and set fileserver_backend
)
in the minion_ config file instead of the
master config file.
Using gitfs Alongside Other Backends
Sometimes it may make sense to use multiple backends; for instance,
if sls
files are stored in git but larger files are stored
directly on the master.
The cascading lookup logic used for multiple remotes is also used
with multiple backends. If the fileserver_backend
option contains multiple
backends:
fileserver_backend:
- roots
- git
Then the roots
backend (the default backend of files in
/srv/salt
) will be searched first for the requested file;
then, if it is not found on the master, each configured git remote will
be searched.
Note
This can be used together with file_roots accepting __env__ as a catch-all environment, since 2018.3.5 and 2019.2.1:
file_roots:
base:
- /srv/salt
__env__:
- /srv/salt
Branches, Environments, and Top Files
When using the GitFS backend, branches, and tags will be mapped to environments using the branch/tag name as an identifier.
There is one exception to this rule: the master
branch
is implicitly mapped to the base
environment.
So, for a typical base
, qa
,
dev
setup, the following branches could be used:
master
qa
dev
top.sls
files from different branches will be merged
into one at runtime. Since this can lead to overly complex
configurations, the recommended setup is to have a separate repository,
containing only the top.sls
file with just one single
master
branch.
To map a branch other than master
as the
base
environment, use the gitfs_base
parameter.
gitfs_base: salt-base
The base can also be configured on a per-remote basis
<gitfs-per-remote-config>
.
Environment Whitelist/Blacklist
2014.7.0
The gitfs_saltenv_whitelist
and gitfs_saltenv_blacklist
parameters allow for
greater control over which branches/tags are exposed as fileserver
environments. Exact matches, globs, and regular expressions are
supported, and are evaluated in that order. If using a regular
expression, ^
and $
must be omitted, and the
expression must match the entire branch/tag.
gitfs_saltenv_whitelist:
- base
- v1.*
- 'mybranch\d+'
Note
v1.*
, in this example, will match as both a glob and a
regular expression (though it will have been matched as a glob, since
globs are evaluated before regular expressions).
The behavior of the blacklist/whitelist will differ depending on which combination of the two options is used:
- If only
gitfs_saltenv_whitelist
is used, then only branches/tags which match the whitelist will be available as environments - If only
gitfs_saltenv_blacklist
is used, then the branches/tags which match the blacklist will not be available as environments - If both are used, then the branches/tags which match the whitelist, but do not match the blacklist, will be available as environments.
Authentication
pygit2
2014.7.0
Both HTTPS and SSH authentication are supported as of version 0.20.3, which is the earliest version of pygit2 supported by Salt for gitfs.
Note
The examples below make use of per-remote configuration parameters, a
feature new to Salt 2014.7.0. More information on these can be found
here <gitfs-per-remote-config>
.
HTTPS
For HTTPS repositories which require authentication, the username and password can be provided like so:
gitfs_remotes:
- https://domain.tld/myrepo.git:
- user: git
- password: mypassword
If the repository is served over HTTP instead of HTTPS, then Salt
will by default refuse to authenticate to it. This behavior can be
overridden by adding an insecure_auth
parameter:
gitfs_remotes:
- http://domain.tld/insecure_repo.git:
- user: git
- password: mypassword
- insecure_auth: True
SSH
SSH repositories can be configured using the ssh://
protocol designation, or using scp-like syntax. So, the following two
configurations are equivalent:
ssh://git@github.com/user/repo.git
git@github.com:user/repo.git
Both gitfs_pubkey
and gitfs_privkey
(or
their per-remote counterparts <gitfs-per-remote-config>
)
must be configured in order to authenticate to SSH-based repos. If the
private key is protected with a passphrase, it can be configured using
gitfs_passphrase
(or simply
passphrase
if being configured per-remote
<gitfs-per-remote-config>
). For example:
gitfs_remotes:
- git@github.com:user/repo.git:
- pubkey: /root/.ssh/id_rsa.pub
- privkey: /root/.ssh/id_rsa
- passphrase: myawesomepassphrase
Finally, the SSH host key must be added to the known_hosts file
<gitfs-ssh-fingerprint>
.
Note
There is a known issue with public-key SSH authentication to Microsoft Visual Studio (VSTS) with pygit2. This is due to a bug or lack of support for VSTS in older libssh2 releases. Known working releases include libssh2 1.7.0 and later, and known incompatible releases include 1.5.0 and older. At the time of this writing, 1.6.0 has not been tested.
Since upgrading libssh2 would require rebuilding many other packages (curl, etc.), followed by a rebuild of libgit2 and a reinstall of pygit2, an easier workaround for systems with older libssh2 is to use GitPython with a passphraseless key for authentication.
GitPython
HTTPS
For HTTPS repositories which require authentication, the username and
password can be configured in one of two ways. The first way is to
include them in the URL using the format
https://<user>:<password>@<url>
, like
so:
gitfs_remotes:
- https://git:mypassword@domain.tld/myrepo.git
The other way would be to configure the authentication in
~/.netrc
:
machine domain.tld
login git
password mypassword
If the repository is served over HTTP instead of HTTPS, then Salt
will by default refuse to authenticate to it. This behavior can be
overridden by adding an insecure_auth
parameter:
gitfs_remotes:
- http://git:mypassword@domain.tld/insecure_repo.git:
- insecure_auth: True
SSH
Only passphrase-less SSH public key authentication is supported using GitPython. The auth parameters (pubkey, privkey, etc.) shown in the pygit2 authentication examples above do not work with GitPython.
gitfs_remotes:
- ssh://git@github.com/example/salt-states.git
Since GitPython wraps the git CLI, the
private key must be located in ~/.ssh/id_rsa
for the user
under which the Master is running, and should have permissions of
0600
. Also, in the absence of a user in the repo URL, GitPython will (just as SSH does) attempt to
login as the current user (in other words, the user under which the
Master is running, usually root
).
If a key needs to be used, then ~/.ssh/config
can be
configured to use the desired key. Information on how to do this can be
found by viewing the manpage for ssh_config
. Here's an
example entry which can be added to the ~/.ssh/config
to
use an alternate key for gitfs:
Host github.com
IdentityFile /root/.ssh/id_rsa_gitfs
The Host
parameter should be a hostname (or hostname
glob) that matches the domain name of the git repository.
It is also necessary to add the SSH host key to the known_hosts file
<gitfs-ssh-fingerprint>
. The exception to this would be if
strict host key checking is disabled, which can be done by adding
StrictHostKeyChecking no
to the entry in
~/.ssh/config
Host github.com
IdentityFile /root/.ssh/id_rsa_gitfs
StrictHostKeyChecking no
However, this is generally regarded as insecure, and is not recommended.
Adding the SSH Host Key to the known_hosts File
To use SSH authentication, it is necessary to have the remote
repository's SSH host key in the ~/.ssh/known_hosts
file.
If the master is also a minion, this can be done using the ssh.set_known_host
<salt.modules.ssh.set_known_host>
function:
# salt mymaster ssh.set_known_host user=root hostname=github.com
mymaster:
----------
new:
----------
enc:
ssh-rsa
fingerprint:
16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
hostname:
|1|OiefWWqOD4kwO3BhoIGa0loR5AA=|BIXVtmcTbPER+68HvXmceodDcfI=
key:
AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
old:
None
status:
updated
If not, then the easiest way to add the key is to su to the user
(usually root
) under which the salt-master runs and attempt
to login to the server via SSH:
$ su -
Password:
# ssh github.com
The authenticity of host 'github.com (192.30.252.128)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.252.128' (RSA) to the list of known hosts.
Permission denied (publickey).
It doesn't matter if the login was successful, as answering
yes
will write the fingerprint to the known_hosts file.
Verifying the Fingerprint
To verify that the correct fingerprint was added, it is a good idea
to look it up. One way to do this is to use nmap
:
$ nmap -p 22 github.com --script ssh-hostkey
Starting Nmap 5.51 ( http://nmap.org ) at 2014-08-18 17:47 CDT
Nmap scan report for github.com (192.30.252.129)
Host is up (0.17s latency).
Not shown: 996 filtered ports
PORT STATE SERVICE
22/tcp open ssh
| ssh-hostkey: 1024 ad:1c:08:a4:40:e3:6f:9c:f5:66:26:5d:4b:33:5d:8c (DSA)
|_2048 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48 (RSA)
80/tcp open http
443/tcp open https
9418/tcp open git
Nmap done: 1 IP address (1 host up) scanned in 28.78 seconds
Another way is to check one's own known_hosts
file,
using this one-liner:
$ ssh-keygen -l -f /dev/stdin <<<`ssh-keyscan github.com 2>/dev/null` | awk '{print $2}'
16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
Warning
AWS tracks usage of nmap and may flag it as abuse. On AWS hosts, the
ssh-keygen
method is recommended for host key
verification.
Note
As of OpenSSH
6.8 the SSH fingerprint is now shown as a base64-encoded SHA256
checksum of the host key. So, instead of the fingerprint looking like
16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
, it would
look like
SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8
.
Refreshing gitfs Upon Push
By default, Salt updates the remote fileserver backends every 60
seconds. However, if it is desirable to refresh quicker than that, the
Reactor
System <reactor>
can be used to signal the master to update
the fileserver on each push, provided that the git server is also a Salt
minion. There are three steps to this process:
On the master, create a file /srv/reactor/update_fileserver.sls, with the following contents:
update_fileserver: runner.fileserver.update
Add the following reactor configuration to the master config file:
reactor: - 'salt/fileserver/gitfs/update': - /srv/reactor/update_fileserver.sls
On the git server, add a post-receive hook
- If the user executing git push is the same as the minion user, use the following hook:
#!/usr/bin/env sh salt-call event.fire_master update salt/fileserver/gitfs/update
- To enable other git users to run the hook after a push, use sudo in the hook script:
#!/usr/bin/env sh sudo -u root salt-call event.fire_master update salt/fileserver/gitfs/update
If using sudo in the git hook (above), the policy must be changed to permit all users to fire the event. Add the following policy to the sudoers file on the git server.
Cmnd_Alias SALT_GIT_HOOK = /bin/salt-call event.fire_master update salt/fileserver/gitfs/update Defaults!SALT_GIT_HOOK !requiretty ALL ALL=(root) NOPASSWD: SALT_GIT_HOOK
The update
argument right after event.fire_master
<salt.modules.event.fire_master>
in this example can really
be anything, as it represents the data being passed in the event, and
the passed data is ignored by this reactor.
Similarly, the tag name salt/fileserver/gitfs/update
can
be replaced by anything, so long as the usage is consistent.
The root
user name in the hook script and sudo policy
should be changed to match the user under which the minion is
running.
Using Git as an External Pillar Source
The git external pillar (a.k.a. git_pillar) has been rewritten for
the 2015.8.0 release. This rewrite brings with it pygit2 support (allowing for access to
authenticated repositories), as well as more granular support for
per-remote configuration. This configuration schema is detailed here
<git-pillar-configuration>
.
Why aren't my custom modules/states/etc. syncing to my Minions?
In versions 0.16.3 and older, when using the git fileserver backend
<salt.fileserver.gitfs>
, certain versions of GitPython may
generate errors when fetching, which Salt fails to catch. While not
fatal to the fetch process, these interrupt the fileserver update that
takes place before custom types are synced, and thus interrupt the sync
itself. Try disabling the git fileserver backend in the master config,
restarting the master, and attempting the sync again.
This issue is worked around in Salt 0.16.4 and newer.