
Semaphore UI 2.19는 2.x 라인에서 가장 큰 릴리스입니다. 그래픽 편집기를 갖춘 워크플로를 도입하고, 러너가 Docker 컨테이너와 Kubernetes 파드에서 작업을 실행할 수 있게 하며, 실행 중인 작업에 단기 JWT 신원 토큰을 발급하도록 Semaphore를 확장하고, 암호화 키 교체를 추가하고, 러너 안정성 문제를 근본적으로 해결하며, 다수의 보안 강화 변경 사항을 함께 제공합니다.
이 라인은 v2.19.0부터 v2.19.14까지의 릴리스를 포함합니다. 패치 릴리스는 마지막에 정리되어 있습니다.
주요 내용
- 워크플로 (Beta) — 작업 템플릿을 승인 게이트가 있는 파이프라인으로 연결합니다. 그래픽 편집기에서 그리고 같은 캔버스에서 실시간으로 지켜볼 수 있습니다.
- Docker 및 Kubernetes 실행기 — 러너가 모든 작업을 새 컨테이너 또는 파드에서 실행할 수 있습니다 (Pro / Enterprise).
- 작업용 JWT 신원 토큰 — 플레이북에서 Vault, AWS, GCP, Azure 및 OIDC 토큰을 받아들이는 모든 서비스에 키 없이 인증합니다.
- 암호화 키 교체 — 핫 리로드와
vaults check명령을 지원하는 라벨이 붙은 키링입니다. - 환경 변수로 전달되는 설문 변수, 그리고
int,text및 새로 디자인된enum유형. - 작업 기록의 실제 서버 측 페이지네이션 — 수백만 개의 작업이 있는 프로젝트도 빠르게 유지됩니다.
- 러너 안정성 — 온라인/오프라인 상태, 해시 처리된 일회용 등록 토큰, 죽은 러너에 멈춘 작업의 자동 복구.
SEMAPHORE_DEBUG_FILTER를 통한 선택적 디버그 로깅.- 보안 강화: 현재 비밀번호 확인, CSRF 출처 검증, 보안 쿠키, API 전반에 걸친 더 엄격한 입력 검증.
- BoltDB 제거 — SQLite, MySQL, PostgreSQL만 지원합니다.
워크플로 (Beta)
워크플로는 하나의 단위로 실행되는 작업 템플릿 그래프입니다. 각 노드는 작업(템플릿을 실행), 승인(사용자가 승인하거나 거부할 때까지 실행을 일시 중지), 노트(실행되지 않는 자유 형식 주석) 중 하나입니다. 엣지는 성공 시, 실패 시, 항상 중 하나의 조건을 가집니다.
워크플로는 프로젝트 사이드바에 Beta 칩이 표시된 새로운 워크플로 항목으로 나타납니다. Pro 에디션에서 사용할 수 있으며, 베타 기간 동안에는 플랜과 관계없이 활성화됩니다.
그래픽 편집기

편집기는 Drawflow 기반의 전체 페이지 캔버스입니다:
- 팔레트에서 노드를 드래그하고, 노드 핸들에서 드래그하여 노드를 연결합니다;
- 엣지를 클릭하여 조건을 변경합니다; 엣지는 색상으로 구분되며 모서리에 범례가 있습니다;
- 노드를 클릭하여 사이드 패널에서 속성을 편집합니다: 템플릿, 수렴 모드(모든 부모 / 임의의 부모), 승인 제한 시간과 메시지, 노트 텍스트;
- 자기 자신으로 향하는 엣지와 순환은 그리는 즉시 거부되며, 문제 패널이 서버 측 검증을 그대로 반영하므로 잘못된 그래프는 저장할 수 없습니다;
- 노드 위치가 저장됩니다; 위치 없이 API를 통해 생성된 워크플로는 자동 위상 정렬 레이아웃을 적용받습니다;
- 툴바 또는
Ctrl+ 마우스 휠로 확대/축소하고, 캔버스를 드래그하여 이동하며, 팔레트를 접어 공간을 확보합니다; - 시작 버전은 실행 버전 관리(
1.4.0,1.4.1, …)의 시작점을 지정합니다; 버전은 실행이 시작하는 모든 작업에 전파됩니다.

실시간 실행 보기
실행 보기는 같은 캔버스를 재사용합니다. 각 노드는 작업 상태를 표시하고, 활성 노드는 강조되며,
대기 중인 승인은 캔버스에 직접 승인 / 거부 버튼을 렌더링합니다. 중지 버튼은
실행의 모든 작업을 강제 중지하고, 대기 중인 승인을 거부하며, 실행을 stopped로 표시합니다.

