
Semaphore UI 2.20은 SIEM 내보내기를 지원하는 감사 로그를 추가하고, 지연 노드, 리비전, 작업 간에 전달되는 출력, 워크플로 변수로 워크플로를 본격적인 파이프라인 엔진으로 성장시키며, 한 구성원이 여러 역할을 가질 수 있고 관리자가 인스턴스 전역 역할과 IdP 그룹 매핑을 사용할 수 있도록 역할을 재설계하고, 호스트별 SSH 및 Git 자격 증명을 위한 호스트 설정을 도입하며, 모든 Ansible 추가 변수를 Vault로 암호화된 파일로 옮기고, Prometheus 지표를 노출합니다.
이 라인은 v2.20.0에서 시작합니다. 패치 릴리스는 출시되는 대로 이 페이지 마지막에 정리됩니다.
주요 내용
- 감사 로그 — 누가, 어디서, 무엇을 했고 결과가 무엇이었는지; 관리자 화면, 보존 기간, SIEM을 위한 Syslog / Splunk HEC 내보내기(내보내기와 필터는 Pro).
- 워크플로 — 지연 노드, 실행에 고정되는 불변 리비전, 다음 작업의 입력으로 전달되는 출력, 실행 대화 상자에서 묻는 워크플로 변수, 단축키와 실행 취소를 갖춘 새로 디자인된 편집기, 워크플로를 시작하는 웹훅.
- 구성원별 여러 역할, ID와 슬러그를 갖는 역할, 인스턴스 전역 권한을 부여하는 전역 역할(Pro), 로그인 시 적용되는 IdP 그룹 → 역할 매핑(Enterprise).
- 외부 신원 — LDAP 및 OIDC 로그인이 이메일이 아니라 공급자의 안정적인 ID로 계정에 연결됩니다; 하나의 로그인 페이지에 여러 LDAP 디렉터리.
- 호스트 설정 — SSH 호스트와 Git URL을 프로젝트 자격 증명에 매핑하여 클론, Galaxy, Terraform 모듈, Ansible에 적용합니다.
- Ansible 추가 변수가 더 이상 명령줄에 나타나지 않습니다; 시크릿은 Ansible Vault로 암호화된 파일로 전달되며, 값 안의 Jinja2는 더 이상 평가되지 않습니다.
- 템플릿: Ansible 작업 디렉터리, 고유한 이름과 작업 API의
template_name, 오류 알림 억제, Dry Run / Diff 숨기기, Galaxy 설치 옵션, 다중 선택 설문 변수, 원격 러너의 설문 시크릿. - 모노레포 저장소는 템플릿 간에 하나의 체크아웃을 공유합니다; Git 재시도, 병렬 서브모듈 가져오기, SSH 호스트 키 검사.
/api/metrics의 Prometheus 지표.- 서버에서 SSH 키 쌍 생성, 그리고 키 저장소에서 공개 키 복사.
감사 로그

Semaphore는 이제 보안과 관련된 이벤트를 전용 추가 전용(append‑only) 로그에 기록합니다. 다음과 같이 활성화합니다:
"audit": {
"enabled": true,
"instance_id": "semaphore-prod"
}
(SEMAPHORE_AUDIT_ENABLED, SEMAPHORE_AUDIT_INSTANCE_ID; instance_id는 필수이며 모든 이벤트에서
해당 설치 환경을 식별합니다.)
기록되는 내용. 8개 범주에 걸친 116가지 이벤트 종류: auth(로그인, 로그아웃, MFA, API 토큰 거부,
거부된 요청, CSRF 차단), iam(사용자, 비밀번호, API 토큰, 신원, 멤버십, 역할, 템플릿 권한),
resource(프로젝트, 백업, 인벤토리, 저장소, 템플릿, 일정, 통합, 호스트 설정, 워크플로, 변수 그룹),
secret(자격 증명 및 시크릿 저장소), task(트리거와 함께 시작, 결과 및 소요 시간과 함께 완료, 승인,
중지, 기록 삭제), runner(등록, 변경, 거부된 보고), system(설정, 라이선스), 그리고 audit 자체
(시작, 보존, 내보내기). 비밀번호, 토큰, 시크릿 값, 작업 출력과 변수는 절대 기록되지 않습니다.
이벤트 엔벨로프. 모든 이벤트는 UUID, 빈틈없는 시퀀스 번호, 마이크로초 단위 UTC 타임스탬프,
행위자(사용자 / 익명 / 시스템 / 러너 / 통합, 세션 또는 API 토큰 인증 방식과 토큰 지문 포함), 출처 IP와
User‑Agent, 대상, 프로젝트, 요청 ID(X-Request-ID 응답 헤더로도 반환), 인스턴스 ID, HA 노드 ID를
담습니다. 결과는 success 또는 failure이며 사유는 정해진 목록에서 선택됩니다; 객체는 저장했지만
이후 단계에서 실패한 작업은 partial = true인 성공으로 기록됩니다. 리버스 프록시 뒤에서는
X-Forwarded-For를 audit.trusted_proxy_cidrs에서 온 경우에만 신뢰합니다.

