The app store for your machine: install, update, and pin versions of every tool and library — without ever building from source.
← / → to navigate · EN/VI switch below
You stop hunting for installers. You name what you need; a trusted catalog delivers it — together with everything it depends on.
The same idea as a phone app store, but for your terminal: thousands of ready-made programs, tested and versioned.
One command installs a program; one command updates everything you have. No installer wizards, no next-next-next.
Most software needs other software to work. The manager figures that out and installs the missing pieces for you.
Packages come from a curated registry the OS or language community maintains — not a random download from the internet.
Building from source means downloading code and compiling it yourself — for a program with 40 dependencies, that's a weekend project. Installing is one command.
You download the raw code, install every dependency yourself in the right order, compile, and fix the errors. Possible — but nobody does it anymore.
Like building a car from scratch in your garage.
Someone else already solved the dependency mess and packaged the result. You get a ready binary at a known version — in seconds, with one command.
Like buying a car from a dealership.
Four ingredients — and the manager's whole job is to handle all of them for you.
nginx, git, flask… compiled and ready to run.
Everything the program needs to work, recursively — the manager resolves the whole tree.
Not "the latest" but 3.0.2 — so you always know exactly what you got.
It came from a named registry (Ubuntu repos, PyPI, crates.io) — so you can re-install the same thing on any machine.
Every manager in this deck plays the same game — only the names of the moves differ.
One line: apt install nginx · pip install flask · cargo add serde.
It looks the package up in the registry's index and works out everything it and its dependencies need.
Download, verify, place in the right spot — the program and its whole dependency tree.
requirements.txt and Cargo.toml record exactly what you used, so the same setup can be rebuilt anywhere.
Nobody builds software from source anymore. You declare what you need — and a package manager delivers it, at a pinned version, on any machine.
Debian/Ubuntu's manager: this is where your system tools — nginx, docker, git, curl — come from.
It's not a Python or Rust tool — it manages the machine itself, for every user and every language.
A single apt for the entire machine. If a program runs on your OS, apt can install it — nginx, docker, git, curl, htop… the OS toolbox of this course.
Debian packages: a .deb is a package you could also grab by hand. The apt command just automates that — with dependency resolution on top.
OS packages are tested against your distribution before they're offered — so they move slower than language packages, but rarely break your machine.
The mental model behind every apt workflow: your machine keeps a local copy of the catalog; the registry keeps the real one.
Downloads the index of what's available and in which versions. Installs nothing — it only updates your view of the store.
Installs from your local index. If it's stale, you might get an old version — which is exactly why you update first.
Brings every installed package to the latest version in the catalog. Your whole machine, one command.
This is 90% of what you'll ever type.
# refresh the catalog, then install nginx
sudo apt update
sudo apt install nginx
# remove / update everything / see what's installed
sudo apt remove nginx
sudo apt upgrade
apt list --installed | grep nginx
sudo = run as admin — needed to touch system files. The last line just filters the installed list.
Update the catalog, then buy. Watch how much the manager does for you.
Millions of Python packages on PyPI — plus two superpowers: venv for isolation, pinning for reproducibility.
pip is the client; PyPI is the store. When you pip install flask, you're buying from PyPI.
flask, requests, pandas, numpy… if it's Python, someone packaged it. pip install <name> and it's on your machine in seconds.
The default registry is PyPI — pip already knows where to look.
By default pip installs into your system Python. Project A needs flask 2, project B needs flask 3 — they fight over one shared shelf.
The fix: a private shelf per project — venv, next slide.
A small text file that turns "works on my machine" into "works everywhere".
# the exact versions this project was built with
flask==3.0.2
requests==2.31.0
gunicorn==21.2.0
# rebuild this exact setup anywhere:
# pip install -r requirements.txt
== pins the exact version. Fresh machine + this file = the same environment, every time.
Create a private environment, work in it, and record what you used.
Two superpowers, one job each: venv keeps projects apart; pinning keeps "yesterday" apart from "today".
A venv is a private Python environment for one project: its own folder, its own packages. Activate it and pip installs there — not into the system.
flask 2 in project A and flask 3 in project B coexist on the same machine.
pip freeze writes every installed package with its exact version into requirements.txt. Anyone, any machine: pip install -r and they get your exact environment.
This is why requirements.txt lives in git.
Chocolatey brings the "one command installs it" magic to Windows — plus winget, the newer one built into Windows.
Same mental model as apt — different OS. Chocolatey is the community store; winget is Microsoft's built-in.
choco install git, choco install ffmpeg… installs both CLI tools and full GUI apps from the community Chocolatey repository.
Windows 10/11 ship with winget, Microsoft's own package manager, with an official catalog: winget install Git.Git.
Name it — it installs with its dependencies; one command updates everything. The OS changes, the idea doesn't.
On Windows you'll mostly type one or the other — same muscle memory.
# Chocolatey (community) — CLI tools and GUI apps
choco install git -y
choco install ffmpeg -y
# winget (built into Windows 10/11)
winget install Git.Git
winget upgrade --all
-y = yes to all prompts. winget upgrade --all updates everything at once — the apt upgrade of Windows.
Rust's package manager is also its build tool: one program that fetches, compiles, runs, and tests your code and its crates.
Python packages ship pre-built, so pip only installs. Rust compiles from source, so cargo builds too — and that's a feature.
cargo add serde declares a dependency; cargo build fetches it from crates.io — Rust's registry — along with everything it depends on.
crate = Rust's package; crates.io = Rust's PyPI.
cargo build compiles, cargo run builds and runs, cargo test runs the tests. One tool drives the whole lifecycle — you never invoke the compiler yourself.
cargo new myapp even scaffolds a ready project — Cargo.toml included.
The manifest: who the project is, and what it depends on. Cargo reads it to both install and build.
[package]
name = "myapp"
version = "0.1.0"
[dependencies]
serde = "1.0"
reqwest = "0.11"
Like requirements.txt, but versions here are minimums — cargo resolves the newest compatible ones and locks them in Cargo.lock.
From an empty directory to a running Rust program in three commands.
OS-level managers run the machine; language-level managers run one language's world. A real project uses both — they cooperate, they don't compete.
apt · choco · winget
Installs and updates the machine itself: system tools (git, curl, nginx), language runtimes (python3, rust), GUI apps. One per machine, shared by everyone.
scope: the whole OS
pip (PyPI) · cargo (crates.io)
Manages the dependencies of programs written in one language: libraries your app imports, at pinned versions. Typically one per project — inside a venv.
scope: one language's registry
apt installs python3 · pip then installs flask inside it · choco sets up the same on Windows — different layers, one machine.
Same four moves everywhere: name it, resolve it, install it, pin it.
| Manager | Level | Registry | Install | Pinning |
|---|---|---|---|---|
| apt | OS · Debian/Ubuntu | Ubuntu / Debian repos | apt install nginx | the repo versions on the machine |
| pip | Language · Python | PyPI | pip install flask | requirements.txt |
| choco | OS · Windows | Chocolatey | choco install git | — (per machine) |
| cargo | Language · Rust | crates.io | cargo build | Cargo.toml + Cargo.lock |
It's not redundancy — it's scope.
apt/choco own the machine (system tools, runtimes, apps); pip/cargo own one language's dependency world. One tool can't cleanly do both.
Each ecosystem has its own catalog, package format, and versioning rules — .deb, .whl, .crate. Each manager speaks its registry's language.
OS packages are tested against your distribution and move slowly; language packages ship daily. Both rhythms coexist on one machine.
The difference between "it works here" and "it works anywhere" is a small text file in git.
pip freeze writes the exact versions you tested into requirements.txt. Commit it to git; any teammate or CI server rebuilds your environment with pip install -r.
No more "works on my machine".
Cargo.toml declares what you want; the auto-generated Cargo.lock records the exact versions cargo chose. Commit both, and every build uses the same crates.
Same idea, different files — pin, commit, reproduce.
Setting up the course's Flask app — every manager in its own lane.
sudo apt install git python3 python3-venv curl — the OS-level toolbox, once per machine.
The same toolbox on a Windows machine: choco install git python curl — so everyone starts from the same ground.
python -m venv .venv, then pip install -r requirements.txt — the app's exact Python dependencies, isolated.
For Rust services in the same project: cargo build fetches and compiles the crates — pinned by Cargo.lock.
Package managers have deep toolboxes. These are real — but not your next step.
Compiling software yourself from raw code. A last resort when a package doesn't exist — or when you're being very specific.
Configuring where Ubuntu fetches packages from (sources lists, mirrors, PPAs). You'll touch this only when chasing a specific package.
Optional dependency sets and build profiles (debug/release tweaks). Useful later, invisible for now.
The older apt-get spelling and the heavier dist-upgrade. apt is the modern front door — stick with it.
You don't download software anymore. You declare what you need — and a manager delivers it, at a pinned version, on any machine.
Next: your first real project — where apt, pip and a text editor finally work together.