실행 상태는 running, approval, success, failed, stopped입니다. 워크플로 진행은
서버가 주도합니다: 워크플로 작업이 하나라도 완료되면 다음 노드가 예약되므로, 자동 실행 자식이
없는 템플릿이 더 이상 실행을 멈추게 하지 않습니다.

노드별 작업 매개변수
모든 작업 노드는 수동 실행과 같은 방식으로 템플릿에 전달하는 매개변수(변수, 인벤토리, 브랜치, 인수, 버전, 메시지)를 재정의할 수 있습니다.
API
GET/POST /api/project/{id}/workflows
GET/PUT/DELETE /api/project/{id}/workflows/{workflow_id}
POST /api/project/{id}/workflows/{workflow_id}/run
GET /api/project/{id}/workflows/{workflow_id}/runs
GET /api/project/{id}/workflows/{workflow_id}/runs/{run_id}
POST /api/project/{id}/workflows/{workflow_id}/runs/{run_id}/stop
GET /api/project/{id}/workflows/{workflow_id}/runs/{run_id}/artifacts
GET /api/project/{id}/workflows/{workflow_id}/runs/{run_id}/approvals
POST /api/project/{id}/workflows/{workflow_id}/runs/{run_id}/approvals/{node_id}
베타의 알려진 제한 사항: 미니맵, 실행 취소/다시 실행, 다중 선택이 없습니다; 워크플로 아티팩트
(set_stats 값)는 아직 원격 러너에서 실행되는 작업 간에 전달되지 않습니다.
Docker 및 Kubernetes 실행기 (Pro / Enterprise)
러너는 러너 호스트에서 직접 실행하는 대신 각 작업을 격리된 환경에서 실행할 수 있습니다.
실행기는 러너 프로세스당 한 번 runner.executor.type(local, docker,
k8s)으로 선택합니다.
Docker (runner.executor.docker, Pro):
| 옵션 | 환경 변수 | 기본값 |
|---|---|---|
host |
SEMAPHORE_RUNNER_DOCKER_HOST |
로컬 소켓 |
tls_verify, cert_path |
SEMAPHORE_RUNNER_DOCKER_TLS_VERIFY, …_CERT_PATH |
|
image |
SEMAPHORE_RUNNER_DOCKER_IMAGE |
semaphoreui/job:latest |
helper_image |
SEMAPHORE_RUNNER_DOCKER_HELPER_IMAGE |
semaphoreui/helper:latest |
network |
SEMAPHORE_RUNNER_DOCKER_NETWORK |
bridge |
pull_policy |
SEMAPHORE_RUNNER_DOCKER_PULL_POLICY |
if-not-present |
cpu_limit, memory_limit |
SEMAPHORE_RUNNER_DOCKER_CPU_LIMIT, …_MEMORY_LIMIT |
|
privileged |
SEMAPHORE_RUNNER_DOCKER_PRIVILEGED |
false |
poll_interval_seconds, cleanup_grace_seconds |
…_POLL_INTERVAL_SECONDS, …_CLEANUP_GRACE_SECONDS |
2, 30 |
Kubernetes (runner.executor.k8s, Enterprise):
| 옵션 | 환경 변수 | 기본값 |
|---|---|---|
kubeconfig |
SEMAPHORE_RUNNER_K8S_KUBECONFIG |
클러스터 내부 |
namespace |
SEMAPHORE_RUNNER_K8S_NAMESPACE |
semaphore |
image |
SEMAPHORE_RUNNER_K8S_IMAGE |
semaphoreui/job:latest |
helper_image |
SEMAPHORE_RUNNER_K8S_HELPER_IMAGE |
semaphoreui/helper:latest |
service_account |
SEMAPHORE_RUNNER_K8S_SERVICE_ACCOUNT |
default |
pull_secrets |
SEMAPHORE_RUNNER_K8S_PULL_SECRETS |
|
poll_interval_seconds, cleanup_grace_seconds |
…_POLL_INTERVAL_SECONDS, …_CLEANUP_GRACE_SECONDS |
3, 30 |
CI에서 두 개의 새 이미지가 게시됩니다: semaphoreui/job(Ansible, Terraform, OpenTofu, Terragrunt,
paramiko)과 semaphoreui/helper. 템플릿은 템플릿 양식의 새로운 실행기 이미지 필드로 자체 작업의
이미지를 재정의할 수 있습니다(실행기 기능이 라이선스되지 않은 경우 PRO로 업그레이드 배지와 함께
표시됩니다).
러너 연결에는 runner.connection.server_ca_cert_file과
runner.connection.skip_tls_verify도 추가되었습니다.
작업용 JWT 신원 토큰
Semaphore는 실행 중인 작업을 위한 OIDC 방식의 신원 공급자 역할을 할 수 있으므로, 플레이북이 장기 자격 증명 없이 Vault, 클라우드 STS 엔드포인트 또는 내부 서비스에 인증할 수 있습니다.

