Àwọn Èdè Ìṣètò
Èdè ètò ìṣirò iṣẹ́-ṣíṣe fún kíkọ́ àwọn ohun èlò tí a lè wọ̀n tí ó sì ṣeé tọ́jú
Lightweight processes and actor model enable millions of concurrent operations with low latency
Supervision trees and 'let it crash' philosophy create self-healing systems that recover from failures
Highly productive web framework with real-time features, LiveView, and performance rivaling compiled languages
Immutable data, pattern matching, and functional composition for maintainable, bug-resistant code
Built-in support for distributed systems with native clustering and inter-node communication
Update running production systems without downtime or dropping connections
# Add Erlang Solutions repository
wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb
sudo dpkg -i erlang-solutions_2.0_all.deb
sudo apt update
# Install Erlang (OTP 26)
sudo apt install esl-erlang -y
# Verify installation
erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().'2. Install Elixir:# Install Elixir via apt
sudo apt install elixir -y
# Verify installation
elixir --version
# Should show: Elixir 1.14+ and Erlang/OTP 26
# Install Hex package manager
mix local.hex --force
# Install Phoenix archive (for Phoenix projects)
mix archive.install hex phx_new --force3. Install PostgreSQL (for database-backed apps):# Install PostgreSQL
sudo apt install postgresql postgresql-contrib -y
# Start PostgreSQL
sudo systemctl start postgresql
sudo systemctl enable postgresql
# Create database user
sudo -u postgres createuser --superuser $USER
sudo -u postgres psql -c "ALTER USER $USER WITH PASSWORD 'yourpassword';"4. Install Node.js (for Phoenix asset compilation):# Install Node.js 18
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install nodejs -y
# Verify installation
node --version
npm --version5. Create Your First Phoenix Application:# Create new Phoenix app
mix phx.new myapp --database postgres
# Navigate to project
cd myapp
# Configure database (edit config/dev.exs if needed)
mix ecto.create
# Install dependencies
mix deps.get
# Start Phoenix server
mix phx.server6. Access Your Application:Visit: http://localhost:40007. Set Up for Production (Systemd Service):# Build release
export MIX_ENV=prod
export SECRET_KEY_BASE=$(mix phx.gen.secret)
export DATABASE_URL=ecto://USER:PASS@localhost/myapp_prod
mix deps.get --only prod
mix compile
mix assets.deploy
mix release
# Create systemd service
sudo nano /etc/systemd/system/myapp.serviceAdd this configuration:[Unit]
Description=My Phoenix App
After=network.target
[Service]
Type=simple
User=deploy
Group=deploy
WorkingDirectory=/home/deploy/myapp
Environment="PORT=4000"
Environment="MIX_ENV=prod"
Environment="SECRET_KEY_BASE=your_secret_key"
Environment="DATABASE_URL=ecto://user:pass@localhost/myapp_prod"
ExecStart=/home/deploy/myapp/_build/prod/rel/myapp/bin/myapp start
Restart=on-failure
RestartSec=5
SyslogIdentifier=myapp
[Install]
WantedBy=multi-user.target8. Start Production Service:sudo systemctl daemon-reload
sudo systemctl start myapp
sudo systemctl enable myapp
# Check status
sudo systemctl status myapp
# View logs
sudo journalctl -u myapp -f9. Set Up Nginx Reverse Proxy:sudo nano /etc/nginx/sites-available/myapp
# Add this configuration:
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://localhost:4000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}
# Enable site
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx10. Set Up SSL with Let's Encrypt:sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com
defmodule MyApp.MixProject do
use Mix.Project
def project do
[
app: :myapp,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
def application do
[
mod: {MyApp.Application, []},
extra_applications: [:logger, :runtime_tools]
]
end
defp deps do
[
{:phoenix, "~> 1.7"},
{:phoenix_live_view, "~> 0.20"},
{:phoenix_ecto, "~> 4.4"},
{:ecto_sql, "~> 3.10"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 3.3"},
{:phoenix_live_reload, "~> 1.4", only: :dev},
{:jason, "~> 1.4"},
{:plug_cowboy, "~> 2.6"}
]
end
end2. Runtime Configuration (config/runtime.exs):import Config
if config_env() == :prod do
database_url = System.get_env("DATABASE_URL") ||
raise "DATABASE_URL not available"
config :myapp, MyApp.Repo,
url: database_url,
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
socket_options: [:inet6]
secret_key_base = System.get_env("SECRET_KEY_BASE") ||
raise "SECRET_KEY_BASE not available"
host = System.get_env("PHX_HOST") || "example.com"
port = String.to_integer(System.get_env("PORT") || "4000")
config :myapp, MyAppWeb.Endpoint,
url: [host: host, port: 443, scheme: "https"],
http: [ip: {0, 0, 0, 0, 0, 0, 0, 0}, port: port],
secret_key_base: secret_key_base,
server: true
end3. Phoenix Endpoint Configuration (lib/myapp_web/endpoint.ex):defmodule MyAppWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :myapp
# WebSocket configuration
socket "/live", Phoenix.LiveView.Socket,
websocket: [connect_info: [session: @session_options]]
# Session configuration
plug Plug.Session,
store: :cookie,
key: "_myapp_key",
signing_salt: "random_salt"
plug MyAppWeb.Router
end4. Database Configuration (Ecto):# config/dev.exs
config :myapp, MyApp.Repo,
username: "postgres",
password: "postgres",
hostname: "localhost",
database: "myapp_dev",
stacktrace: true,
show_sensitive_data_on_connection_error: true,
pool_size: 105. Router Configuration:defmodule MyAppWeb.Router do
use MyAppWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, {MyAppWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", MyAppWeb do
pipe_through :browser
live "/", HomeLive
live "/posts", PostLive.Index
live "/posts/:id", PostLive.Show
end
scope "/api", MyAppWeb do
pipe_through :api
resources "/users", UserController
resources "/posts", PostController
end
end6. LiveView Example:defmodule MyAppWeb.CounterLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
{:ok, assign(socket, :count, 0)}
end
def handle_event("inc", _params, socket) do
{:noreply, update(socket, :count, &(&1 + 1))}
end
def handle_event("dec", _params, socket) do
{:noreply, update(socket, :count, &(&1 - 1))}
end
def render(assigns) do
# Template with counter and buttons
end
end7. GenServer for State Management:defmodule MyApp.Counter do
use GenServer
# Client API
def start_link(initial_value) do
GenServer.start_link(__MODULE__, initial_value, name: __MODULE__)
end
def increment do
GenServer.call(__MODULE__, :increment)
end
def get_value do
GenServer.call(__MODULE__, :get_value)
end
# Server callbacks
def init(initial_value) do
{:ok, initial_value}
end
def handle_call(:increment, _from, state) do
{:reply, state + 1, state + 1}
end
def handle_call(:get_value, _from, state) do
{:reply, state, state}
end
end8. Supervision Tree:defmodule MyApp.Application do
use Application
def start(_type, _args) do
children = [
MyApp.Repo,
MyAppWeb.Endpoint,
{Phoenix.PubSub, name: MyApp.PubSub},
MyApp.Counter # Add your GenServer here
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
end9. Testing Configuration:# test/myapp_web/live/counter_live_test.exs
defmodule MyAppWeb.CounterLiveTest do
use MyAppWeb.ConnCase
import Phoenix.LiveViewTest
test "increments counter", %{conn: conn} do
{:ok, view, _html} = live(conn, "/counter")
assert view |> element("h1") |> render() =~ "Counter: 0"
view |> element("button", "+") |> render_click()
assert view |> element("h1") |> render() =~ "Counter: 1"
end
end10. Performance & Production Best Practices:Ṣiṣe ni awọn iṣẹju pẹlu ilana fifi sori ẹrọ VPS wa
Deploy ni nipa 2 iṣẹju • Full root access • Support by ticket and email