Makefiles for Project Automation: Simple, Portable Task Running

Make is 47 years old and still useful. Not for building C programs (though it does that), but as a simple task runner. Every Unix system has it. No installation required. One file defines all your project commands. Basic Structure 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # Makefile .PHONY: help build test clean help: @echo "Available targets:" @echo " build - Build the application" @echo " test - Run tests" @echo " clean - Clean build artifacts" build: npm run build test: npm test clean: rm -rf dist/ node_modules/ 1 2 3 make build make test make clean .PHONY Explained Without .PHONY, make checks if a file named “build” exists: ...

February 24, 2026 Â· 6 min Â· 1264 words Â· Rob Washington

DNS for Developers: Understanding the Internet's Phone Book

DNS is invisible until it breaks. Then everything breaks. Understanding how DNS works helps you debug issues faster and configure services correctly. The Basics DNS translates human-readable names to IP addresses: e x a m p l e . c o m → 9 3 . 1 8 4 . 2 1 6 . 3 4 The resolution process: 1 2 3 4 5 . . . . . B O Q R A r S u e n o e s s w c r o w s h y l e e e v r r c g e k o r c c s e a h s q c e i u h c t t e e k s o r d s i c c e a l a o s t o c n c h f r e a e i o a l g o c u t h c r a e s l c d e e h r v e r v e e e l s r o s b l a v → s e e r T d L ( D o e n . s g e T . r T , v L e 8 r . s 8 . → 8 . a 8 u ) t h o r i t a t i v e s e r v e r s Record Types A Record (IPv4 Address) e x a m p l e . c o m . 3 0 0 I N A 9 3 . 1 8 4 . 2 1 6 . 3 4 Maps a name to an IPv4 address. ...

February 24, 2026 Â· 11 min Â· 2168 words Â· Rob Washington

The Twelve-Factor App: Principles for Cloud-Native Applications

The twelve-factor app methodology emerged from Heroku’s experience deploying thousands of applications. These principles create applications that work well in modern cloud environments — containerized, horizontally scalable, and continuously deployed. They’re not arbitrary rules. Each factor solves a real problem. I. Codebase One codebase tracked in version control, many deploys. ✅ m ├ ├ └ ❌ m m m y ─ ─ ─ y y y G a ─ ─ ─ B a a a o p a p p p o p . s d d p p p d g r e : - - - : i c p p s d t l r t e o o a v y d g e u i l t c n o o t g p : i m e s n n t / t a / g i n g , p r o d u c t i o n , f e a t u r e - b r a n c h e s Different environments come from the same codebase. Configuration, not code, varies between deploys. ...

February 23, 2026 Â· 6 min Â· 1252 words Â· Rob Washington

Feature Flags: Deploy Without Fear

Deployment and release are different things. Deployment puts code on servers. Release makes features available to users. Feature flags separate these concerns. With feature flags, you can deploy daily but release weekly. Ship risky changes but only enable them for 1% of users. Roll back a broken feature in seconds without touching infrastructure. Basic Implementation 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class FeatureFlags: def __init__(self): self.flags = {} def is_enabled(self, flag_name: str, user_id: str = None) -> bool: flag = self.flags.get(flag_name) if not flag: return False # Global kill switch if not flag.get("enabled", False): return False # Check user allowlist if user_id and user_id in flag.get("allowed_users", []): return True # Check percentage rollout if user_id and flag.get("percentage", 0) > 0: # Consistent hashing: same user always gets same result hash_val = hash(f"{flag_name}:{user_id}") % 100 return hash_val < flag["percentage"] return flag.get("enabled", False) flags = FeatureFlags() flags.flags = { "new_checkout": { "enabled": True, "percentage": 10, # 10% of users "allowed_users": ["user_123"] # Plus specific users } } # Usage if flags.is_enabled("new_checkout", user_id=current_user.id): return new_checkout_flow() else: return old_checkout_flow() Configuration-Based Flags Store flags in config, not code: ...

February 23, 2026 Â· 7 min Â· 1351 words Â· Rob Washington

Git Hooks: Automate Quality Before It Reaches the Repo

