Lesson 0: System Setup and Your First Project
Get your Erlang development environment set up and create the project structure for our WebSocket chat server
Learn Erlang Step-By-Step
Lesson 0: System Setup and Your First Project
Welcome to Learn Erlang Step-By-Step! This tutorial series will take you from complete beginner to building a real-time WebSocket chat server using pure Erlang. No frameworks, no shortcuts - just the fundamentals that will make you understand how systems like Phoenix LiveView actually work under the hood.
Why Learn Erlang Step-By-Step?
Most web developers jump straight into frameworks like Phoenix without understanding the incredible concurrent programming model that makes Erlang special. By building everything from scratch, you’ll learn:
- The Actor Model - How lightweight processes communicate
- Fault Tolerance - The famous “let it crash” philosophy
- Hot Code Reloading - Updating systems without downtime
- OTP Behaviors - Battle-tested patterns for building robust systems
- Raw Networking - TCP sockets and protocol implementation
What We’ll Build
By the end of this series, you’ll have created a complete WebSocket chat server that can handle thousands of concurrent users. Here’s what makes it special:
- Pure Erlang - No external dependencies
- Fault Tolerant - Crashed processes automatically restart
- Concurrent - Each user gets their own lightweight process
- Real-time - WebSocket communication with live updates
- Scalable - Built using proven OTP patterns
Prerequisites
- Basic programming experience (any language)
- Comfort with the command line
- Willingness to type code and make mistakes
You don’t need to know functional programming or Erlang syntax - we’ll learn by doing.
Installing Erlang
Let’s get your development environment set up. We’ll install Erlang and the essential tools you need.
macOS Installation
# Using Homebrew (recommended)brew install erlang
# Verify installationerl -version
Ubuntu/Debian Installation
# Update package listsudo apt-get update
# Install Erlangsudo apt-get install erlang
# Verify installationerl -version
Windows Installation
- Download the Windows installer from erlang.org/downloads
- Run the installer with default settings
- Open Command Prompt and verify:
Terminal window erl -version
Alternatively, use Chocolatey:
choco install erlang
Installing Rebar3 (Build Tool)
Rebar3 is Erlang’s standard build tool - like npm for Node.js or cargo for Rust.
Unix/macOS:
# Download rebar3curl -L https://github.com/erlang/rebar3/releases/latest/download/rebar3 -o rebar3
# Make it executablechmod +x rebar3
# Move to system pathsudo mv rebar3 /usr/local/bin/
macOS with Homebrew:
brew install rebar3
Windows:
# With Chocolateychoco install rebar3
Verify Installation:
rebar3 version
Creating Your First Erlang Project
Now let’s create the project structure for our chat server.
1. Initialize the Project
# Create project directorymkdir erlang_chatcd erlang_chat
# Create standard Erlang/OTP structuremkdir src priv
2. Create Build Configuration
Create rebar.config
in the project root:
{erl_opts, [debug_info]}.
{deps, []}.
{shell, [ {apps, [chat_server]}]}.
What this does:
debug_info
- Includes debugging information in compiled filesdeps
- External dependencies (empty for now)shell
- Automatically loads our app when starting rebar3 shell
3. Create Application Specification
Create src/chat_server.app.src
:
{application, chat_server, [{description, "WebSocket Chat Server"}, {vsn, "0.1.0"}, {registered, []}, {applications, [kernel, stdlib]}, {mod, {chat_server_app, []}}, {env, []} ]}.
What this means:
application
- Declares this as an OTP applicationdescription
- Human-readable descriptionvsn
- Version stringapplications
- Dependencies (kernel and stdlib are always required)mod
- Entry point module when application startsenv
- Configuration variables
4. Create the Application Module
Create src/chat_server_app.erl
with minimal code:
-module(chat_server_app).-behaviour(application).
-export([start/2, stop/1]).
start(_StartType, _StartArgs) -> {ok, spawn(fun() -> loop() end)}.
stop(_State) -> ok.
% Simple loop to keep the process aliveloop() -> receive stop -> ok end.
What this does:
- Implements the
application
behaviour start/2
is called when the application starts- Returns
{ok, Pid}
where Pid is a process that stays alive stop/1
is called when the application stops
5. Project Structure Overview
Your project should now look like this:
erlang_chat/├── rebar.config # Build configuration├── src/ # Erlang source files (.erl)│ ├── chat_server.app.src # Application specification│ └── chat_server_app.erl # Application module├── priv/ # Static files (HTML, CSS, JS)└── _build/ # Compiled files (created by rebar3)
Testing Your Setup
Let’s verify everything works by compiling the project:
# Compile the projectrebar3 compile
You should see output like:
===> Verifying dependencies...===> Analyzing applications...===> Compiling chat_server
Start the Erlang Shell
# Start rebar3 shell with your project loadedrebar3 shell
You’ll see the Erlang shell prompt:
Erlang/OTP 26 [erts-14.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]
Eshell V14.0 (abort with ^G)1>
Your application will automatically start when you run rebar3 shell
.
Basic Shell Commands
Try these commands to get familiar:
% Check what's loaded (you should see chat_server in the list)1> application:which_applications().[{chat_server,"WebSocket Chat Server","0.1.0"}, {stdlib,"ERTS CXC 138 10","5.0"}, {kernel,"ERTS CXC 138 10","9.0"}]
% Simple arithmetic2> 2 + 3.5
% Create a list3> MyList = [1, 2, 3].[1,2,3]
% Exit the shell4> q().
Understanding What You’ve Built
Even though you haven’t written any Erlang code yet, you’ve created a proper OTP application structure. Here’s what each piece does:
OTP Application
Think of this as a “service” that can be started, stopped, and supervised. It’s the deployment unit in Erlang.
Rebar3
Your build tool that handles:
- Compiling Erlang code
- Managing dependencies
- Running tests
- Creating releases
Project Structure
Follows Erlang conventions:
src/
- Source codepriv/
- Static assetsrebar.config
- Build settings
What’s Next?
In Lesson 1, we’ll write your first Erlang module and understand:
- Basic syntax and data types
- Pattern matching (Erlang’s superpower)
- Function definitions
- The module system
You’ll write actual code and see how Erlang’s unique features work.
Quick Preview
Here’s a tiny taste of what Erlang looks like:
-module(hello).-export([greet/1]).
greet(Name) when is_list(Name) -> "Hello, " ++ Name ++ "!";greet(Name) when is_atom(Name) -> "Hello, " ++ atom_to_list(Name) ++ "!".
Notice the pattern matching and guards - this is what makes Erlang special for building robust systems.
Troubleshooting
Common Issues
“erl: command not found”
- Erlang isn’t installed or not in your PATH
- Try reinstalling or check your system’s PATH variable
“rebar3: command not found”
- Rebar3 isn’t installed or not in PATH
- Make sure you moved it to
/usr/local/bin/
or equivalent
Permission denied errors
- Use
sudo
when moving files to system directories - Or install to a user directory that’s in your PATH
Compilation errors
- Make sure file extensions are correct (
.erl
for Erlang source) - Check that
rebar.config
has proper Erlang syntax
Getting Help
- Erlang Documentation: erlang.org/doc
- Rebar3 Guide: rebar3.org
- Community: erlangforums.com
Ready to write some Erlang? Let’s move on to Lesson 1: Your First Erlang Module!
This is part of the “Learn Erlang Step-By-Step” tutorial series. Each lesson builds on the previous ones, so make sure you complete the exercises before moving forward.
Finished this lesson?
Mark it as complete to track your progress
This open source tutorial is brought to you by Pennypack Software - we build reliable software systems.
Found an issue? Edit this page on GitHub or open an issue