From: Thomas Walker Lynch Date: Sat, 13 Sep 2025 16:18:38 +0000 (-0700) Subject: including the remote mount scripts X-Git-Url: https://git.reasoningtechnology.com/style/static/git-favicon.png?a=commitdiff_plain;h=b13ab1428c3c080e70440479fe5e3727eb1803bb;p=subu including the remote mount scripts --- diff --git a/README.md b/README.md index 66a2cbf..5e65176 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,44 @@ +* Key terms -developer/shell/subu is what I am using to run a sub user. I haven't been maintaining any of the rest of it. +masu == master user +subu == sub user +* Description +The scripts here can be used to give a master user the ability to administer sub users. The master user can add sub-users, delete them, and adminnister the sub users files. -# `subu` — Sub-User Shell Launcher +Sub users are containers built over the user system. -## Overview +User processes all have pids, and contained permissions. -`subu` is a shell script used to launch an interactive login shell under a **sub-user** account. -It provides an isolated session under a consistent naming scheme, while correctly configuring GUI forwarding and persistent services. +User's have virtual memory. -Sub-users are named using the convention: +User files have owners, and ownership permissions, and also group permissions (sharing permissions) via unix and ACLs. -``` -Thomas- -``` +IP policy routine rules support network isolation by uid. -This naming scheme is required because Linux user names must be globally unique — the kernel has no built-in notion of subusers (yet!). +X windows has sharing facilities and security policies for the display. ---- +Most I/O devices already give virtual presentations of themselves to users. I.e. give each user full functionality while keeping the users separate. Those which do not have always been a pain when writing containers, no exception here. -## Syntax -```bash -subu -``` +* Key to this approach are the tools: -Where `` is the symbolic sub-identity (e.g., `incommon`, `dev`, `tester`). +machinectl +bindfs +wg and iproute2 ---- +* Experience -## Behavior +I've been using this approach for some years, though much of it is ad hoc. Occasionally I wrote scripts but many were then deprecated. Slowly the full picture is emerging in in this git repo. -- Launches a shell as user `Thomas-` -- Detects whether the current session is under **Wayland** or **X11**: - - Under Wayland: uses `xhost +SI:localuser:Thomas-` - - Under X11: extracts the appropriate `.Xauthority` cookie to `$HOME/subu//.Xauthority` -- Sets `DISPLAY` and `XAUTHORITY` for graphical applications -- Enables lingering via `loginctl enable-linger` so sub-user services persist -- Runs the user’s shell (as listed in `/etc/passwd`) in **login mode** (`-l`) +It would be great to get together with another person who would like to experiment with this. Having two or more users would hasten the maturity of the scripts. -The shell launched will source `.bash_profile`, which should in turn source `.bashrc`: +* Also included, scripts for putting the master users and their subus on a remotely mounted encrypted drive. This adds the conveience of being able to walk up to linux boxes and provide one's user data, or to remotely mount a user on a box. -```bash -# Inside ~/.bash_profile -if [ -f "$HOME/.bashrc" ]; then - . "$HOME/.bashrc" -fi -``` +To do: -This ensures that aliases, prompts, and other interactive settings are applied. +Initializing, adding, and deleting subu. Adding and removing subu can become so common that there is a data management problem. At one point I had a python module with a constant 'table' of data. I plan to use sqlite for managing this problem and to introduce a new set of scripts. I will probably jump to C to support suid root and begin the integration of subu into Linux. ---- +Static local mounts of masu have not been developed, because I do not use them personally. It would require a simplification of the current remote mount scripts. -## Subuser: `incommon` - -The subuser named `incommon` is a shared environment used across all sub-users. -It is referenced in the PATH: - -``` -/home/Thomas/subu_data/incommon/executable -``` - -This allows tools and scripts to be shared without duplication. - ---- - -## Example - -```bash -subu incommon -``` - -This spawns a login shell as user `Thomas-incommon`, with GUI forwarding, shared executable access, and persistent services via systemd. - ---- - -## Notes - -- Each `` must have a corresponding home directory: - ``` - /home/Thomas/subu_data/ - ``` -- Ensure that the sub-user exists in `/etc/passwd` with a valid shell. -- Sub-users can run GUI applications (e.g., Emacs, Firefox) with correct X access. -- Sessions are sandboxed per sub-user, ideal for role-based separation, testing, or containment. - ---- diff --git a/developer/mockup/sqlite/schema.sql b/developer/mockup/sqlite/schema.sql new file mode 100644 index 0000000..faf7053 --- /dev/null +++ b/developer/mockup/sqlite/schema.sql @@ -0,0 +1,79 @@ +-- Schema for the subu server +-- + +-- List Tables +-- SQLite does not support PSQL style types +-- +-- CREATE TYPE List AS ( +-- id SERIAL, -- Integer ID +-- name TEXT NOT NULL -- Name of the list entry +-- ); +-- +-- so though these all have the same `List` form, they are declared independently +-- + CREATE TABLE db_property_list ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL UNIQUE + ); + + CREATE TABLE db_event_list ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL UNIQUE + ); + + CREATE TABLE shell_list ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL UNIQUE + ); + + CREATE TABLE system_resource_list ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL UNIQUE + ); + + CREATE TABLE user_type_list ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL UNIQUE + ); + +-- Data Tables +-- + CREATE TABLE db_property ( + id INTEGER PRIMARY KEY, + property_id INTEGER NOT NULL REFERENCES db_property_list(id), + type TEXT NOT NULL, + value TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ); + + CREATE TABLE db_event ( + id INTEGER PRIMARY KEY, + event_time DATETIME DEFAULT CURRENT_TIMESTAMP, + event_id INTEGER NOT NULL REFERENCES db_event_list(id), + user_id INTEGER REFERENCES user(id) + ); + + CREATE TABLE user ( + id INTEGER PRIMARY KEY, + login_gid INTEGER NOT NULL UNIQUE, + name TEXT NOT NULL UNIQUE, + home_directory TEXT NOT NULL, + shell INTEGER NOT NULL REFERENCES shell_list(id), + parent_id INTEGER REFERENCES user(id), + user_type_id INTEGER NOT NULL REFERENCES user_type_list(id), + status TEXT DEFAULT 'active' + ); + + CREATE TABLE share ( + id INTEGER PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES user(id), + other_user_id INTEGER NOT NULL REFERENCES user(id), + permissions TEXT NOT NULL + ); + + CREATE TABLE system_resource ( + id INTEGER PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES user(id), + resource_id INTEGER NOT NULL REFERENCES system_resource_list(id), + granted_by INTEGER REFERENCES user(id) + ); diff --git a/developer/shell/.githolder b/developer/shell/.githolder deleted file mode 100644 index e69de29..0000000 diff --git a/developer/shell/subu b/developer/shell/subu deleted file mode 100644 index ae30e07..0000000 --- a/developer/shell/subu +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -set -x - -subu="$1" -if [ -z "$subu" ]; then - echo "No subuser name supplied" - exit 1 -fi - -# actual subu user name and subu home directory -subu_user="Thomas-$subu" -subu_dir="/home/Thomas/subu_data/$subu" - -# detect current display and authority -display_val="${DISPLAY:-:0}" -authority_val="${XAUTHORITY:-$HOME/.Xauthority}" - -# construct guest's authority path (destination) -subu_Xauthority_path="$HOME/subu/$subu/.Xauthority" - -if [ "$XDG_SESSION_TYPE" = "wayland" ]; then - # Wayland/XWayland uses a temporary XAUTHORITY file (already in $XAUTHORITY) - echo "Wayland session detected" - xhost +SI:localuser:"$subu_user" -else - # X11 session – extract the proper cookie - echo "X11 session detected" - mkdir -p "$(dirname "$subu_Xauthority_path")" - touch "$subu_Xauthority_path" - xauth extract "$subu_Xauthority_path" "$display_val" -fi - -# allow guest processes to outlive login -sudo loginctl enable-linger "$subu_user" - -# Launch the subuser shell with DISPLAY and XAUTHORITY -sudo machinectl shell "$subu_user"@ /bin/bash -c " - export DISPLAY='$display_val'; - export XAUTHORITY='$subu_Xauthority_path'; - umask 077 - exec \"\$SHELL\" -l -" diff --git a/developer/source/cc/README.org b/developer/source/cc/README.org new file mode 100644 index 0000000..17433fb --- /dev/null +++ b/developer/source/cc/README.org @@ -0,0 +1,5 @@ + +These are currently not used. Eventually the main subu commands will be C programs and setuid root so that master users (and only master users) can seamlessly manipulate sub users. + +I started on this, then decided to let the scripts stabilize first. + diff --git a/developer/source/io/bestow_audio.sh b/developer/source/io/bestow_audio.sh new file mode 100755 index 0000000..20545e8 --- /dev/null +++ b/developer/source/io/bestow_audio.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# give_audio.sh — run as master user "Thomas" +# Usage: ./give_audio.sh +# Example: ./give_audio.sh Thomas-US # give card to subuser +# ./give_audio.sh Thomas # reclaim for master + +set -euo pipefail + +target="${1-}" +if [[ -z "$target" ]]; then + echo "❌ usage: $0 "; exit 2 +fi + +master="Thomas" + +# don't use sudo -v as it dumps the password into the emacs shell +sudo echo >& /dev/null + +run() { echo "+ $*"; eval "$*"; } + +# --- sanity checks --- +if ! id "$target" &>/dev/null; then + echo "❌ user not found: $target"; exit 1 +fi +if [[ "$(id -un)" != "$master" ]]; then + echo "❌ must be run as master user '$master'"; exit 1 +fi + +# Gather all subusers (Thomas-*) +mapfile -t subusers < <(getent passwd | awk -F: '$1 ~ /^'"$master"'-/ {print $1}' | sort) + +stop_master_audio() { + run "systemctl --user stop pipewire pipewire-pulse wireplumber || true" +} + +start_master_audio() { + # start services (not only sockets) to avoid lazy-activation races + run "systemctl --user start pipewire.service pipewire-pulse.service wireplumber.service" +} + +stop_subu_audio() { + local u="$1" + run "sudo machinectl shell ${u}@ /bin/bash -lc 'systemctl --user stop pipewire pipewire-pulse wireplumber || true'" +} + +start_subu_audio() { + local u="$1" + # Keep subuser from trying to bind to logind (not the active seat) + run "sudo machinectl shell ${u}@ /bin/bash -lc 'export WIREPLUMBER_DISABLE_PLUGINS=logind; systemctl --user import-environment WIREPLUMBER_DISABLE_PLUGINS; systemctl --user start pipewire.service pipewire-pulse.service wireplumber.service'" +} + +# --- stop everyone first (to release ALSA cleanly) --- +stop_master_audio +for u in "${subusers[@]}"; do + stop_subu_audio "$u" +done + +# Small settle time so ALSA reservation clears +sleep 0.5 + +# --- start only the target --- +if [[ "$target" == "$master" ]]; then + start_master_audio +else + # ensure linger for target so user services can run + run "sudo loginctl enable-linger '$target' || true" + start_subu_audio "$target" +fi + +# --- quick verification (best-effort) --- +if [[ "$target" == "$master" ]]; then + # Show default sink name (may require pipewire-pulse to be fully up) + run "pactl info | sed -n 's/^Default Sink: /Default Sink: /p'" +else + run "sudo machinectl shell ${target}@ /bin/bash -lc 'pactl info | sed -n \\\"s/^Default Sink: /Default Sink: /p\\\"'" +fi diff --git a/developer/source/login/login_to_subu.sh b/developer/source/login/login_to_subu.sh new file mode 100755 index 0000000..ca28743 --- /dev/null +++ b/developer/source/login/login_to_subu.sh @@ -0,0 +1,135 @@ +#!/bin/bash +# launch_subu.sh — Start a subuser shell (console or GUI-aware, with systemd user session) + +set -euo pipefail +umask 0077 + +subu="$1" +if [ -z "$subu" ]; then + echo "❌ No subuser name supplied" + exit 1 +fi + +subu_user="Thomas-$subu" +if ! id "$subu_user" &>/dev/null; then + echo "❌ User $subu_user does not exist" + exit 1 +fi + +# Check required commands +error_flag=0 +for cmd in machinectl xauth xhost dbus-run-session; do + if ! command -v "$cmd" &>/dev/null; then + echo "❌ $cmd not found" + error_flag=1 + fi +done +if [ "$error_flag" -eq 1 ]; then + exit 1 +fi + +# don't use sudo -v, because it will echo the password into the emacs shell +sudo echo >& /dev/null + + +# Something broke when I turned this off. What was it. Will have to turn it off again and +# test. +# +# Enable lingering so user services can persist +sudo loginctl enable-linger "$subu_user" + +# Decide how to set the use_xauth and use_xhost flags. +# +# As of the time of this writing, on my machines, Wayland insists on +# xauth, while my X11 is refuses to use it, thus it needs xhost control. +# So this is how I determine how to set the flags here. +# + +# bash will evaluate this variables inside a quoted if even when the +# gate is falase, so everything needs to be initialized, whether used +# or not. +subu_Xauthority_path="" +use_xauth=0 +use_xhost=0 +if [[ -n "${WAYLAND_DISPLAY:-}" ]]; then + has_display=true + XDG_SESSION_TYPE="wayland" + subu_Xauthority_path="$HOME/subu/$subu/.Xauthority" + use_xauth=1 + use_xhost=0 + echo "🌀 Wayland session - Using xauth for access control" + +elif [[ -n "${DISPLAY:-}" ]]; then + has_display=true + XDG_SESSION_TYPE="x11" + use_xauth=0 + use_xhost=1 + echo "🧱 X11 session - Using xhost for access control" + +else + has_display=false + XDG_SESSION_TYPE="tty" + use_xauth=0 + use_xhost=0 + echo "🖳 Console session (no X detected)" +fi + +if [[ "$use_xhost" -eq 1 ]]; then + xhost +SI:localuser:"$subu_user" +fi +if [[ "$use_xauth" -eq 1 ]]; then + mkdir -p "$(dirname "$subu_Xauthority_path")" + touch "$subu_Xauthority_path" + xauth extract "$subu_Xauthority_path" "$DISPLAY" +fi + +if $has_display; then + + + sudo machinectl shell "$subu_user"@ /bin/bash -c " + + # --- session env from parent --- + export DISPLAY=\"${DISPLAY:-${WAYLAND_DISPLAY}}\"; + export XDG_RUNTIME_DIR='/run/user/$(id -u "$subu_user")'; + export XDG_SESSION_TYPE=\"$XDG_SESSION_TYPE\"; + export XDG_SESSION_CLASS=\"user\"; + export XDG_DATA_DIRS=\"/usr/share/gnome:/usr/local/share/:/usr/share/\"; + export USE_XAUTH=$use_xauth + + # Only set XAUTHORITY when we actually prepared it (Wayland/xauth case) + if [[ \"\$USE_XAUTH\" -eq 1 ]]; then + export XAUTHORITY=\"$subu_Xauthority_path\" + fi + + if command -v /usr/bin/gnome-keyring-daemon &>/dev/null; then + eval \$(/usr/bin/gnome-keyring-daemon --start) + export GNOME_KEYRING_CONTROL GNOME_KEYRING_PID + fi + + # WirePlumber: ignore logind (subuser isn't the active seat) + systemctl --user set-environment WIREPLUMBER_DISABLE_PLUGINS=logind + systemctl --user import-environment DISPLAY XAUTHORITY WAYLAND_DISPLAY XDG_RUNTIME_DIR XDG_SESSION_TYPE + + # Bring up audio (sockets first, then services) + systemctl --user enable --now pipewire.socket pipewire-pulse.socket >/dev/null 2>&1 || true + systemctl --user restart wireplumber pipewire pipewire-pulse + + exec dbus-run-session -- bash -l + " + +else + + # Console mode with DBus session (give it audio too) + sudo machinectl shell "$subu_user"@ /bin/bash -c " + export XDG_RUNTIME_DIR='/run/user/$(id -u "$subu_user")}'; + + systemctl --user set-environment WIREPLUMBER_DISABLE_PLUGINS=logind + systemctl --user import-environment XDG_RUNTIME_DIR + systemctl --user enable --now pipewire.socket pipewire-pulse.socket >/dev/null 2>&1 || true + systemctl --user restart wireplumber pipewire pipewire-pulse + + exec dbus-run-session -- bash -l + " +fi + + diff --git a/developer/source/login/logout_subu.sh b/developer/source/login/logout_subu.sh new file mode 100644 index 0000000..a4a4206 --- /dev/null +++ b/developer/source/login/logout_subu.sh @@ -0,0 +1,3 @@ +# As root: +# loginctl terminate-user Thomas-US +loginctl terminate-user $1 diff --git a/developer/source/mount/README.org b/developer/source/mount/README.org new file mode 100644 index 0000000..73fd09f --- /dev/null +++ b/developer/source/mount/README.org @@ -0,0 +1,149 @@ + +When the master users are not remote mounted, but rather have static home directories on the local machine, these scripts are not needed. + +masu == master user +subu == sub user + +These 'mount' scripts are for keeping master users on a remote, optionally encrypted, device. + +I have one example running, so there might be generalization issues with these scripts. + +The order and type of the command arguments are the first part of each +command name. The command description follows. For example: + +`map_name__mounted_masu_list.sh` + +is given a `map_name` and provides a list of the masu found at the mount point with that name. (Note, that /dev/mapper/ is mounted at /mnt/.) + + +For mounting a remote device. + +The remote device has at the top level master user home directories. Each master user home directory has a sub directory called subu_data. Each directory in subu_data is owned by a sub-user, and is the home directory for that sub-user. Each master user also has a `subu` sub-directory. The contents of the subu directory will parallel that of the subu_data directory, but differ in that the contained files will be owned by the master user. + +1. the remote device is mounted under /mnt/map_name + + `device_mapname__open_mount.sh` ` + + `mapname` is the name that appears under /dev/mapper, it is also used + as the /mnt/ mount point. + + if is not to be opened with cryptsetup, instead mount it to the mount pt directly. + +2. Each master user is mount --bind from the /mnt/ to /home + + masu__to_home.sh + + There is currently no script to map bind all the masu in one call. + +3. master users have subu home directories under /home//subu_data. These + are owned by the subu users. Map the /home//subu_data directories to + `/home/subu`n using + + masu__map_own_all.sh + + The `/home/subu` directories are bindfs mapped to be be owned by the master + user, so that the master user may administer them. + + + +* bindfs problem + + On my Fedora install once it was bound by root, it stayed there. On + Debian it keeps losing the mounts, for sure on a logout or login, + and maybe other times also --- the machinectl logins and logouts I + bet that is what is doing it. Hence very time I go to use a mount + in subu it is not there or filled with the dreaded question mark + garbage, has to be umount then remounted. + + -------------------------------------------------------------------------------- + You're exactly right in your diagnosis: Debian's behavior under + systemd with machinectl is unmounting user bind mounts on + login/logout cycles—especially when using enable-linger, systemd + --user, or machinectl shell. + + This differs from Fedora, which preserves those mounts more consistently unless explicitly torn down. Let’s first address why it’s happening, then provide a robust, recoverable fix. + 🔍 Why This Happens + + When machinectl or loginctl manages a user session: + + systemd creates a private mount namespace per user. + + Any mounts (especially bind mounts) not made within that + namespace or not managed by systemd itself (i.e. not via .mount + units) can be: + + Torn down on logout, + + Hidden due to namespace isolation, + + Disconnected if user lingering is toggled. + + If your bindfs mount is outside the user’s namespace (i.e. mounted by root), but then accessed inside a user-managed session, systemd may unmount it or lose visibility. + ✅ Recommended Fix + + There are two paths: + A. Use a systemd .mount unit (most stable) + + Create a file /etc/systemd/system/home-Thomas-subu-.mount: + + [Unit] + Description=Bind mount subu user home + + [Mount] + What=/home/Thomas/subu_data/ + Where=/home/Thomas/subu/ + Type=none + Options=bind + + [Install] + WantedBy=multi-user.target + + Enable and start it: + + sudo systemctl daemon-reexec + sudo systemctl enable --now home-Thomas-subu-.mount + + Repeat for each subu. + + This ensures systemd manages the bind mount in its native way and it won’t get torn down. + B. Remount automatically on login via ~/.bash_profile or a systemd --user unit + + You can modify your script to: + + Skip sudo if already root + + Be idempotent + + Automatically remount on session start + + Then in ~/.bash_profile or ~/.config/systemd/user/subu-mount.service: + + [Unit] + Description=Re-mount subu directory for Thomas + + [Service] + Type=oneshot + ExecStart=/home/Thomas/executable/subu/user_open_subu.sh Thomas US + + [Install] + WantedBy=default.target + + Enable with: + + systemctl --user daemon-reexec + systemctl --user enable --now subu-mount.service + + This guarantees it will come up as part of your login, even after a reboot. + 🔄 Temporary Workaround + + If you want a quick way to check all subu are mounted and remount them if not, write a watchdog script: + + #!/bin/bash + for subu in $(ls /home/Thomas/subu_data); do + mountpoint="/home/Thomas/subu/$subu" + if ! mountpoint -q "$mountpoint"; then + /home/Thomas/executable/subu/user_open_subu.sh Thomas "$subu" + fi + done + + Would you like me to auto-generate the .mount or .service files for each subu? We can script the system-wide setup cleanly. diff --git a/developer/source/mount/device_mapname__open_mount.sh b/developer/source/mount/device_mapname__open_mount.sh new file mode 100755 index 0000000..20df0e1 --- /dev/null +++ b/developer/source/mount/device_mapname__open_mount.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +if [[ $EUID -ne 0 ]]; then + echo "❌ This script must be run as root." >&2 + exit 1 +fi + +# Function to unlock and mount the device +device_mount() { + local device_node=$1 # e.g., /dev/sdb1 + local device_name=$2 # e.g., Zathustra + local mount_point="/mnt/$device_name" + + # Check if cryptsetup is installed + if ! command -v cryptsetup &> /dev/null; then + echo "Error: cryptsetup is not installed!" + return 1 + fi + + # Check if the device is already mounted + if mount | grep "on $mount_point" > /dev/null; then + echo "Device $device_name is already mounted at $mount_point." + return 0 + fi + + # Make sure the mount point exists + mkdir -p "$mount_point" + + # Unlock the encrypted device + sudo cryptsetup luksOpen "$device_node" "$device_name-crypt" + + # Mount the unlocked device + sudo mount "/dev/mapper/$device_name-crypt" "$mount_point" + + echo "$device_name mounted at $mount_point" +} + +# Run the function with the device node and device name as arguments +device_mount "$1" "$2" diff --git a/developer/source/mount/device_umount.sh b/developer/source/mount/device_umount.sh new file mode 100755 index 0000000..7bc8275 --- /dev/null +++ b/developer/source/mount/device_umount.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +if [[ $EUID -ne 0 ]]; then + echo "❌ This script must be run as root." >&2 + exit 1 +fi + +umount /mnt/"$1" +cryptsetup close "$1" diff --git a/developer/source/mount/mapname__mounted_masu_list.sh b/developer/source/mount/mapname__mounted_masu_list.sh new file mode 100755 index 0000000..0ef5381 --- /dev/null +++ b/developer/source/mount/mapname__mounted_masu_list.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Function to list users in the /mnt//user_data directory +device_user_list() { + local device=$1 + local user_data_dir="/mnt/$device/user_data" + + if [ ! -d "$user_data_dir" ]; then + echo "Error: $user_data_dir does not exist!" + return 1 + fi + + # List all user directories in the user_data directory + find "$user_data_dir" -maxdepth 1 -mindepth 1 -type d -exec basename {} \; +} + +# Run the function with the device name as an argument +device_user_list "$1" diff --git a/developer/source/mount/masu__map_own_all.sh b/developer/source/mount/masu__map_own_all.sh new file mode 100755 index 0000000..a1b22a3 --- /dev/null +++ b/developer/source/mount/masu__map_own_all.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Check if the correct number of arguments is passed +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +user=$1 + +# Get the list of sub-users by calling the user_list_subu_home.sh script +subu_list=$(./user_list_subu_homedir.sh "$user") + +# Check if we received any sub-users +if [ -z "$subu_list" ]; then + echo "No sub-users found for $user." + exit 1 +fi + +# Loop through the sub-users and call user_open_subu.sh for each +for subu in $subu_list; do + echo "Opening sub-user: $subu" + ./masu_subu__map_own.sh "$user" "$subu" +done diff --git a/developer/source/mount/masu__subu_data_dir_list.sh b/developer/source/mount/masu__subu_data_dir_list.sh new file mode 100755 index 0000000..5c7e405 --- /dev/null +++ b/developer/source/mount/masu__subu_data_dir_list.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Function to list sub-users in /home//subu_data +subu_home_dir_list() { + local user=$1 + local subu_home_dir="/home/$user/subu_data" + + if [ ! -d "/home/$user" ]; then + echo "Error: /home/$user does not exist!" + return 1 + fi + + if [ ! -d "$subu_home_dir" ]; then + echo "Error: $subu_home_dir does not exist!" + return 1 + fi + + # List all sub-users in the subu directory + find "$subu_home_dir" -maxdepth 1 -mindepth 1 -type d -exec basename {} \; +} + +# Run the function with the user as an argument +subu_home_dir_list "$1" diff --git a/developer/source/mount/masu__subu_dir_llst.sh b/developer/source/mount/masu__subu_dir_llst.sh new file mode 100755 index 0000000..6b24a53 --- /dev/null +++ b/developer/source/mount/masu__subu_dir_llst.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Function to list sub-users in /home//subu +subu_list() { + local user=$1 + local subu_dir="/home/$user/subu" + + if [ ! -d "/home/$user" ]; then + echo "Error: /home/$user does not exist!" + return 1 + fi + + if [ ! -d "$subu_dir" ]; then + echo "Error: $subu_dir does not exist!" + return 1 + fi + + # List all sub-users in the subu directory + find "$subu_dir" -maxdepth 1 -mindepth 1 -type d -exec basename {} \; +} + +# Run the function with the user as an argument +subu_list "$1" diff --git a/developer/source/mount/masu__to_home.sh b/developer/source/mount/masu__to_home.sh new file mode 100755 index 0000000..e708f8e --- /dev/null +++ b/developer/source/mount/masu__to_home.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Function to bind mount a user's data to /home/ +device_user_bind() { + local device=$1 + local user=$2 + local user_data_dir="/mnt/$device/user_data/$user" + local home_dir="/home/$user" + + if [ ! -d "$user_data_dir" ]; then + echo "Error: $user_data_dir does not exist!" + return 1 + fi + + # Create the home directory if it doesn't exist + mkdir -p "$home_dir" + + # Mount --bind the user data to the home directory + sudo mount --bind "$user_data_dir" "$home_dir" + echo "Mounted $user_data_dir -> $home_dir" +} + +# Run the function with the device name and user as arguments +device_user_bind "$1" "$2" diff --git a/developer/source/mount/masu_subu__map_own.sh b/developer/source/mount/masu_subu__map_own.sh new file mode 100755 index 0000000..fa039a7 --- /dev/null +++ b/developer/source/mount/masu_subu__map_own.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# Function to bind mount with UID/GID mapping +subu_bind() { + local user=$1 + local subu=$2 + + # Check if bindfs is installed + if ! command -v bindfs &> /dev/null; then + echo "Error: bindfs is not installed!" + return 1 + fi + + # Get the username and group name for the main user + master_user_name=$user + master_group=$user + + # Get the username and group name for the sub-user + subu_user_name="${user}-${subu}" + subu_group="${user}-${subu}" + + # Check if the user and sub-user exist + if ! id "$master_user_name" &>/dev/null; then + echo "Error: User '$master_user_name' not found!" + return 1 + fi + if ! id "$subu_user_name" &>/dev/null; then + echo "Error: Sub-user '${master_user_name}-${subu}' not found!" + return 1 + fi + + # Directories to be bind-mounted + subu_data_path="/home/$user/subu_data/$subu" + subu_mount_point_path="/home/$user/subu/$subu" + + # Check if sub-user directory exists + if [ ! -d "$subu_data_path" ]; then + echo "Error: Sub-user directory '$subu_data_path' does not exist!" + return 1 + fi + + # Create the mount point if it doesn't exist + mkdir -p "$subu_mount_point_path" + + # Perform the bind mount using bindfs with UID/GID mapping + sudo bindfs\ + --map="$subu_user_name/$master_user_name:@$subu_group/@$master_group" \ + "$subu_data_path" \ + "$subu_mount_point_path" + + # Verify if the mount was successful + if [ $? -eq 0 ]; then + echo "Successfully bind-mounted $subu_data_path to $subu_mount_point_path with UID/GID mapping." + else + echo "Error: Failed to bind-mount $subu_data_path to $subu_mount_point_path, might already exist." + fi +} + +# Call the function with user and subu as arguments +subu_bind "$1" "$2" diff --git a/developer/source/mount/masu_subu__uid.sh b/developer/source/mount/masu_subu__uid.sh new file mode 100755 index 0000000..fcb7175 --- /dev/null +++ b/developer/source/mount/masu_subu__uid.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Function to lookup the UID of the user and sub-user combination +get_subu_uid() { + local user=$1 + local subu=$2 + + # Concatenate user and sub-user name (no space around the = sign) + local subu_user="${user}-${subu}" + + # Lookup the UID for the sub-user (user-subuser) combination + subu_uid=$(id -u "$subu_user" 2>/dev/null) + + # If found, return only the UID, otherwise return nothing + if [ -n "$subu_uid" ]; then + echo "$subu_uid" + fi +} + +# Call the function with user and subu as arguments +get_subu_uid "$1" "$2" diff --git a/developer/source/mount/mount_pt_list.sh b/developer/source/mount/mount_pt_list.sh new file mode 100755 index 0000000..79f261b --- /dev/null +++ b/developer/source/mount/mount_pt_list.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Function to list available devices under /mnt, excluding /mnt itself +mount_pt_list() { + # List all directories in /mnt that are potentially available for mounting + find /mnt -mindepth 1 -maxdepth 1 -type d -exec basename {} \; +} + +# Call the function to display available devices +mount_pt_list diff --git a/developer/sqlite/schema.sql b/developer/sqlite/schema.sql deleted file mode 100644 index faf7053..0000000 --- a/developer/sqlite/schema.sql +++ /dev/null @@ -1,79 +0,0 @@ --- Schema for the subu server --- - --- List Tables --- SQLite does not support PSQL style types --- --- CREATE TYPE List AS ( --- id SERIAL, -- Integer ID --- name TEXT NOT NULL -- Name of the list entry --- ); --- --- so though these all have the same `List` form, they are declared independently --- - CREATE TABLE db_property_list ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL UNIQUE - ); - - CREATE TABLE db_event_list ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL UNIQUE - ); - - CREATE TABLE shell_list ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL UNIQUE - ); - - CREATE TABLE system_resource_list ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL UNIQUE - ); - - CREATE TABLE user_type_list ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL UNIQUE - ); - --- Data Tables --- - CREATE TABLE db_property ( - id INTEGER PRIMARY KEY, - property_id INTEGER NOT NULL REFERENCES db_property_list(id), - type TEXT NOT NULL, - value TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP - ); - - CREATE TABLE db_event ( - id INTEGER PRIMARY KEY, - event_time DATETIME DEFAULT CURRENT_TIMESTAMP, - event_id INTEGER NOT NULL REFERENCES db_event_list(id), - user_id INTEGER REFERENCES user(id) - ); - - CREATE TABLE user ( - id INTEGER PRIMARY KEY, - login_gid INTEGER NOT NULL UNIQUE, - name TEXT NOT NULL UNIQUE, - home_directory TEXT NOT NULL, - shell INTEGER NOT NULL REFERENCES shell_list(id), - parent_id INTEGER REFERENCES user(id), - user_type_id INTEGER NOT NULL REFERENCES user_type_list(id), - status TEXT DEFAULT 'active' - ); - - CREATE TABLE share ( - id INTEGER PRIMARY KEY, - user_id INTEGER NOT NULL REFERENCES user(id), - other_user_id INTEGER NOT NULL REFERENCES user(id), - permissions TEXT NOT NULL - ); - - CREATE TABLE system_resource ( - id INTEGER PRIMARY KEY, - user_id INTEGER NOT NULL REFERENCES user(id), - resource_id INTEGER NOT NULL REFERENCES system_resource_list(id), - granted_by INTEGER REFERENCES user(id) - ); diff --git a/developer/subu b/developer/subu deleted file mode 100755 index 979c638..0000000 --- a/developer/subu +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/env /bin/bash -# set -x - -subu="$1" -if [ -z "$subu" ]; then - echo "No subuser name supplied" - exit 1 -fi -subu_user="Thomas-$subu" - -# share the X display -# - export DISPLAY=:0 - export XAUTHORITY=${XAUTHORITY:-$(ls -1 /run/user/$(id -u)/.mutter-Xwaylandauth.* 2>/dev/null | head -n 1)} - if [ -z "$XAUTHORITY" ]; then - export XAUTHORITY="$HOME/.Xauthority" - fi - xauth -f "$XAUTHORITY" generate "$DISPLAY" . trusted - xauth extract - "$DISPLAY" | sudo -u "$subu_user" \ - XAUTHORITY="/home/$subu_user/.Xauthority" \ - xauth merge - - -# Login the subu -# - sudo loginctl enable-linger "$subu_user" - sudo machinectl shell "$subu_user"@ /bin/bash -c " - export DISPLAY=:0; - export XAUTHORITY=/home/$subu_user/.Xauthority; - bash -i - " -