From 5659f2a538bc87f00b903514533a0eb2fa8b368e Mon Sep 17 00:00:00 2001 From: robcholz <84130577+robcholz@users.noreply.github.com> Date: Sun, 8 Feb 2026 02:25:12 -0500 Subject: [PATCH] fix: now project dir correctly mounted --- src/explain.rs | 2 +- src/instance.rs | 2 ++ src/ssh.sh | 18 +++++++++++++++++- src/vm.rs | 13 +++---------- src/vm_manager.rs | 35 ++++++++++++++++++++++++++++++++--- 5 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/explain.rs b/src/explain.rs index 7a6e1e8..519e325 100644 --- a/src/explain.rs +++ b/src/explain.rs @@ -46,7 +46,7 @@ fn default_mounts(cwd: &Path) -> Result, Box bool { pub(crate) fn build_ssh_login_actions( config: &Arc>, project_name: &str, + project_guest_dir: &str, guest_dir: &str, key_name: &str, home_links_script: &str, @@ -409,6 +410,7 @@ pub(crate) fn build_ssh_login_actions( .replace("__SSH_USER__", &ssh_user) .replace("__SUDO_PASSWORD__", &sudo_password) .replace("__PROJECT_NAME__", project_name) + .replace("__PROJECT_GUEST_DIR__", project_guest_dir) .replace("__KEY_PATH__", &key_path) .replace("__VIBEBOX_SHELL_SCRIPT__", &commands::render_shell_script()) .replace("__VIBEBOX_HOME_LINKS__", home_links_script); diff --git a/src/ssh.sh b/src/ssh.sh index 7f3e57e..75773a3 100644 --- a/src/ssh.sh +++ b/src/ssh.sh @@ -3,6 +3,7 @@ set -eu SSH_USER="__SSH_USER__" PROJECT_NAME="__PROJECT_NAME__" +PROJECT_GUEST_DIR="__PROJECT_GUEST_DIR__" KEY_PATH="__KEY_PATH__" diag() { echo "[vibebox][diag] $*" >&2; } @@ -49,7 +50,7 @@ dump_diag() { } # 1) tmpfs mount -TARGET="/root/${PROJECT_NAME}/.vibebox" +TARGET="${PROJECT_GUEST_DIR}/.vibebox" if [ -d "$TARGET" ] && ! mountpoint -q "$TARGET"; then mount -t tmpfs tmpfs "$TARGET" fi @@ -78,6 +79,21 @@ __VIBEBOX_SHELL_SCRIPT__ VIBEBOX_SHELL_EOF chmod 644 /etc/profile.d/vibebox.sh +# Auto-cd into project for interactive shells +cat > /etc/profile.d/vibebox-project.sh <<'VIBEBOX_PROJECT_EOF' +case "$-" in + *i*) + project_home="${HOME}/__PROJECT_NAME__" + if [ "$USER" = "__SSH_USER__" ] && [ -d "$project_home" ]; then + cd "$project_home" + elif [ "$USER" = "__SSH_USER__" ] && [ -d "__PROJECT_GUEST_DIR__" ]; then + cd "__PROJECT_GUEST_DIR__" + fi + ;; +esac +VIBEBOX_PROJECT_EOF +chmod 644 /etc/profile.d/vibebox-project.sh + if ! grep -q "vibebox-aliases" "${USER_HOME}/.bashrc" 2>/dev/null; then { echo "" diff --git a/src/vm.rs b/src/vm.rs index bbade9d..21d5324 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -32,6 +32,7 @@ const DEBIAN_COMPRESSED_DISK_URL: &str = "https://cloud.debian.org/images/cloud/ const DEBIAN_COMPRESSED_SHA: &str = "6ab9be9e6834adc975268367f2f0235251671184345c34ee13031749fdfbf66fe4c3aafd949a2d98550426090e9ac645e79009c51eb0eefc984c15786570bb38"; const DEBIAN_COMPRESSED_SIZE_BYTES: u64 = 280901576; const SHARED_DIRECTORIES_TAG: &str = "shared"; +pub const PROJECT_GUEST_BASE: &str = "/usr/local/vibebox-mounts"; const BYTES_PER_MB: u64 = 1024 * 1024; const DEFAULT_CPU_COUNT: usize = 2; @@ -247,7 +248,8 @@ where let mut directory_shares = Vec::new(); if !args.no_default_mounts { - login_actions.push(Send(format!("cd {project_name}"))); + let project_guest_dir = PathBuf::from(PROJECT_GUEST_BASE).join(project_name); + login_actions.push(Send(format!("cd {}", project_guest_dir.display()))); // discourage read/write of .git folder from within the VM. note that this isn't secure, since the VM runs as root and could unmount this. // I couldn't find an alternative way to do this --- the MacOS sandbox doesn't apply to the Apple Virtualization system @@ -255,15 +257,6 @@ where login_actions.push(Send(r"mount -t tmpfs tmpfs .git/".into())); } - directory_shares.push( - DirectoryShare::new( - project_root, - PathBuf::from("/root/").join(project_name), - false, - ) - .expect("Project directory must exist"), - ); - directory_shares.push(mise_directory_share); } diff --git a/src/vm_manager.rs b/src/vm_manager.rs index 2e6fadd..992cc1f 100644 --- a/src/vm_manager.rs +++ b/src/vm_manager.rs @@ -25,7 +25,7 @@ use crate::{ session_manager::{ GLOBAL_DIR_NAME, INSTANCE_FILENAME, VM_MANAGER_PID_NAME, VM_MANAGER_SOCKET_NAME, }, - vm::{self, DirectoryShare, LoginAction, VmInput}, + vm::{self, DirectoryShare, LoginAction, PROJECT_GUEST_BASE, VmInput}, }; const VM_MANAGER_LOCK_NAME: &str = "vm.lock"; @@ -200,6 +200,30 @@ fn cleanup_stale_manager(instance_dir: &Path) { let _ = fs::remove_file(&pid_path); } +fn inject_project_mount( + mounts: &mut Vec, + project_root: &Path, + ssh_user: &str, + project_name: &str, +) { + let guest_tilde = format!("~/{project_name}"); + let guest_home = format!("/home/{ssh_user}/{project_name}"); + let guest_base = format!("{PROJECT_GUEST_BASE}/{project_name}"); + let already_mapped = mounts.iter().any(|spec| { + let parts: Vec<&str> = spec.split(':').collect(); + if parts.len() < 2 { + return false; + } + let guest = parts[1]; + guest == guest_tilde || guest == guest_home || guest == guest_base + }); + if already_mapped { + return; + } + let host = project_root.display(); + mounts.insert(0, format!("{host}:{guest_tilde}:read-write")); +} + fn is_socket_path(path: &Path) -> bool { fs::metadata(path) .map(|meta| meta.file_type().is_socket()) @@ -252,7 +276,7 @@ fn rewrite_mount_spec(spec: &str, ssh_user: &str) -> (String, Option) return (spec.to_string(), None); } - let root_base = "/usr/local/vibebox-mounts"; + let root_base = PROJECT_GUEST_BASE; let root_path = if rel.is_empty() { root_base.to_string() } else { @@ -563,7 +587,7 @@ impl VmExecutor for RealVmExecutor { fn run_manager_with( project_root: &Path, - args: vm::VmArg, + mut args: vm::VmArg, auto_shutdown_ms: u64, executor: &dyn VmExecutor, options: ManagerOptions, @@ -602,8 +626,12 @@ fn run_manager_with( .lock() .map(|cfg| cfg.ssh_user_display()) .unwrap_or_else(|_| DEFAULT_SSH_USER.to_string()); + if !args.no_default_mounts { + inject_project_mount(&mut args.mounts, project_root, &ssh_user, &project_name); + } let (args, home_links_script) = prepare_mounts_and_links(args, &ssh_user); + let project_guest_dir = format!("{PROJECT_GUEST_BASE}/{project_name}"); let ssh_guest_dir = format!("/root/{}", GLOBAL_DIR_NAME); let extra_shares = vec![DirectoryShare::new( instance_dir.clone(), @@ -613,6 +641,7 @@ fn run_manager_with( let extra_login_actions = build_ssh_login_actions( &config, &project_name, + &project_guest_dir, ssh_guest_dir.as_str(), "ssh_key", &home_links_script,