Skip to content

Instantly share code, notes, and snippets.

@NorkzYT
Last active July 1, 2025 18:26
Show Gist options
  • Save NorkzYT/14449b247dae9ac81ba4664564669299 to your computer and use it in GitHub Desktop.
Save NorkzYT/14449b247dae9ac81ba4664564669299 to your computer and use it in GitHub Desktop.
Proxmox CIFS Share Mount Wizard Script

Proxmox LXC ⇆ CIFS Mount Wizard

proxmox-lxc-cifs-share.sh is an interactive helper that mounts a network CIFS/SMB share on a Proxmox VE node and bind-mounts it into an unprivileged LXC container in one pass.
It automates:

  1. Creating a host-side mountpoint under /mnt/lxc_shares/<folder>.
  2. Writing a properly-tuned /etc/fstab entry (persistent, systemd.automount, uid/gid mapping, etc.).
  3. Mounting the share immediately.
  4. Creating/ensuring a lxc_shares group inside the container (GID 10000) and adding your target user.
  5. Injecting the bind-mount (mpX:) into the live LXC configuration with pct set.
  6. Restarting the container and handing you a ready-to-use path at /mnt/<folder>.

Note: the script assumes the target LXC is currently running. It will stop and restart that container briefly as part of its process.


Features

  • Idempotent — safe to re-run; existing fstab lines, groups or mp-entries are skipped.
  • Snapshot-safe — uses pct set, thus bind-mounts are applied to the active config, not stale snapshots.
  • Clean dependency checks — aborts if pct or mount.cifs are missing or you are not on a Proxmox host.
  • Diagnostic output — numbered steps tell you exactly what happens and where (mp0, mp1, …).
  • Optional --noserverino flag to fix “Stale file handle” errors on Synology/TrueNAS shares.

Prerequisites

Item Notes
Proxmox VE node Tested on Proxmox VE 8 / Debian 12 host. Run on the node, not inside a container.
Unprivileged LXC container Must already exist. The script stops and restarts it briefly.
CIFS/SMB share Hostname/IP, share name, and valid credentials.
Root privileges Use sudo or run as root.
cifs-utils package apt update && apt install cifs-utils (usually present on Proxmox).

Quick-start

# 1. Get the script
curl -o proxmox-lxc-cifs-share.sh https://gist.githubusercontent.com/NorkzYT/14449b247dae9ac81ba4664564669299/raw/66b73972f7054a13fb5fb2a7646f7bb004827763/proxmox-lxc-cifs-share.sh
chmod +x proxmox-lxc-cifs-share.sh

# 2. Run it (on the Proxmox node)
sudo ./proxmox-lxc-cifs-share.sh
root@proxmox-node:/opt# chmod +x proxmox-lxc-cifs-share.sh
root@proxmox-node:/opt# ./proxmox-lxc-cifs-share.sh 
=== Proxmox CIFS Share Mount Wizard ===
1) Folder name under /mnt/lxc_shares (e.g. nas_rwx): appdata
2) CIFS host (IP/DNS, e.g. 10.0.0.2): 10.0.0.2
3) Share name (e.g. media): appdata
4) SMB username: xxx
5) SMB password: xxx
6) LXC numeric ID (e.g. 105): 103
7) Container username (e.g. ubuntu): ubuntu

Validating container 103...
Retrieving UID/GID for 'ubuntu' inside LXC 103...
  ↳ container UID=1000, GID=1000
Parsing idmap offset from container config...
  ↳ Warning: idmap offset not found; defaulting to 100000
  ↳ host idmap offset=100000
  ↳ will mount with host UID=101000, GID=101000
Stopping LXC 103...
Ensuring host mount point exists at /mnt/lxc_shares/appdata...
Building fstab entry...
  ↳ Removing old /etc/fstab entry...
  ↳ Adding new /etc/fstab entry...
Reloading systemd daemon...
Stopping potential systemd units mnt-lxc_shares-appdata.automount & mnt-lxc_shares-appdata.mount...
Mounting //10.0.0.2/appdata → /mnt/lxc_shares/appdata...
Configuring bind-mount into LXC (no backups)...
  ↳ Bind-mount set as mp0 → /mnt/appdata
Starting LXC 103...

✅  Configuration complete!
Inspect inside the container with:
    ls -ld /mnt/appdata