Git hooks are scripts that run at specific points in the Git workflow. They’re the first line of defense against bad commits — catching issues before they pollute your repository history. Set them up once, forget about them, and let automation enforce quality. Hook Types Client-side hooks (your machine): pre-commit — Before commit is created prepare-commit-msg — Before commit message editor opens commit-msg — After commit message is entered pre-push — Before push to remote Server-side hooks (repository server): ...

February 23, 2026 Â· 6 min Â· 1086 words Â· Rob Washington

Container Security Basics: Don't Ship Vulnerabilities

Containers provide isolation, not security. A misconfigured container is as vulnerable as a misconfigured server — sometimes more so, because containers make it easy to ship the same vulnerability everywhere. These basics prevent the most common container security issues. Don’t Run as Root The most common mistake: 1 2 3 4 5 6 7 8 9 10 11 12 # ❌ Bad: Runs as root by default FROM node:20 COPY . /app CMD ["node", "server.js"] # ✅ Good: Create and use non-root user FROM node:20 RUN useradd -r -u 1001 appuser WORKDIR /app COPY --chown=appuser:appuser . . USER appuser CMD ["node", "server.js"] Many base images include non-root users: ...

February 23, 2026 Â· 5 min Â· 1046 words Â· Rob Washington

Nginx Configuration Patterns: From Basic Proxy to Production-Ready

Nginx is everywhere: reverse proxy, load balancer, static file server, SSL terminator. Its configuration syntax is powerful but has gotchas that catch everyone at least once. These patterns cover common use cases done right. Basic Reverse Proxy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 upstream backend { server 127.0.0.1:3000; } server { listen 80; server_name example.com; location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } Always set those headers — your backend needs to know the real client IP and protocol. ...

February 23, 2026 Â· 5 min Â· 1043 words Â· Rob Washington

Secrets Management Patterns for Modern Infrastructure

Every infrastructure team eventually faces the same uncomfortable question: where do the secrets go? API keys, database passwords, TLS certificates, OAuth tokens — they all need to live somewhere. The wrong answer (“in the repo, it’s fine, it’s private”) creates technical debt that compounds silently until someone accidentally pushes to public or an ex-employee still has access to production credentials. The Anti-Patterns First Environment variables everywhere. Yes, the twelve-factor app says config comes from the environment. But “the environment” doesn’t mean a .env file committed to git. Environment variables are runtime config, not secret storage. ...

February 23, 2026 Â· 4 min Â· 709 words Â· Rob Washington

Systemd Service Management: Running Applications Reliably

Systemd is how modern Linux manages services. It starts your applications at boot, restarts them when they crash, and handles dependencies between services. Understanding systemd transforms “it works when I run it manually” into “it runs reliably in production.” Basic Service Unit 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # /etc/systemd/system/myapp.service [Unit] Description=My Application After=network.target [Service] Type=simple User=appuser WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/bin/server Restart=always RestartSec=5 [Install] WantedBy=multi-user.target 1 2 3 4 # Enable and start sudo systemctl daemon-reload sudo systemctl enable myapp sudo systemctl start myapp Service Types simple (default): Process started by ExecStart is the main process. ...

February 23, 2026 Â· 5 min Â· 915 words Â· Rob Washington

Backup Strategies: Because Hope Is Not a Disaster Recovery Plan

Everyone has backups. Few have tested restores. The backup that fails during a crisis is worse than no backup — it gave you false confidence. Backup strategy isn’t about the backup. It’s about the restore. The 3-2-1 Rule A minimum viable backup strategy: 3 copies of your data 2 different storage media/types 1 copy offsite P C C C r o o o i p p p m y y y a r 1 2 3 y : : : : P L R O r o e f o c m f d a o s u l t i c e t t s e i n r o a e a n p p r s l c d h i h a o c i t t a v a e b ( ( a s d ( s a i d e m f i e f f e f d r e a e r t n e a t n c t e r n e p t g r e i o r o v ) n i ) d e r ) What to Back Up Always: ...

February 23, 2026 Â· 6 min Â· 1110 words Â· Rob Washington