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.

References