Setup a development environment with SSH access to GitHub and optional reverse tunneling for direct terminal access. This environment is suitable for training AI models and general development work.
- Working access to the BUas Coder.ai environment
- Authenticate with your student GitHub account
- Request a password from your instructor
- A working and active connection to the BUas VPN for off-campus access
- Setup scripts (download these to your local machine first):
setup.sh: Initial environment configurationstartup.sh: Post-restart restoration scriptpackages.txt: System packages to install (optional - edit as needed)
Note: You must have an active BUas VPN connection or be connected to the BUas network.
From the Coder.ai landing page:
- Click on "Workspaces"
- Choose: New Workspace > Student Dev Environment
- Enter a workspace name (e.g., "Block-2a-dev")
- Leave other settings unchanged
- Click "Create workspace"
- Wait for the workspace to build
Once created, select the appropriate image for your project and ensure it shows "Running" status.
- From the workspace page, click "Jupyter Notebook" to launch the file manager
- Navigate to your home directory (typically
/home/<your year & block>/) - Click "Upload" and select the downloaded scripts:
setup.shstartup.shpackages.txt(optional)
- Close the file manager when complete
- From the workspace page, click "Terminal" to launch a bash shell
- Verify you're in your home directory:
pwd # Should show something like /home/y2b/ or /home/y3a/ cd /home/<your year & block>/
- Make scripts executable:
chmod +x setup.sh startup.sh
- Run the setup script:
./setup.sh
- When prompted, verify the directory path is correct and type
yto continue - Follow the on-screen instructions carefully
The setup script will generate an SSH key pair and prompt you to add the public key to GitHub.
SECURITY WARNING: NEVER add an SSH public key to your GitHub account unless you completely trust the source!
Adding an SSH public key to your GitHub account grants complete access to your repositories to whoever holds the private key. In this case, YOU hold the private key at /home/<your year & block>/ssh/id_ed25519.
NEVER share this private key file with anyone. EVER.
When prompted by the setup script:
- Copy the public key displayed (the entire line starting with
ssh-ed25519) - Visit https://github.com/settings/keys
- Click "New SSH key"
- Enter a title like "BUas Coder.ai Workspace"
- Paste the key in the "Key" field
- Click "Add SSH key"
- Return to the terminal and press Enter to continue
After adding your SSH key, you'll be prompted to enter a repository URL. You can find this on your GitHub project page:
- Go to your repository on GitHub
- Click "Code" > "Local" > "SSH"
- Copy the URL (format:
git@github.com:username/repo.git) - Paste it when prompted by the setup script
The repository will be cloned to your home directory.
The packages.txt file allows you to automatically install system packages every time your workspace starts. This is useful for installing tools and libraries that aren't included in the base image.
The file should contain one package name per line:
# This is a comment - lines starting with # are ignored
vim
htop
tmux
tree
Here are some commonly useful packages:
Text editors:
vim- Vi improved text editornano- Simple text editoremacs- Extensible text editor
System monitoring:
htop- Interactive process vieweriotop- I/O monitoringncdu- Disk usage analyzer
Development tools:
tmux- Terminal multiplexertree- Directory structure viewerjq- JSON processorcurl- Data transfer toolwget- File downloader
Build tools:
build-essential- Compilation tools (gcc, make, etc.)cmake- Cross-platform build systemgit-lfs- Git Large File Storage
When you run startup.sh after a workspace restart:
- The script checks if
packages.txtexists in your home directory - If found, it reads the file (skipping comments and empty lines)
- Checks if the apt package cache is older than 15 days
- Updates the cache if needed
- Installs all listed packages using
apt-get install
You can edit packages.txt at any time:
Via Jupyter file manager:
- Open Jupyter from the workspace page
- Navigate to your home directory
- Open
packages.txt(or create it if it doesn't exist) - Add one package name per line
- Save the file
Via terminal:
# Add a package to the file
echo "htop" >> /home/<your year & block>/packages.txt
# Edit the file directly
nano /home/<your year & block>/packages.txt- Package installation requires the apt cache to be updated, which can take time on first run
- Not all packages are available - if a package fails, check the name on https://packages.ubuntu.com
- Python packages should be installed via
pip, not throughpackages.txt - The workspace may already have many development tools pre-installed
When your workspace restarts (due to inactivity or maintenance), you'll need to restore your SSH configuration:
- Open a terminal from the workspace page
- Navigate to your home directory:
cd /home/<your year & block>/
- Run the startup script:
./startup.sh
- Verify the directory and type
yto continue
The startup script will:
- Restore your SSH keys from persistent storage
- Install any packages listed in
packages.txt - Test your GitHub connection
You can then continue working with git as normal.
You can connect to your coder.ai workspace directly from VSCode using the official Coder extension, enabling you to work with remote files, terminals, and most importantly, the remote Jupyter kernel for running notebooks.
- Open VSCode on your local machine
- Go to Extensions (Ctrl+Shift+X / Cmd+Shift+X)
- Search for "Coder"
- Install the official "Coder" extension by Coder
- Restart VSCode if prompted
- Click the Coder icon in the VSCode sidebar (or use Command Palette: "Coder: Open")
- Click "Add Workspace" or the "+" icon
- Enter your coder.ai URL:
http://coder.ai.buas.nl - Authenticate with your credentials
- Select your workspace from the list
- VSCode will connect and reload with a remote connection
You should now see your workspace files in the Explorer pane and can open terminals that run directly on your coder.ai instance.
The coder.ai workspace provides a Jupyter server that you can connect to from VSCode for running notebooks.
Make sure you have the Jupyter extension installed on the remote:
- With your VSCode connected to coder.ai, open Extensions (Ctrl+Shift+X / Cmd+Shift+X)
- Search for "Jupyter"
- Install the official "Jupyter" extension by Microsoft
- If you see "Install in SSH: [hostname]", click it to install on the remote
- Reload VSCode if prompted
Open a terminal in VSCode (it should be connected to your remote workspace) and run:
jupyter notebook list --jsonYou should see output like:
{"base_url": "/@245484/Y2B-20251120-v0p4.main/apps/jupyter/", "hostname": "0.0.0.0", "notebook_dir": "/home/y2b", "password": false, "pid": 271, "port": 8888, "secure": false, "sock": "", "token": "", "url": "http://0.0.0.0:8888/@245484/Y2B-20251120-v0p4.main/apps/jupyter/"}Note the url field - this is your Jupyter server URL. The server typically runs without a token (token is empty).
- Open Command Palette (Ctrl+Shift+P / Cmd+Shift+P)
- Type:
Jupyter: Specify Jupyter Server for Connections - Select "Existing: Specify the URI of an existing server"
- Enter the full URL from the previous step:
http://0.0.0.0:8888/@245484/Y2B-20251120-v0p4.main/apps/jupyter/- Replace the path after
/8888/with your actual base_url from the JSON output - No token is needed since the server runs without authentication
- Replace the path after
Now you can use Jupyter notebooks with the remote kernel:
- Open or create a
.ipynbfile in your workspace - Click "Select Kernel" in the top right of the notebook
- Choose "Existing Jupyter Server"
- Select the server you just configured
- Choose your desired Python environment (e.g., Python 3)
- Run a test cell to verify the connection:
import sys print(f"Running on: {sys.version}") print(f"Python path: {sys.executable}")
You should see output confirming you're running on the remote coder.ai environment.
If your workspace has GPU access, test it with:
import torch
print(f"CUDA available: {torch.cuda.is_available()}")
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")If you can't connect to the Jupyter server:
- Verify the server is running:
jupyter notebook list
- Check the exact URL format - it should include the full base_url path
- Try reconnecting VSCode to the workspace (disconnect and reconnect from the Coder sidebar)
If the kernel connects but won't start:
- Check for Python environment issues in the remote terminal:
python --version which python
- Try selecting a different kernel from the kernel picker
- Restart the Jupyter server (requires stopping it from the coder.ai web interface and starting it again)
If files don't appear after connecting:
- Ensure you've selected the correct workspace in the Coder extension
- Check you have proper file permissions in your workspace
- Try reloading the VSCode window (Command Palette → "Developer: Reload Window")
- Full IDE experience with IntelliSense, debugging, and extensions
- Native Jupyter notebook support with better editing than the web interface
- Integrated terminal for running commands alongside your code
- Git integration works seamlessly with your configured SSH keys
- Extension ecosystem - install VSCode extensions that run on the remote
- Local file editing of remote files without manual uploading
If git operations take a long time and ultimately fail:
- Run the startup script again to restore SSH configuration:
cd /home/<your year & block>/ ./startup.sh
- Test GitHub connectivity:
You should see: "Hi username! You've successfully authenticated..."
ssh -T git@github.com
If you can't authenticate with GitHub:
- Verify your public key is added to GitHub at https://github.com/settings/keys
- Check that your SSH keys exist in persistent storage:
ls -la /home/<your year & block>/ssh/
- Re-run startup.sh to restore keys to
~/.ssh/
Symptoms: Git operations fail with errors about dubious ownership or SSH refuses to use your keys due to permission issues.
Cause: After a workspace restart, file ownership in your SSH directory may no longer match your current user, or permissions may have been reset.
Solution:
The startup.sh script automatically fixes ownership and permissions, but if you encounter this error, you can manually fix it:
# Fix ownership (if running as root)
chown -R root:root /home/<your year & block>/ssh/
# Fix permissions
chmod 700 /home/<your year & block>/ssh/
chmod 600 /home/<your year & block>/ssh/id_ed25519
chmod 644 /home/<your year & block>/ssh/id_ed25519.pub
chmod 600 /home/<your year & block>/ssh/config
# Then re-run startup to copy with correct permissions
cd /home/<your year & block>/
./startup.shThis resets ownership for your current user and ensures proper permissions on all SSH files.
Thanks to Alex K for identifying this issue.
If packages fail to install:
- Check your
packages.txtfile for syntax errors (one package per line) - Verify you have sudo/root privileges
- Manually update apt cache:
sudo apt-get update
Symptoms: When connected via SSH tunnel, pip commands fail with "externally-managed-environment" error, but work fine in the coder.ai web terminal.
Cause: The coder.ai web terminal sets environment variables (like PIP_BREAK_SYSTEM_PACKAGES=1) that SSH sessions don't inherit by default.
Solution:
The ssh_setup.sh script creates a .coder_env file that sets these variables. Make sure:
- You've run
ssh_setup.shafter the most recent restart - Your
~/.bashrcsources the environment file:tail -5 ~/.bashrc # Should show: source /home/<your year & block>/.coder_env
- You're using a login shell when connecting:
# Use this connection method (note the 'bash -l'): ssh -t -p 443 USER@ssh.myhost.com 'ssh -t -p 10022 root@localhost "bash -l"'
If pip still doesn't work, manually source the environment:
source /home/<your year & block>/.coder_env
echo $PIP_BREAK_SYSTEM_PACKAGES # Should show: 1Symptoms: When connecting via SSH tunnel, you start in /root instead of your project directory.
Solution:
Include cd /home/<your year & block> in your connection command:
ssh -t -p 443 USER@ssh.myhost.com 'ssh -t -p 10022 root@localhost "bash -l -c \"cd /home/<your year & block> && tmux -CC new -A -s myshell\""'The cd command must be inside the bash -l -c context so it happens before tmux starts.
For advanced users who prefer working in a local terminal instead of the web interface, you can set up a reverse SSH tunnel to connect directly from your laptop.
- A server with a public IP address that you control (e.g.,
ssh.myhost.com) - SSH access to that server on port 443
- Your coder.ai workspace SSH public key added to your server's authorized_keys
Download these additional scripts:
ssh_setup.sh: Configure SSH server on coder.aitunnel.sh: Start reverse tunneltunnel_stop.sh: Stop reverse tunnel
-
Upload the additional scripts to your home directory
-
Make them executable:
cd /home/<your year & block>/ chmod +x ssh_setup.sh tunnel.sh tunnel_stop.sh
-
Configure SSH server (run once per workspace instance):
./ssh_setup.sh
This will:
- Install OpenSSH server
- Configure it for root login
- Set up your authorized_keys for passwordless access (if available)
- Prompt you to set a root password
-
Add your laptop's public key for passwordless access:
On your laptop:
cat ~/.ssh/id_ed25519.pub # or id_rsa.pub
Copy the output, then on coder.ai:
echo "YOUR_PUBLIC_KEY" > /home/<your year & block>/ssh/authorized_keys
Run
ssh_setup.shagain to install the key. -
Start the reverse tunnel:
./tunnel.sh
When prompted:
- Enter your server hostname (e.g.,
ssh.myhost.com) - Enter your username on that server
- Verify the configuration
The tunnel will start in the background and display connection instructions.
- Enter your server hostname (e.g.,
Once the tunnel is running, you can connect from your laptop. The SSH connection uses different environment initialization than the coder.ai web terminal, so we need to use specific commands to match that environment.
Basic two-hop connection:
ssh USERNAME@ssh.myhost.com
ssh -p 10022 root@localhostDirect connection with full environment (recommended):
To get the same environment as the coder.ai web terminal (including pip compatibility, CUDA variables, and correct working directory):
ssh -t -p 443 USERNAME@ssh.myhost.com 'ssh -t -p 10022 root@localhost "cd /home/<your year & block> && bash -l"'The -l flag launches a login shell which sources all environment configurations, and cd ensures you start in your working directory instead of /root.
With iTerm2 tmux integration (best experience):
For the best experience with native iTerm2 tmux integration:
ssh -t -p 443 USERNAME@ssh.myhost.com 'ssh -t -p 10022 root@localhost "bash -l -c \"cd /home/<your year & block> && tmux -CC new -A -s myshell\""'Replace USERNAME with your actual username, 443 with your server's SSH port if different, and /home/<your year & block> with your actual home directory.
This command:
- Uses login shell (
bash -l) to load all environment variables - Changes to your working directory before starting tmux
- Creates or attaches to a tmux session named "myshell"
- Uses iTerm2's native tmux integration mode (
-CC)
Understanding the Environment Difference:
The coder.ai web terminal sets environment variables like PIP_BREAK_SYSTEM_PACKAGES=1 that allow pip to work. SSH sessions don't automatically get these variables. The ssh_setup.sh script creates a .coder_env file that's sourced by .bashrc to provide these variables. Using bash -l ensures this file is sourced.
Setting up an iTerm2 profile:
For easy access, create an iTerm2 profile:
- Open iTerm2 → Preferences → Profiles
- Create a new profile (e.g., "Coder.ai")
- In the "General" tab, set the command to the tmux command above (with your actual username and directory)
- Save the profile
Now you can launch your coder.ai workspace with native tmux integration directly from iTerm2.
Check tunnel status:
ps aux | grep ssh | grep 10022
tail -f /tmp/tunnel.logStop the tunnel:
./tunnel_stop.shRestart after workspace restart:
After each workspace restart, you'll need to:
- Run
./ssh_setup.shto restore SSH server - Run
./tunnel.shto restart the reverse tunnel
- The reverse tunnel requires your server to have
GatewayPortsconfigured appropriately - Keep
GatewayPorts no(default) for maximum security - this restricts tunnel access to localhost on your server - Never share your private SSH keys
- Use strong passwords or key-based authentication only
- Consider setting up firewall rules on your server to restrict access
For issues related to:
- Workspace access: Contact your instructor
- VPN connection: Contact BUas IT support
- Script errors: Check the troubleshooting section above


