Introduction
Every time you set up a new machine or rebuild your environment manually, you waste time and introduce inconsistencies. Automating your development environment ensures consistency, saves time, and makes it easy to recreate your setup anywhere.
Dotfiles Management
What to Version Control
# Typical dotfiles structure
DOTFILES=(
".bashrc"
".zshrc"
".vimrc"
".gitconfig"
".tmux.conf"
".config/nvim/"
".config/alacritty/"
".ssh/config"
)
Using Dotfiles Repo
# bootstrap.sh - Dotfiles installation script
#!/bin/bash
# Clone dotfiles
git clone https://github.com/username/dotfiles.git ~/.dotfiles
# Create symlinks
for file in ~/.dotfiles/.*; do
filename=$(basename $file)
if [ "$filename" != "." ] && [ "$filename" != ".." ]; then
ln -sf "$file" ~/$filename
fi
done
# Install dependencies
./install_deps.sh
Docker-Based Development
Development Container
# Dockerfile.dev
FROM python:3.11-slim
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
vim \
&& rm -rf /var/lib/apt/lists/*
# Install Python dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt
# Set up working directory
WORKDIR /app
# Default command
CMD ["/bin/bash"]
# docker-compose.yml for development
version: '3.8'
services:
dev:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/app
- ~/.gitconfig:/root/.gitconfig
environment:
- EDITOR=vim
ports:
- "8000:8000"
Environment Scripts
Setup Script
#!/bin/bash
# setup.sh - Complete development environment setup
set -e
echo "Setting up development environment..."
# Check OS
if [ "$(uname)" = "Darwin" ]; then
OS="macos"
elif [ "$(uname)" = "Linux" ]; then
OS="linux"
else
echo "Unsupported OS"
exit 1
fi
# Install package manager
if [ "$OS" = "macos" ]; then
if ! command -v brew &> /dev/null; then
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
fi
# Install essential tools
install_tools() {
echo "Installing essential tools..."
if [ "$OS" = "macos" ]; then
brew install git vim tmux zsh curl wget python
elif [ "$OS" = "linux" ]; then
apt-get update
apt-get install -y git vim tmux zsh curl wget python3 python3-pip
fi
}
# Configure shell
configure_shell() {
echo "Configuring shell..."
# Install Oh My Zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools.sh)"
# Install plugins
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
}
# Install programming languages
install_languages() {
echo "Installing language runtimes..."
# Python
pip install --upgrade pip setuptools wheel
# Node.js
if ! command -v node &> /dev/null; then
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
fi
}
# Install development tools
install_dev_tools() {
echo "Installing development tools..."
# VS Code
if [ "$OS" = "linux" ]; then
wget -q https://packages.microsoft.com/keys/microsoft.asc -O- | apt-key add -
add-apt-repository "deb [arch=amd64] https://packages.microsoft.com/repos/code stable main"
apt-get update && apt-get install -y code
fi
# Docker
if ! command -v docker &> /dev/null; then
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
fi
}
# Run all installations
install_tools
configure_shell
install_languages
install_dev_tools
echo "Setup complete!"
Configuration Management
Using chezmoi
# Install chezmoi
brew install chezmoi
# Initialize with your dotfiles
chezmoi init https://github.com/username/dotfiles.git
# Apply configuration
chezmoi apply
# Edit configuration
chezmoi edit ~/.bashrc
# Update from remote
chezmoi update
Ansible for Development Setup
# dev_setup.yml
---
- hosts: localhost
connection: local
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
- name: Install basic packages
apt:
name:
- git
- vim
- curl
- wget
- htop
- tmux
- zsh
state: present
- name: Install Python
apt:
name:
- python3
- python3-pip
state: present
- name: Install Node.js
apt:
name: nodejs
state: present
- name: Create development directory
file:
path: ~/dev
state: directory
Package Management
Homebrew Bundle
# Brewfile - Define all dependencies
tap "homebrew/bundle"
tap "homebrew/cask"
tap "homebrew/core"
# Core utilities
brew "git"
brew "vim"
brew "tmux"
brew "zsh"
brew "fzf"
brew "ripgrep"
brew "jq"
brew "yq"
# Development tools
brew "docker"
brew "[email protected]"
brew "node"
brew "go"
# Applications
cask "visual-studio-code"
cask "iterm2"
cask "alfred"
# Install from Brewfile
brew bundle install
Cloud Development Environments
Dev Container Configuration
# .devcontainer/devcontainer.json
{
"name": "My Project",
"image": "mcr.microsoft.com/vscode/devcontainers/base:ubuntu",
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/node:1": {}
},
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-azuretools.vscode-docker",
"dbaeumer.vscode-eslint"
],
"settings": {
"editor.formatOnSave": true,
"files.exclude": {
"**/node_modules": true,
"**/__pycache__": true
}
}
}
},
"postCreateCommand": "pip install -r requirements.txt",
"remoteUser": "vscode"
}
Backup and Sync
Syncing Configuration
#!/usr/bin/env python3
# sync_config.py - Sync configuration across machines
import os
import shutil
import subprocess
from pathlib import Path
CONFIGS = {
"dotfiles": "~/.dotfiles",
"ssh": "~/.ssh",
"gitconfig": "~/.gitconfig",
"vim": "~/.vim",
"tmux": "~/.tmux.conf",
"vscode": "~/Library/Application Support/Code/User",
}
REMOTE = "username@server:backup/"
def backup():
"""Backup local configs to remote."""
for name, path in CONFIGS.items():
expanded = os.path.expanduser(path)
if os.path.exists(expanded):
print(f"Backing up {name}...")
# Use rsync or similar
def restore():
"""Restore configs from remote."""
for name, path in CONFIGS.items():
expanded = os.path.expanduser(path)
print(f"Restoring {name}...")
# Use rsync or similar
if __name__ == "__main__":
import sys
if len(sys.argv) > 1:
if sys.argv[1] == "backup":
backup()
elif sys.argv[1] == "restore":
restore()
Conclusion
Automating your development environment saves time and ensures consistency. Start with simple dotfiles, then gradually add Docker, scripts, and configuration management. The investment pays off quickly.
Comments