관리자 화면. 사용자 메뉴의 감사 로그(/audit-log)는 이벤트를 최신순으로 페이지당 50개씩
나열하며 이전 / 최신 페이지 이동을 제공합니다; 행을 열면 누가, 객체, 위치, 시각, 상세,
기술 정보 섹션과 이벤트를 SIEM으로 전송되는 JSON 형태로 복사하는 버튼이 있는 카드가 표시됩니다.
접근에는 새로운 감사 로그 읽기 전역 권한이 필요합니다.
보존. audit.retention_days는 더 오래된 이벤트를 일괄 삭제하며, HA 노드가 서로 충돌하지 않도록
지터를 두고 매시간 실행됩니다; 무언가를 삭제한 모든 실행은 그 자체로 기록됩니다.
Pro: 필터 및 내보내기. 기간, 사용자, 프로젝트, 이벤트 종류, 결과, IP로 필터링하고; 카드의 임의 값을 기준으로 전환하며; 현재 선택 항목을 CSV 또는 JSON Lines로 내보냅니다.
Pro: SIEM 내보내기. 수신기가 중단되어도 아무것도 누락되지 않도록 각자 커서를 갖는 두 가지 대상:
audit.syslog를 통한 TLS 기반 Syslog(RFC 5424, 이벤트 JSON을 본문으로)와 audit.splunk_hec를
통한 Splunk HTTP Event Collector(url, token, index, source, sourcetype, ca_file, …).
전달은 시퀀스 순서대로 최소 한 번 보장되며, HA에서는 Redis 리스로 조정하여 대상마다 한 노드만
내보냅니다. 세 가지 Prometheus 시리즈가 내보내기 상태를 설명합니다:
semaphore_audit_export_pending_events, semaphore_audit_export_oldest_pending_seconds,
semaphore_audit_export_errors_total.
저장: 테이블 audit_event, audit_event_sequence, audit_export_state(마이그레이션 v2.20.9부터
v2.20.11까지). API: GET /api/audit/events 및 GET /api/audit/events/export.
워크플로
워크플로는 Pro 기능입니다; Beta 라벨은 사라졌습니다.
지연 노드
작업, 승인, 노트에 이어 네 번째 노드 종류입니다: 지연은 지정한 초 동안 실행을 일시 중지한 뒤
엣지를 해제합니다. 실행 보기는 카드에 실시간 카운트다운을 표시하며, 실행을 중지하면 지연도
취소됩니다. 필드 delay_seconds, 마이그레이션 v2.20.2.
리비전
워크플로를 저장할 때마다 그래프의 새 리비전이 생성됩니다; 실행은 자신이 시작한 리비전을
고정하므로, 워크플로를 편집해도 진행 중인 실행이 바뀌지 않고 과거 실행의 노드가 고아가 되지
않습니다. 편집기는 rev. N 칩과 이전 리비전을 아직 실행 중인 실행 수를 표시하고, 실행 보기는 어떤
리비전을 실행하는지 보여줍니다. 어떤 실행도 참조하지 않는 리비전은 더 새로운 리비전이 저장될 때
삭제됩니다. API: GET …/workflows/{id}/revisions 및 …/revisions/{revision_id}.
출력과 입력

작업은 그 뒤의 노드에 구조화된 데이터를 넘길 수 있습니다. 워크플로가 시작한 모든 작업은
SEMAPHORE_OUTPUTS_FILE을 받으며, 거기에 JSON 객체로 기록한 내용이 그 작업의 출력이 됩니다:
cat > "$SEMAPHORE_OUTPUTS_FILE" <<EOF
{"image_tag": "1.4.2", "replicas": 3, "subnet_ids": ["subnet-1", "subnet-2"]}
EOF
Ansible은 번들로 제공되는 콜백 플러그인을 통해 ansible.builtin.set_stats로 출력을 생성합니다;
Terraform, OpenTofu, Terragrunt의 출력은 output -json에서 자동으로 수집됩니다(sensitive 값은
건너뛰고 수집되지 않음으로 표시됩니다). 출력은 작업이 성공할 때만 읽히며, 제한은 출력 100개, 각
32 KB, 파일당 256 KB입니다.
작업 노드로 들어오는 연결은 입력을 전달합니다 — 원본 노드의 출력으로 대상 템플릿의 설문 변수를 채웁니다:
- 이름 기준(기본값): 이름이 설문 변수와 같은 모든 출력이 해당 변수를 채웁니다.
- 입력 명시적 매핑: 전달할
variable ← output key쌍을 나열합니다; 워크플로에 완료된 실행이 있으면 패널이 그 실행이 생성한 키를 제안합니다.

