|
#!/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}" |
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
andGID=1000
but I've had to adjust these toUID=0
andGID=10000
. (which matchesroot:lxc_shares
)From my unprivileged lxc, I tried updating the permissions on the mounted shares from
root:lxc_shares
to1000: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 useUID=1000
(which is is my first created user)?