What if your next Phoenix deploy to a dirt-cheap Hetzner VPS happened with zero local compiles, zero env headaches—just hit ‘publish release’ and watch it fly?
That’s not sci-fi. It’s the raw power of GitHub Actions teamed with Elixir’s Mix releases, transforming a simple wishlist app into a bulletproof CI/CD machine. Picture this: your code lives in GitHub. A release drops. Tests spin up Postgres in a container, Elixir 1.19 brews on Ubuntu 24.04, and boom—production binary rsyncs over, migrations run, systemd restarts. No server-side Elixir. No architecture mismatches tripping you up.
The dev behind Wishlist Palace nailed it after ditching local builds from his ThinkPad T480 (EndeavourOS Arch flavor—wild choice). Hetzner’s CX23 VPS? Ubuntu 24.04. Instant mismatch. Claude AI scripted the Actions workflow, and suddenly it’s CI/CD for pennies.
Why Ditch Local Builds for GitHub Actions?
Local compiles? They’re like packing for a trip on your clunky old bike—works until the road curves. Hetzner VPS demands matching arches; your laptop laughs. But GitHub’s Ubuntu runners? Perfect harmony. Mix releases bundle the Erlang VM, your app, everything—self-contained magic. Drop it anywhere Linux runs.
Here’s the gem from the setup:
rsync -avz –delete _build/prod/rel/wish_list/ deploy@$VPS_IP:/opt/wish_list/
Rsync. Smart. Only changed files. No full overwrites wasting bandwidth.
And systemd? Restart post-rsync: sudo systemctl restart wish_list. Verify with systemctl is-active. Primitive? Sure. But rock-solid for a 4GB/2vCPU beast costing next to nothing.
My hot take—the unique twist you won’t find in the original: this echoes the Netscape moment in ‘95, when browsers made web apps deployable sans custom clients. Mix releases + GitHub Actions? They’re brewing the same for edge computing. Cheap Hetzner boxes everywhere, Phoenix binaries sipping resources like fine whiskey. Predict this: in two years, Elixir edges out Node for IoT deploys—fault-tolerant, tiny footprints. Hype? Nah. Physics favors it.
How’s the Workflow Actually Tick?
Two jobs. Test first—Postgres 16 container spins (health-checked, ports mapped). Elixir setup via erlef/action. Deps, compile (warnings-as-errors—brutal, love it), migrate test DB, mix test.
Green? Build job fires.
Prod env. Deps only prod. Assets deploy in the web app. mix release wish_list. SSH setup from secrets (private key, VPS IP). Rsync deletes extras. Then migrations via eval:
/opt/wish_list/bin/wish_list eval "WishListDomain.Release.migrate()"
Source env vars, restart service, check active. Triggered on GitHub Release publish. Testing guards the gates.
It’s lean. No Docker bloat—Elixir’s binary is the container, lighter than air. Phoenix assets? Pre-built. Migrations? Release-handled, zero app restarts mid-migrate.
But here’s the energy: imagine scaling. Blue-green? Swap symlinks. Rollouts? Parametrize. This skeleton grows into Kubernetes envy on a $5 VPS.
Is Hetzner + Phoenix the Ultimate Indie Stack?
Hetzner CX23: 4GB RAM, 2 vCPU, NVMe—eats Phoenix for breakfast. Postgres alongside? No sweat. Mix rel scales horizontally if needed, but vertically first—OTP’s gift.
Corporate PR spin? GitHub pushes Copilot Actions now, but this raw YAML? Purist joy. No vendor lock. SSH + rsync > flashy PaaS for tinkerers.
Wishlist Palace thrives here—low traffic, high reliability. Elixir’s VM? Immortal processes laughing at crashes.
Look, devs chase AWS Lambda for ‘serverless,’ but Hetzner’s VPS + this workflow? True freedom. Pay per hour, tweak kernel, colocate DB. Phoenix’s live upgrades? Future-proof it.
And the wonder: AI like Claude scripting this in minutes. Platform shift—GitHub as your factory, Hetzner your warehouse. Deploy velocity hits light speed.
Skeptical? Fork the repo, secret in your VPS IP/SSH key, release. Feels like cheating.
Real-World Gotchas (And Fixes)
Secrets: SSH_PRIVATE_KEY, VPS_IP. Deploy user needs sudo for systemctl—no pwless sudo? Tweak.
DB? Same VPS Postgres. Migrations eval against prod URL—env sourced.
Assets? Monorepo-ish (apps/wish_list_web). Tailwind? Esbuild? Deploys fine.
Upgrade path: OTP 27, Elixir 1.19—pin it.
One punchy caveat. Single-node. HA? Replicate later.
🧬 Related Insights
- Read more: Layoffs Killed the Ladder-Climbing Dream—Now It’s Side Hustles and Vibe Coding
- Read more: Voice Coding Hype: I Tried Ditching the Keyboard
Frequently Asked Questions
What is a Mix release for Phoenix apps?
Mix release bundles your Elixir/Phoenix app with Erlang VM into a single binary—no Elixir install needed on servers. Runs anywhere Linux matches.
How do I deploy Phoenix to Hetzner with GitHub Actions?
Use this YAML: test job with Postgres container, build job rsyncs release, SSH runs migrations/restart. Secrets for SSH key/IP. Trigger on release publish.
Does GitHub Actions work for Elixir on Ubuntu VPS?
Yes—erlef/setup-beam handles Elixir/OTP. Ubuntu 24.04 runner matches Hetzner perfectly. Self-contained rels avoid arch issues.