Goulin's personal photo
Written by Goulin Khoge
September 6, 2024

Optimizing My Development Workflow: A Guide to Remote Setup with Home Lab

Introduction

As developers, we often find ourselves switching between operating systems, facing compatibility issues, or longing for a more flexible development environment. In this post, I'll share my journey of setting up a remote development environment using a home lab, and how it has transformed my workflow.

The Challenge: Architecture Limitations

While using MacOS with Apple Silicon (ARM-based CPU), I frequently encountered limitations when debugging Python libraries or building OCI images incompatible with ARM architecture. Despite the existence of Rosetta for x86 simulation, the terminal environment quickly became messy and difficult to manage.

The Solution: A Home Lab Server

To overcome these challenges, I decided to build a home lab with carefully selected PC components running Ubuntu Server 24.04 LTS. This server serves multiple purposes:

  1. Hosting my favorite movies and TV shows
  2. Running a VaultWarden instance for personal password management
  3. Providing a versatile development environment

Remote Development with VS Code

My typical development workflow involves:

Visual Studio Code makes remote development via SSH remarkably smooth, offering:

Ensuring Safety: Isolated Dev Environments

To protect against potentially harmful code execution and to facilitate experimentation, isolated development environments are crucial. While there are multiple options available, I chose LXD containers for their balance of isolation and resource efficiency.

Comparison of Isolation Solutions

QEMU virtual machines offer the strongest isolation by emulating entire systems, but they come with higher resource overhead and slower startup times. Both Docker and LXD containers use the same Linux kernel features for isolation, making them more lightweight and efficient compared to full VMs.

The key difference between Docker and LXD lies in their intended use cases. Docker containers are designed primarily for running single applications, whereas LXD containers provide a system container-like experience, allowing multiple applications to run within a single container. This makes LXD feel more like a full OS environment.

After considering these factors, I chose LXD containers for my setup due to their balance of isolation and flexibility, particularly their ability to easily run multiple applications in a system-like environment. To start an LXD container:

bash
lxc launch ubuntu:24.04 test-container lxc exec test-container -- sudo --login --user ubuntu

This setup allows me to create isolated environments that feel like full systems, making it easy to experiment with different configurations and run multiple services without the overhead of full virtual machines.

Secure Remote Access with Tailscale

Tailscale provides secure remote access to the home lab server without exposing ports on the home's public IP. It's the Swiss Army knife of networking.

What is Tailscale?

Tailscale creates a private cloud (tailnet) connecting:

Key Features

Tailscale SSH

Tailscale Funnel

Setup Process

Setting up Tailscale on a new LXD container:

bash
# install Tailscale curl -fsSL https://tailscale.com/install.sh | sh # Login and Run tailscale up --ssh

Benefits

Tailscale provides:

  1. Accessibility from anywhere
  2. Secure and stable connections
  3. No need for complex firewall rules or VPN configurations
  4. Seamless operation across different platforms and network environments

Additional Setup Tips

Quick GitHub Access

For seamless GitHub access:

  1. Install the GitHub CLI tool: Official installation instructions for Ubuntu
  2. Set up credentials using
    1. gh auth login -p https --skip-ssh-key -w
    2. Go to: https://github.com/login/device/select_account

Share an HTTP server

console
$ sudo tailscale funnel --bg PORT Available on the internet: https://test-container.tailc123.ts.net/ |-- proxy http://127.0.0.1:3000 $ curl https://test-container.tailc123.ts.net hello, world

Physical Server Access

In case of SSH issues, consider setting up a PiKVM for remote physical access to your server. This blog post from Tailscale explain how to setup a remotely accessible PiKVM: Access PiKVM from anywhere.

Docker Support in LXD Containers

To enable Docker within LXD containers:

  1. Create a Docker storage pool:
bash
lxc storage create docker btrfs
  1. Use this function to create Docker-ready containers:
bash
# create lxd container with docker support function create-dev-container { container_name=$1 setup_script="https://gist.githubusercontent.com/goulinkh/ec7cad52772cc869bcf8802c656a1abf/raw/2d9ac50de6143844274e599d7b24238345ba3c50/setup-dev.sh" lxc launch ubuntu:24.04 $container_name lxc config device add $container_name docker disk pool=docker source=$container_name path=/var/lib/docker lxc config set $container_name security.nesting=true \ security.syscalls.intercept.mknod=true \ security.syscalls.intercept.setxattr=true lxc restart $container_name lxc exec $container_name -- bash -c "curl -fsSL $setup_script | bash" }

Conclusion

Setting up a remote development environment with a home lab has significantly improved my workflow, offering flexibility, security, and efficiency. By leveraging tools like VS Code, LXD containers, and Tailscale, you can create a powerful, versatile development setup that adapts to your needs.

Whether you're dealing with architecture incompatibilities, seeking a more isolated development environment, or simply want the freedom to work from any device, this setup provides a robust solution. Give it a try, and experience the benefits of remote development for yourself!