값은 변수 유형으로 변환되고, 승인 및 지연 노드는 출력을 그대로 통과시키며, 명시적 매핑이 이름 기준
전달보다 우선하고, 필수 변수에 값이 없으면 노드의 작업이 시작되기 전에 실패하여 실행이 실패 시
엣지를 따라갑니다. 실행 보기는 노드별로 출력 N개 배지를 표시하고, 작업 대화 상자에는 출력 표가
있으며, 작업 로그는 전달된 값마다 Input "x" <- output "y" of node N 줄로 시작합니다. 출력은 평문으로
저장되고 secret 변수를 절대 채우지 않습니다; secret은 출력으로 전달할 수 없습니다. 원격 러너의
작업도 출력을 생성하고 받습니다; Docker 및 Kubernetes 실행기는 아직 출력을 수집하지 않습니다.

워크플로 변수와 실행 대화 상자
워크플로는 자체 설문 변수를 가지며, 실행이 시작될 때 실행 “…” 대화 상자에서 한 번 묻습니다
(변수가 없는 워크플로는 이전처럼 즉시 시작합니다). 답변은 실행에 저장되고, 실행 캔버스 위의
변수 띠에 칩으로 표시되며, 노드 패널의 명시적 바인딩을 통해서만 작업에 도달합니다 — 워크플로
변수가 이름만으로 템플릿에 유입되는 일은 없습니다. 시크릿은 워크플로 변수로 허용되지 않습니다.
POST …/workflows/{id}/runs는 {"environment": {"image_tag": "1.4.3"}}를 받습니다; 유형에 맞지 않는
답변이나 누락된 필수 값은 시작을 거부합니다.
워크플로 작업의 환경
워크플로가 시작한 모든 작업은 모든 앱에서, 원격 러너에서도 SEMAPHORE_WORKFLOW_ID,
SEMAPHORE_WORKFLOW_RUN_ID, SEMAPHORE_WORKFLOW_URL(web_host 필요),
SEMAPHORE_OUTPUTS_FILE을 받습니다.
새로 디자인된 편집기

- 종류 타일, 상태, 소요 시간, 출력 배지, 인라인 승인 / 거부를 갖춘 새로운 노드 카드; 즉석 조건 드롭다운과 삭제 버튼이 있는 엣지 라벨; 점 격자 캔버스.
- 노드의
+핸들, 캔버스 우클릭 또는 빈 상태 버튼에서 열리는 빠른 추가 메뉴: 노드 종류와 작업 템플릿을 검색할 수 있는 목록이며, 새 노드는 성공 시로 연결됩니다. - 실행 취소 / 다시 실행(
Ctrl/⌘+Z,Ctrl/⌘+Shift+Z), 워크플로 이름의 인라인 변경, 문제가 있는 노드로 이동하는 문제 메뉴, 저장되지 않은 변경을 알리는 저장 배지, 페이지 이탈 경고. - 캔버스 단축키: 화살표로 이동(
Shift로 크게),+/-확대/축소,0으로 그래프 맞춤,1로 확대 초기화,Esc로 선택 해제; 노드 카드는 키보드로 포커스할 수 있습니다. - 플로팅 컨트롤: 확대 / 축소, 보기 맞춤, 정리 자동 레이아웃, 확대 비율.
- 셰브론 하나로 팔레트와 주 내비게이션을 함께 접을 수 있으며, 상태가 기억됩니다.
- 트랙패드 오버스크롤이 더 이상 macOS에서 브라우저의 뒤로 가기 제스처를 유발하지 않습니다.

웹훅이 워크플로를 시작합니다
이제 통합이 템플릿 대신 워크플로를 실행할 수 있습니다(통합 양식의 실행: 템플릿 / 워크플로).
추출된 모든 값은 워크플로 설문의 답변이 됩니다. 이러한 통합을 관리하려면 Pro의
workflow_integrations_management 기능이 필요합니다. 템플릿 통합에서는 템플릿이 재정의를 허용하는
경우, git_branch라는 이름으로 추출된 작업 매개변수 값이 시작되는 작업의 브랜치를 설정합니다.
API 변경
POST …/workflows/{id}/run이 POST …/workflows/{id}/runs로 이름이 변경되었으며 environment
본문을 받습니다. 실행 상세 정보에는 revision_id, revision, 노드별 delay 객체, task.artifacts가
포함됩니다. 클라이언트가 작업에 지정한 workflow_run_id, workflow_node_id, artifacts는
무시되므로, 작업이 다른 사람의 실행에 속한 노드인 것처럼 위장할 수 없습니다.
역할 및 접근 제어
구성원별 여러 역할

