When building a Singularity/Apptainer image from a definition file, is there a portable way to make a SSH key of the host system available during the build?
To give some context:
I have a definition file where in the %post
section I'm cloning a private git repository using SSH, i.e.:
git clone git@github.com:luator/private_repo.git
This fails because the SSH keys of the host system are not available in the container during the build.
I could probably copy the key in the container and delete it from there at the end of the build process. However, for this, I would need to hard-code the path to the key in the definition file, which is bad when using the same definition file on another machine where the path is different.
Is there a more portable way of making the git clone
work during the build?
This answer is based on discussions with drdaved on the Apptainer Slack.
The way we found to do this was to let the Apptainer build process use the host machine's ssh-agent
by setting the SSH_AUTH_SOCK
environment variable. That way, if your key is known to the agent on the host, it can be used in the container during build.
The SSH_AUTH_SOCK
on the host must be bound into the container.
Check where your SSH_AUTH_SOCK
is on the host; if it's in a directory that is already bound into the container during build (e.g. /tmp
), you're ready to go.
Otherwise, you need to bind it in manually.
A common location for the socket is something like /run/user/1000/keyring/ssh
, so you could add --bind /run
into the container build command.
The advantage of this method is that the key is at no point copied to the container image.
The only information that is stored is the socket that your host machine's ssh-agent
was running on.
AFAIK this is not a security issue.
Note that we have to do some mild trickery as environment variables on the host are not passed to the build process, and there is no way of directly setting environment variables in the build command. Hence, we set via --build-arg
, and use the build arg in %post
to set the environment variable.
Example test.def
file:
Bootstrap: docker
From: ubuntu:latest
%post
apt update
apt install git -y
export SSH_AUTH_SOCK={{ SSH_AUTH_SOCK }}
git clone git@github.com:luator/private-repo.git
Build command (if your SSH_AUTH_SOCK
will already bound to the container):
apptainer build --build-arg SSH_AUTH_SOCK=$SSH_AUTH_SOCK test.sif test.def
Build command (if your SSH_AUTH_SOCK
will not already bound to the container, and is available at /run/...
):
apptainer build --build-arg SSH_AUTH_SOCK=$SSH_AUTH_SOCK --bind /run test.sif test.def