- 템플릿별로 작업 러너에 JWT 발급으로 활성화합니다; 하나 이상의 **대상(audience)**과
TTL(
jwt.max_ttl로 상한 제한)을 설정합니다. - 작업은
SEMAPHORE_JWT환경 변수로 토큰을 받습니다. - 토큰은 ES256(ECDSA P‑256)으로 서명되며 ID만 포함합니다:
task_id,project_id,template_id,user_id와 표준iss,sub,aud,exp,nbf,iat,jti클레임. - 공개 키는
GET /.well-known/jwks.json에 게시됩니다.
서버 설정:
"jwt": {
"enabled": true,
"issuer": "https://semaphore.example.com",
"default_ttl": "1h",
"max_ttl": "24h"
}
환경 변수: SEMAPHORE_JWT_ENABLED, SEMAPHORE_JWT_ISSUER, SEMAPHORE_JWT_DEFAULT_TTL,
SEMAPHORE_JWT_MAX_TTL.
설문 변수
변수를 환경 변수로 전달
설문 변수에 이제 변수 전달 방식 설정이 있습니다: 앱별 CLI 방식(Ansible의 --extra-vars,
Terraform/OpenTofu의 -var, 셸 스크립트의 CLI 인수) 또는 프로세스 환경
변수입니다. 변수 이름이 그대로 사용되므로 Terraform 사용자는 단순히 TF_VAR_region으로 이름을 지으면 됩니다.
환경 변수는 프로세스 목록에 나타나지 않으므로, 시크릿에 더 안전한
선택입니다.

새로운 유형
int— 검증이 포함된 숫자 입력;text— 여러 줄 텍스트;enum— 이름/값 쌍과 기본값을 갖춘 새로 디자인된 편집기.

작업 대화 상자는 각 유형을 그에 맞게 렌더링합니다:

기존 survey_vars JSON에 저장됩니다 — 마이그레이션이 필요하지 않습니다.
템플릿 및 작업
-
동적 플레이북 선택기. 플레이북 파일 경로 필드가 저장소에서 발견된 플레이북을 나열합니다(
GET /api/project/{id}/repositories/{repository_id}/playbooks). 목록은 선택한 브랜치를 따르며, 저장소를 읽을 수 없을 때는 자유 텍스트로 대체됩니다. -
Ansible Galaxy 설치 건너뛰기 —
requirements.yml의 롤과 컬렉션 설치를 건너뛰는 템플릿별 옵션으로, 작업별로 재정의할 수도 있습니다. -
변수 그룹의 유형이 지정된 변수, 숫자 포함:

-
작업 기록 페이지네이션. 기록 페이지는 이전에 최신 200개의 작업을 가져와 클라이언트 측에서 페이지를 넘겼기 때문에 그보다 오래된 작업에는 접근할 수 없었습니다. 이제 백엔드는 키셋 커서 (
?count=20&before=<task_id>,X-Has-Next응답 헤더)를 사용하여COUNT(*)와OFFSET없이 한 번에 한 페이지씩 반환합니다. 푸터에는 페이지당 행 수와 이전/다음 컨트롤이 있습니다. 같은 페이지네이션이 템플릿별 작업 목록과 대시보드에도 적용됩니다.
-
작업 목록은 최대 5초에 한 번만 다시 로드됩니다; 여러 중복 요청이 제거되었습니다.
-
일정은 서버 측 cron 파서로 검증되므로, 클라이언트와 서버가 더 이상 불일치하지 않습니다.
-
작업의 브랜치 재정의는 템플릿이 허용하는 경우에만 받아들여집니다.
-
Git 작업이 저장소 디렉터리별로 직렬화됩니다. 병렬 작업 허용이 설정된 템플릿은 하나의 작업 사본을 공유하며, 동시
git pull/git checkout이 이를 손상시킬 수 있었습니다. 이제 업데이트와 체크아웃은 로컬 및 러너 실행 모두에서, 인벤토리 저장소를 포함하여 하나의 임계 영역을 이룹니다.
러너

