How-to: Getting Podman to Correctly Mount a Native Folder on a Mac

Omer Azmon
Intuit Engineering
Published in
7 min readMar 1, 2022

--

Person holding sign: Follow These Steps

This blog post is co-authored by Phillip Nalwalker, Staff Software Engineer in the Intuit Developer Productivity Team, and Omer Azmon, Principal Software Engineer in the Intuit Developer Productivity Team.

This is the first in a series of blog posts about how we’ve implemented Podman at Intuit for both local development and continuous integration (CI) to drive development velocity across the company for products like TurboTax, QuickBooks and Mint.

In the course of our migration journey, we’ve applied our engineering skills to come up with solutions to common challenges, and to share them with the broader community of container users.

Here’s one that has garnered a high level of interest, both online and in conversation with other product development teams: how to run a container using Podman on a Mac. As you’ll see on GitHub at https://github.com/containers/podman/issues/8016, in “podman’s remote client case, bind volume will use source folders on podman server’s host.” As the issue is open, it appears that there is no official solution at this time.

In this blog, you’ll learn how to configure the Podman virtual machine (VM) to mount a native folder correctly and automatically. This is a one-time operation and I have included a script that idempotently performs the configuration.

If you aren’t interested in how the script works skip directly to “Running the Scripts.”

How to make it work

To configure a Podman VM to mount a remote native folder on a Mac, use the following procedure:

  • To allow the Podman VM to mount a folder on the Mac using the ssh protocol, we enable remote login to the macOS. For the Mac UI this is done by going to System Preferences > Sharing and selecting the check-box by Remote login. The same can be done from command line: sudo systemsetup -setremotelogin on
  • To allow the Podman VM to have a constant IP to connect to, even when you move your laptop around, we add an IP alias to our laptop. We suggest the 192.168.126.1 address as it is rarely used and not reachable from outside the laptop. Use the following command line: sudo ifconfig en0 alias 192.168.126.1
  • In case you don’t know, you can obtain your current logged in user by running: who am i. Don’t use ‘root’ ever.
  • Now we can connect to the Podman VM to configure it. Use: podman machine ssh. If the Podman VM does not exist yet, you can run: podman machine init. If you are using a non-default VM, add its name at the end of command.
  • We need to install sshfs as it is not part of the default CoreOS container. Issue on the container’s command line: sudo rpm-ostree install sshfs — allow-inactive. This is the CoreOS equivalent of yum or apt.
  • Next we need to create the automatic mounting of the folder we choose, so if the VM is rebooted, the mount does not disappear. The mount point will be /var/vmhost. While the folder name can be changed, it should remain in /var as many other locations in the Podman VM are restricted or reset to default upon reboot. In any case, the file names must match the mount point.
  • Create a file /etc/systemd/system/run-vmhost.automount with a mode of 0644. Make its content be as follows:
[Unit]
Description=Podman VM host automounter
[Automount]
Where=/var/vmhost
DirectoryMode=0755
[Install]
WantedBy=multi-user.target
  • Create a file /etc/systemd/system/run-vmhost.mount with a mode of 0644. Make its content as follows, replacing {{USERNAME}} with the user name from step 3 above. We assign the uid and gid of the “coreos” user, 1000 to the mount and make sure to provide the exec flag in case our users want to execute scripts from the mounted volume. Note that the IP address given must match the IP address from step 2 above:
[Unit]
Description=Podman VM host mount
[Mount]
What={{USERNAME}}@192.168.126.1:/Users/{{USERNAME}}
Where=/var/vmhost
Type=fuse.sshfs
Options=user,uid=1000,gid=1000,allow_other,IdentityFile=/root/.ssh/id_rsa,StrictHostKeyChecking=no,exec
[Install]
WantedBy=multi-user.target
  • Create the mount point directory using the command: mkdir -p /var/vmhost
  • To enable automounting on next reboot and, from thereon, run the command: systemctl enable run-user-vmhost.automount
  • For automatic mounting to succeed, we need to set up certificate/key-based authentication between the VM and the MAC:
  • Change directory to /root/.ssh directory
  • If there is no id_rsa.pub file there, execute: ssh-keygen -t rsa
  • Copy the content of id_rsa.pub file generated, and paste it into the ~/.ssh/authorized_keys file on the Mac host.
  • Reboot for all changes to take effect, using the command: sudo systemctl reboot