프로젝트 구성원은 역할 집합을 가지며, 팀 페이지에서 칩으로 편집합니다. API는 기존 role과 함께
roles: ["manager", "release_approver"]를 받습니다; 응답은 역할이 하나인 구성원에 대해서만 스칼라
role을 유지합니다. 관리자가 아닌 사용자는 마지막 소유자로부터 기본 제공 Owner 역할을 가져올 수
없습니다.
ID, 슬러그, 범위를 갖는 역할
역할은 이제 정수 id와 slug(^[A-Za-z0-9_-]{1,100}$, 양식의 이름에서 파생)를 갖는 행입니다; 네
가지 기본 제공 역할도 행이며 더 이상 사용자 지정 역할로 가려질 수 없습니다. 역할에는 범위가
있습니다: 기본 제공, 공유(모든 프로젝트에서 사용 가능), 프로젝트. 사용 중인 역할을 삭제하면 영향
범위(구성원, 프로젝트, 템플릿 권한, 매핑)와 함께 409를 반환하며, ?force=true로 다시 시도할 수
있습니다 — UI에서는 할당과 함께 삭제. 마이그레이션 v2.20.12와 v2.20.13이 역할 테이블을 다시
빌드합니다; 업그레이드 참고 사항을 확인하십시오.
전역 역할 및 권한 (Pro)

인스턴스 전역 권한이 더 이상 관리자 플래그만으로 결정되지 않습니다. 전역 역할은 네 가지 권한
마스크 — 사용자 관리, 전역 역할 관리, 시스템 설정 관리, 감사 로그 읽기 — 를 부여하며, 사용자
페이지의 역할 탭(/users/roles)과 사용자 대화 상자의 전역 역할 탭에서 사용자에게 할당합니다.
이 탭은 유효 권한과 각 권한을 부여하는 역할도 함께 보여줍니다. 모든 관리 라우트는 네 비트 중
하나로 보호되며, GET /api/user는 global_permissions를 반환합니다. 인스턴스는 항상 관리자를 최소
한 명 유지하며, 이는 HA 노드 간에 안전한 행 잠금으로 보장됩니다. 사용자 관리 권한을 가진 사용자는
관리자나 자신에게 없는 권한을 가진 사용자를 편집할 수 없습니다. API: /api/global-roles,
/api/users/{id}/global-roles, /api/users/{id}/global-permissions, 카탈로그는
/api/global-roles/permissions.
그룹 역할 매핑 (Enterprise)

새로운 그룹 매핑 페이지(/role-mappings)에서 신원 공급자 그룹을 프로젝트 역할에 매핑합니다:
공급자, 그룹, 프로젝트, 역할. OIDC 로그인마다 사용자의 매핑된 역할이 토큰의 그룹(공급자의
groups_claim)과 일치하도록 조정됩니다. 매핑된 역할은 팀 페이지에서 provider: group 툴팁이 있는
잠긴 칩으로 표시되며 구성원 역할로서 제거할 수 없습니다; 매핑된 역할은 프로젝트의 마지막 소유자로
계산되지 않습니다. 비밀번호 또는 LDAP 로그인은 그룹 정보를 전달하지 않으므로 매핑된 역할을
지웁니다. API: /api/role_mappings.
인증 및 신원