-
하트비트 생존 여부에서 도출되는 러너 페이지의 온라인 / 오프라인 상태.
-
일회용 등록 토큰. 러너를 먼저 UI에서 생성한 뒤, 한 번만 표시되고 SHA‑256 해시로만 저장되며 한 시간 후 만료되는
smrs_…토큰으로 나중에 등록할 수 있습니다. 대화 상자에는 환경 변수, 설정 파일, Docker용으로 바로 복사할 수 있는 명령이 표시됩니다. 토큰을 다시 생성하면 이미 등록된 러너가 재설정되어 다시 등록할 수 있습니다.
SEMAPHORE_WEB_ROOT=https://semaphore.example.com \ SEMAPHORE_RUNNER_REGISTRATION_TOKEN=smrs_… \ semaphore runner register --config ./config.runner.json semaphore runner start --config ./config.runner.json -
멈춘 작업 복구. 러너는 프로세스 시작 시간(
X-Runner-Started-At)을 전송합니다. 폴링을 중단한 러너는runners.offline_timeout_sec(120초) 후 오프라인으로 표시됩니다: 새 작업을 받지 않으며starting상태의 작업은 재할당됩니다.runners.task_fail_timeout_sec(420초) 후에는running상태의 작업이 명확한 메시지와 함께 실패 처리됩니다. 재시작하여 메모리 내 작업 풀을 잃은 러너는 즉시 감지됩니다. 조정은runners.reconcile_interval_sec(30초)마다 실행됩니다. -
러너에서 다른 곳으로 재할당된 작업은 이전 러너에서 종료됩니다.
-
오래된 러너 대체 동작이 사라졌습니다: 모든 러너가 오프라인이면 작업은 최대 30분 동안 폴링하지 않은 러너로 전달되는 대신 큐에서 대기합니다.
-
러너별 RSA 암호화 키 제거. 러너‑서버 트래픽은 TLS에 의존합니다; 이로써 등록과
setup에서 키 교환 단계가 삭제됩니다. -
러너 클라이언트의 TCP 연결 누수를 수정했습니다; 잘못된 등록 토큰은
400을 반환합니다.
시크릿 및 암호화
- 암호화 키 교체. 새로운
encryption블록은 라벨이 붙은 키링을 설명합니다: 인라인keys(값 또는 파일), 또는 모든 파일이 파일 이름으로 명명된 키가 되는keys_folder, 그리고 시크릿 키와 옵션 키를 가리키는active포인터. 암호문에 이제 키 ID가 포함되므로 한 번에 모두 재암호화하지 않고도 키를 교체할 수 있습니다.keys_poll_interval(기본값15s)이 설정된encryption.keys_file은 키링을 핫 리로드합니다. 새로운 CLI:semaphore vaults check;semaphore vaults rekey는 키링을 중심으로 다시 작성되었습니다. 기존의 단일access_key_encryption은 여전히 작동합니다. option_encryption— 데이터베이스에 저장된 옵션을 위한 별도의 키.- 자체 아이콘이 있는 OpenBao 시크릿 저장소 유형(Vault 공급자를 통해 라우팅).
- 정적 자격 증명 없는 AWS Secrets Manager — IAM 역할 사용 체크박스.
- Vault/OpenBao 저장소를 위한 TLS 검증 건너뛰기 옵션.
- 동기화된 읽기 전용 시크릿 필드가 업데이트 시 더 이상 지워지지 않습니다.
관측성
- 네임스페이스 기반 디버그 로깅.
--debug-filter/SEMAPHORE_DEBUG_FILTER는 Node.jsdebug방식으로 어떤 하위 시스템이 디버그 출력을 내보낼지 선택합니다:runner,runner,task_pool,task_*,*,*,-db. 사용 가능한 네임스페이스:runner,task_pool,task_runner,task_logger,git,terraform,session,ldap,schedule,db,ha. 필터는 로그 수준이DEBUG일 때만 적용되며, 수준을 올리지는 않습니다. Syslog 훅도 같은 필터를 따릅니다. - 러너, 작업, 인증 전반에 걸쳐 많은 새로운 컨텍스트 디버그 구문이 추가되었습니다; 선택된 워크스페이스가 시작 시 출력됩니다.
보안