Running the Scripts

There are two scripts provided. One outer script setup.sh to run commands on the Mac. The other provision-vm.sh to run commands on the VM. The following scripts implement the above procedure idempotently.

  • Copy the following script into a file provision-vm.sh
#!/bin/bashset -eUSERNAME=$1
SSHFS_PATH=”/usr/bin/sshfs”
MOUNT_POINT=”/var/vmhost”
VAR_VM_HOST_AUTOMOUNT_UNIT=”var-vmhost.automount”
VAR_VM_HOST_AUTOMOUNT_PATH=”/etc/systemd/system/${VAR_VM_HOST_AUTOMOUNT_UNIT}”
VAR_VM_HOST_UNIT=”var-vmhost.mount”
VAR_VM_HOST_PATH=”/etc/systemd/system/${VAR_VM_HOST_UNIT}”
SSH_DIR=/root/.ssh
SSH_PUBLIC_KEY_PATH=”${SSH_DIR}/id_rsa.pub”
SSH_PRIVATE_KEY_PATH=”${SSH_DIR}/id_rsa”
echo “Mount point is ${MOUNT_POINT}”[ ! -f ${SSHFS_PATH} ] && echo “Installing sshfs” && rpm-ostree install sshfs — allow-inactiveecho “Creating mount point”
mkdir -p ${MOUNT_POINT}
[ ! -f ${SSH_PUBLIC_KEY_PATH} ] && echo “Generating SSH Key” && mkdir -p ${SSH_DIR} && cd ${SSH_DIR} && ssh-keygen -t rsa -f ${SSH_PRIVATE_KEY_PATH} -b 2048 -q -N “”[ ! -f ${VAR_VM_HOST_AUTOMOUNT_PATH} ] && echo “Creating systemd automount” && cat << EOF > ${VAR_VM_HOST_AUTOMOUNT_PATH}
[Unit]
Description=Podman VM host automounter
[Automount]
Where=${MOUNT_POINT}
DirectoryMode=0755
[Install]
WantedBy=multi-user.target
EOF
chmod 0644 ${VAR_VM_HOST_AUTOMOUNT_PATH}
[ ! -f ${VAR_VM_HOST_PATH} ] && echo “Creating systemd mount” && cat << EOF > ${VAR_VM_HOST_PATH}
[Unit]
Description=Podman VM host mount
[Mount]
What=${USERNAME}@192.168.126.1:/Users/${USERNAME}
Where=${MOUNT_POINT}
Type=fuse.sshfs
Options=user,uid=1000,gid=1000,allow_other,IdentityFile=${SSH_PRIVATE_KEY_PATH},StrictHostKeyChecking=no,exec
[Install]
WantedBy=multi-user.target
EOF
chmod 0644 ${VAR_VM_HOST_PATH}
echo “Enabling systemd automount”
systemctl enable ${VAR_VM_HOST_AUTOMOUNT_UNIT}
echo “Starting systemd automount”
systemctl start ${VAR_VM_HOST_AUTOMOUNT_UNIT}
  • Copy the following script into a file setup.sh
#!/bin/bashset -ePROVISIONING_SH=”./provision-vm.sh”
VM_NAME=”${1:-podman-machine-default}”
SSH_IDENTITY_PATH=”/root/.ssh/id_rsa”
SSH_DIR=/root/.ssh
LOCAL_SSH_DIR=~/.ssh
SSH_PUBLIC_KEY_PATH=”${SSH_DIR}/id_rsa.pub”
USERNAME=$(id -un)
IP_ADDRESS=”192.168.126.1"
NETWORK_INTERFACE=”en0"
AUTHORIZED_KEYS_FILE=”${LOCAL_SSH_DIR}/authorized_keys”
echo “Found username: ${USERNAME}”[ “${USERNAME}” == “root” ] && echo “Please do not run this script as root, run as a normal user without sudo!” && exit 1echo “Setting remote login on”
sudo systemsetup -setremotelogin on
echo “Assigning IP address”
IFCONFIG_OUTPUT=$(ifconfig)
[ ! “${IFCONFIG_OUTPUT}” == *”${IP_ADDRESS}”* ] && sudo ifconfig ${NETWORK_INTERFACE} alias ${IP_ADDRESS}
echo “Provisioning VM”
podman machine ssh “cat >provision-vm.sh” <provision-vm.sh
podman machine ssh ${VM_NAME} “sudo chmod +x ${PROVISIONING_SH} && sudo ${PROVISIONING_SH} ${USERNAME}”
echo “Getting SSH public key from VM”
SSH_PUB_KEY=$(podman machine ssh ${VM_NAME} “sudo cat ${SSH_PUBLIC_KEY_PATH}”)
echo “Concatenating VM SSH public key to authorized keys”
mkdir -p ${LOCAL_SSH_DIR} && touch ${AUTHORIZED_KEYS_FILE}
AUTHORIZED_KEYS=$(cat ${AUTHORIZED_KEYS_FILE})
[ ! “${AUTHORIZED_KEYS}” == *”${SSH_PUB_KEY}”* ] && echo ${SSH_PUB_KEY} >> ${AUTHORIZED_KEYS_FILE}
  • Run the script using the command : sh setup.sh
    If using the non-default Podman VM use:
    sh setup.sh {{PodmanVMName}}

