For writing and testing DAGs on a Mac you do not need Docker. Airflow installs with pip into a virtual
environment, and airflow standalone starts every component with a local SQLite database. The one
step that matters is the constraints file, which pins every dependency to a combination the Airflow
team has tested.
Copy and paste
# 1. Python 3.10 to 3.14; here 3.13 from Homebrew
brew install python@3.13
# 2. A virtual environment for Airflow
python3.13 -m venv ~/airflow-venv
source ~/airflow-venv/bin/activate
pip install --upgrade pip
# 3. Airflow, pinned with the official constraints file
AIRFLOW_VERSION=3.3.2
PYTHON_VERSION="$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"
CONSTRAINT_URL="https://raw.githubusercontent.com/apache/airflow/constraints-${AIRFLOW_VERSION}/constraints-${PYTHON_VERSION}.txt"
pip install "apache-airflow==${AIRFLOW_VERSION}" --constraint "${CONSTRAINT_URL}"
# 4. Where Airflow keeps its files, and two settings for a clean local setup
export AIRFLOW_HOME=~/airflow
export AIRFLOW__CORE__LOAD_EXAMPLES=False
export NO_PROXY="*"
# 5. Start everything
airflow standalone
When the terminal prints Airflow is ready, open http://localhost:8080 and
sign in as admin. The password appears once in the terminal, on a line like
Simple auth manager | Password for user 'admin': ..., and is saved in a file; see
how to find the admin password.
Put your DAG files in ~/airflow/dags, creating the folder if it does not exist. The install takes
about two minutes on a recent Mac.
What standalone starts
airflow standalone creates the database on the first run, then starts four components in one
terminal and prefixes their logs with their names:
| Component | Does |
|---|---|
api-server |
serves the UI and the API on port 8080 |
scheduler |
creates DAG runs and starts tasks, with the LocalExecutor |
dag-processor |
reads the files in the DAGs folder |
triggerer |
runs deferred tasks and sensors |
AIRFLOW_HOME then contains airflow.cfg, the SQLite database airflow.db, the logs folder and
the generated password file. Ctrl+C stops everything.
Things that go wrong
FileNotFoundError: [Errno 2] No such file or directory: 'airflow'. standalone starts the
other components by running the airflow command, so the virtual environment must be active. Calling
~/airflow-venv/bin/airflow standalone without activating it starts the database and then fails. Run
source ~/airflow-venv/bin/activate first.
Port 8080 is taken. Change the port and the address together. With the port alone, the API server starts but tasks cannot reach it and stay queued:
export AIRFLOW__API__PORT=8081
export AIRFLOW__API__BASE_URL=http://localhost:8081
A new DAG does not appear. The DAG processor looks for new files every five minutes, and new DAGs start paused. See how to fix “DAG not showing in the UI”.
Tasks crash with SIGSEGV. That is what NO_PROXY="*" in step 4 helps with; see
how to fix SIGSEGV task crashes on macOS.
Symbol not found: _Py_GetArgcArgv. The Airflow documentation links this error to some Python
builds on macOS. Use another Python, for example the installer from python.org.
Every time you start it
The export lines last only for the current terminal. Put them, together with the source line, in a
small script or in ~/.zshrc, so that every start uses the same AIRFLOW_HOME and the same settings.
Upgrading
Change AIRFLOW_VERSION, run the pip install line again with the new constraints file, then update
the database:
airflow db migrate
The Airflow documentation also supports uv: in a uv virtual environment, replace pip install
with uv pip install and keep the same --constraint option.
Tested on macOS with Homebrew Python 3.13 and Airflow 3.3.2.