From 445f3515836ae9f35f7158b14d86424e96d08b00 Mon Sep 17 00:00:00 2001 From: windweller Date: Wed, 19 Nov 2025 17:54:43 -0500 Subject: [PATCH 1/4] adding a modal environment for dev (with support on filesync/vscode/TCP port and jupyter notebook). --- dev_deployment/README.md | 5 ++ dev_deployment/trace_dev_modal_image.py | 65 +++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 dev_deployment/README.md create mode 100644 dev_deployment/trace_dev_modal_image.py diff --git a/dev_deployment/README.md b/dev_deployment/README.md new file mode 100644 index 00000000..2255c0df --- /dev/null +++ b/dev_deployment/README.md @@ -0,0 +1,5 @@ +# Starting a Dev Environment on Modal + +``` +modal run trace_dev_modal_image.py +``` \ No newline at end of file diff --git a/dev_deployment/trace_dev_modal_image.py b/dev_deployment/trace_dev_modal_image.py new file mode 100644 index 00000000..868d7602 --- /dev/null +++ b/dev_deployment/trace_dev_modal_image.py @@ -0,0 +1,65 @@ +""" +This sets up a Modal container that runs a Jupyter Lab. +It will: +1. Expose a tunnel for ssh and for jupyter (with public URL link) +2. Attach a persistent volume (for data storage). +""" + +import os +import secrets +import subprocess +from pathlib import Path + +import modal + +# Run this command: `modal volume create trace-dev` +volume = modal.Volume.from_name("trace-dev") + +ssh_key_path = Path.home() / ".ssh" / "id_rsa_modal.pub" + +image = ( + modal.Image.debian_slim() + .pip_install("jupyter") + .apt_install("openssh-server") + .run_commands("mkdir /run/sshd") + .add_local_file(str(ssh_key_path), "/root/.ssh/authorized_keys", copy=True) +) +app = modal.App("Trace-dev-jupyter", image=image) + +@app.function(volumes={"/vol/trace-dev-home/": volume}, timeout=3600) +def run_jupyter(): + + # a nested setup to start SSH connection and Jupyter + + subprocess.Popen(["/usr/sbin/sshd", "-D", "-e"]) + + with modal.forward(port=22, unencrypted=True) as ssh_tunnel: + hostname, port = ssh_tunnel.tcp_socket + connection_cmd = f'ssh -p {port} root@{hostname}' + print("Run `ssh-add ~/.ssh/id_rsa_modal` to add SSH key credential") + print(f"ssh into container using: {connection_cmd}") + + token = secrets.token_urlsafe(13) + + with modal.forward(8888) as tunnel: + url = tunnel.url + "/?token=" + token + print(f"Starting Jupyter at {url}") + subprocess.run( + [ + "jupyter", + "notebook", + "--no-browser", + "--allow-root", + "--ip=0.0.0.0", + "--port=8888", + "--LabApp.allow_origin='*'", + "--LabApp.allow_remote_access=1", + ], + env={**os.environ, "JUPYTER_TOKEN": token, "SHELL": "/bin/bash"}, + stderr=subprocess.DEVNULL, + ) + +@app.local_entrypoint() +def main(): + # Server() + run_jupyter.remote() From eabaa26898d061165e91413017b6ac6ba3859cf4 Mon Sep 17 00:00:00 2001 From: windweller Date: Wed, 19 Nov 2025 18:22:01 -0500 Subject: [PATCH 2/4] improve some usability --- dev_deployment/README.md | 12 +++++++++++- dev_deployment/trace_dev_modal_image.py | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/dev_deployment/README.md b/dev_deployment/README.md index 2255c0df..14cedc9e 100644 --- a/dev_deployment/README.md +++ b/dev_deployment/README.md @@ -1,5 +1,15 @@ # Starting a Dev Environment on Modal +Run it as a blocking command: + ``` modal run trace_dev_modal_image.py -``` \ No newline at end of file +``` + +Run it detached (might need to shut down app through the Modal interface): + +``` +modal run --detach trace_dev_modal_image.py +``` + +Or simply run it in a screen or tmux session. \ No newline at end of file diff --git a/dev_deployment/trace_dev_modal_image.py b/dev_deployment/trace_dev_modal_image.py index 868d7602..f1efbcb5 100644 --- a/dev_deployment/trace_dev_modal_image.py +++ b/dev_deployment/trace_dev_modal_image.py @@ -2,7 +2,11 @@ This sets up a Modal container that runs a Jupyter Lab. It will: 1. Expose a tunnel for ssh and for jupyter (with public URL link) -2. Attach a persistent volume (for data storage). +2. Add Trace repo code into the container and include it in the PYTHONPATH +3. Attach a persistent volume (for data storage). + +The code lives in the ephemeral space, but any results should be saved in the persistent volume, +mounted under `/vol/trace-dev-home/`. """ import os @@ -12,21 +16,29 @@ import modal +MINUTES = 60 # seconds +HOURS = 60 * MINUTES + # Run this command: `modal volume create trace-dev` volume = modal.Volume.from_name("trace-dev") ssh_key_path = Path.home() / ".ssh" / "id_rsa_modal.pub" +project_root = Path(__file__).parent.parent image = ( modal.Image.debian_slim() .pip_install("jupyter") .apt_install("openssh-server") + .env({ + "PYTHONPATH": "/root/Trace" # add KernelBench to python path + }) .run_commands("mkdir /run/sshd") .add_local_file(str(ssh_key_path), "/root/.ssh/authorized_keys", copy=True) + .add_local_dir(str(project_root), "/root/Trace", copy=True) ) app = modal.App("Trace-dev-jupyter", image=image) -@app.function(volumes={"/vol/trace-dev-home/": volume}, timeout=3600) +@app.function(volumes={"/vol/trace-dev-home/": volume}, timeout=24 * HOURS) def run_jupyter(): # a nested setup to start SSH connection and Jupyter @@ -61,5 +73,5 @@ def run_jupyter(): @app.local_entrypoint() def main(): - # Server() + subprocess.run(["ssh-add", "~/.ssh/id_rsa_modal"]) run_jupyter.remote() From 786029307a0726da143aa2710e700eba66961eb7 Mon Sep 17 00:00:00 2001 From: windweller Date: Thu, 20 Nov 2025 14:59:21 -0500 Subject: [PATCH 3/4] modified to upload current state of files locally to remote as well --- dev_deployment/trace_dev_modal_image.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev_deployment/trace_dev_modal_image.py b/dev_deployment/trace_dev_modal_image.py index f1efbcb5..ac5b1d55 100644 --- a/dev_deployment/trace_dev_modal_image.py +++ b/dev_deployment/trace_dev_modal_image.py @@ -34,7 +34,8 @@ }) .run_commands("mkdir /run/sshd") .add_local_file(str(ssh_key_path), "/root/.ssh/authorized_keys", copy=True) - .add_local_dir(str(project_root), "/root/Trace", copy=True) + .add_local_dir(str(project_root / "opto"), "/root/Trace/opto", copy=True) + .add_local_dir(str(project_root / "tests"), "/root/Trace/tests", copy=True) ) app = modal.App("Trace-dev-jupyter", image=image) From e607628e251f3a8c502537bb7be223448dfd8346 Mon Sep 17 00:00:00 2001 From: windweller Date: Thu, 20 Nov 2025 15:53:29 -0500 Subject: [PATCH 4/4] finalized the deployment command --- dev_deployment/trace_dev_modal_image.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dev_deployment/trace_dev_modal_image.py b/dev_deployment/trace_dev_modal_image.py index ac5b1d55..20d92e3d 100644 --- a/dev_deployment/trace_dev_modal_image.py +++ b/dev_deployment/trace_dev_modal_image.py @@ -27,13 +27,16 @@ image = ( modal.Image.debian_slim() - .pip_install("jupyter") + .pip_install("jupyter", "graphviz") .apt_install("openssh-server") .env({ "PYTHONPATH": "/root/Trace" # add KernelBench to python path }) .run_commands("mkdir /run/sshd") .add_local_file(str(ssh_key_path), "/root/.ssh/authorized_keys", copy=True) + .add_local_file(str(project_root / "setup.py"), "/root/Trace/setup.py", copy=True) + .add_local_file(str(project_root / "pyproject.toml"), "/root/Trace/pyproject.toml", copy=True) + .add_local_file(str(project_root / "README.md"), "/root/Trace/README.md", copy=True) .add_local_dir(str(project_root / "opto"), "/root/Trace/opto", copy=True) .add_local_dir(str(project_root / "tests"), "/root/Trace/tests", copy=True) ) @@ -42,6 +45,9 @@ @app.function(volumes={"/vol/trace-dev-home/": volume}, timeout=24 * HOURS) def run_jupyter(): + # set up Trace env + subprocess.run(["pip", "install", "-e", "/root/Trace"]) + # a nested setup to start SSH connection and Jupyter subprocess.Popen(["/usr/sbin/sshd", "-D", "-e"]) @@ -56,7 +62,7 @@ def run_jupyter(): with modal.forward(8888) as tunnel: url = tunnel.url + "/?token=" + token - print(f"Starting Jupyter at {url}") + print(f"\033[91mStarting Jupyter at {url}\033[0m") subprocess.run( [ "jupyter",