- 비밀번호를 변경하려면 이제 현재 비밀번호가 필요합니다 (CWE‑620).
- 상태를 변경하는 요청에 대한 Origin / Referer 검증 (CSRF 강화).
- HTTPS로 제공될 때 세션 쿠키가
Secure로 표시됩니다. - 러너 등록 토큰은 해시로 저장되며 만료됩니다; 러너별 암호화 키가 제거되었습니다.
- 사용자 지정 역할 생성 시 호출자의 권한을 확인합니다 (권한 상승 수정).
- Git URL 검증; 조작된 ref가 플래그로 읽히지 않도록 git에
--end-of-options를 전달합니다; 커밋 해시의 형식을 확인합니다; 저장소 탐색 전에 브랜치를 검증합니다; 플레이북 경로를 검증합니다. - 액세스 키 페이로드와 템플릿
app필드를 검증합니다. - JWT 클레임은 ID만 포함합니다 — 이름이나 이메일이 외부 시스템으로 유출되지 않습니다.
- 러너 토큰이 더 이상 프로젝트 백업에 기록되지 않습니다.
- API는 쓰기 오류 후 부분적으로 작성된 응답을 계속 보내는 대신 즉시 반환합니다.
- 보안 SLA가
SECURITY.md에 게시되었습니다; 릴리스 아티팩트는[email protected]GPG 키로 서명됩니다.
UI 및 현지화

- 체코어 번역.
- 템플릿 양식의 JWT 및 일정 섹션을 위한 드롭다운 카드.
- 라이트 모드에서 클립보드 복사 아이콘이 보입니다; 실행 중인 작업 스피너 수정; 템플릿 양식 여백 수정; 워크플로 Beta 라벨.
- 통합 변수 추출이 JSON 객체와 배열을 문자열화하는 대신 그대로 유지합니다.
업그레이드 참고 사항
호환성이 깨지는 변경 및 동작 변경
- BoltDB가 제거되었습니다.
bolt는 더 이상 유효한 dialect가 아닙니다; 서버는 “Bolt is not supported starting from version 2.19” 메시지와 함께 시작을 거부합니다. 먼저 SQLite, MySQL 또는 PostgreSQL로 마이그레이션하십시오. - 러너 암호화 키가 제거되었습니다. 서버와 러너 모두 2.19여야 합니다. 러너‑서버 트래픽이 TLS로 보호되는지 확인하십시오. 키를 기대하던 스크립트 기반 러너 프로비저닝은 업데이트해야 합니다.
- 작업 목록 API가 페이지네이션됩니다.
GET /api/project/{id}/tasks/last는count와before를 받습니다;limit도 여전히 받아들여지지만, 한 번의 응답에서 최신 200개 작업에 의존하던 클라이언트는 페이지를 나눠야 합니다. - 오래된 러너 대체 동작이 없습니다. 모든 러너가 오프라인이면 작업은 큐에 남아 있습니다.
- 등록에서 러너
active플래그가 제거되었습니다. - 프로젝트 백업에 더 이상 러너 토큰이 포함되지 않습니다.
- SQLite:
v2.19.14는session및task테이블을 다시 빌드하여 올바른 외래 키를 추가합니다(사용자 삭제 수정). 고아 세션은 제거됩니다. 업그레이드 전에 데이터베이스를 백업하십시오.
새로운 설정
jwt, runners, encryption, option_encryption, secrets_path, db.dialect,
runner.executor.{type,docker,k8s}, runner.connection.{server_ca_cert_file,skip_tls_verify},
runner.registration_token_file, runner.token_file. 모두 선택 사항입니다; 기존 설정은 계속
작동합니다. config.schema.yaml과 설정 참조 문서가 다시 생성되었습니다.
데이터베이스 마이그레이션
v2.18.6(템플릿 jwt_params), v2.18.15(워크플로 테이블), v2.19.2(runner.started_at),
v2.19.11(project__workflow_node.task_params_id), v2.19.12(project__template.executor_image),
v2.19.14(SQLite session/task 재빌드). MariaDB 12.1 마이그레이션 호환성이 수정되었습니다.
패치 릴리스
| 버전 | 변경 사항 |
|---|---|
| 2.19.8 | SQLite 마이그레이션 수정; 사용자 삭제 수정(session/task 외래 키); DB 쿼리에서 대소문자를 구분하지 않는 문자열 비교 |
| 2.19.9 | SEMAPHORE_RUNNER_EXECUTOR_TYPE 환경 변수; 설정 omitempty 정리 |
| 2.19.10 | 실행기 설정 수정; Docker 빌드 옵션 수정 |
| 2.19.11 | 선택된 워크스페이스를 로그에 출력; helper 이미지의 latest 태그; DB 마이그레이션 테스트 |
| 2.19.12 | 러너 설정 옵션의 nil 포인터 수정; 오류 전파 수정 |
| 2.19.14 | 설정의 기존 secrets_path 처리 수정 |
의존성
Go 1.26; go-git 5.19, go-oidc 3.19, golang.org/x/crypto 0.53, go-ldap 3.4.13,
modernc.org/sqlite 1.52. 문서가 git 서브모듈로 추가되었습니다; THIRD-PARTY-LICENSES.md가 다시 생성되었습니다.
