mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-10-02 08:06:17 +00:00
Update lxc-mount-manager.sh
This commit is contained in:
@@ -1,18 +1,17 @@
|
||||
#!/bin/bash
|
||||
# ==========================================================
|
||||
# ProxMenux - LXC Mount Manager (Standalone - CLEAN v1)
|
||||
# ProxMenux - LXC Mount Manager
|
||||
# ==========================================================
|
||||
# Author : MacRimi
|
||||
# Copyright : (c) 2024 MacRimi
|
||||
# License : MIT
|
||||
# Version : 3.0-clean
|
||||
# Version : 3.1-enhanced
|
||||
# Last Updated: $(date +%d/%m/%Y)
|
||||
# ==========================================================
|
||||
|
||||
BASE_DIR="/usr/local/share/proxmenux"
|
||||
source "$BASE_DIR/utils.sh"
|
||||
|
||||
|
||||
SHARE_COMMON_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main/scripts/global/share-common.func"
|
||||
if ! source <(curl -s "$SHARE_COMMON_URL" 2>/dev/null); then
|
||||
SHARE_COMMON_LOADED=false
|
||||
@@ -25,7 +24,6 @@ initialize_cache
|
||||
|
||||
# ==========================================================
|
||||
|
||||
|
||||
get_container_uid_shift() {
|
||||
local ctid="$1"
|
||||
local conf="/etc/pve/lxc/${ctid}.conf"
|
||||
@@ -36,12 +34,10 @@ get_container_uid_shift() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
|
||||
local unpriv
|
||||
unpriv=$(grep "^unprivileged:" "$conf" | awk '{print $2}')
|
||||
|
||||
if [[ "$unpriv" == "1" ]]; then
|
||||
|
||||
uid_shift=$(grep "^lxc.idmap" "$conf" | grep 'u 0' | awk '{print $5}' | head -1)
|
||||
echo "${uid_shift:-100000}"
|
||||
return 0
|
||||
@@ -51,7 +47,6 @@ get_container_uid_shift() {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
setup_container_access() {
|
||||
local ctid="$1" group_name="$2" host_gid="$3" host_dir="$4"
|
||||
local uid_shift mapped_gid
|
||||
@@ -63,51 +58,181 @@ setup_container_access() {
|
||||
|
||||
uid_shift=$(get_container_uid_shift "$ctid")
|
||||
|
||||
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# CONTAINER TYPE DETECTION AND STRATEGY
|
||||
# ===================================================================
|
||||
|
||||
if [[ "$uid_shift" -eq 0 ]]; then
|
||||
msg_ok "$(translate "PRIVILEGED container detected - using direct UID/GID mapping")"
|
||||
mapped_gid="$host_gid"
|
||||
msg_ok "$(translate "Privileged container - using same GID as host:") $host_gid"
|
||||
container_type="privileged"
|
||||
else
|
||||
msg_ok "$(translate "UNPRIVILEGED container detected - using mapped UID/GID")"
|
||||
mapped_gid=$((uid_shift + host_gid))
|
||||
msg_ok "$(translate "Unprivileged container - using mapped GID:") $mapped_gid (host GID: $host_gid, shift: $uid_shift)"
|
||||
container_type="unprivileged"
|
||||
msg_ok "UID shift: $uid_shift, Host GID: $host_gid → Container GID: $mapped_gid"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
pct exec "$ctid" -- sh -c "
|
||||
if ! getent group $group_name >/dev/null 2>&1; then
|
||||
groupadd -g $mapped_gid $group_name 2>/dev/null || true
|
||||
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# STEP 1: ACL TOOLS (only for unprivileged containers)
|
||||
# ===================================================================
|
||||
|
||||
if [[ "$container_type" == "unprivileged" ]]; then
|
||||
if ! command -v setfacl >/dev/null 2>&1; then
|
||||
msg_info "$(translate "Installing ACL tools (REQUIRED for unprivileged containers)...")"
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y acl >/dev/null 2>&1
|
||||
if command -v setfacl >/dev/null 2>&1; then
|
||||
msg_ok "$(translate "ACL tools installed successfully")"
|
||||
else
|
||||
msg_error "$(translate "Failed to install ACL tools - permissions may not work correctly")"
|
||||
fi
|
||||
else
|
||||
ct_gid=\$(getent group $group_name | cut -d: -f3)
|
||||
if [ \"\$ct_gid\" != \"$mapped_gid\" ]; then
|
||||
msg_ok "$(translate "ACL tools already available")"
|
||||
fi
|
||||
else
|
||||
msg_ok "$(translate "Privileged container - ACL tools not required (using POSIX permissions)")"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# STEP 2: CONTAINER GROUP CONFIGURATION
|
||||
# ===================================================================
|
||||
|
||||
msg_info "$(translate "Configuring container group with") $container_type $(translate "strategy...")"
|
||||
|
||||
pct exec "$ctid" -- sh -c "
|
||||
# Remove existing group if GID is wrong
|
||||
if getent group $group_name >/dev/null 2>&1; then
|
||||
current_gid=\$(getent group $group_name | cut -d: -f3)
|
||||
if [ \"\$current_gid\" != \"$mapped_gid\" ]; then
|
||||
groupdel $group_name 2>/dev/null || true
|
||||
groupadd -g $mapped_gid $group_name 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
getent passwd | while IFS=: read -r username _ uid gid _ home _; do
|
||||
if [ \"\$uid\" -eq 0 ] || [ \"\$uid\" -ge 1000 ] || [ \"\$username\" = \"nobody\" ] || [ \"\$username\" = \"www-data\" ]; then
|
||||
usermod -aG $group_name \"\$username\" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
# Create group with correct GID
|
||||
groupadd -g $mapped_gid $group_name 2>/dev/null || true
|
||||
" 2>/dev/null
|
||||
|
||||
msg_ok "$(translate "Container group configured:") $group_name (GID: $mapped_gid)"
|
||||
|
||||
if command -v setfacl >/dev/null 2>&1; then
|
||||
pct exec "$ctid" -- getent passwd | awk -F: '{print $1, $3}' | while read user uid; do
|
||||
[[ "$uid" -eq 0 ]] && continue
|
||||
host_uid=$((uid_shift + uid))
|
||||
setfacl -m u:$host_uid:rwx "$host_dir" 2>/dev/null || true
|
||||
done
|
||||
msg_ok "$(translate "ACL permissions applied for container users")"
|
||||
|
||||
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# STEP 3: USER PROCESSING (different strategies)
|
||||
# ===================================================================
|
||||
|
||||
local container_users
|
||||
container_users=$(pct exec "$ctid" -- getent passwd | awk -F: '{print $1 ":" $3}' 2>/dev/null)
|
||||
|
||||
local users_added=0
|
||||
local acls_applied=0
|
||||
|
||||
if [[ "$container_type" == "privileged" ]]; then
|
||||
|
||||
|
||||
msg_ok "$(translate "Privileged container:") $users_added $(translate "users added to group (no ACLs needed)")"
|
||||
|
||||
else
|
||||
|
||||
msg_info "$(translate "Using UNPRIVILEGED strategy: mapped UIDs + ACL permissions")"
|
||||
|
||||
while IFS=: read -r username ct_uid; do
|
||||
if [[ -n "$username" && "$ct_uid" =~ ^[0-9]+$ ]]; then
|
||||
local host_uid=$((uid_shift + ct_uid))
|
||||
|
||||
if pct exec "$ctid" -- usermod -aG "$group_name" "$username" 2>/dev/null; then
|
||||
users_added=$((users_added + 1))
|
||||
|
||||
if command -v setfacl >/dev/null 2>&1; then
|
||||
setfacl -m u:$host_uid:rwx "$host_dir" 2>/dev/null
|
||||
setfacl -m d:u:$host_uid:rwx "$host_dir" 2>/dev/null
|
||||
acls_applied=$((acls_applied + 1))
|
||||
fi
|
||||
|
||||
case "$username" in
|
||||
root|www-data|ncp|nobody|ubuntu|debian)
|
||||
msg_ok "$(translate "Configured user:") $username (CT_UID:$ct_uid → HOST_UID:$host_uid)"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
done <<< "$container_users"
|
||||
|
||||
msg_ok "$(translate "Unprivileged container:") $users_added $(translate "users added,") $acls_applied $(translate "ACL entries applied")"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# STEP 4: DIRECTORY PERMISSIONS
|
||||
# ===================================================================
|
||||
msg_info "$(translate "Setting optimal directory permissions...")"
|
||||
|
||||
chmod 2775 "$host_dir" 2>/dev/null || true
|
||||
chgrp "$group_name" "$host_dir" 2>/dev/null || true
|
||||
|
||||
msg_ok "$(translate "Host directory permissions:") 2775 root:$group_name"
|
||||
|
||||
msg_ok "$(translate "Group mapping ensured:") host=$host_gid → ct=$mapped_gid"
|
||||
msg_ok "$(translate "Multi-approach access configuration completed")"
|
||||
|
||||
|
||||
|
||||
|
||||
# ===================================================================
|
||||
# STEP 5: VERIFICATION
|
||||
# ===================================================================
|
||||
msg_info "$(translate "Verifying configuration...")"
|
||||
|
||||
if [[ "$container_type" == "unprivileged" ]] && command -v getfacl >/dev/null 2>&1; then
|
||||
local acl_count=$(getfacl "$host_dir" 2>/dev/null | grep "^user:" | grep -v "^user::" | wc -l)
|
||||
msg_ok "$(translate "ACL entries configured:") $acl_count"
|
||||
|
||||
# Show sample ACL entries
|
||||
if [[ $acl_count -gt 0 ]]; then
|
||||
echo -e "${TAB}${BGN}$(translate "ACL entries:")${CL}"
|
||||
getfacl "$host_dir" 2>/dev/null | grep "^user:" | grep -v "^user::" | head -3 | while read acl_line; do
|
||||
echo -e "${TAB} ${BL}$acl_line${CL}"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
local test_users=("www-data" "root" "ncp" "nobody")
|
||||
local successful_tests=0
|
||||
|
||||
for test_user in "${test_users[@]}"; do
|
||||
if pct exec "$ctid" -- id "$test_user" >/dev/null 2>&1; then
|
||||
if pct exec "$ctid" -- su -s /bin/bash "$test_user" -c "ls '$4' >/dev/null 2>&1" 2>/dev/null; then
|
||||
successful_tests=$((successful_tests + 1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $successful_tests -gt 0 ]]; then
|
||||
msg_ok "$(translate "Access verification:") $successful_tests $(translate "users can access mount point")"
|
||||
fi
|
||||
|
||||
|
||||
if [[ "$container_type" == "privileged" ]]; then
|
||||
msg_ok "$(translate "PRIVILEGED container configuration completed - using direct POSIX permissions")"
|
||||
else
|
||||
msg_ok "$(translate "UNPRIVILEGED container configuration completed - using ACL permissions")"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -133,6 +258,10 @@ get_next_mp_index() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
add_bind_mount() {
|
||||
local ctid="$1" host_path="$2" ct_path="$3"
|
||||
local mpidx result
|
||||
@@ -147,7 +276,6 @@ add_bind_mount() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
||||
if pct config "$ctid" | grep -q "$host_path"; then
|
||||
echo -e
|
||||
msg_warn "$(translate "Directory already mounted in container configuration.")"
|
||||
@@ -177,61 +305,6 @@ add_bind_mount() {
|
||||
|
||||
|
||||
|
||||
select_container_mount_point() {
|
||||
local ctid="$1"
|
||||
local host_dir="$2"
|
||||
local choice mount_point existing_dirs options
|
||||
|
||||
while true; do
|
||||
choice=$(whiptail --title "$(translate "Configure Mount Point inside LXC")" \
|
||||
--menu "$(translate "Where to mount inside container?")" 18 70 5 \
|
||||
"1" "$(translate "Create new directory in /mnt")" \
|
||||
"2" "$(translate "Use existing directory in /mnt")" \
|
||||
"3" "$(translate "Enter path manually")" \
|
||||
"4" "$(translate "Cancel")" 3>&1 1>&2 2>&3) || return 1
|
||||
|
||||
case "$choice" in
|
||||
1)
|
||||
mount_point=$(whiptail --inputbox "$(translate "Enter folder name for /mnt:")" 10 60 "shared" 3>&1 1>&2 2>&3) || continue
|
||||
[[ -z "$mount_point" ]] && continue
|
||||
mount_point="/mnt/$mount_point"
|
||||
pct exec "$ctid" -- mkdir -p "$mount_point" 2>/dev/null
|
||||
;;
|
||||
|
||||
2)
|
||||
existing_dirs=$(pct exec "$ctid" -- ls -1 /mnt 2>/dev/null | awk '{print "/mnt/"$1" "$1}')
|
||||
if [[ -z "$existing_dirs" ]]; then
|
||||
whiptail --msgbox "$(translate "No existing directories found in /mnt")" 8 60
|
||||
continue
|
||||
fi
|
||||
mount_point=$(whiptail --title "$(translate "Select Existing Folder")" \
|
||||
--menu "$(translate "Choose a folder from /mnt:")" 20 70 10 \
|
||||
$existing_dirs 3>&1 1>&2 2>&3) || continue
|
||||
;;
|
||||
|
||||
3)
|
||||
mount_point=$(whiptail --inputbox "$(translate "Enter full path:")" 10 70 "/mnt/shared" 3>&1 1>&2 2>&3) || continue
|
||||
[[ -z "$mount_point" ]] && continue
|
||||
pct exec "$ctid" -- mkdir -p "$mount_point" 2>/dev/null
|
||||
;;
|
||||
|
||||
4)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if pct exec "$ctid" -- test -d "$mount_point" 2>/dev/null; then
|
||||
echo "$mount_point"
|
||||
return 0
|
||||
else
|
||||
whiptail --msgbox "$(translate "Could not create or access directory:") $mount_point" 8 70
|
||||
continue
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
|
||||
mount_host_directory_to_lxc() {
|
||||
|
||||
# Step 1: Select container
|
||||
@@ -256,9 +329,7 @@ mount_host_directory_to_lxc() {
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
msg_ok "$(translate 'Select LXC container')"
|
||||
|
||||
|
||||
msg_ok "$(translate 'Container selected and running')"
|
||||
|
||||
# Step 2: Select host directory
|
||||
local host_dir
|
||||
@@ -266,7 +337,7 @@ mount_host_directory_to_lxc() {
|
||||
if [[ -z "$host_dir" ]]; then
|
||||
return 1
|
||||
fi
|
||||
msg_ok "$(translate 'Select Host directory')"
|
||||
msg_ok "$(translate 'Host directory selected')"
|
||||
|
||||
# Step 3: Setup group
|
||||
local group_name="sharedfiles"
|
||||
@@ -280,7 +351,7 @@ mount_host_directory_to_lxc() {
|
||||
chown -R root:"$group_name" "$host_dir" 2>/dev/null || true
|
||||
chmod -R 2775 "$host_dir" 2>/dev/null || true
|
||||
|
||||
msg_ok "$(translate 'Select container mount point')"
|
||||
msg_ok "$(translate 'Host group configured')"
|
||||
|
||||
# Step 4: Select container mount point
|
||||
local ct_mount_point
|
||||
@@ -316,19 +387,9 @@ $(translate "Proceed?")"
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Step 7: Setup access ======================================================
|
||||
|
||||
# Step 7: Setup access (handles both privileged and unprivileged)
|
||||
setup_container_access "$container_id" "$group_name" "$group_gid" "$host_dir"
|
||||
|
||||
# ===========================================================================
|
||||
|
||||
|
||||
|
||||
|
||||
# Step 8: Final setup
|
||||
pct exec "$container_id" -- chgrp "$group_name" "$ct_mount_point" 2>/dev/null || true
|
||||
pct exec "$container_id" -- chmod 2775 "$ct_mount_point" 2>/dev/null || true
|
||||
@@ -341,6 +402,11 @@ $(translate "Proceed?")"
|
||||
echo -e "${TAB}${BGN}$(translate 'Mount Point:')${CL} ${BL}$ct_mount_point${CL}"
|
||||
echo -e "${TAB}${BGN}$(translate 'Group:')${CL} ${BL}$group_name (GID: $group_gid)${CL}"
|
||||
|
||||
if [[ "$uid_shift" -eq 0 ]]; then
|
||||
echo -e "${TAB}${BGN}$(translate 'Permission Strategy:')${CL} ${BL}POSIX (direct mapping)${CL}"
|
||||
else
|
||||
echo -e "${TAB}${BGN}$(translate 'Permission Strategy:')${CL} ${BL}ACL (mapped UIDs)${CL}"
|
||||
fi
|
||||
|
||||
echo -e ""
|
||||
if whiptail --yesno "$(translate "Restart container to activate mount?")" 8 60; then
|
||||
@@ -370,9 +436,7 @@ $(translate "Proceed?")"
|
||||
read -r
|
||||
}
|
||||
|
||||
# ==========================================================
|
||||
|
||||
|
||||
# Main menu
|
||||
main_menu() {
|
||||
while true; do
|
||||
choice=$(dialog --title "$(translate 'LXC Mount Manager')" \
|
||||
@@ -401,6 +465,4 @@ main_menu() {
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
|
||||
main_menu
|
||||
|
Reference in New Issue
Block a user