- 외부 신원. LDAP 및 OIDC 로그인은 이메일이 아니라 공급자의 안정적인 ID(OIDC
sub, LDAP DN)로 새user__external_identity테이블을 통해 Semaphore 계정에 연결됩니다. 이로써 입력한 주소를 그대로 받아들이는 IdP가 다른 사람의 계정을 차지하던 유형의 버그가 사라집니다.external_auth_email_matching(기본값auto, 그 외always,never)은 신원이 없는 기존 외부 사용자를 이메일로 한 번 더 매칭할 수 있는지 제어합니다; 로컬 비밀번호 계정은 절대 차지되지 않습니다. OIDC 이메일은email_verified이고 공급자가require_verified_email을 설정한 경우에만 인정됩니다. 사용자는 계정 대화 상자에서 직접 신원을 연결하고 해제합니다 (/api/users/{id}/identities,POST /api/user/identities/ldap,/api/auth/oidc/{provider}/login?link=1). - 여러 LDAP 디렉터리.
ldap_providers는 이름이 지정된 디렉터리의 맵이며, 각 디렉터리는 자체 서버, 바인드, 검색, 매핑, 색상, 순서를 가집니다; 기존의 평면ldap_*블록은ldap공급자로 계속 작동합니다. 로그인 페이지는 탭이 둘 이상일 때 선택기를 표시하며, 내부 탭은 비밀번호를 디렉터리로 보내지 않습니다.GET /api/auth/login은ldap_providers와login_with_password를 반환합니다. - LDAPS 인증서가 기본적으로 검증됩니다. 자체 서명 인증서에는
ldap_tls_skip_verify(평면 블록) 또는tls_skip_verify(공급자별)를 설정하십시오. - 절대 세션 수명.
auth.max_session_life_hours(SEMAPHORE_AUTH_MAX_SESSION_LIFE_HOURS)는 활동 여부와 무관하게 로그인 후 정해진 시간이 지나면 세션을 만료시킵니다;0은 비활성 타임아웃만 유지합니다. - 프로젝트가 없고 생성 권한도 없는 사용자는 제출할 수 없는 양식 대신 아직 프로젝트가 없습니다
페이지를 보게 됩니다; 이 경우
POST /api/projects는403을 반환합니다. - 사용자 메뉴에서 선택한 언어가 서버에 저장되어 브라우저가 달라도 사용자를 따라갑니다
(
/api/user/options의lang).
호스트 설정

