--- title: "DevPod on AWS" date: 2025-02-11T20:00:00+02:00 weight: 1 cascade: type: docs --- ## Sources - [DevPod](https://devpod.sh/docs/what-is-devpod) โš™๏ธ - [DevContainer](https://containers.dev) ๐Ÿณ ## Introduction ๐Ÿš€ In this article, I want to introduce a fantastic tool that belongs to the same family as GitPod and Codespaces: **DevPod**! It lets you create development environments effortlessly โ€” without getting locked in to a single provider. ๐Ÿ”’โŒ DevPod is based on the **DevContainer** architecture and uses the specifications contained in a [devcontainer.json](https://containers.dev) file to launch your development environment. Personally, I use it to quickly deploy network mockups with ContainerLab. ๐Ÿ’ป๐Ÿงฐ ## What is a DevContainer? ๐Ÿค” A development container (often called a "dev container") lets you use a container as a full-fledged development environment. (Check out the official [containers.dev](https://containers.dev) documentation for more details.) Let's break it down: Have you ever heard the phrase "It works on my machine"? If you're a developer, you've probably run into this problem when collaborating with others. But guess what? **DevContainers** solve the problem of environment drift by providing consistent, reproducible Docker environments. Say goodbye to installation headaches! ๐Ÿ’†โ€โ™€๏ธ With DevContainers, all you need is: 1. A `.devcontainer` folder in your project. 2. A `devcontainer.json` file that tells VS Code how to configure the container. 3. Docker installed locally The cornerstone of the DevContainer is the `devcontainer.json` file. For example: ```json { "name": "Python DevContainer", "image": "mcr.microsoft.com/devcontainers/python:3.10", "features": { "docker-in-docker": "latest" }, "extensions": [ "ms-python.python", "ms-azuretools.vscode-docker" ] } ``` **What's happening here?** ๐Ÿ•ต๏ธโ€โ™€๏ธ - **"image"** โ€“ This uses a ready-to-use Python 3.10 environment. - **"features"** โ€“ This adds Docker support inside the container. - **"extensions"** โ€“ Installs useful extensions for Python and Docker in VS Code. DevContainers are great for local development, but sometimes you need more power โ€” maybe your workloads are huge, or you want to run specialized labs. That's where **DevPod** comes in. ๐Ÿ’ช **So you can easily deploy labs to the Cloud** ## What is DevPod? ๐Ÿค– **DevPod** is an open-source tool that lets you launch development environments either on your local machine or in the cloud provider of your choice. Think of it as a self-hosted, highly customizable version of GitHub Codespaces. ๐ŸŽ‰ In my day-to-day networking adventures, I deploy ContainerLab-based setups with DevContainers on AWS. Let's see how you can use DevPod to do exactly that (details on ContainerLab will follow in another article, I promise!). ๐Ÿ˜œ ## AWS Provider ๐ŸŒ DevPod uses **Providers**, which are configuration modules that define where and how DevPod launches your environment. Here's the list of providers: ![Provider_list](provider.en.png#center) We're going to focus on the **AWS Provider** โ€” even though there are plenty of configuration options: ![Provider_list](aws_options.en.png#center) Before you panic at all these settings, don't worry. If you're just doing a bit of experimenting, the default values will usually do the job. ๐Ÿ™Œ > [!NOTE] **The perks of open source** ๐ŸŽ > > The fact that DevPod is open-source means you can peek under the hood to see exactly how it works. Check out the AWS code [here](https://github.com/loft-sh/devpod-provider-aws/tree/main) if you're curious. ## How the AWS code works Let's look at what DevPod does on AWS by examining the [aws.go code](https://github.com/loft-sh/devpod-provider-aws/blob/main/pkg/aws/aws.go). At a high level, it handles: 1. **Initialization**: Reading the configuration and setting up the AWS SDK clients (with custom credentials if needed). 2. **Networking**: Finding or creating the appropriate subnet, VPC, and security groups. 3. **AMI selection**: Choosing a suitable AMI (by default, a recent Ubuntu 22.04 image) and determining the root device. 4. **IAM setup**: Verifying that an appropriate instance role and instance profile exist, along with the associated policies. 5. **Instance lifecycle**: Creating, starting, stopping, checking the status of, and deleting instances. 6. **User data injection**: Generating a script (Base64-encoded) that configures the instance (adds users and SSH keys) on first boot. 7. **Optional DNS**: Managing Route 53 records for the instance if the configuration requires it. From my perspective, two points stand out as potentially the most critical: - **(#4) IAM setup** - **(#6) User data injection** ### Why are points #4 and #6 "tricky"? - **IAM setup** is mainly handled by the `CreateDevpodInstanceProfile` function. It creates a role named `devpod-ec2-role` that can perform the following operations: - **EC2 operations**: For example, it can describe or stop instances โ€” in particular, the instance associated with it. - **SSM operations**: By attaching the AmazonSSMManagedInstanceCore policy, the instance can be managed by AWS Systems Manager. - **KMS operations (optional)**: If configured, it can run `kms:Decrypt` on a specific KMS key, which is useful for managing session data or secrets. - **User data injection** is essentially a startup script inserted into the instance as Base64. This script sets up a `devpod` user with sudo rights, creates the SSH folders, and inserts your public key into the appropriate file. In the code, [it looks like this](https://github.com/loft-sh/devpod-provider-aws/blob/9d2730c34ecee40cb42596c602381b92ad9c6682/pkg/aws/aws.go#L967-L980): ```bash useradd devpod -d /home/devpod mkdir -p /home/devpod if grep -q sudo /etc/groups; then usermod -aG sudo devpod elif grep -q wheel /etc/groups; then usermod -aG wheel devpod fi echo "devpod ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/91-devpod mkdir -p /home/devpod/.ssh echo " + string(publicKey) + " >> /home/devpod/.ssh/authorized_keys chmod 0700 /home/devpod/.ssh chmod 0600 /home/devpod/.ssh/authorized_keys chown -R devpod:devpod /home/devpod ``` Since DevPod is open-source, you can easily check it out for yourself. It's a great learning tool if you want to understand all the inner workings! ๐Ÿ”ฉ ## IAM roles and policies You'll need to create an IAM user and attach an IAM policy to it that grants just enough permissions for DevPod. For example: - **EC2 actions:** - Description: `ec2:DescribeSubnets`, `ec2:DescribeVpcs`, `ec2:DescribeImages`, `ec2:DescribeInstances`, `ec2:DescribeSecurityGroups` - Instance management: `ec2:RunInstances`, `ec2:StartInstances`, `ec2:StopInstances`, `ec2:TerminateInstances`, `ec2:CancelSpotInstanceRequests` - Security groups & tags: `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`, `ec2:CreateTags` - **IAM actions:** - `iam:GetInstanceProfile`, `iam:CreateRole`, `iam:PutRolePolicy`, `iam:AttachRolePolicy`, `iam:CreateInstanceProfile`, `iam:AddRoleToInstanceProfile` - **Route 53 (optional):** - `route53:ListHostedZones`, `route53:GetHostedZone`, `route53:ChangeResourceRecordSets` ## AWS Configuration ๐Ÿ—๏ธ I usually use the AWS web console to set this up, but you can absolutely do it via the CLI too. ### Step 1: Log in to the AWS console 1. Go to the [AWS Management Console](https://aws.amazon.com/console/). 2. Use an account with the appropriate rights to create IAM resources. ### Step 2: Create a custom IAM policy #### **A. Go to the IAM console** - In the AWS menu, find **IAM**. #### **B. Create a new policy** 1. Click **Policies** in the left-hand menu. 2. Click **Create policy**. #### **C. Switch to the JSON tab** - Paste something like this, adjusting as needed: ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "EC2Actions", "Effect": "Allow", "Action": [ "ec2:DescribeSubnets", "ec2:DescribeVpcs", "ec2:DescribeImages", "ec2:DescribeInstances", "ec2:DescribeSecurityGroups", "ec2:RunInstances", "ec2:StartInstances", "ec2:StopInstances", "ec2:TerminateInstances", "ec2:CancelSpotInstanceRequests", "ec2:CreateSecurityGroup", "ec2:AuthorizeSecurityGroupIngress", "ec2:CreateTags", "ec2:DeleteTags" ], "Resource": "*" }, { "Sid": "IAMActions", "Effect": "Allow", "Action": [ "iam:GetInstanceProfile", "iam:CreateRole", "iam:PutRolePolicy", "iam:AttachRolePolicy", "iam:CreateInstanceProfile", "iam:AddRoleToInstanceProfile" ], "Resource": "*" }, { "Sid": "Route53Actions", "Effect": "Allow", "Action": [ "route53:ListHostedZones", "route53:GetHostedZone", "route53:ChangeResourceRecordSets" ], "Resource": "*" } ] } ``` - Click **Next** (tags are optional), then **Next: Review**. #### **D. Review and create** 1. Name it `DevpodToolPolicy` (or whatever you prefer). 2. Add an optional description. 3. Click **Create policy**. ### Step 3: Create or update the IAM user #### **A. Create a new user (if needed)** 1. Click **Users** in IAM. 2. Click **Add user**. 3. Give it a name (e.g., `devpod-tool-user`). 4. Choose **Programmatic access** if you want CLI access. ๐Ÿค– 5. Click **Next**. #### **B. Attach your new policy** 1. On the permissions page, choose **Attach policies directly**. 2. Check `DevpodToolPolicy`. 3. Click **Create**. 4. And there you go! ### Step 4: Verify and you're done Go back to **Users** โ†’ **devpod-tool-user** โ†’ **Permissions** to confirm that `DevpodToolPolicy` is indeed attached. โœ… ### Step 5: Use these credentials - If you created a programmatic user, make sure to note down the **Access Key ID** and the **Secret Access Key**. ![devpod_user_sumup](devpod_user.en.png#center) **Bonus**: Note your **VPC ID** (in the VPC section on AWS). You'll need it when configuring DevPod. ## Configuring DevPod ๐Ÿ› ๏ธ ### 1. Configure the AWS profile ```bash aws configure --profile Devpod ``` When prompted for: 1. The Access Key ID 2. The Secret Access Key 3. The default region (e.g., `eu-west-1`) 4. The output format (I usually leave it blank) ### 2. Add the profile to DevPod 1. In DevPod, create a new provider and choose **AWS**. 2. Select the **AWS region** (e.g., `eu-west-1`). 3. Expand the AWS options. 4. **AWS disk size**: e.g., 40 GB to start. 5. **Instance type**: e.g., `t2.small`. 6. **AWS profile**: select `Devpod` (or whatever name you chose). 7. **AWS VPC ID**: add your VPC. 8. You can leave the rest as default. Click **Add Provider**. ![added_new_provider](new_provider.en.png#center) ## Testing a deployment ๐Ÿงช ### Deploy Let's do a quick test using one of the pre-built Docker images: 1. Go to **Workspaces** in DevPod. 2. Click **Create Workspace**. 3. Choose your new **AWS** provider. 4. Choose your preferred IDE (VS Code, etc.). 5. On the right, select a quick-start example (e.g., Python). ๐Ÿ 6. Click **Create Workspace**. ![new_worspace](new_worskapce.en.png#center) Wait a few moments, and your cloud-based environment will pop up in VS Code. ๐ŸŽŠ ![vscode](vscode.en.png#center) ### Stop When you're not using the environment, click **Stop** to shut down the EC2 instance. You'll only pay for storage โ€” no compute time. Great for your wallet. ๐Ÿ’ฐ ![Stopped Instance](stopped_instance.en.png#center) ### Delete Deleting the workspace removes all AWS resources associated with that environment, so you won't pay a dime. But you'll need to redeploy if you want to use it again. โ™ป๏ธ ![Delete Instance](delete_instance.en.png#center) ## Conclusion ๐Ÿ’ก By combining **DevContainers** and **DevPod** on **AWS**, you can build flexible, self-managed development environments that scale with your needs โ€” without being locked into vendor-specific platforms. Say goodbye to "It works on my machine!" issues and hello to frictionless coding. ๐Ÿš€โœจ Have fun! ๐ŸŽ‰