Apache Airflow — HAOS Apps 애드온 설치 가이드
Home Assistant OS(HAOS)의 Apps(구 애드온) 기능으로 Apache Airflow를 설치하기 위한 구성입니다. Standalone 모드(webserver + scheduler + triggerer가 컨테이너 1개에서 동작)로 실행하며, 메타데이터 DB는 이미 구축되어 있는 외부 PostgreSQL 서버(HA에서 쓰는 서버와 동일 인스턴스, DB는 분리)를 사용합니다.
1. 왜 n8n처럼 image만 지정하면 안 되는가
| n8n | Apache Airflow | |
|---|---|---|
| 공식 이미지 실행 방식 | 컨테이너를 그냥 실행하면 서버가 자동으로 뜸 | ENTRYPOINT만 있고, 실행 시 webserver / scheduler / standalone 같은 명령 인자를 직접 줘야 함 |
HAOS Apps config.yaml | image: 옵션만으로 충분 | image: 옵션에는 command/args를 지정하는 필드가 없음 |
| 결론 | image pull 방식으로 끝 | 얇은 Dockerfile + 실행 스크립트(run.sh)가 반드시 필요 |
그래서 이번 구성은 image를 쓰지 않고, Supervisor가 직접 빌드하도록 Dockerfile을 포함합니다.
2. 파일 구성
apache_airflow/
├── config.yaml # 애드온 메타데이터 + 옵션 스키마
├── Dockerfile # apache/airflow 공식 이미지를 기반으로 한 얇은 빌드 정의 (config.yaml의 version을 BUILD_VERSION으로 자동 전달받아 이미지 태그에 사용)
├── run.sh # 옵션 → 환경변수 변환, DB 준비, airflow standalone 실행
└── README.md # 이 문서
이 폴더 전체를 로컬 애드온 저장소(/addons/) 또는 GitHub 애드온 저장소에 그대로 올리면 Supervisor가 인식합니다.
3. config.yaml 옵션 설명
| 옵션 | 설명 | 기본값 |
|---|---|---|
postgres_host | Postgres 서버 호스트명 또는 IP | (필수 입력) |
postgres_port | Postgres 포트 | 5432 |
postgres_db | Airflow 전용 메타 DB 이름 | airflow |
postgres_user | 접속 계정 | airflow |
postgres_password | 접속 비밀번호 | (필수 입력) |
executor | LocalExecutor(병렬 실행) 또는 SequentialExecutor(순차 실행) | LocalExecutor |
admin_username | 웹 UI 관리자 계정명 | admin |
load_examples | 샘플 DAG 로드 여부 | false |
timezone | Airflow 기본 표시 타임존 | Asia/Seoul |
fernet_key | Connection 암호화 키. 비워두면 재시작마다 새로 생성되어 기존 Connection 값을 못 읽게 될 수 있음 | (아래 명령으로 발급한 값이 이미 채워져 있음) |
fernet_key 발급 방법
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
config.yaml의fernet_key기본값은 위 명령으로 실제 발급한 값입니다. 재발급하고 싶다면 위 명령을 다시 실행해 나온 값으로 옵션을 교체하세요. 단, 기존 값을 바꾸면 그 키로 암호화된 기존 Connection의 비밀번호를 더 이상 복호화하지 못하니, 값을 바꿀 때는 Connection들을 다시 등록해야 할 수 있습니다.
map 설정으로 두 개의 영구 저장 경로가 컨테이너에 마운트됩니다.
| map type | 컨테이너 경로 | 용도 |
|---|---|---|
addon_config | /config (AIRFLOW_HOME) | DAG, 로그, 플러그인 등 Airflow 전체 데이터 영속화 |
4. 관리자 비밀번호 확인 (Airflow 3.x)
Airflow 3.x는 airflow standalone 실행 시 인증 관리자를 SimpleAuthManager로 강제합니다. 이 관리자는 사용자명/역할만 설정 가능하고(admin_username), 비밀번호는 항상 자동 생성됩니다. (이전에 있던 admin_password/admin_email/admin_firstname/admin_lastname 옵션은 Airflow 3.x에서 전혀 쓰이지 않아 옵션 목록에서 제거했습니다.)
- 최초 실행 시 로그(로그 탭)에 한 번 비밀번호가 출력됩니다.
- 이후에는
/config/simple_auth_manager_passwords.json.generated파일(addon_config, Samba/File editor로 접근 가능)에서 확인할 수 있습니다. 컨테이너 안에서는/config/...경로지만, HAOS 호스트 쪽 실제 경로는/addon_configs/local_apache_airflow/simple_auth_manager_passwords.json.generated입니다 (로컬 설치 기준. GitHub 저장소로 설치한 경우local_대신 해시된 저장소 식별자가 붙습니다). - 직접 원하는 값으로 바꾸고 싶다면 애드온을 중지한 뒤 이 파일을 열어 값을 수정하고 다시 시작하면 됩니다.
5. Postgres — 기존 HA용 서버 재사용하기
HA(Recorder)가 쓰고 있는 Postgres 서버(postgres/postgres/homeassistant)를 그대로 재사용할 수 있습니다. 단,
- ✅ 서버/계정(
postgres/postgres)은 재사용해도 안전 — 접속만 하는 것이므로 문제 없음 - ⚠️ DB(
homeassistant)는 재사용하지 말 것 — Airflow가db migrate로 자체 테이블(수십 개)을 만드는데, HA Recorder의 purge/vacuum 부하 및 스키마 마이그레이션과 섞이면 유지보수가 어려워짐
그래서 postgres_db 옵션은 기본값 airflow로 DB만 분리해서 씁니다. run.sh가 시작 시 airflow DB가 없으면 postgres 계정 권한으로 자동 생성하므로, 사용자가 미리 DB를 만들어둘 필요는 없습니다. 다음 값만 채우면 됩니다.
postgres_host: "<HA Postgres 애드온의 내부 호스트명>"
postgres_port: 5432
postgres_user: "postgres"
postgres_password: "postgres"
postgres_db: "airflow"
postgres_host를 모른다면: HA 애드온 간 내부 DNS 이름은{REPO}_{SLUG}형식에서_를-로 바꾼 값입니다(예: 로컬 설치는local-<슬러그>, 저장소 설치는<해시>-<슬러그>). 정확한 값은 사용 중인 Postgres 애드온의 문서/로그에서 확인하세요.
6. run.sh 동작 순서
/data/options.json(애드온 설정 화면에서 입력한 값)을jq로 읽어 셸 변수로 변환postgres_host/postgres_password가 비어 있으면 즉시 종료 (필수값 검증)psql로postgres_db가 존재하는지 확인 → 없으면 자동 생성AIRFLOW__*환경변수 설정 (DB 커넥션 문자열, executor, 타임존, fernet key,simple_auth_manager_users등)airflow db migrate— 메타 DB 스키마 초기화/갱신exec airflow standalone— webserver(api-server) + scheduler + triggerer 실행. 관리자 계정은 SimpleAuthManager가 자동 생성
7. 설치 절차
apache_airflow/폴더(이 4개 파일 포함)를 HA의 로컬 애드온 경로(/addons/apache_airflow/)에 두거나, GitHub 저장소로 만들어 설정 → 애드온 → 애드온 스토어 → 저장소 추가로 등록- 애드온 스토어에서 “Apache Airflow” 설치 (최초 설치 시 Supervisor가 Dockerfile을 직접 빌드하므로 몇 분 소요될 수 있음)
- 설정 탭에서 위 옵션들을 입력 (
postgres_host,postgres_password최소 필수) - 애드온 시작 → 로그 탭에서
Airflow is ready메시지와 함께 출력되는 관리자 비밀번호를 확인 (섹션 4 참고) - Supervisor 패널의 “웹 UI 열기” 버튼 또는
http://<HAOS IP>:8088접속 →admin_username과 위에서 확인한 비밀번호로 로그인
8. 주의사항 / 트러블슈팅
- 인증 관리자 제약: Airflow 3.x의
airflow standalone은 다른 인증 관리자(FAB 등)를 설정해도 무조건 SimpleAuthManager를 강제합니다. 커스텀 비밀번호나 FAB 기반 세밀한 권한 관리가 꼭 필요하다면 standalone 대신 webserver(api-server)/scheduler/dag-processor/triggerer를 각각 별도 프로세스로 띄우는 구조로 다시 설계해야 합니다. - root 권한 실행: 이 이미지는 관리 편의를 위해
AIRFLOW_ALLOW_RUNNING_AS_ROOT=true로 root 실행되도록 되어 있습니다. 보안을 더 강화하고 싶다면 비루트 실행으로 전환할 수 있습니다(권한/볼륨 소유권 추가 설정 필요). - SQLite가 아님: Standalone이라고 해서 SQLite를 쓰는 게 아니라, 지정한 외부 Postgres를 그대로 사용합니다. 따라서
executor: LocalExecutor로 병렬 실행이 가능합니다. - DAG 추가 방법:
/share(Samba/File editor로 접근 가능) 또는/config/dags(addon_config, 애드온 내부 전용)에.py파일을 올리면 자동으로 인식됩니다. - 수정사항 반영에는 재빌드가 필요:
run.sh,Dockerfile은COPY/FROM으로 이미지 안에 박혀 빌드되는 파일이라, 파일 내용만 바꾸고 애드온을 재시작해도 반영되지 않습니다. 애드온 페이지에서 재빌드를 실행하거나, 캐시가 재사용되는 것 같으면(빌드 로그에Using cache만 뜨는 경우) 애드온을 삭제 후 재설치하세요. load_examples등 boolean 옵션이 빈 값("")으로 넘어가는 문제:run.sh의get_option()이 과거jq -r ".$1 // empty"형태였는데, jq의//연산자는false도 “값 없음”으로 취급해 빈 문자열로 바꿔버립니다. 그 결과AIRFLOW__CORE__LOAD_EXAMPLES=""가 되어AirflowConfigException: Failed to convert value to bool에러와 함께 scheduler/triggerer/dag-processor가 전부 죽는 증상이 발생했습니다 (webserver 격인 api-server는 이 코드 경로를 안 타서 죽지 않고 떠 있어서 원인 파악이 헷갈릴 수 있음). 지금 버전은has()로 키 존재 여부만 검사하도록 고쳤고,load_examples에는 추가로${LOAD_EXAMPLES:-false}폴백을 넣어 어떤 이유로든 값이 비면 안전하게false로 떨어지게 했습니다.- 버전 업그레이드:
config.yaml의version값만 올리면 됩니다 (예:3.3.0→3.3.1). Supervisor가 빌드 시 이 값을BUILD_VERSION빌드 인자로 자동 전달하고,Dockerfile이 이를 받아FROM apache/airflow:${BUILD_VERSION}-python3.11과LABEL io.hass.version에 그대로 사용하므로Dockerfile은 따로 손댈 필요가 없습니다.- 단, 올리려는 버전의
apache/airflow:<version>-python3.11이미지 태그가 Docker Hub에 실제로 존재하는지 먼저 확인하세요. - 2.x → 3.x처럼 메이저 버전을 건널 때는 DAG 코드/Provider 호환성도 반드시 사전 확인하세요 (공식 업그레이드 가이드).
version만 바꿔도 이미지는 새로 재빌드해야 반영됩니다. 애드온 페이지의 재빌드 버튼을 쓰거나, 캐시가 재사용되는 것 같으면 애드온을 삭제 후 재설치하세요.
- 단, 올리려는 버전의
- 백업:
addon_config(/config)만 백업하면 DAG/로그/플러그인은 복구되지만, 메타데이터는 Postgres 서버 쪽 백업에 의존합니다. Postgres 백업 주기를 꼭 확인하세요. 메이저 버전 업그레이드 전에는 Postgres 쪽airflowDB를 반드시pg_dump로 백업해두는 걸 강력히 권장합니다.