Build Your Own GitHub Codespaces Alternative in 222 Lines of Pulumi
-
Bas Steins
- 13 Feb, 2025
![Build Your Own GitHub Codespaces Alternative in 222 Lines of Pulumi](/images/posts/cloudy.jpg)
tl;dr
In this article, we use Pulumi to spin up a cloud-based development environment that emulates GitHub Codespaces. We define the environment using the devcontainer.json
spec and establish a secure tunnel to mount your local file system on a remote server.
This setup runs on Hetzner Cloud, starts in under 5 minutes, and costs less than one-sixth the price of GitHub Codespaces.
The full source of the project is in a GitHub Repository.
Introduction
Containers are a fantastic way to package and run your applications—and standardize them. Similarly, devcontainers provide a consistent environment for development across teams. GitHub Codespaces leverages the VSCode devcontainer specification to offer a ready-to-use cloud development environment.
However, what if you need to attach local resources, external infrastructure, or other cloud-based services to your development setup? This guide shows you how to achieve that using Pulumi to provision and manage your own cloud-based development environment.
Objective
Our objective is to create a single, reproducible definition for your development environment. We achieve this by:
- Provisioning a Remote Server: Using Pulumi to create a development server (with flexibility to choose different cloud providers or even self-hosted hardware).
- Defining the Environment: Using the
devcontainer.json
spec to standardize the development environment. - Attaching Local Resources: Optionally connecting your local file system via a secure tunnel to the remote server.
This complete setup should be ready in less than 5 minutes and easily reproducible for every developer on your team.
Why Is This Important?
Key Benefits
Feature | GitHub Codespaces | Our Solution |
---|---|---|
Hardware/Provider Choice | Limited | Full control |
Monthly Cost (4vCPU) | $ 51.12 | $ 8.23 |
Local FS Integration | No | Yes (via SSHfs) |
Cloud Resource Colocation | No | Yes (via Pulumi) |
Backup/Snapshot Control | Managed | Self-service |
Reproducibility
Whether you’re working in a team or switching between machines as a solo developer, having a consistent environment eliminates the classic “works on my machine” problem.
Run on the Hardware You Want (GPU, ARM, etc.)
Modern applications often require specialized hardware—like GPUs or ARM processors. Unlike GitHub Codespaces, which offers fixed configurations, our approach lets you choose the exact hardware that meets your needs. Whether it’s via a specific cloud provider or your own infrastructure, you’re in control.
Co-locate with Your Cloud Resources
In complex projects, your development environment might need to interact with cloud resources such as databases, storage services, or APIs. With Pulumi, you can provision these resources alongside your development server for better integration and lower latency.
Attach Your Local Storage with Secure Tunnels
You might prefer to keep your code on your local machine while developing on a remote server. Our setup uses a secure tunnel to mount your local file system onto the remote server. (Be sure to follow security best practices when exposing local resources.)
Control the Environment Lifecycle and Backups
Running your own environment means you control its lifecycle. With Pulumi, you can automate tasks like creating backups, taking snapshots, or loading database fixtures—ensuring your environment always aligns with your project’s needs.
Cost Efficiency
GitHub Codespaces is a remarkable product, but its costs can add up quickly—especially for teams with heavy usage. Consider the following cost breakdown for running Codespaces on a 4 vCPU, 16 GB RAM machine for 40 hours per week:
Plan | Cost per Hour | Hours per Month | Free Hours | Billable Hours | Cost per Month |
---|---|---|---|---|---|
GitHub Standard | $ 0.36 | 173 | 30 | 142 | $ 51.12 |
GitHub Pro | $ 0.36 | 173 | 45 | 128 | $ 46.08 |
Now, compare that with alternative cloud providers:
Provider | Instance Type | vCPUs | RAM | GPU | GPU Memory | Cost per Hour | Cost per Month |
---|---|---|---|---|---|---|---|
Hetzner | CCX23 | 4 | 16 | n/a | n/a | $ 0.0475 | $ 8.23 |
RunPod.io | RTX 4000 Ada | 5 | 31 | RTX 4000 Ada | 20 | $ 0.20 | $ 34.64 |
DigitalOcean | H100 | 10 | 240 | H100 | 80 | $ 3.39 | $ 587.14 |
While GitHub Codespaces offers a seamless experience—especially with its tight GitHub integration—the flexibility to choose hardware and reduce costs makes a custom solution very appealing for many teams.
Example Setup / Demo
In this demo, we’ll use Pulumi to provision a development server on Hetzner Cloud. The Pulumi program will:
- Create a Virtual Machine on Hetzner Cloud
- Install Docker on the VM
- Establish a Secure Tunnel to mount your local file system on the remote server
- Launch the Development Environment using the devcontainer CLI with a remote Docker host
- Open VSCode pointed at the remote server, with your local file system mounted
Prerequisites
Make sure you have the following installed:
Also, ensure you have a Hetzner Cloud account and an API key.
Configuring
-
Clone the Repository
git clone https://github.com/bascodes/pulumi-selfhosted-codespace.git
-
Change into the directory
cd pulumi-selfhosted-codespace
-
Adjust your configuration in
pulumi-program/Pulumi.yaml
Open
pulumi-program/Pulumi.yaml
and update the settings to match your environment:config: userPublicKeyPath: "/home/your_username/.ssh/id_ed25519.pub" # Path to your public SSH key userPrivateKeyPath: "/home/your_username/.ssh/id_ed25519" # Path to your private SSH key workspaceExportDirectory: "/home/your_username/workspace" # Local directory for workspace export devcontainerConfigPath: "../.devcontainer/demo/devcontainer.json" # Path to your devcontainer configuration localDockerHost: "unix:///var/run/docker.sock" # Docker host for local Docker daemon sshdPort: 2222 # SSH port to be used on the VM userName: "your_username" # Username for the development environment userUid: 1000 # User ID (adjust if necessary) userGid: 1000 # Group ID (adjust if necessary) hcloudServerType: "cax11" # Hetzner server type hcloudServerLocation: "nbg1" # Hetzner server location
-
Deploy the Infrastructure
Run the following command to provision your environment:
pulumi up
Within a few minutes, your new development environment will be live!
Conclusion and Next Steps
You’ve now built a cost-effective, reproducible cloud-based development environment using Pulumi and Hetzner Cloud. This setup gives you the flexibility to choose the hardware that best meets your needs, co-locate with other cloud resources, and even attach your local file system securely.
Next Steps
- Explore Customization: Tweak the configuration to add features such as GPU support, additional storage, or integrations with other cloud services.
- Enhance Security: Review best practices for securing tunnels and exposed endpoints.
- Automate Maintenance: Use Pulumi to further automate lifecycle tasks like backups, snapshots, and updates.
By following this guide, you gain full control over your development environment—ensuring consistency, cost efficiency, and the flexibility to scale as your projects evolve.