새로운 프로젝트 페이지 호스트 설정은 SSH 호스트와 Git URL을 프로젝트 자격 증명에 매핑합니다:
- 호스트 매핑(
bastion.example.com)은 생성된ssh_config의Host블록으로서 SSH 키를 연결합니다; - URL 매핑(
https://github.com/acme/,/로 끝나는 접두사는 그룹 전체를 포함)은 GitinsteadOf재작성으로서 SSH 키 또는 로그인/비밀번호(HTTPS만)를 연결합니다; 가장 구체적인 URL이 우선합니다.
매핑은 템플릿 저장소와 그 서브모듈, requirements.yml의 롤과 컬렉션, terraform init 모듈,
플레이북이 실행하는 git 명령, 인벤토리 저장소와 인벤토리 호스트, 그리고 브랜치 및 플레이북 탐색에
적용되며, 원격 러너로도 전달됩니다. 비공개 키는 디스크에 닿지 않습니다 — 매핑마다 SSH 에이전트가
하나씩 IdentityAgent로 바인딩됩니다; 비밀번호는 GIT_CONFIG_PARAMETERS를 통해 전달되고, 저장소
URL은 작업 로그에서 마스킹됩니다. 매핑이 참조하는 키는 삭제할 수 없습니다. 매핑은 프로젝트 백업에
포함됩니다. git_client: cmd_git이 필요합니다. 테이블 project__host_config, 마이그레이션
v2.20.7; API /api/project/{id}/host_configs.
템플릿 및 작업

-
Ansible 작업 디렉터리. 다른 작업 디렉터리는 저장소의 하위 디렉터리에서
ansible-playbook을 실행합니다; 경로는 체크아웃 내부에 있어야 합니다(working_directory, 마이그레이션v2.20.3). -
프로젝트별 고유한 템플릿 이름(마이그레이션
v2.20.4), 그리고POST /api/project/{id}/tasks가template_id대신template_name을 받습니다. -
템플릿별 오류 알림 억제 — 기존의 성공 알림 억제와 나란히 제공됩니다; 이메일 알림이 처음으로 두 설정을 모두 따릅니다(
suppress_error_alerts, 마이그레이션v2.20.5). -
템플릿별로 작업 대화 상자에서 Dry Run / Diff 숨기기; 서버도 해당 템플릿에 대해
--check/--diff추가를 중단합니다(task_params.hide_dry_run,hide_diff). -
Galaxy 설치 옵션 — Galaxy 설치 건너뛰기,
ansible-galaxy role install및collection install을 위한 개별 CLI 인수(플래그 허용 목록 방식이며,--token,--api-key와 경로 플래그는 거부됩니다), 작업별 재정의 프롬프트를 담은 접을 수 있는 섹션. -
플레이북 선택기는 입력하는 대로 하위 디렉터리를 나열하고 앱별로 필터링하며(Ansible은
.yml, Terraform / OpenTofu / Terragrunt / Pulumi는 최상위 디렉터리, 그 외.sh,.py,.ps1), Ansible 레이아웃 디렉터리와 점으로 시작하는 디렉터리를 건너뛰고, 항목을 30개로 제한하며, 저장소 루트에 한정된 얕은 클론을 탐색합니다. -
다중 선택 설문 변수 — 새로운
select유형은 여러 값을 받으며 작업 대화 상자에서 칩으로 렌더링됩니다;default_value는 배열일 수 있습니다.
-
설문 시크릿이 원격 러너에 도달합니다. 이전에는
secret설문 답변이 러너에 빈 값으로 도착했습니다. 이제는 작업에 바인딩된 액세스 키로 암호화되어 저장되고(access_key.task_id,expire_at, 마이그레이션v2.20.1), 러너를 담당하는 HA 노드가 복호화하며, 작업이 끝나면 삭제되고 매시간 정리됩니다; 키 저장소, 백업, 키 API에서는 숨겨집니다. -
YAML 추가 변수. 변수 그룹 편집기에 표 | JSON | YAML 토글과 전체 화면 편집기가 추가되었습니다; 변환은 엄격합니다(날짜는 문자열로 유지되고, 객체가 아닌 루트와 유한하지 않은 숫자는 거부됩니다). 저장 방식은 변경되지 않았습니다.

-
작업 페이지는 작업을 시작한 일정 또는 통합의 이름을 표시하고 링크하며, 삭제된 출처는
#id (deleted)로 표시합니다. 로그를 복사할 때 로그 타임스탬프가 더 이상 선택되지 않습니다. -
일정은 저장 전에 서버에서 표현식을 검증하므로
@hourly가 받아들여지며, 시간대 배너를 닫을 수 있습니다.
-
로컬 작업을 중지하면 프로세스 그룹 전체가 종료됩니다:
SIGTERM, 15초 유예 기간, 그다음SIGKILL; 고아가 된ssh또는 공급자 프로세스가 더 이상 작업보다 오래 살아남지 않습니다. 중지된 Terraform plan은 더 이상 계속되지 않으며,SIGTERM에0으로 종료된 plan을 성공으로 읽지 않습니다. -
인벤토리
repository_id는file유형에만 유지되며 해당 프로젝트에 속해야 합니다. -
서버 로그의 Task added to queue / Task started 항목에 사용자 이름이 표시됩니다.
시크릿 및 Ansible Vault
-
추가 변수가 명령줄이 아니라 파일로 전달됩니다. 변수 그룹, 설문 답변, 워크플로 입력, 작업 상세 정보는
--extra-vars @file로 전달되는0600YAML 파일에 기록됩니다. 시크릿 —secret설문 답변과 변수 그룹 시크릿 — 은 네이티브 Go 구현으로 Ansible Vault 1.1 / AES‑256 형식으로 암호화된 두 번째 파일에 들어가며(ansible-vault바이너리가 필요하지 않습니다),ansible-playbook의--vault-id <uuid>@prompt에 응답하는 일회용 비밀번호로 잠금이 해제됩니다. 값도 비밀번호도ps에 나타나지 않으며, 두 파일 모두 작업이 끝나면 제거됩니다. -
값 안의 Jinja2는 코드가 아니라 데이터입니다.
{{,{%,{#또는#jinja2:헤더를 포함한 모든 문자열은 재귀적으로!unsafe로 태그되므로,{{ lookup('pipe', 'id') }}와 같은 설문 답변은 문자 그대로 전달됩니다. 구분자가 없는 문자열은 의도적으로 태그하지 않습니다: ansible‑core 2.19 이상은!unsafe스칼라를 다시 해석하므로"2026.08"이 부동소수점 수로 바뀌게 됩니다. -
새로운
extra_vars디버그 네임스페이스(SEMAPHORE_DEBUG_FILTER=extra_vars)는 변수가 어떻게 분리되고 기록되는지 로깅합니다 — 이름, 파일, 크기만이며 값은 절대 기록하지 않습니다. -
서버에서 SSH 키 쌍 생성. 키 저장소의 SSH 키 생성은 RSA 키를 만듭니다; 공개 키는 키와 함께 보관되고 표시 / 숨기기와 복사 버튼으로 제공되며, 생성 직후 대화 상자에도 표시됩니다 (
generate_ssh_key).
-
키 업데이트는 재정의가 설정된 경우에만
type,secret과 공개 부분을 기록하므로, 클라이언트가 시크릿을 교체하지 않고 키의 페이로드를 변경할 수 없습니다. -
서버 환경 변수 또는
dirs.secrets아래 파일에서 자격 증명을 읽는 방법이 이제 문서화되었습니다(키 저장소 양식의 환경 변수 / 파일 탭).
저장소 및 Git
- 모노레포: 모든 템플릿에 단일 체크아웃. 저장소 옵션으로 템플릿마다 사본을 두는 대신 저장소를
한 번만 클론하여 템플릿 간에 공유합니다; 체크아웃은 fetch와 pull 동안 잠기며 이후 작업은 병렬로
실행됩니다. 이러한 저장소의 템플릿은 자체 브랜치를 가질 수 없고, 그 작업은 브랜치나 커밋을
재정의할 수 없습니다(
monorepo, 마이그레이션v2.20.11). - Git 재시도.
clone과pull은 최대 1분으로 제한된 지수 지연으로 재시도됩니다;git_attempts(SEMAPHORE_GIT_ATTEMPTS, 기본값4). - 병렬 서브모듈.
git_submodule_jobs(SEMAPHORE_GIT_SUBMODULE_JOBS, 기본값4)가--jobs로 전달됩니다. - SSH 호스트 키 검사. 새로운
ssh섹션:config_path,known_hosts_file(SEMAPHORE_SSH_KNOWN_HOSTS_FILE),strict_host_key_checking—no(기본값),yes또는accept-new— 이 SSH 기반 Git에 적용됩니다. - 저장소 탐색은 브랜치별 키를 갖는 얕은 클론을 사용합니다; 자격 증명은 베어메탈 클론을 위해 퍼센트 인코딩되며 로그와 이벤트 피드에서는 마스킹됩니다.
러너 및 통합
-
runner.check_interval_seconds(SEMAPHORE_RUNNER_CHECK_INTERVAL_SECONDS, 기본값5)는 러너가 얼마나 자주 폴링할지 설정합니다; 러너 페이지의 고급 옵션 스위치가 이 값을 생성된 환경 변수, 설정, Docker 스니펫에 넣습니다(v2.19.17에서 제공). -
runner.connection.timeout_seconds(SEMAPHORE_RUNNER_CONNECTION_TIMEOUT_SECONDS, 기본값3)는 연결, TLS 핸드셰이크, 응답 헤더를 각각 제한합니다; 로그 업로드는 중단되지 않습니다. -
runners.default_global_runners_mode(SEMAPHORE_DEFAULT_GLOBAL_RUNNERS_MODE:disable,prefer,require)가 더 이상 사용되지 않는use_remote_runner를 대체하고,runners.registration_token이 최상위runner_registration_token을 대체합니다. -
SEMAPHORE_DEBUG_FILTER=runner아래의 서버 측 러너 진단: 토큰 거부 사유, 재시작 및 온라인 감지, 거부된 진행 보고, 디스패치 추적. -
러너
unregister요청이 인증됩니다; 러너 클라이언트는 HTTP 리다이렉트를 거부합니다. -
기존 HMAC‑SHA256과 나란히 HMAC‑SHA512 웹훅 인증(
hmac-sha512); 서명 헤더를 설정할 수 있습니다.
-
통합이 다른 프로젝트에 속한 웹훅은 거부됩니다.
관측성
-
Prometheus 지표. 정적 서비스 자격 증명을 사용하는 HTTP Basic Auth 뒤의
GET /api/metrics:"metrics": { "enabled": true, "username": "prometheus", "password": "…" }(
SEMAPHORE_METRICS_ENABLED,SEMAPHORE_METRICS_USERNAME,SEMAPHORE_METRICS_PASSWORD.) 시리즈:semaphore_tasks_running,semaphore_tasks_total{status}, 표준go_*및process_*수집기, 그리고 Pro의 감사 내보내기 게이지. -
새로운 디버그 네임스페이스
extra_vars와runner; 저장소 탐색이 Git 출력을 DEBUG 수준으로 로깅합니다. -
프로젝트 백업의 내보내기와 복원이 로깅됩니다.
보안
- 이메일 대신 공급자 ID로 신원을 연결합니다; LDAPS 인증서 검증이 기본적으로 켜집니다.
- 추가 변수를 명령줄에서 제거했습니다; 시크릿은 Vault로 암호화되고, 값 안의 Jinja2는 평가되지 않습니다.
- 클라이언트가 보낸 작업에서 위조된
workflow_run_id,workflow_node_id,artifacts를 제거합니다. - 관리 라우트를 관리자 플래그가 아니라 명시적인 전역 권한으로 보호합니다; 알 수 없는 권한 비트는 거부됩니다; 사용자 관리에 권한 상승 방지 장치가 적용됩니다.
- 플레이북 선택기를 저장소 루트로 한정하고(
OpenRoot), 개수를 제한하고 필터링합니다. - 추가 변수의 루트와 YAML 숫자를 검증합니다; Galaxy CLI 인수에 허용 목록을 적용합니다.
- 저장소 자격 증명을 로그와 이벤트 피드에서 마스킹합니다; Git 설정 매개변수에서
=를 이스케이프합니다. - 감사 엔드포인트는 크로스 사이트 읽기와 잘못된 형식의 커서를 거부합니다; 신뢰할 수 있는 프록시 네트워크를 검증합니다.
- 러너
unregister가 인증됩니다; 러너 클라이언트가 리다이렉트를 거부합니다. - 웹훅의 프로젝트 및 통합 ID를 검증합니다.
- 로컬 작업을 프로세스 그룹 전체와 함께 중지합니다.
업그레이드 참고 사항
호환성이 깨지는 변경 및 동작 변경
- 템플릿 이름은 프로젝트별로 고유해야 합니다. 마이그레이션
v2.20.4가 고유 인덱스를 추가합니다; 업그레이드 전에 중복된 이름을 변경하십시오. - 역할 테이블이 다시 빌드됩니다(
v2.20.12/v2.20.13). 먼저 백업하십시오. 슬러그가 기본 제공 역할이나 다른 역할과 대소문자 구분 없이 충돌하는 사용자 지정 역할은 이름이 변경됩니다(로그에 기록됨); 해결할 수 없는 역할을 가리키는 템플릿 권한은 삭제됩니다(로그에 기록됨). 멤버십은project__user_role로 이동했으며,project__user.role컬럼은 사라졌습니다. GET /api/project/{id}/users는 역할이 하나인 구성원에 대해서만role을 반환합니다 —roles를 읽으십시오./roles*가 이동했습니다: 관리자 플래그에서 전역 역할 관리 권한으로 바뀌었습니다; 관리자는 영향을 받지 않습니다.- LDAPS 인증서가 기본적으로 검증됩니다. 자체 서명 인증서에는
ldap_tls_skip_verify또는 공급자의tls_skip_verify를 설정하십시오. ansible-playbook호출 방식이 달라집니다:--extra-vars @file을 사용하고, 작업에 시크릿이 있으면 vault가 없는 템플릿에서도 두 번째 파일과--vault-id <uuid>@prompt가 추가됩니다. 명령줄을 파싱하는 모든 것, 그리고 vault 프롬프트를 금지하는ansible.cfg가 영향을 받습니다.- 추가 변수 값 안의 Jinja2가 더 이상 평가되지 않습니다. 웹훅이나 설문 값의 템플릿 처리에 의존하던 플레이북은 더 이상 그렇게 동작하지 않습니다.
- 워크플로 실행 엔드포인트 이름 변경:
POST …/workflows/{id}/run→…/runs. - 모노레포 저장소가 템플릿 설정보다 우선합니다: 템플릿별 브랜치가 없고, 작업에서 브랜치나 커밋을 재정의할 수 없습니다.
- **인벤토리
repository_id**가file을 제외한 모든 유형에서 삭제됩니다. - 로컬 작업을 중지하면 프로세스 그룹이 함께 종료됩니다(Windows에는 아직 해당 동작이 없습니다).
- 워크플로 출력은 아직 Docker 및 Kubernetes 실행기에서 수집되지 않습니다; 설문 시크릿도 아직 그 실행기에는 도달하지 않습니다.
새로운 설정
audit, metrics, auth.max_session_life_hours, ssh.{config_path,known_hosts_file,strict_host_key_checking},
git_attempts, git_submodule_jobs, ldap_providers, ldap_tls_skip_verify,
external_auth_email_matching, OIDC 공급자별 groups_claim 및 require_verified_email,
runner.check_interval_seconds, runner.connection.timeout_seconds,
runners.{default_global_runners_mode,registration_token}. 모두 선택 사항입니다. 포인터 유형의 설정
필드도 이제 환경 변수로 설정할 수 있습니다. 설정 및 CLI 참조 문서 페이지는 소스에서 생성됩니다.
데이터베이스 마이그레이션
v2.20.0 외부 신원 · v2.20.1 작업에 바인딩된 설문 시크릿 · v2.20.2 지연 노드 ·
v2.20.3 작업 디렉터리 · v2.20.4 고유한 템플릿 이름 · v2.20.5 오류 알림 억제 ·
v2.20.7 호스트 설정 · v2.20.8 워크플로 리비전 · v2.20.9–v2.20.11 감사 로그 및 인덱스,
엣지 입력 매핑, 모노레포 플래그 · v2.20.12–v2.20.13 역할 테이블, 워크플로 변수 ·
v2.20.14 워크플로 통합 및 그룹 매핑 · v2.20.16 전역 역할.
의존성
Go 1.26; Alpine 3.24 기반 Docker 이미지; prometheus/client_golang 1.23 추가; go-oidc 3.21,
go-ldap 3.4.14, golang.org/x/crypto 0.57, modernc.org/sqlite 1.59, logrus 1.10; 프런트엔드
js-yaml 5 및 cron-parser 5.10. 새로운 원클릭 배포: Cloudzy, RepoCloud, Pethost.
