TL;DR: A lightweight, self-hosted alternative to GitPod or GitHub Codespaces. Provision a fresh VM instantly just by SSH-ing into a new subdomain (e.g., ssh demo-foo.example.com).
ssh <name>.example.com creates and connects you to a new VM./persist/ directory for data that survives VM resets.These scripts turn a server (or VM) into a bountiful 🌳 "VM tree", on which you can easily start up ephemeral VMs. Originally for our self-hosted cloud development environments, but usable in many ways: in a CI/CD pipeline, as acceptance testing environments, for demoing purposes, or really anything you can use an Ubuntu environment for.
We didn't develop this as a product, but to scratch our own itch as a DevOps team. We've been using this (and its previous in-house version) for 8+ years as our dev environments, and we ❤️ that fresh VMs just "grow on the VM tree for easy picking". It's literally how our team survived COVID's years of WFH. :)
It's the same philosophy as GitPod, DevPod, CodeSpaces, CodeSandbox or Nimbus, but self-hosted, free (as in beer and speech) and probably a bit more old-school:
ssh,bash,docker or k8s involved, no .json files in git repos (but you can add anything if you want to),vi! 😁)For the VMs, it uses LXD/Incus containers or QEMU VMs.
demo-. Personal ones with username-.)https://demo-foo.example.com. (A pre-configured Caddy reverse-proxy deals with TLS and forwards HTTP requests to the right VM.)sudo touch /nopassword.)/persist/ is shared between a user's all personal VMs. (Makes working on multiple VMs easy, even at the same time.)sudo touch /nokill.)/persist/ are persistent and survive the nightly killing of VMs. (So it's recommended to keep your work there.)/persist/autoexec.sh (chmod 755) exists, it will be run with user permissions right after boot. (For multiple environments, we recommend detecting $HOSTNAME.)docker-compatible.ssh demo-foo-centos8.example.com (Then on you can use just demo-foo.example.com.)/home/user/.ssh/authorized_keys by the VM's owner..ssh/config. (And your team members'.).ssh/config snippet specifies to use a "jump" user called vmtree on the server. (Only the people who have their SSH key in the vmtree user's authorized_keys file can connect, of course.)vmtree user's authorized_keys file force-runs the /vmtree/vmtree-vm.sh script on the server. (It's not possible to run anything else via SSH with this user.).ssh/config passes name of the VM you requested to the /vmtree/vmtree-vm.sh script./vmtree/vmtree-vm.sh script does security checks regarding naming convention, etc./vmtree/vmtree-vm.sh script starts an LXD/Incus container with the VM name you specified, passing it a cloud-init script that pre-configures the VM with your SSH key (and possibly other things)./vmtree/vmtree-vm.sh script attaches your "personal disk" to the VM at /persist/./vmtree/vmtree-vm.sh script waits for the VM to obtain an IP address and have SSH started./vmtree/vmtree-vm.sh script connects your SSH session to the SSH port of the LXD/Incus container.And from cron:
/vmtree/cron-killme.sh checks for a /killme file on the VMs, and if one's there, deletes the VM./vmtree/cron-nopassword.sh checks for a /nopassword file on the VMs, and if one's there, reconfigures Caddy to NOT do HTTP authentication for the VM's subdomain./vmtree/cron-stop.sh checks for a /nokill file on the VMs, and if the file is NOT THERE, deletes the VM. (If it's a personal VM, still stops the VM, but doesn't delete. This is because people forget about their VMs.)/vmtree/cron-renew.sh checks if the TLS certificate needs to be renewed, and renews it if necessary, with acme.sh.Just a few.
bash code (including comments), so I'm pretty sure your DevOps team can deal with it if necessary.When you occasionally run into LXD's limitations, , you can start real QEMU VMs instead of LXD/Incus containers by specifying -vm as the 4th part of the VM name. For example ssh demo-myrealvm1-ubuntu2004-vm8.example.com creates a QEMU VM called "demo-myrealvm1", using 8GB of memory, running an older Ubuntu version, 20.04.
Full QEMU VMs are needed -- for example -- if you want to run a full Kubernetes cluster on the VM. (But docker and docker-compose does work on LXD/Incus containers with the configuration that these scripts already do for you.)
The advantages of QEMU VMs is that they have fewer limitations, but the disadvantage is that they allocate the memory they are given (memory is not shared, as it is with LXD/Incus containers).
On an Ubuntu 24.04 or 22.04 server with a public IP address, run:
sudo git clone https://github.com/kkovacs/vmtree.git /vmtree
sudo cp ~/.ssh/authorized_keys /vmtree/keys/my
sudo /vmtree/install.sh
Then put the snippet it prints out in your .ssh/config file (on your PC, not on the server, of course).
This basic setup will use ip.me, nip.io, and a self-signed certificate to set up the fullest possible functionality without using your own domain.
example.com).example.com and *.example.com point to the host server's IP. (Wait until it propagates.)sudo git clone https://github.com/kkovacs/vmtree.git /vmtree~/.ssh/id_*.pub files on their PCs) to /vmtree/keys/<username> files.sudo /vmtree/install.sh --skip-install to do basic checks and generate a default /vmtree/.env file./vmtree/.env file. Fill out:
example.com)apt-get install incus now.sudo /vmtree/install.sh again to finish the installation..ssh/config files.1 commits
Shell
100.0%
TL;DR: A lightweight, self-hosted alternative to GitPod or GitHub Codespaces. Provision a fresh VM instantly just by SSH-ing into a new subdomain (e.g., ssh demo-foo.example.com).
ssh <name>.example.com creates and connects you to a new VM./persist/ directory for data that survives VM resets.These scripts turn a server (or VM) into a bountiful 🌳 "VM tree", on which you can easily start up ephemeral VMs. Originally for our self-hosted cloud development environments, but usable in many ways: in a CI/CD pipeline, as acceptance testing environments, for demoing purposes, or really anything you can use an Ubuntu environment for.
We didn't develop this as a product, but to scratch our own itch as a DevOps team. We've been using this (and its previous in-house version) for 8+ years as our dev environments, and we ❤️ that fresh VMs just "grow on the VM tree for easy picking". It's literally how our team survived COVID's years of WFH. :)
It's the same philosophy as GitPod, DevPod, CodeSpaces, CodeSandbox or Nimbus, but self-hosted, free (as in beer and speech) and probably a bit more old-school:
ssh,bash,docker or k8s involved, no .json files in git repos (but you can add anything if you want to),vi! 😁)For the VMs, it uses LXD/Incus containers or QEMU VMs.
demo-. Personal ones with username-.)https://demo-foo.example.com. (A pre-configured Caddy reverse-proxy deals with TLS and forwards HTTP requests to the right VM.)sudo touch /nopassword.)/persist/ is shared between a user's all personal VMs. (Makes working on multiple VMs easy, even at the same time.)sudo touch /nokill.)/persist/ are persistent and survive the nightly killing of VMs. (So it's recommended to keep your work there.)/persist/autoexec.sh (chmod 755) exists, it will be run with user permissions right after boot. (For multiple environments, we recommend detecting $HOSTNAME.)docker-compatible.ssh demo-foo-centos8.example.com (Then on you can use just demo-foo.example.com.)/home/user/.ssh/authorized_keys by the VM's owner..ssh/config. (And your team members'.).ssh/config snippet specifies to use a "jump" user called vmtree on the server. (Only the people who have their SSH key in the vmtree user's authorized_keys file can connect, of course.)vmtree user's authorized_keys file force-runs the /vmtree/vmtree-vm.sh script on the server. (It's not possible to run anything else via SSH with this user.).ssh/config passes name of the VM you requested to the /vmtree/vmtree-vm.sh script./vmtree/vmtree-vm.sh script does security checks regarding naming convention, etc./vmtree/vmtree-vm.sh script starts an LXD/Incus container with the VM name you specified, passing it a cloud-init script that pre-configures the VM with your SSH key (and possibly other things)./vmtree/vmtree-vm.sh script attaches your "personal disk" to the VM at /persist/./vmtree/vmtree-vm.sh script waits for the VM to obtain an IP address and have SSH started./vmtree/vmtree-vm.sh script connects your SSH session to the SSH port of the LXD/Incus container.And from cron:
/vmtree/cron-killme.sh checks for a /killme file on the VMs, and if one's there, deletes the VM./vmtree/cron-nopassword.sh checks for a /nopassword file on the VMs, and if one's there, reconfigures Caddy to NOT do HTTP authentication for the VM's subdomain./vmtree/cron-stop.sh checks for a /nokill file on the VMs, and if the file is NOT THERE, deletes the VM. (If it's a personal VM, still stops the VM, but doesn't delete. This is because people forget about their VMs.)/vmtree/cron-renew.sh checks if the TLS certificate needs to be renewed, and renews it if necessary, with acme.sh.Just a few.
bash code (including comments), so I'm pretty sure your DevOps team can deal with it if necessary.When you occasionally run into LXD's limitations, , you can start real QEMU VMs instead of LXD/Incus containers by specifying -vm as the 4th part of the VM name. For example ssh demo-myrealvm1-ubuntu2004-vm8.example.com creates a QEMU VM called "demo-myrealvm1", using 8GB of memory, running an older Ubuntu version, 20.04.
Full QEMU VMs are needed -- for example -- if you want to run a full Kubernetes cluster on the VM. (But docker and docker-compose does work on LXD/Incus containers with the configuration that these scripts already do for you.)
The advantages of QEMU VMs is that they have fewer limitations, but the disadvantage is that they allocate the memory they are given (memory is not shared, as it is with LXD/Incus containers).
On an Ubuntu 24.04 or 22.04 server with a public IP address, run:
sudo git clone https://github.com/kkovacs/vmtree.git /vmtree
sudo cp ~/.ssh/authorized_keys /vmtree/keys/my
sudo /vmtree/install.sh
Then put the snippet it prints out in your .ssh/config file (on your PC, not on the server, of course).
This basic setup will use ip.me, nip.io, and a self-signed certificate to set up the fullest possible functionality without using your own domain.
example.com).example.com and *.example.com point to the host server's IP. (Wait until it propagates.)sudo git clone https://github.com/kkovacs/vmtree.git /vmtree~/.ssh/id_*.pub files on their PCs) to /vmtree/keys/<username> files.sudo /vmtree/install.sh --skip-install to do basic checks and generate a default /vmtree/.env file./vmtree/.env file. Fill out:
example.com)apt-get install incus now.sudo /vmtree/install.sh again to finish the installation..ssh/config files.1 commits
Shell
100.0%