CI/CD Patterns That Actually Work: Beyond the Tutorial Examples

Every CI/CD tutorial shows you “hello world” pipelines. Then you hit production and realize none of that scales. Here are the patterns that actually work. The Fundamental Truth CI/CD pipelines are software. They need: Version control (they’re in your repo, good start) Testing (who tests the tests?) Refactoring (your 500-line YAML file is technical debt) Observability (why did that deploy take 45 minutes?) Treat them with the same rigor as your application code. ...

March 12, 2026 Â· 6 min Â· 1208 words Â· Rob Washington

GitOps Done Right: When Git Becomes Your Control Plane

GitOps sounds simple: Git is the source of truth, automation syncs it to reality. In practice, most teams get it wrong. Here’s how to get it right. The Core Principle GitOps isn’t “we use Git.” It’s a specific operational model: Declarative: You describe what you want, not how to get there Versioned: All changes go through Git (audit trail for free) Automated: Software agents continuously reconcile desired vs actual state Observable: You can always answer “what’s deployed where?” The magic is in reconciliation. Traditional CI/CD pushes changes. GitOps pulls desired state and converges toward it. The system heals itself. ...

March 12, 2026 Â· 8 min Â· 1516 words Â· Rob Washington

Observability Beyond Logs: Building Systems That Tell You What's Wrong

You’ve got logging. Great. Now your system is down and you’re grep’ing through 50GB of text trying to figure out why. Sound familiar? Observability isn’t about collecting more data. It’s about collecting the right data and making it queryable. The goal: any engineer should be able to answer arbitrary questions about system behavior without deploying new code. The Three Pillars (And Why They’re Not Enough) You’ve heard this: logs, metrics, traces. The “three pillars of observability.” It’s a useful framework, but it misses something crucial: correlation. ...

March 12, 2026 Â· 4 min Â· 779 words Â· Rob Washington

SSH Config Mastery: Stop Typing Long Commands

Still typing ssh -i ~/.ssh/my-key.pem -p 2222 user@server.example.com? There’s a better way. The SSH Config File ~/.ssh/config transforms verbose commands into simple ones. # s # s s s B h A h e f f - t p o i e r r r o e ~ d / . s s h / p r o d - k e y . p e m - p 2 2 2 2 d e p l o y @ p r o d . e x a m p l e . c o m Basic Config # H H H o o o ~ s s s / t t t . H U P I H U I H U s p o s o d s o s d d o s s r s e r e t s e e e s e h o t r t n a t r n v t r / d N t g N t N c a d 2 i i a d i a d o m e 2 t n m e t m e n e p 2 y g e p y e v f l 2 F l F e i p o i s o i 1 l g r y l t y l 9 o o e a e 2 p d g . e . ~ i ~ 1 r e / n / 6 x . g . 8 a s . s . m s e s 1 p h x h . l / a / 1 e p m s 0 . r p t 0 c o l a o d e g m - . i k c n e o g y m - . k p e e y m . p e m Now just: ...

March 11, 2026 Â· 15 min Â· 3056 words Â· Rob Washington

Makefiles for Project Automation

Makefiles aren’t just for C projects. They’re a simple, universal way to document and run project tasks. Why Make Every project has tasks: build, test, deploy, clean. Make provides: Documentation — Tasks are visible in the Makefile Consistency — Same commands for everyone Dependencies — Tasks can depend on others Portability — Make is everywhere Basic Syntax 1 2 target: dependencies command Important: Commands must be indented with a tab, not spaces. ...

March 11, 2026 Â· 5 min Â· 965 words Â· Rob Washington

Dotfiles Management: Your Dev Environment as Code

New machine? Reinstall? Your perfect dev environment should be one command away. Here’s how to manage dotfiles properly. The Problem You spend hours configuring: Shell (zsh, bash) Editor (vim, nvim, VS Code) Git config SSH config Tmux Aliases and functions Then you get a new laptop and do it all again. Badly. The Basic Solution Put dotfiles in a Git repo, symlink them. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # Create repo mkdir ~/dotfiles cd ~/dotfiles git init # Move configs mv ~/.zshrc ~/dotfiles/zshrc mv ~/.vimrc ~/dotfiles/vimrc mv ~/.gitconfig ~/dotfiles/gitconfig # Create symlinks ln -sf ~/dotfiles/zshrc ~/.zshrc ln -sf ~/dotfiles/vimrc ~/.vimrc ln -sf ~/dotfiles/gitconfig ~/.gitconfig # Push to GitHub git remote add origin git@github.com:username/dotfiles.git git push -u origin main Stow: Symlink Manager GNU Stow makes symlinks manageable: ...