Testing

You can now test your handiwork by doing the following:

  • Use: podman machine ssh to reconnect to the Podman VM. If you are using a non-default VM, add it’s name at the end of command.
  • On the VM command line run: ls -als /var/vmhost. You should see the home directory of the user running the VM.
  • To share your $HOME directory (mounted as /var/vmhost on the Podman virtual machine) as /vmhost with the container being run by Podman. Execute a command similar to the following on MacOS and you should see the home directory of the user:
podman run -ti -v /var/vmhost:/vmhost docker.intuit.com/docker-rmt/centos ls -als /vmhost

Tips

How to use MacOS volume mounts with “podman play kube”

Follow the above steps under “How to make it work” or “running the scripts,” in order for ${HOME} to be mounted to /var/vmhost on the Podman Linux VM.

Set a hostPath volume and volumeMount in your Kubernetes pod YAML file, such that the volume’s hostPath is pointed to /var/vmhost:

apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: docker.com/my-image-path/my-image-name:1.2.3
name: test-container
volumeMounts:
# Path to mount to in the container
- mountPath: /vmhost
name: test-volume
volumes:
- name: test-volume
hostPath:
# Path on the Podman Linux VM
path: /var/vmhost

Preventing VM/container clock drift

The goal of mounting your Mac laptop volume to your Podman VM is to be able to access files on your Mac laptop from your container. We have found at Intuit that the VM clock can drift from that of the host machine. This can be problematic when accessing files with time sensitive information such as security tokens. systemd-timesyncd is not enabled by default on the Podman Fedora CoreOS VM. By enabling and starting this service you can ensure that your VM and in turn container’s time is accurate. SSH into the Podman Machine using podman-machine-ssh then execute the following commands:

sudo systemctl enable systemd-timesyncd
sudo systemctl start systemd-timesyncd

These lines may be added to the provision.sh script outlined above.

To validate the time is now being synchronized run the following command on the Podman VM:

[core@localhost ~]$ sudo timedatectl
Local time: Fri 2022–01–28 15:57:15 UTC
Universal time: Fri 2022–01–28 15:57:15 UTC
RTC time: Fri 2022–01–28 15:57:15
Time zone: UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
[core@localhost ~]$

The important thing to look for is “System clock synchronized.” You may also verify the date by running date on both the Podman VM and your Mac.

Closing

We anticipate the Podman development team will completely automate volume mounting to make it transparent in a future release, but for now the above scripts make mounting a volume on your Mac to a container relatively straightforward.

Stay tuned as in our next post we will cover how we use Podman in our production CI environment to execute builds for thousands of services!

Call-to-Action

We hope the above scripts help with mounting the native Mac filesystem to a container running Podman in easier and would appreciate feedback. We’d also like to read about any best practices your teams may also be following with Podman. Please feel free to comment on this blog post letting us know the scripts worked for you, if you have questions, or if you have any other experiences using Podman you would like to share.

Intuit is hiring! Please check out our career center at: https://www.intuit.com/careers

--

--

Omer Azmon
Intuit Engineering

A Principal Tools Engineer in the Core Team at Intuit. His primary focus over the last several years has been developer productivity.