on main help sign in
feat: removed rust and rename to vibebox
197207drobcholz
docs/tasks.md+2−2
@@ -36,6 +36,6 @@
36## Integration
36## Integration
37
37
381. [x] Wire up the vm and tui.
381. [x] Wire up the vm and tui.
39−2. [ ] Use ssh to connect to vm.
39+2. [x] Use ssh to connect to vm.
403. [ ] wire up SessionManager.
403. [ ] wire up SessionManager.
41−4. [ ] VM should be separated by per-session VM daemon process (only accepts if to shutdown vm and itself).
41+4. [ ] VM should be separated by a per-session VM daemon process (only accepts if to shut down vm and itself).
src/instance.rs+21−30
@@ -1,12 +1,8 @@
1use std::{
1use std::{
2− env,
2+ env, fs,
3− fs,
4 io::{self, Write},
3 io::{self, Write},
5 net::{SocketAddr, TcpStream},
4 net::{SocketAddr, TcpStream},
6− os::unix::{
7− fs::PermissionsExt,
5+ os::unix::{fs::PermissionsExt, io::OwnedFd},
8− io::OwnedFd,
9− },
10 path::{Path, PathBuf},
6 path::{Path, PathBuf},
11 process::{Command, Stdio},
7 process::{Command, Stdio},
12 sync::{
8 sync::{
@@ -17,8 +13,8 @@ use std::{
17};
13};
18
14
19use serde::{Deserialize, Serialize};
15use serde::{Deserialize, Serialize};
20−use uuid::Uuid;
21use std::sync::mpsc::Sender;
16use std::sync::mpsc::Sender;
17+use uuid::Uuid;
22
18
23use crate::{
19use crate::{
24 session_manager::INSTANCE_DIR_NAME,
20 session_manager::INSTANCE_DIR_NAME,
@@ -30,7 +26,7 @@ const INSTANCE_TOML: &str = "instance.toml";
30const SSH_KEY_NAME: &str = "ssh_key";
26const SSH_KEY_NAME: &str = "ssh_key";
31const SERIAL_LOG_NAME: &str = "serial.log";
27const SERIAL_LOG_NAME: &str = "serial.log";
32const SSH_GUEST_DIR: &str = "/root/.vibebox";
28const SSH_GUEST_DIR: &str = "/root/.vibebox";
33−const DEFAULT_SSH_USER: &str = "vibebox";
29+const DEFAULT_SSH_USER: &str = "vibecoder";
34const SSH_CONNECT_RETRIES: usize = 30;
30const SSH_CONNECT_RETRIES: usize = 30;
35const SSH_CONNECT_DELAY_MS: u64 = 500;
31const SSH_CONNECT_DELAY_MS: u64 = 500;
36const SSH_SETUP_SCRIPT: &str = include_str!("ssh.sh");
32const SSH_SETUP_SCRIPT: &str = include_str!("ssh.sh");
@@ -76,12 +72,8 @@ pub fn run_with_ssh(
76 true,
72 true,
77 )?];
73 )?];
78
74
79− let extra_login_actions = build_ssh_login_actions(
75+ let extra_login_actions =
80− &config,
76+ build_ssh_login_actions(&config, &project_name, SSH_GUEST_DIR, SSH_KEY_NAME);
81− &project_name,
82− SSH_GUEST_DIR,
83− SSH_KEY_NAME,
84− );
85
77
86 vm::run_with_args_and_extras(
78 vm::run_with_args_and_extras(
87 args,
79 args,
@@ -107,7 +99,9 @@ fn ensure_instance_dir(project_root: &Path) -> Result<PathBuf, io::Error> {
107 Ok(instance_dir)
99 Ok(instance_dir)
108}
100}
109
101
102+fn ensure_ssh_keypair(
103+ instance_dir: &Path,
110−fn ensure_ssh_keypair(instance_dir: &Path) -> Result<(PathBuf, PathBuf), Box<dyn std::error::Error>> {
104+) -> Result<(PathBuf, PathBuf), Box<dyn std::error::Error>> {
111 let private_key = instance_dir.join(SSH_KEY_NAME);
105 let private_key = instance_dir.join(SSH_KEY_NAME);
112 let public_key = instance_dir.join(format!("{SSH_KEY_NAME}.pub"));
106 let public_key = instance_dir.join(format!("{SSH_KEY_NAME}.pub"));
113
107
@@ -129,12 +123,13 @@ fn ensure_ssh_keypair(instance_dir: &Path) -> Result<(PathBuf, PathBuf), Box<dyn
129 "-N",
123 "-N",
130 "",
124 "",
131 "-f",
125 "-f",
132− private_key
133− .to_str()
134− .ok_or("ssh key path not utf-8")?,
126+ private_key.to_str().ok_or("ssh key path not utf-8")?,
135 "-C",
127 "-C",
136 "vibebox",
128 "vibebox",
137 ])
129 ])
130+ .stdin(Stdio::null())
131+ .stdout(Stdio::null())
132+ .stderr(Stdio::inherit())
138 .status()?;
133 .status()?;
139
134
140 if !status.success() {
135 if !status.success() {
@@ -283,8 +278,7 @@ fn spawn_ssh_io(
283 let ssh_connected = Arc::new(AtomicBool::new(false));
278 let ssh_connected = Arc::new(AtomicBool::new(false));
284 let ssh_started = Arc::new(AtomicBool::new(false));
279 let ssh_started = Arc::new(AtomicBool::new(false));
285 let ssh_ready = Arc::new(AtomicBool::new(false));
280 let ssh_ready = Arc::new(AtomicBool::new(false));
286− let input_tx_holder: Arc<Mutex<Option<Sender<VmInput>>>> =
281+ let input_tx_holder: Arc<Mutex<Option<Sender<VmInput>>>> = Arc::new(Mutex::new(None));
287− Arc::new(Mutex::new(None));
288
282
289 let instance_path = instance_dir.join(INSTANCE_TOML);
283 let instance_path = instance_dir.join(INSTANCE_TOML);
290 let config_for_output = config.clone();
284 let config_for_output = config.clone();
@@ -415,9 +409,7 @@ fn spawn_ssh_io(
415 );
409 );
416 break;
410 break;
417 }
411 }
418− thread::sleep(std::time::Duration::from_millis(
412+ thread::sleep(std::time::Duration::from_millis(SSH_CONNECT_DELAY_MS));
419− SSH_CONNECT_DELAY_MS,
420− ));
421 continue;
413 continue;
422 }
414 }
423
415
@@ -427,9 +419,7 @@ fn spawn_ssh_io(
427 let status = Command::new("ssh")
419 let status = Command::new("ssh")
428 .args([
420 .args([
429 "-i",
421 "-i",
430− ssh_key_for_thread
431− .to_str()
432− .unwrap_or(".vibebox/ssh_key"),
422+ ssh_key_for_thread.to_str().unwrap_or(".vibebox/ssh_key"),
433 "-o",
423 "-o",
434 "IdentitiesOnly=yes",
424 "IdentitiesOnly=yes",
435 "-o",
425 "-o",
@@ -447,6 +437,9 @@ fn spawn_ssh_io(
447 "-o",
437 "-o",
448 "ConnectTimeout=5",
438 "ConnectTimeout=5",
449 ])
439 ])
440+ .env_remove("LC_CTYPE")
441+ .env_remove("LC_ALL")
442+ // .env_remove("LANG")
450 .arg(format!("{ssh_user}@{ip}"))
443 .arg(format!("{ssh_user}@{ip}"))
451 .stdin(Stdio::inherit())
444 .stdin(Stdio::inherit())
452 .stdout(Stdio::inherit())
445 .stdout(Stdio::inherit())
@@ -458,8 +451,7 @@ fn spawn_ssh_io(
458 ssh_connected_for_thread.store(false, Ordering::SeqCst);
451 ssh_connected_for_thread.store(false, Ordering::SeqCst);
459 eprintln!("[vibebox] ssh exited with status: {status}");
452 eprintln!("[vibebox] ssh exited with status: {status}");
460 if let Some(tx) = input_tx_holder_for_thread.lock().unwrap().clone() {
453 if let Some(tx) = input_tx_holder_for_thread.lock().unwrap().clone() {
461− let _ =
462− tx.send(VmInput::Bytes(b"systemctl poweroff\n".to_vec()));
454+ let _ = tx.send(VmInput::Bytes(b"systemctl poweroff\n".to_vec()));
463 }
455 }
464 break;
456 break;
465 }
457 }
@@ -479,8 +471,7 @@ fn spawn_ssh_io(
479 ssh_connected_for_thread.store(false, Ordering::SeqCst);
471 ssh_connected_for_thread.store(false, Ordering::SeqCst);
480 eprintln!("[vibebox] ssh exited with status: {status}");
472 eprintln!("[vibebox] ssh exited with status: {status}");
481 if let Some(tx) = input_tx_holder_for_thread.lock().unwrap().clone() {
473 if let Some(tx) = input_tx_holder_for_thread.lock().unwrap().clone() {
482− let _ =
483− tx.send(VmInput::Bytes(b"systemctl poweroff\n".to_vec()));
474+ let _ = tx.send(VmInput::Bytes(b"systemctl poweroff\n".to_vec()));
484 }
475 }
485 break;
476 break;
486 }
477 }
src/lib.rs+1−1
@@ -1,6 +1,6 @@
1+pub mod instance;
1pub mod session_manager;
2pub mod session_manager;
2pub mod tui;
3pub mod tui;
3pub mod vm;
4pub mod vm;
4−pub mod instance;
5
5
6pub use session_manager::{SessionError, SessionManager, SessionRecord};
6pub use session_manager::{SessionError, SessionManager, SessionRecord};
src/provision.sh+2−13
@@ -15,16 +15,10 @@ apt-get install -y --no-install-recommends \
15 git \
15 git \
16 ripgrep \
16 ripgrep \
17 openssh-server \
17 openssh-server \
18− locales \
19 sudo
18 sudo
20
19
21−# Set hostname to "vibe" so it's clear that you're inside the VM.
20+# Set hostname to "vibebox" so it's clear that you're inside the VM.
22−hostnamectl set-hostname vibe
21+hostnamectl set-hostname vibebox
23−
24−# Locale (fix: setlocale: LC_CTYPE ... UTF-8)
25−sed -i 's/^# *en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen
26−locale-gen
27−update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
28
22
29# SSH: host keys + base config (doesn't depend on runtime user)
23# SSH: host keys + base config (doesn't depend on runtime user)
30ssh-keygen -A
24ssh-keygen -A
@@ -54,11 +48,6 @@ systemctl poweroff
54sleep 100 # sleep here so that we don't see the login screen flash up before the shutdown.
48sleep 100 # sleep here so that we don't see the login screen flash up before the shutdown.
55EOF
49EOF
56
50
57−
58−# Install Rust
59−curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal --component "rustfmt,clippy"
60−
61−
62# Install Mise
51# Install Mise
63curl https://mise.run | sh
52curl https://mise.run | sh
64echo 'eval "$(~/.local/bin/mise activate bash)"' >> .bashrc
53echo 'eval "$(~/.local/bin/mise activate bash)"' >> .bashrc
src/vm.rs+2−8
@@ -795,12 +795,7 @@ where
795 continue;
795 continue;
796 }
796 }
797
797
798− match poll_with_wakeup(
798+ match poll_with_wakeup(libc::STDIN_FILENO, wakeup_read.as_raw_fd(), &mut buf, -1) {
799− libc::STDIN_FILENO,
800− wakeup_read.as_raw_fd(),
801− &mut buf,
802− -1,
803− ) {
804 PollResult::Shutdown | PollResult::Error => break,
799 PollResult::Shutdown | PollResult::Error => break,
805 PollResult::Spurious => continue,
800 PollResult::Spurious => continue,
806 PollResult::Ready(bytes) => {
801 PollResult::Ready(bytes) => {
@@ -858,8 +853,7 @@ where
858 wakeup_read.as_raw_fd(),
853 wakeup_read.as_raw_fd(),
859 &mut buf,
854 &mut buf,
860 100,
855 100,
861− )
856+ ) {
862− {
863 PollResult::Shutdown | PollResult::Error => break,
857 PollResult::Shutdown | PollResult::Error => break,
864 PollResult::Spurious => continue,
858 PollResult::Spurious => continue,
865 PollResult::Ready(bytes) => {
859 PollResult::Ready(bytes) => {