March 11, 2026 Â· 7 min Â· 1469 words Â· Rob Washington

SSL Certificates: Automation That Doesn't Expire

Certificate expiration is the outage you always see coming and somehow never prevent. Here’s how to automate SSL so it stops being a problem. The Problem SSL certificates expire. When they do: Users see scary browser warnings APIs reject connections Mobile apps fail silently Trust is broken And it’s always on a Friday night. Let’s Encrypt + Certbot Free, automated, trusted certificates. Basic Setup 1 2 3 4 5 6 7 8 # Install certbot apt install certbot python3-certbot-nginx # Get certificate (nginx plugin handles everything) certbot --nginx -d example.com -d www.example.com # Test renewal certbot renew --dry-run Certbot adds a cron job automatically for renewal. ...

March 11, 2026 Â· 3 min Â· 464 words Â· Rob Washington

Cloud Cost Optimization: Stop Burning Money

Your cloud bill is too high. It always is. Here’s how to actually reduce it without breaking things. Quick Wins 1. Find Unused Resources 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # AWS: Find unattached EBS volumes aws ec2 describe-volumes \ --filters Name=status,Values=available \ --query 'Volumes[*].[VolumeId,Size,CreateTime]' \ --output table # Find old snapshots (>90 days) aws ec2 describe-snapshots --owner-ids self \ --query 'Snapshots[?StartTime<=`2026-01-01`].[SnapshotId,VolumeSize,StartTime]' \ --output table # Find unattached Elastic IPs aws ec2 describe-addresses \ --query 'Addresses[?AssociationId==`null`].[PublicIp,AllocationId]' \ --output table Delete them. Unattached EBS volumes cost money. Unused EIPs cost $3.65/month each. ...

March 11, 2026 Â· 6 min Â· 1095 words Â· Rob Washington

Ansible Patterns That Scale

Ansible is easy to start, hard to scale. Here’s how to structure playbooks that don’t become unmaintainable nightmares. Directory Structure Start organized, stay organized: a ├ ├ │ │ │ │ │ │ │ │ │ ├ │ │ │ ├ │ │ │ └ n ─ ─ ─ ─ ─ s ─ ─ ─ ─ ─ i b a i ├ │ │ │ │ │ └ p ├ ├ └ r ├ ├ └ c l n n ─ ─ l ─ ─ ─ o ─ ─ ─ o e s v ─ ─ a ─ ─ ─ l ─ ─ ─ l / i e y e l b n p ├ └ s ├ └ b s w d s c n p e l t r ─ ─ t ─ ─ o i e a / o g o c e o o ─ ─ a ─ ─ o t b t m i s t . r d g k e s a m n t i c y u h g ├ ├ └ i h g s . e b o x g o f / c o r ─ ─ ─ n o r y r a n r n g t s o ─ ─ ─ g s m v s e s i t u / t u l e e s / o s p a w d s p r s q n . _ l e a . _ s . l y v l b t y v . y / m a . s a m a y m l r y e b l r m l s m r a s l / l v s / e e r s s . . y y m m l l Inventory Patterns Static YAML Inventory 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # inventory/production/hosts.yml all: children: webservers: hosts: web1.example.com: web2.example.com: vars: http_port: 80 databases: hosts: db1.example.com: postgresql_port: 5432 db2.example.com: postgresql_port: 5433 Dynamic Inventory For cloud infrastructure, use dynamic inventory: ...

March 11, 2026 Â· 9 min Â· 1795 words Â· Rob Washington

GitOps for Kubernetes: Deployments as Code

Push to Git, watch your cluster update. That’s the GitOps promise. Here’s how to actually implement it. What GitOps Is GitOps means: Git is the source of truth for infrastructure and application state Changes happen through Git (PRs, not kubectl apply) A controller watches Git and reconciles cluster state Drift is automatically corrected The cluster converges to match what’s in Git, continuously. Why GitOps Over kubectl apply 1 2 3 4 5 6 # Bad: Who ran this? When? From where? kubectl apply -f deployment.yaml # Good: PR reviewed, approved, merged, tracked forever git commit -m "Scale API to 5 replicas" git push Over CI-Push Traditional CI/CD pushes to the cluster: ...

March 11, 2026 Â· 7 min Â· 1380 words Â· Rob Washington