#!/usr/bin/env bash
# proxmox-lxc-cifs-share.sh
# https://gist.github.com/NorkzYT/14449b247dae9ac81ba4664564669299
#
# Mount a CIFS/SMB share on a Proxmox VE host and bind-mount it into
# an unprivileged LXC container as any container user, by dynamically
# mapping UIDs/GIDs.
#
# ---------------------------------------------------------------
# Compatible with Proxmox VE 7-8. Tested on Debian 12 host.
# ---------------------------------------------------------------
set -euo pipefail
#
#----------------------#
#----- Preconditions --#
#----------------------#
#
# Must be root
if [[ $EUID -ne 0 ]]; then
echo "ERROR: Please run as root." >&2
exit 1
fi
# Helper for error + exit
error_exit() {
echo "ERROR: $1" >&2
exit 1
}
# Ensure required commands exist
command -v bash >/dev/null 2>&1 || error_exit "Please run with bash: bash $0"
command -v pct >/dev/null 2>&1 || error_exit "'pct' command not found. Run this on the Proxmox host."
command -v mount.cifs >/dev/null 2>&1 || error_exit "cifs-utils missing. Install: apt update && apt install cifs-utils"
command -v systemd-escape >/dev/null 2>&1 || error_exit "systemd-escape missing. Required for systemd unit management."
#
#----------------------#
#----- Parse Flags ----#
#----------------------#
#
NOSERVERINO=0
if [[ "${1:-}" == "--noserverino" ]]; then
NOSERVERINO=1
shift
fi
#
#----------------------#
#----- User Input -----#
#----------------------#
#
echo "=== Proxmox CIFS Share Mount Wizard ==="
read -r -p "1) Folder name under /mnt/lxc_shares (e.g. nas_rwx): " folder_name
read -r -p "2) CIFS host (IP/DNS, e.g. 10.0.0.2): " cifs_host
read -r -p "3) Share name (e.g. media): " share_name
read -r -p "4) SMB username: " smb_username
read -s -p "5) SMB password: " smb_password && echo
read -r -p "6) LXC numeric ID (e.g. 105): " lxc_id
read -r -p "7) Container username (e.g. ubuntu): " lxc_username
echo
#
#----------------------#
#----- Validation -----#
#----------------------#
#
echo "Validating container ${lxc_id}..."
pct status "$lxc_id" &>/dev/null \
|| error_exit "LXC ${lxc_id} does not exist."
echo "Retrieving UID/GID for '${lxc_username}' inside LXC ${lxc_id}..."
if ! container_uid=$(pct exec "$lxc_id" -- id -u "$lxc_username" 2>/dev/null); then
error_exit "User '${lxc_username}' not found in container ${lxc_id}."
fi
container_gid=$(pct exec "$lxc_id" -- id -g "$lxc_username")
echo " ↳ container UID=${container_uid}, GID=${container_gid}"
echo "Parsing idmap offset from container config..."
idmap_offset=$(pct config "$lxc_id" \
| awk '/^lxc.idmap: u 0 /{print $4; exit}')
if [[ -z "$idmap_offset" ]]; then
echo " ↳ Warning: idmap offset not found; defaulting to 100000"
idmap_offset=100000
fi
echo " ↳ host idmap offset=${idmap_offset}"
host_uid=$(( idmap_offset + container_uid ))
host_gid=$(( idmap_offset + container_gid ))
echo " ↳ will mount with host UID=${host_uid}, GID=${host_gid}"
#
#----------------------#
#--- Stop Container ----#
#----------------------#
#
echo "Stopping LXC ${lxc_id}..."
pct stop "$lxc_id"
while [[ "$(pct status "$lxc_id")" != "status: stopped" ]]; do
sleep 1
done
#
#----------------------#
#--- Host-side Mount --#
#----------------------#
#
mnt_root="/mnt/lxc_shares/${folder_name}"
echo "Ensuring host mount point exists at ${mnt_root}..."
mkdir -p "$mnt_root"
echo "Building fstab entry..."
options="_netdev,x-systemd.automount,noatime,nobrl"
options+=",uid=${host_uid},gid=${host_gid},dir_mode=0770,file_mode=0770"
options+=",username=${smb_username},password=${smb_password}"
(( NOSERVERINO )) && options+=",noserverino"
fstab_entry="//${cifs_host}/${share_name} ${mnt_root} cifs ${options} 0 0"
# Remove any stale entry
if grep -Eqs "^//${cifs_host}/${share_name}[[:space:]]+${mnt_root}[[:space:]]+cifs" /etc/fstab; then
echo " ↳ Removing old /etc/fstab entry..."
sed -i "\|^//${cifs_host}/${share_name} ${mnt_root} .*|d" /etc/fstab
fi
echo " ↳ Adding new /etc/fstab entry..."
echo "$fstab_entry" >> /etc/fstab
echo "Reloading systemd daemon..."
systemctl daemon-reload
unit_base=$(systemd-escape --path "$mnt_root")
echo "Stopping potential systemd units ${unit_base}.automount & ${unit_base}.mount..."
systemctl stop "${unit_base}.automount" "${unit_base}.mount" >/dev/null 2>&1 || true
if mountpoint -q "$mnt_root"; then
echo " ↳ Unmounting existing mount..."
umount -l "$mnt_root"
fi
echo "Mounting //${cifs_host}/${share_name}${mnt_root}..."
mount "$mnt_root"
#
#----------------------#
#--- Container Bind ----#
#----------------------#
#
echo "Configuring bind-mount into LXC (no backups)..."
pct set "$lxc_id" \
--mp0 "${mnt_root},mp=/mnt/${folder_name},backup=0"
echo " ↳ Bind-mount set as mp0 → /mnt/${folder_name}"
echo "Starting LXC ${lxc_id}..."
pct start "$lxc_id"
#
#----------------------#
#----- Completion ------#
#----------------------#
#
echo -e "\n✅ Configuration complete!"
echo "Inspect inside the container with:"
echo " ls -ld /mnt/${folder_name}"
@rucknapucknavitz
Copy link

