Apache Airflow — HAOS App (Local App)

Apache Airflow — HAOS Apps 애드온 설치 가이드

Home Assistant OS(HAOS)의 Apps(구 애드온) 기능으로 Apache Airflow를 설치하기 위한 구성입니다. Standalone 모드(webserver + scheduler + triggerer가 컨테이너 1개에서 동작)로 실행하며, 메타데이터 DB는 이미 구축되어 있는 외부 PostgreSQL 서버(HA에서 쓰는 서버와 동일 인스턴스, DB는 분리)를 사용합니다.


1. 왜 n8n처럼 image만 지정하면 안 되는가

n8nApache Airflow
공식 이미지 실행 방식컨테이너를 그냥 실행하면 서버가 자동으로 뜸ENTRYPOINT만 있고, 실행 시 webserver / scheduler / standalone 같은 명령 인자를 직접 줘야 함
HAOS Apps config.yamlimage: 옵션만으로 충분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_hostPostgres 서버 호스트명 또는 IP(필수 입력)
postgres_portPostgres 포트5432
postgres_dbAirflow 전용 메타 DB 이름airflow
postgres_user접속 계정airflow
postgres_password접속 비밀번호(필수 입력)
executorLocalExecutor(병렬 실행) 또는 SequentialExecutor(순차 실행)LocalExecutor
admin_username웹 UI 관리자 계정명admin
load_examples샘플 DAG 로드 여부false
timezoneAirflow 기본 표시 타임존Asia/Seoul
fernet_keyConnection 암호화 키. 비워두면 재시작마다 새로 생성되어 기존 Connection 값을 못 읽게 될 수 있음(아래 명령으로 발급한 값이 이미 채워져 있음)

fernet_key 발급 방법

python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

config.yamlfernet_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 옵션은 기본값 airflowDB만 분리해서 씁니다. 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 동작 순서

  1. /data/options.json(애드온 설정 화면에서 입력한 값)을 jq로 읽어 셸 변수로 변환
  2. postgres_host / postgres_password가 비어 있으면 즉시 종료 (필수값 검증)
  3. psqlpostgres_db가 존재하는지 확인 → 없으면 자동 생성
  4. AIRFLOW__* 환경변수 설정 (DB 커넥션 문자열, executor, 타임존, fernet key, simple_auth_manager_users 등)
  5. airflow db migrate — 메타 DB 스키마 초기화/갱신
  6. exec airflow standalone — webserver(api-server) + scheduler + triggerer 실행. 관리자 계정은 SimpleAuthManager가 자동 생성

7. 설치 절차

  1. apache_airflow/ 폴더(이 4개 파일 포함)를 HA의 로컬 애드온 경로(/addons/apache_airflow/)에 두거나, GitHub 저장소로 만들어 설정 → 애드온 → 애드온 스토어 → 저장소 추가로 등록
  2. 애드온 스토어에서 “Apache Airflow” 설치 (최초 설치 시 Supervisor가 Dockerfile을 직접 빌드하므로 몇 분 소요될 수 있음)
  3. 설정 탭에서 위 옵션들을 입력 (postgres_host, postgres_password 최소 필수)
  4. 애드온 시작 → 로그 탭에서 Airflow is ready 메시지와 함께 출력되는 관리자 비밀번호를 확인 (섹션 4 참고)
  5. 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, DockerfileCOPY/FROM으로 이미지 안에 박혀 빌드되는 파일이라, 파일 내용만 바꾸고 애드온을 재시작해도 반영되지 않습니다. 애드온 페이지에서 재빌드를 실행하거나, 캐시가 재사용되는 것 같으면(빌드 로그에 Using cache만 뜨는 경우) 애드온을 삭제 후 재설치하세요.
  • load_examples 등 boolean 옵션이 빈 값("")으로 넘어가는 문제: run.shget_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.yamlversion 값만 올리면 됩니다 (예: 3.3.03.3.1). Supervisor가 빌드 시 이 값을 BUILD_VERSION 빌드 인자로 자동 전달하고, Dockerfile이 이를 받아 FROM apache/airflow:${BUILD_VERSION}-python3.11LABEL 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 쪽 airflow DB를 반드시 pg_dump로 백업해두는 걸 강력히 권장합니다.