This repository is a workspace for working through Programming Phoenix (1.4), split into three subprojects — hello/, rumbl/, and rumbl_umbrella/ — one per stage of the book, as described below.
The book was written in 2019, and its exact dependency versions are by
now outdated — current releases of Elixir, Phoenix, Ecto, and their
supporting libraries have moved well past what it was written against,
and following it verbatim against today's toolchain runs into breakage
at nearly every step. Despite that, the book remains genuinely valuable:
its structure, and the way it walks through building a real
Phoenix + OTP application end to end (contexts, channels, an OTP
supervision tree, testing strategy), still holds up as a model for how
this kind of application should be put together. That's the reason for
this repository's first order of business — before writing any
application code — being to reconstruct a toolchain close to what
existed in 2019 (.tool-versions below), so the book's own examples
run as originally written rather than fighting version drift the whole
way through.
The intent is for this repository to work as a companion to the book: a place to keep the code, the runtime steps, and the notes on wherever reality (a changed API, a library that no longer behaves the same way) diverged from the text — for anyone else treating Programming Phoenix as I do, as essential reading for real-world Elixir + Phoenix
Versions pinned in .tool-versions:
- Erlang 22.3.4.27
- Elixir 1.9.4-otp-22
- Node.js 12.22.12
- hello/ — the "It's ALIVE!" skeleton app from the book's early chapters (Chapter 2).
- rumbl/ — the single-app
rumblbuild-up (Chapters 3–10): controllers, Ecto, auth, video CRUD, channels. - rumbl_umbrella/ —
rumblrestructured into an umbrella app (Chapter 11 onward): theinfo_sysOTP information system, WolframAlpha backend, and channel/OTP testing (Chapters 12–13).
On Fedora 44 (GCC 16 / OpenSSL 3.5), Erlang 22 fails to build with a plain
asdf install because:
- GCC 16 defaults to C23, where
falseis a reserved word, which breaksttsl_drv.c. - OpenSSL 3.5 removed
openssl/engine.h, required by OTP 22'scryptomodule, and Fedora 44 has noopenssl1.1compatibility package.
mkdir -p ~/local/src
cd ~/local/src
curl -O https://www.openssl.org/source/openssl-1.1.1w.tar.gz
tar xzf openssl-1.1.1w.tar.gz
cd openssl-1.1.1w
./config --prefix="$HOME/local/openssl-1.1.1w" shared
make -j"$(nproc)"
make install_sw install_ssldirsCFLAGS="-O2 -g -std=gnu17" \
KERL_CONFIGURE_OPTIONS="--disable-fop --with-ssl=$HOME/local/openssl-1.1.1w" \
asdf installThis installs erlang, elixir, and nodejs as defined in .tool-versions.
The flags only affect the Erlang build; Elixir and Node ignore them
harmlessly.
crypto.so ends up linked against the local OpenSSL via an embedded
rpath, so no persistent LD_LIBRARY_PATH is needed.
mix archive.install hex phx_new grabs the latest release, which requires
a newer Elixir than the one pinned here. Install a version compatible with
Elixir 1.9.4 instead:
mix archive.install hex phx_new 1.4.17 --force| phx_new | requires Elixir |
|---|---|
| 1.8.x | ~> 1.17 |
| 1.6.x | ~> 1.12 |
| 1.5.x | ~> 1.7 |
| 1.4.x | ~> 1.5 (works with 1.9.4) |
Check the installed version with:
mix phx.new -v:observer.start() doesn't work out of the box on this Erlang 22 build —
Fedora 44's system wxWidgets (3.2.9) is too new for OTP 22's wx
bindings to link against. See OBSERVER.md for the fix
(building wxWidgets 3.0.5 into an isolated prefix and rebuilding Erlang
against it).
docker compose up -dStarts postgres:18.1 on port 5432 (user/password postgres), used by
the book's exercises.
mix phx.new hellomix.exs generated by phx_new 1.4.17 leaves several deps unpinned
(ecto_sql, postgrex, plug_cowboy, etc.). There's no command that
does this automatically — mix deps.get doesn't consider Elixir/OTP
compatibility when resolving versions, so it fetches today's latest
releases, which require Elixir 1.15+ and in some cases Erlang syntax OTP
22 can't even compile (e.g. cowlib's HTTP/3 module). You have to edit
mix.exs by hand and replace the deps block with versions from the
Elixir 1.9 / OTP 22 era:
defp deps do
[
{:phoenix, "~> 1.4.17"},
{:phoenix_pubsub, "~> 1.1"},
{:phoenix_ecto, "~> 4.4.0"},
{:ecto_sql, "~> 3.7.2"},
{:postgrex, "~> 0.15.13"},
{:phoenix_html, "~> 2.11"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:gettext, "~> 0.19.1"},
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.5.2"},
{:cowboy, "~> 2.8.0"},
{:cowlib, "~> 2.9.1"},
{:ranch, "~> 1.7.1"},
{:plug, "~> 1.13.6"},
{:plug_crypto, "~> 1.2.5"},
{:db_connection, "~> 2.7.0"},
{:decimal, "~> 2.3.0"},
{:mime, "~> 1.6.0"},
{:file_system, "~> 1.0.0"}
]
endThen reset the lock file and dependencies before fetching again:
rm -f mix.lock
rm -rf deps _build
mix deps.get
mix compilemix ecto.create
mix phx.server