This is great - thank you.
I do think you need to revert to the original instructions in the first part of step 1 from the revision on March 7.

10000 in the LXC will map correctly to 110000 in the PVE
(mapping 110000 in the LXC will incorrectly map on the PVE)

When I made this change it’s working great on my tteck Jellyfin container.

echo "Creating group 'lxc_shares' with GID=10000 in LXC..."
pct exec $lxc_id -- groupadd -g 10000 lxc_shares```

@NorkzYT
Copy link
Author

NorkzYT commented Jun 9, 2024

@rucknapucknavitz

No problem, I have revised the script with the change you requested. Thank you.

I will be changing the following line as well to use 10000 instead of 110000:
https://github.com/NorkzYT/Wolflith/blob/b10bc7b4680bf240a1055ea7d7f36435107e6c15/Ansible/playbooks/provision-proxmox-lxc.yml#L145

@campmeharder
Copy link

campmeharder commented Jun 13, 2024

Hi there for some reason not working with me, new to proxmox that is why Im using this, thanks btw, but even though it says complete it doesnt show. I tried it with the *arr that are in a lxc. Also type on line 34 read -sp "Enter SMB password: " smb_password && echo

the message im getting is mount error(16): Device or resource busy. Im trying to connect it to my synology rackstation so not sure what could be giving that error.

@Puntoboy
Copy link

This works great, but I'm having an issue with sub folder permissions. Any existing folder in the share I cannot write to so I see errors in the web GUIs for the LXCs. If I create a folder in the root from the LXC, then it's writeable, so it's existing folders that are the issue.

@Puntoboy
Copy link

Puntoboy commented Jun 22, 2024

The permissions look the same, test3 is a folder I created within the LXC, Movies is one I created inside the NAS server before connecting the LXC.

I can connect to test3 fine, but I cannot write to Movies or any of the other subfolders (root folder is fine).

image

@rucknapucknavitz
Copy link

This isn’t a script issue so not really a topic for this thread, it’s a permissions issue.
Checkout some chmod tutorials online, like this one: https://www.tomshardware.com/how-to/change-file-directory-permissions-linux

@Puntoboy
Copy link

This isn’t a script issue so not really a topic for this thread, it’s a permissions issue. Checkout some chmod tutorials online, like this one: https://www.tomshardware.com/how-to/change-file-directory-permissions-linux

this script is supposed to fix the permissions issue with the LXCs. Hence why I asked.

@rucknapucknavitz
Copy link

Sounds like it could be a share host permission issue, unless you’re sharing directly from the proxmox host?

@Puntoboy
Copy link

I'm sharing from a Cockpit LXC on the same host.

Problem is now, since rebooting, the host won't even mount that share now.

image

@LarsNorgaard
Copy link

There's a bug, if you have snapshots saved of the LXC. The Mp0: isn't getting added to the "running" version, but instead to the saved snapshot.

@souljedi
Copy link

souljedi commented Nov 19, 2024

Thanks for the script. Working great! On my version of proxmox I had to make one tiny modification and change from:
read -sp "Enter SMB password: " smb_password && echo to read -p "Enter SMB password: " smb_password && echo

@anubis-genix
Copy link

anubis-genix commented Dec 26, 2024

Great and useful script. Unfortunately I'm getting the error: Stale file handle when trying to open a txt file on my share.
Any ideas?

Edit:
Found the fix for my problem.

pvesm set --options noserverino

@rikmueller
Copy link

Thank you so much! All my attempts to achieve this on my own have been a waste of time with no success...

@hehh2001
Copy link

hehh2001 commented May 7, 2025

非常感谢,很好用

@b1ackm0x
Copy link

b1ackm0x commented Jun 12, 2025

Manual on Read

Screenshot from 2025-06-12 13-49-07

Fyi, I renamed your file for my convienience, lol.

Line 34: read -sp is erroring out,it was not even prompted, do you have to separate the arguments?

mountcifs.sh: 34: read: Illegal option -s

Try:

read -s -p

Also LXD ID? is this the ID # or the the name of the container?

I have been having problems mounting my truenas share through proxmox to ANYTHING(Plex, Torrent, Youtube Downloader) . This script would be a great help. Thank you!
Hope it gets worked out, I wasnt able to use it.

Some of my input and the errors returned, hope it helps.

Enter SMB username: kodi4pi
mountcifs.sh: 34: read: Illegal option -s
Enter the LXC ID: 501
Enter the username within the LXC that needs access to the share (e.g., jellyfin, plex): admin
Creating group 'lxc_shares' with GID=10000 in LXC...
mountcifs.sh: 40: pct: not found
Adding user admin to group 'lxc_shares'...
mountcifs.sh: 43: pct: not found

@NorkzYT
Copy link
Author

NorkzYT commented Jun 12, 2025

@rucknapucknavitz @campmeharder @Puntoboy @souljedi @anubis-genix @rikmueller @hehh2001 @b1ackm0x

It has been a long while since I have been able to work on this. I have updated the file and have added a README.md file for context.

I hope this fixes any issues anyone may have and makes the setup process more seamless than before.

Have a wonderful rest of your day everyone!

@b1ackm0x
Copy link

b1ackm0x commented Jun 12, 2025 via email

@deku-m
Copy link

deku-m commented Jun 26, 2025

Thanks for the script.

But isnt it better to use
lxc.mount.entry: /mnt/${folder_name} /mnt/${folder_name}none bind 0 0
Instead of
mp0: /mnt/${folder_name},mp=/mnt/${folder_name}

As you disable the snapshotting of the LXC when using MP0 which could sometimes be convenient? I have read that somewhere.

@neil-bh
Copy link

neil-bh commented Jun 26, 2025

Thank you for providing this script/wizard to apply a solution to such a common issue.

I have this working but noticed that my docker containers were having permission issues accessing their data. The docker containers I use typically use UID=1000 and GID=1000 but I've had to adjust these to UID=0 and GID=10000. (which matches root:lxc_shares)

From my unprivileged lxc, I tried updating the permissions on the mounted shares from root:lxc_shares to 1000:10000 (myuser1:lxc_shares), using: chown -Rf 1000:10000 /mnt/nas and although there were no errors, the UID didn't change. Perhaps this is not possible because Proxmox has mounted these from the host as root? I'm not sure exactly how to change that from root (if at all possible?)

Is this acceptable practice using UID=0 (root) or is there a way to change it so that I can use UID=1000 (which is is my first created user)?

@NorkzYT
Copy link
Author

NorkzYT commented Jun 27, 2025

@deku-m

That is true. Nice catch. I have updated the script. Thank you.

Edit:
I am reverting it since I do not want to allow backups or snapshots of the mounted CIFS Share. Especially on a multi-terabyte NAS.

@NorkzYT
Copy link
Author

NorkzYT commented Jun 27, 2025

@neil-bh

chown inside the container fails since the ownership is fixed at mount time. I will update the script today to fix this issue as well.

@NorkzYT
Copy link
Author

NorkzYT commented Jun 27, 2025

Script has been updated.

@neil-bh
Copy link

neil-bh commented Jun 27, 2025

Thanks @NorkzYT - I can confirm I can now configure my docker containers to write to a folder that resides on the share using the UID=10000 and GID=10000 (which I believe is the equivalent of UID 1000 and GID 1000 (myuser1:myuser1) (?)

@NorkzYT
Copy link
Author

NorkzYT commented Jun 28, 2025

@neil-bh

That is exactly what you should be seeing — UID/GID 10000 on the host corresponds to UID/GID 1000 inside your unprivileged LXC.

@rfResearch
Copy link

Hi @NorkzYT - Very useful script, thank you for sharing. I've added a new function to generate a config file for the user inputs and an additional function to take the config file as input. I've also added a fonction to list the LXC IDs and the LXC usernames in the user input section, and a completion check.
I've noticed that the LXC container must be started before the execution of the script in order to work.

#!/usr/bin/env bash
# proxmox-lxc-cifs-share.sh
# https://gist.github.com/NorkzYT/14449b247dae9ac81ba4664564669299
#
# Mount a CIFS/SMB share on a Proxmox VE host and bind-mount it into
# an unprivileged LXC container as any container user, by dynamically
# mapping UIDs/GIDs.
#
# ---------------------------------------------------------------
# Compatible with Proxmox VE 7-8.  Tested on Debian 12 host.
# ---------------------------------------------------------------

set -euo pipefail

#
#----------------------#
#----- Preconditions --#
#----------------------#
#

# Must be root
if [[ $EUID -ne 0 ]]; then
  echo "ERROR: Please run as root." >&2
  exit 1
fi

# Helper for error + exit
error_exit() {
  echo "ERROR: $1" >&2
  exit 1
}

# Function to display help
show_help() {
  echo "Usage: $0 [OPTIONS]"
  echo
  echo "Mount a CIFS/SMB share on a Proxmox VE host and bind-mount it into an unprivileged LXC container."
  echo
  echo "Options:"
  echo "  --config FILE      Specify a configuration file with parameters."
  echo "  --noserverino      Disable serverino option for CIFS mount."
  echo "  --help             Display this help message."
  echo
  echo "Configuration File Format:"
  echo "The configuration file should contain the following parameters:"
  echo "  folder_name=your_folder_name"
  echo "  cifs_host=your_cifs_host_ip_or_dns"
  echo "  share_name=your_share_name"
  echo "  smb_username=your_smb_username"
  echo "  smb_password=your_smb_password"
  echo "  lxc_id=your_lxc_numeric_id"
  echo "  lxc_username=your_container_username"
  echo
  echo "Example configuration file:"
  echo "folder_name=nas_rwx"
  echo "cifs_host=10.0.0.2"
  echo "share_name=media"
  echo "smb_username=your_username"
  echo "smb_password=your_password"
  echo "lxc_id=105"
  echo "lxc_username=ubuntu"
  exit 0
}

# Function to list LXC container IDs
list_lxc_ids() {
  echo "Available LXC container IDs:"
  pct list | awk 'NR>1 {print $1}'  # Ignore the header and print only the IDs
}

# Function to list usernames in the LXC container
list_usernames() {
  local lxc_id="$1"
  echo "Validating container ${lxc_id}..."
  pct status "$lxc_id" &>/dev/null \
    || error_exit "LXC ${lxc_id} does not exist."
  echo "Available usernames in LXC container ${lxc_id}:"
  pct exec "$lxc_id" -- getent passwd | awk -F: '{print $1}'  # Print only the usernames
}

# Ensure required commands exist
command -v bash         >/dev/null 2>&1 || error_exit "Please run with bash: bash $0"
command -v pct          >/dev/null 2>&1 || error_exit "'pct' command not found. Run this on the Proxmox host."
command -v mount.cifs   >/dev/null 2>&1 || error_exit "cifs-utils missing. Install: apt update && apt install cifs-utils"
command -v systemd-escape >/dev/null 2>&1 || error_exit "systemd-escape missing. Required for systemd unit management."

#
#----------------------#
#----- Parse Flags ----#
#----------------------#
#

NOSERVERINO=0
config_file=""

# Parse command line arguments
while [[ $# -gt 0 ]]; do
  case $1 in
    --noserverino)
      NOSERVERINO=1
      shift
      ;;
    --config)
      config_file="$2"
      shift 2
      ;;
    --help)
      show_help
      ;;
    *)
      echo "ERROR: Unknown option $1" >&2
      exit 1
      ;;
  esac
done


#
#----------------------#
#----- User Input -----#
#----------------------#
#
if [[ -n "$config_file" ]]; then
  # Read parameters from the configuration file
  if [[ ! -f "$config_file" ]]; then
    error_exit "Configuration file '$config_file' not found."
  fi
  source "$config_file"
else
  # Ask parameters to the user
  echo "=== Proxmox CIFS Share Mount Wizard ==="
  read -r -p "1) Folder name under /mnt/lxc_shares (e.g. nas_rwx): " folder_name
  read -r -p "2) CIFS host (IP/DNS, e.g. 10.0.0.2): "     cifs_host
  read -r -p "3) Share name (e.g. media): "             share_name
  read -r -p "4) SMB username: "                       smb_username
  read -s -p "5) SMB password: "                       smb_password && echo

  # List available LXC container IDs
  list_lxc_ids
  read -r -p "6) LXC numeric ID (e.g. 105): "           lxc_id

  # List available usernames in the selected LXC container
  list_usernames "$lxc_id" 
 read -r -p "7) Container username (e.g. ubuntu): "   lxc_username
  echo

  # Set default configuration file path
  default_config_file_path="./proxmox-lxc-cifs-share.conf"
  config_file_path="$default_config_file_path"

  # Ask if the user wants to generate a configuration file
  read -r -p "Do you want to generate a configuration file? (y/n): " generate_config

  if [[ "$generate_config" == "y" || "$generate_config" == "Y" ]]; then
    read -r -p "Enter the path for the configuration file [default: $default_config_file_path]: " user_input

    # Use default path if no input is provided
    if [[ -n "$user_input" ]]; then
      config_file_path="$user_input"
    fi

    # Create the configuration file and write parameters to it
    {
      echo "folder_name=${folder_name}"
      echo "cifs_host=${cifs_host}"
      echo "share_name=${share_name}"
      echo "smb_username=${smb_username}"
      echo "smb_password=${smb_password}"
      echo "lxc_id=${lxc_id}"
      echo "lxc_username=${lxc_username}"
    } > "$config_file_path"

    echo "Configuration file created at: $config_file_path"
  fi
fi

#
#----------------------#
#----- Validation -----#
#----------------------#
#

echo "Validating container ${lxc_id}..."
pct status "$lxc_id" &>/dev/null \
  || error_exit "LXC ${lxc_id} does not exist."

echo "Retrieving UID/GID for '${lxc_username}' inside LXC ${lxc_id}..."
if ! container_uid=$(pct exec "$lxc_id" -- id -u "$lxc_username" 2>/dev/null); then
  error_exit "User '${lxc_username}' not found in container ${lxc_id}."
fi
container_gid=$(pct exec "$lxc_id" -- id -g "$lxc_username")
echo "  ↳ container UID=${container_uid}, GID=${container_gid}"

echo "Parsing idmap offset from container config..."
idmap_offset=$(pct config "$lxc_id" \
  | awk '/^lxc.idmap: u 0 /{print $4; exit}')
if [[ -z "$idmap_offset" ]]; then
  echo "  ↳ Warning: idmap offset not found; defaulting to 100000"
  idmap_offset=100000
fi
echo "  ↳ host idmap offset=${idmap_offset}"

host_uid=$(( idmap_offset + container_uid ))
host_gid=$(( idmap_offset + container_gid ))
echo "  ↳ will mount with host UID=${host_uid}, GID=${host_gid}"

#
#----------------------#
#--- Stop Container ----#
#----------------------#
#

echo "Stopping LXC ${lxc_id}..."
pct stop "$lxc_id"
while [[ "$(pct status "$lxc_id")" != "status: stopped" ]]; do
  sleep 1
done

#
#----------------------#
#--- Host-side Mount --#
#----------------------#
#

mnt_root="/mnt/lxc_shares/${folder_name}"
echo "Ensuring host mount point exists at ${mnt_root}..."
mkdir -p "$mnt_root"

echo "Building fstab entry..."
options="_netdev,x-systemd.automount,noatime,nobrl"
options+=",uid=${host_uid},gid=${host_gid},dir_mode=0770,file_mode=0770"
options+=",username=${smb_username},password=${smb_password}"
options+=",iocharset=utf8"  # Add option iocharset=utf8
(( NOSERVERINO )) && options+=",noserverino"

fstab_entry="//${cifs_host}/${share_name} ${mnt_root} cifs ${options} 0 0"

# Remove any stale entry
if grep -Eqs "^//${cifs_host}/${share_name}[[:space:]]+${mnt_root}[[:space:]]+cifs" /etc/fstab; then
  echo "  ↳ Removing old /etc/fstab entry..."
  sed -i "\|^//${cifs_host}/${share_name} ${mnt_root} .*|d" /etc/fstab
fi

echo "  ↳ Adding new /etc/fstab entry..."
echo "$fstab_entry" >> /etc/fstab

echo "Reloading systemd daemon..."
systemctl daemon-reload

unit_base=$(systemd-escape --path "$mnt_root")
echo "Stopping potential systemd units ${unit_base}.automount & ${unit_base}.mount..."
systemctl stop "${unit_base}.automount" "${unit_base}.mount" >/dev/null 2>&1 || true

if mountpoint -q "$mnt_root"; then
  echo "  ↳ Unmounting existing mount..."
  umount -l "$mnt_root"
fi

echo "Mounting //${cifs_host}/${share_name} → ${mnt_root}..."
mount "$mnt_root"

#
#----------------------#
#--- Container Bind ----#
#----------------------#
#

echo "Configuring bind-mount into LXC (no backups)..."
pct set "$lxc_id" \
  --mp0 "${mnt_root},mp=/mnt/${folder_name},backup=0"
echo "  ↳ Bind-mount set as mp0 → /mnt/${folder_name}"

echo "Starting LXC ${lxc_id}..."
pct start "$lxc_id"

#
#----------------------#
#--- Access Validation --#
#----------------------#
#

echo "Checking access to the mount from container ${lxc_id}..."
if pct exec "$lxc_id" -- test -d "/mnt/${folder_name}"; then
  echo "  ↳ Access to the mount confirmed."
  
  # Display access rights
  echo "Access rights of the share:"
  pct exec "$lxc_id" -- ls -ld "/mnt/${folder_name}"
else
  error_exit "ERROR: The mount is not accessible from container ${lxc_id}."
fi

#
#----------------------#
#----- Completion ------#
#----------------------#
#

echo -e "\n✅  Configuration complete!"
echo "Inspect inside the container with:"
echo "    ls -ld /mnt/${folder_name}"

@neil-bh
Copy link

neil-bh commented Jul 1, 2025

That suggestion from @rfResearch looks great! If @NorkzYT decides to merge it could I also make a request based on a common use case...

When running the script for the first time, all is great and I end up with CIFS share accessible in my unprivileged LXC container . But then I decide I would like the CIFS share available in another of my unprivileged LXC containers - so I'd run the script again. I am prompted to create the mount again on the host (although it already exists) - I can see from the script that it will remove the existing line in fstab if it already exists, so maybe that's good enough? Or perhaps confirm with the user that the share already exists: "would you like to skip the host mount?"... or... maybe pass in a parameter for executing in this use case to additional LXC containers, e.g. bash ./proxmox-lxc-cifs-share.sh add? Or we could simply even use the config file approach with all the values populated to simplify adding the share to more LXC containers?

Another idea here... Is it possible to provide more than 1 user when prompted at step 7 for the lxc username? (Update: I noticed in @rfResearch's version they are not using lxc_shares as a group, so it's using username:username which I believe is the typical way to do it, and therefore probably negates my idea of being able to add more than one user to the share - after all, I cant think of a situation where i'd need multiple different user accounts to have individual access the share)

@NorkzYT
Copy link
Author

NorkzYT commented Jul 1, 2025

@rfResearch @neil-bh

Thank you for all the information. I will revise the script with your recommendations this weekend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment