yona is a free, open source project & work management project written in Kotlin and released under Apache-2.0. It has 501 GitHub stars, 156 forks and 234 open issues, and was last pushed 14 days ago. On this registry it ranks #70 of 73 tracked projects in Project & Work Management, with 5 head-to-head comparisons available.

What is yona?

yona is a self-hosted project collaboration platform — an issue tracker, board, code review tool, and Git/SVN/Mercurial repository host in one application — for teams and organizations that want to keep their code and project data on their own infrastructure instead of on a hosted service.

What it is

The original Yona is a self-hosted project collaboration platform built on Play Framework, Java, and Ebean, with Git or SVN repositories embedded inside it. It ran in production for years at Naver, Naver Labs, and a number of other companies and public institutions. This repository is a rewrite of that application on a Kotlin, Spring Boot, and JPA (Hibernate) stack, with Thymeleaf replacing Scala templates and JDK 21 replacing Java 8. The goal is to keep screens, data model, and behaviour as close to the legacy product as possible while swapping only the runtime and build tooling.

The concrete problem it solves is ownership. A self-hosted install removes the risk of service shutdown and data lock-in, and it replaces the legacy Play Framework application with a current JVM stack without forcing users to relearn the product. Repositories, issues, boards, code review, groups, and wiki all live in one application under the operator's control. Migration paths are built in, including importing GitHub projects and moving data from another Yona instance.

Key capabilities

  • Embedded version control with a choice of Git, SVN, or Mercurial per repository, reachable over HTTP(S) and SSH, with Git LFS support, member-only access control, and online file editing and committing.
  • A project-based issue tracker and board with cross-project issue moves, sub-tasks, body change history, and issue templates.
  • Block-based code review: review threads attached to individual code blocks, plus review scores.
  • Account security including LDAP, OAuth2 social login, two-factor authentication with TOTP apps and WebAuthn/passkeys, backup codes, login brute-force prevention, known-device recognition, and an audit log of security and administrative events.
  • Repository access and signing features: SSH public key registration, GPG commit signature verification, and per-repository deploy keys.
  • Scoped personal API tokens (PAT) and an OAuth2 Authorization Server with Dynamic Client Registration for third-party apps.
  • A built-in MCP (Model Context Protocol) server exposed at the single /mcp Streamable HTTP endpoint, where spring-ai-starter-mcp-server-webmvc publishes the @Tool methods in IssueMcpTools, PullRequestMcpTools, and WikiMcpTools, authenticated by OAuth2 or a scoped PAT and re-checked per call by McpScopeGuard.
  • Groups (organizations) that aggregate issues and posts across group projects and members, Hangul-capable project and group names, and migration tooling for other services and other Yona instances.

Who uses it and how

  • Organizations that cannot accept a hosted service shutting down or holding their data: the legacy application was used for years at Naver, Naver Labs, and other companies and public institutions.
  • Teams that need directory-based sign-in with LDAP, social OAuth2 login, and two-factor authentication enforced on the same system that hosts their Git, SVN, or Mercurial repositories.
  • Teams moving off GitHub projects or off another Yona instance, using the built-in import and migration paths rather than a manual export.
  • Teams wiring AI agents into their tracker: Claude and other MCP clients authenticate over OAuth2 or with a scoped PAT and then read or modify issues, pull requests, and wiki pages directly.
  • Frontend contributors, who work against a hybrid adapter scheme in which vanilla yona.*.js delegates to Vue 3 Web Components where a custom element is present, with 17 widgets already converted and their build output committed under src/main/resources/static/lib/yona-vue-widgets/.

Getting started

Requirements are JDK 21 plus one supported database — MariaDB by default, or PostgreSQL, MySQL, SQL Server, CUBRID, or H2 for an embedded trial with no separate install. Run it from a checkout on Linux or macOS with ./gradlew bootRun, or gradlew.bat on Windows.

How it compares

No comparable paid products are listed in the available facts, so yona stands alone in this registry as the self-hosted project hosting entry. The only named relative is the legacy Yona it is ported from, which it replaces on the Java/Scala Play Framework and Ebean stack with Kotlin, Spring Boot, JPA/Hibernate, and Thymeleaf. Both are Apache-2.0 and self-hosted; the difference is the runtime and the added Mercurial, two-factor, GPG, OAuth2, and MCP features.

When to use it — and when not to

Choosing yona means operating JDK 21 and a database (MariaDB, PostgreSQL, MySQL, SQL Server, CUBRID, or H2) yourself, plus whatever identity, SSH, and signing material the deployment enables. Anyone who wants a managed service with no operational surface should not pick it, and anyone who needs exact legacy behaviour today should read docs/parity/index.md, docs/TEMPLATE_BACKLOG.md, and docs/coverage/index.md first, since the port is explicitly still in progress and 234 issues remain open. The README is written largely in Korean, and the shared markdown editor fragment is deliberately excluded from the Vue migration because its Shadow DOM encapsulation would break existing JavaScript.

project readme (upstream, from github) — read inline

[English]

yona

21세기 협업 개발 플랫폼
  • Official Site: http://yona.io
  • 이 저장소는 Yona(Play Framework/Java/Ebean 기반의 설치형 프로젝트 협업 플랫폼)를 Kotlin + Spring Boot + JPA(Hibernate) 스택으로 새로 옮겨 쓴 프로젝트입니다. 화면 구조·데이터 모델·동작 방식은 legacy Yona와 최대한 동일하게 유지하면서, 런타임과 빌드 도구만 현재 JVM 생태계로 교체하는 것을 목표로 합니다.

Yona란?

  • Git/SVN/Mercurial 저장소가 내장된 설치형 이슈 트래커 + 게시판 + 코드 리뷰 플랫폼
  • 네이버/네이버랩스를 비롯해 여러 기업·공공기관에서 수년간 실사용되며 다듬어진 애플리케이션

주요 기능

  • 서비스 종료나 데이터 종속 걱정 없는 설치형
  • 프로젝트 기반의 유연한 이슈 트래커와 게시판 — 프로젝트 간 이슈 이동, 서브 태스크, 본문 변경이력, 이슈 템플릿
  • 내장 코드 저장소 — Git / SVN / Mercurial 3종 선택 가능, 온라인 수정·커밋, HTTP(S)뿐 아니라 SSH로도 접근 가능, 프로젝트 멤버 전용 접근 제어, Git LFS 지원
  • 블록 기반 코드 리뷰 — 코드 블록 단위 리뷰 스레드, 리뷰 점수
  • 그룹(조직) 기능 — 그룹 단위 이슈/게시글 통합 관리, 그룹 프로젝트·멤버
  • 한글 기반 — 프로젝트 이름 및 그룹 이름에 한글 사용 가능
  • 계정 보안 — LDAP 지원, 소셜 로그인(OAuth2), 2단계 인증(TOTP 앱 + WebAuthn/패스키), 백업 코드, 로그인 브루트포스 방지, 알려진 기기 인식
  • 저장소 접근/서명 — SSH 공개키 등록, GPG 커밋 서명 검증, 저장소별 Deploy Key
  • API 및 자동화 — 범위(scope) 지정 가능한 개인용 API 토큰(PAT), 서드파티 앱을 위한 OAuth2 Authorization Server(Dynamic Client Registration 포함), MCP(Model Context Protocol) 서버 내장 — Claude 등 AI 에이전트가 OAuth2로 인증해 이슈/PR/위키에 직접 접근 가능 (아래 참고)
  • 감사 로그 — 주요 보안/관리 이벤트 추적
  • 다른 서비스·다른 Yona 인스턴스로의 마이그레이션(GitHub 프로젝트 Import 등)

추가 읽을거리

Yona (New): 무엇이 바뀌었나

Old Yona New Yona
언어 Java / Scala 템플릿 Kotlin
프레임워크 Play Framework 2.x Spring Boot
ORM Ebean JPA / Hibernate
뷰 엔진 Scala Template(.scala.html) Thymeleaf
JDK Java 8 Java 21
지원 DB MariaDB(기본) 또는 H2(내장형) MariaDB / PostgreSQL / MySQL / SQL Server / CUBRID / H2(내장형)
지원 VCS Git / SVN Git / SVN / Mercurial

포팅 진행 상황과 legacy 대비 의도적으로 남겨둔 차이점은 docs/parity/index.md, docs/TEMPLATE_BACKLOG.md, docs/coverage/index.md에 기록돼 있습니다.

이식 과정에서 legacy에는 없던 기능도 새로 추가됐습니다:

  • Mercurial 저장소 지원(기존 Git/SVN 2종에서 3종으로)
  • 2단계 인증(TOTP 앱 + WebAuthn/패스키) 및 로그인 보안 강화(브루트포스 방지, 알려진 기기 인식)
  • GPG 커밋 서명 검증, 저장소별 Deploy Key
  • 범위 지정 API 토큰(PAT) 및 OAuth2 Authorization Server(서드파티 앱 연동, Dynamic Client Registration)
  • MCP(Model Context Protocol) 서버 내장 — 자세한 내용은 아래 참고
  • 감사 로그(보안/관리 이벤트 추적)

프론트엔드 위젯: Vue 3 Web Components로 점진 전환

일부 화면 위젯은 jQuery 기반 vanilla JS에서 Vue 3 Web Components로 옮겨가고 있습니다. 각 위젯은 하이브리드 어댑터 방식으로 적용됩니다 — 기존 vanilla yona.*.js 파일이 대상 엘리먼트가 새 커스텀 엘리먼트인지 확인해 맞으면 그 컴포넌트에 위임하고, 아니면 원래 로직을 그대로 씁니다. 그래서 화면 템플릿을 건드리지 않는 위젯(Typeahead/Pagination 등)도 있고, 템플릿의 태그 하나만 바뀌는 위젯도 있습니다.

  • 위젯 소스: yona-projects/components (Vue 3 SFC를 네이티브 커스텀 엘리먼트로 빌드, 위젯마다 자체 Shadow DOM을 가짐)
  • 빌드 산출물은 src/main/resources/static/lib/yona-vue-widgets/에 그대로 커밋돼 있어서, components 저장소를 따로 클론/빌드하지 않아도 이 저장소만으로 바로 실행됩니다.
  • 현재 적용된 위젯(17개): Dialog, Toast, Popover, LoginDialog, Switch, Dropdown, Typeahead, Pagination, Attachments, ScrollElevator, PageSlide, ReviewForm, 마크다운 도움말(HelpMarkdown), 라벨 편집기 3종(새 라벨 폼, 카테고리 편집 다이얼로그, 라벨 편집 다이얼로그)
  • 화면 전반에서 공유하는 마크다운 에디터 프래그먼트는 이번 전환 범위에서 제외했습니다 — 에디터의 ``가 Shadow DOM에 완전히 캡슐화돼 있어, 그 프래그먼트를 참조하는 기존 JS(첨부파일 드래그드롭, 임시저장 등)가 여러 화면에서 깨지기 때문입니다. ReviewForm 안에서 쓰는 마크다운 에디터는 그 공용 프래그먼트와 무관한 별개 인스턴스라 이 문제가 없어 전환 대상에 포함했습니다.

AI 에이전트 연동 (MCP 서버)

yona는 MCP(Model Context Protocol) 서버를 내장하고 있어, Claude 같은 AI 에이전트가 이슈·PR·위키 페이지를 직접 조회·조작할 수 있습니다.

  • 엔드포인트는 /mcp(Streamable HTTP) 하나이며, spring-ai-starter-mcp-server-webmvc가 @Tool로 표시된 메서드를 자동으로 노출합니다(IssueMcpTools/PullRequestMcpTools/WikiMcpTools).
  • 인증은 OAuth2(yona 자체가 Dynamic Client Registration을 지원하는 OAuth2 Authorization Server 역할을 겸함) 또는 범위 지정 API 토큰(PAT) 둘 다로 가능합니다 — 도구 호출마다 McpScopeGuard가 해당 토큰/토큰의 스코프로 실제 접근 가능한지 재검사합니다.
  • API 토큰 발급/스코프 관리는 사용자 설정 화면(API 토큰)에서, OAuth 앱 등록은 사용자 설정 화면 (OAuth 앱)에서 할 수 있습니다.

요구 사항

  • JDK 21
  • 운영/테스트 DB 중 하나: MariaDB(기본), PostgreSQL, MySQL, SQL Server, CUBRID, H2(설치 없이 바로 써보기)

빌드 & 실행

# Linux / macOS
./gradlew bootRun

# Windows
gradlew.bat bootRun

테스트:

./gradlew test        # Linux/macOS
gradlew.bat test       # Windows

데이터베이스 선택

기본 Spring 프로파일은 mariadb입니다. 다른 DB로 운영하려면 spring.profiles.active를 아래 중 하나로 지정하세요(src/main/resources/application.yml에 각 프로파일의 접속 설정이 있습니다). 로컬 개발용 MariaDB/PostgreSQL 컨테이너는 저장소 루트의 docker-compose.yml로 바로 띄울 수 있습니다.

프로파일 DB
mariadb (기본값) MariaDB
postgres PostgreSQL
mysql MySQL
mssql Microsoft SQL Server
cubrid CUBRID
h2 H2(내장형) — Docker/별도 서버 설치 없이 파일 기반으로 바로 실행(./data/h2/yona)
java -jar yona.jar --spring.profiles.active=postgres

# 설치 없이 바로 써보기(H2)
java -jar yona.jar --spring.profiles.active=h2

통합 테스트는 실제 Docker 컨테이너(Testcontainers) 기준으로 5개 서버 DB 전부 검증돼 있습니다 (H2는 내장형이라 컨테이너가 필요 없습니다). 특정 DB로만 테스트를 돌리려면(동시에 두 개 이상 돌리면 gradle 빌드 출력 디렉터리가 꼬이니 항상 한 번에 하나씩만 실행하세요):

./gradlew test -Dyona.it.db=postgres   # mariadb|postgres|mysql|mssql|cubrid|h2

운영 환경 설정 (특히 Windows)

물리 저장소(git bare repo, svn repo, git-lfs 객체, 첨부파일 업로드)를 디스크의 어느 경로에 둘지는 아래 4개 설정으로 제어합니다. 기본값이 /tmp/yona/... 형태의 유닉스 절대경로이기 때문에, Windows에서 운영할 때는 반드시 아래 값들을 Windows 경로로 재설정해야 합니다.

설정 키 기본값 용도
yona.git.base-dir /tmp/yona/git Git bare 저장소 루트
yona.svn.base-dir /tmp/yona/svn SVN 저장소 루트
yona.lfs.base-dir /tmp/yona/lfs Git LFS 객체 저장 루트
yona.upload.base-dir ${yona.data:data}/uploads (상대경로) 첨부파일 업로드 루트

설정 변경 방법

  1. application.yml에 직접 지정 (가장 확실한 방법)

    yona:
      git:
        base-dir: "D:/yona-data/git"
      svn:
        base-dir: "D:/yona-data/svn"
      lfs:
        base-dir: "D:/yona-data/lfs"
      upload:
        base-dir: "D:/yona-data/uploads"
    

    Windows 경로도 슬래시(/)로 적으면 됩니다(자바가 두 구분자를 모두 인식합니다). 백슬래시를 쓸 경우 YAML 이스케이프 때문에 \\로 두 번 써야 하므로, 슬래시 표기를 권장합니다.

  2. 실행 시 커맨드라인 인자로 지정 (application.yml을 건드리지 않고 배포별로 다르게 줄 때)

    java -jar yona.jar --yona.git.base-dir=D:\yona-data\git --yona.svn.base-dir=D:\yona-data\svn --yona.lfs.base-dir=D:\yona-data\lfs --yona.upload.base-dir=D:\yona-data\uploads
    

    -D로 JVM 시스템 프로퍼티를 주는 방식(java -Dyona.git.base-dir=D:\... -jar yona.jar)도 동일하게 동작합니다.

  3. 환경 변수 — Spring Boot의 relaxed binding 규칙상 yona.git.base-dir에 대응하는 환경 변수명은 YONA_GIT_BASEDIR처럼 하이픈(-)이 빠진 형태입니다(다른 YONA_* 설정들처럼 밑줄로 치환되는 게 아님). 헷갈리기 쉬우므로 1번(yml) 또는 2번(커맨드라인 인자) 방식을 권장합니다.

Windows에서 Fork(하드링크 복제) 사용 시 전제 조건

프로젝트 Fork는 저장소를 실제로 복사하지 않고 파일시스템 하드링크로 복제합니다 (ProjectServiceImpl.cloneHardLinkedRepository). 이 방식이 정상 동작하려면:

  • yona.git.base-dir(및 yona.svn.base-dir) 전체가 하나의 NTFS 볼륨(드라이브) 안에 있어야 합니다. 서로 다른 드라이브 간에는 하드링크가 불가능해 Fork가 실패합니다(폴백 복사 없음, 의도적 설계).
  • 저장 위치가 NTFS여야 합니다. FAT32/exFAT로 포맷된 외장 디스크나 일부 네트워크 드라이브는 하드링크 자체를 지원하지 않아 Fork가 실패합니다.

서버 관련 설정

  • LDAP: application.yml의 ldap 섹션
  • 소셜 로그인(OAuth2): application.yml의 spring.security.oauth2 섹션
  • WebAuthn(패스키): application.yml의 yona.security.webauthn.relying-party-id/ relying-party-name — 배포 도메인에 맞게 반드시 재설정해야 합니다(기본값은 localhost).
  • 2단계 인증(TOTP) 암호화 키: 환경변수 YONA_TOTP_ENCRYPTION_PASSWORD/ YONA_TOTP_ENCRYPTION_SALT를 배포 전 반드시 설정해야 합니다. 기본값은 저장소에 커밋된 placeholder 값(yona-totp-dev-only-password 등)이라, 프로덕션에서 이 값을 그대로 쓰면 모든 사용자의 TOTP 시크릿이 소스코드로 노출된 키로 암호화되어 2단계 인증이 실질적인 보호 효과가 없어집니다. 이 값을 설정하지 않고 부팅하면 서버 로그에 [SECURITY WARNING] TOTP encryption key is still the committed placeholder default 에러가 남으니, 배포 파이프라인에서 이 로그를 감시하는 것도 권장합니다(TotpEncryptionKeyGuard).
  • SSH(Git/Mercurial 접근, SSH 키 등록): SSH: 시스템 sshd 연동
  • GPG 커밋 서명 검증, Deploy Key, API 토큰/OAuth2 앱은 별도 설정 없이 기본 활성화되어 있으며, 사용자별 설정 화면에서 바로 쓸 수 있습니다.

Google Analytics

  • legacy와 동일하게 Google Analytics 트래킹 스크립트가 실제로 구현되어 있습니다 (GlobalModelAttributeAdvice가 sendYonaUsage 모델 속성을 채우면 templates/site/layout.html이 그 값에 따라 GA 스크립트를 렌더링합니다).

  • 다만 기본값은 legacy(application.send.yona.usage = true, 기본 켜짐)와 반대로 꺼짐(false) 입니다. 켜고 싶다면 application.yml에서 아래 항목을 true로 설정합니다.

    yona:
      analytics:
        send-usage: true
    

마이그레이션

  • GitHub 프로젝트를 이 저장소로 Import하는 기능을 제공합니다(MigrationService, MigrationApiController). github.client.id / github.client.secret / github.allow.migration 설정으로 활성화합니다.
  • Yona의 별도 백업/이관 도구인 Yona Export는 이 저장소(Kotlin/Spring 이식판) 대상으로는 아직 포팅되지 않았습니다 — 진행 상황은 docs/parity/index.md 참고.

Contribution

  • 코드 기여의 기준이 되는 브랜치는 next입니다(main은 오래된 스냅샷이라 실제 개발은 전부 next에서 이루어지고 있습니다 — 저장소의 기본 브랜치도 next입니다).
  • 저장소를 fork한 다음 next 브랜치를 기준으로 작업하신 다음 next 브랜치로 pull request를 보내주세요.

운영 가이드

legacy Yona의 설치/운영 문서를 yona 기준으로 다시 쓴 것들이다 — docs/guide/:

영문 버전은 legacy와 동일하게 별도 위치에 있다 — 운영 문서는 docs/*.md, 사용자 가이드는 docs/userManual/, 기술 문서는 영문 원본이 있던 5개(markdown/mailbox/watch/label-typeahead/name-validation)만 docs/technical/에 있다(나머지 11개는 legacy도 한글 전용이었다).

서비스로 상시 구동할 때 참고할 systemd 유닛 예시와 DB 튜닝 샘플은 support-script/에 있다.

legacy Yona(Yobi/nFORGE 포함)의 설계 스펙·비전 문서·릴리즈노트는 원문 그대로 docs/legacy-reference/에 보존되어 있다.

코드 구조 개요

docs/parity/index.md, docs/TEMPLATE_BACKLOG.md, docs/coverage/index.md에 legacy yona 대비 이식 진행 상황과 의도적으로 남겨둔 차이점들이 기록되어 있습니다.

문서 작성 규칙: docs/parity/, docs/coverage/, docs/golden/는 docs/yona-wiki/ 방식(인덱스는 표만, 상세 서술은 개별 파일)을 따릅니다. 신규 티켓/배치/발견 사항을 기록할 때는 인덱스 표 아래에 서술을 이어 쓰지 말고, 해당 디렉터리의 새 파일(tickets/.md, batches/.md, findings/.md 등)을 만든 뒤 인덱스에 표 한 줄과 링크만 추가하세요.

라이선스

yona는 Apache License 2.0으로 제공됩니다. 서드파티 구성 요소 고지는 NOTICE, 원 프로젝트 기여자 명단은 AUTHORS를 참고하세요.


[한국어]

yona

Yona is a web-based project hosting software.

  • Official Site (original project): http://yona.io
  • This repository (search5/yona) is a rewrite of the original Yona (a self-hosted project collaboration platform built on Play Framework/Java/Ebean) onto a Kotlin + Spring Boot + JPA (Hibernate) stack. The goal is to keep screen structure, data model, and behavior as close as possible to legacy Yona while replacing only the runtime and build tooling with the current JVM ecosystem.

What is Yona?

  • A self-hosted issue tracker + bulletin board + code review platform with an embedded Git/SVN/Mercurial repository
  • An application battle-tested for years at NAVER, NAVER LABS, and various companies and public institutions

Key features

  • Self-hosted — no dependency on a third-party service that could shut down or lock in your data
  • A flexible, project-based issue tracker and bulletin board — issue transfer between projects, sub-tasks, body change history, issue templates
  • Embedded code repository — choose Git, SVN, or Mercurial, online edit/commit, access over SSH as well as HTTP(S), access restricted to project members, Git LFS support
  • Block-based code review — review threads per code block, review scores
  • Group (organization) features — unified management of issues/posts across a group, group projects and members
  • Korean-friendly — project and group names can use Korean characters
  • Account security — LDAP support, social login (OAuth2), two-factor authentication (TOTP apps + WebAuthn/passkeys), backup codes, login brute-force protection, known-device recognition
  • Repository access/signing — SSH public keys, GPG commit signature verification, per-repository deploy keys
  • API & automation — scoped personal access tokens (PATs), an OAuth2 Authorization Server for third-party apps (including Dynamic Client Registration), and a built-in MCP (Model Context Protocol) server — AI agents such as Claude can authenticate via OAuth2 and access issues, pull requests, and wiki pages directly (see below)
  • Audit log for key security/admin events
  • Migration to/from other services or Yona instances (GitHub project import, etc.)

Further reading (original project resources)

Yona (original) → yona (this port): what changed

legacy Yona yona (this port)
Language Java / Scala templates Kotlin
Framework Play Framework 2.x Spring Boot
ORM Ebean JPA / Hibernate
View engine Scala Template (.scala.html) Thymeleaf
JDK Java 8 Java 21
Supported DB MariaDB (default) or embedded H2 MariaDB / PostgreSQL / MySQL / SQL Server / CUBRID / embedded H2
Supported VCS Git / SVN Git / SVN / Mercurial

Porting progress and deliberate differences from legacy are tracked in docs/parity/index.md, docs/TEMPLATE_BACKLOG.md, and docs/coverage/index.md.

Some features were added during the port that legacy never had:

  • Mercurial repository support (Git/SVN grew to three VCS types)
  • Two-factor authentication (TOTP apps + WebAuthn/passkeys) and stronger login security (brute-force protection, known-device recognition)
  • GPG commit signature verification and per-repository deploy keys
  • Scoped personal access tokens (PATs) and an OAuth2 Authorization Server for third-party apps (including Dynamic Client Registration)
  • A built-in MCP (Model Context Protocol) server — see below for details
  • An audit log for security/admin events

Frontend widgets: gradual migration to Vue 3 Web Components

Some UI widgets are being migrated from jQuery-based vanilla JS to Vue 3 Web Components. Each widget is applied via a hybrid-adapter pattern — the existing vanilla yona.*.js file checks whether its target element is now the new custom element and delegates to it if so, otherwise falling back to the original logic unchanged. That means some widgets (Typeahead, Pagination, etc.) need no template changes at all, while others need only a single tag swap.

  • Widget source: yona-projects/components (Vue 3 SFCs built as native custom elements, each with its own Shadow DOM)
  • The build output is committed as-is under src/main/resources/static/lib/yona-vue-widgets/, so this repository runs on its own without cloning or building the components repo separately.
  • Widgets applied so far (17): Dialog, Toast, Popover, LoginDialog, Switch, Dropdown, Typeahead, Pagination, Attachments, ScrollElevator, PageSlide, ReviewForm, the markdown help panel (HelpMarkdown), and the 3-part label editor (new-label form, category-edit dialog, label-edit dialog).
  • The shared markdown editor fragment used across many screens is excluded from this migration — its `` is fully encapsulated inside Shadow DOM, which would break the existing JS that reaches into it from other screens (attachment drag-and-drop, draft autosave, etc.). ReviewForm's own markdown editor instance is self-contained and unrelated to that shared fragment, so it does not have this problem and is included.

AI agent integration (MCP server)

yona has a built-in MCP (Model Context Protocol) server, so AI agents such as Claude can directly query and act on issues, pull requests, and wiki pages.

  • A single /mcp endpoint (Streamable HTTP) exposes all methods annotated @Tool via spring-ai-starter-mcp-server-webmvc (IssueMcpTools/PullRequestMcpTools/WikiMcpTools).
  • Authentication works with either OAuth2 (yona itself acts as an OAuth2 Authorization Server with Dynamic Client Registration support) or a scoped personal access token (PAT) — every tool call is re-checked against the caller's actual scopes by McpScopeGuard.
  • Issue/manage API tokens from the user settings screen (API Tokens), and register OAuth apps from the user settings screen (OAuth Apps).

Requirements

  • JDK 21
  • One of the supported/tested DBs: MariaDB (default), PostgreSQL, MySQL, SQL Server, CUBRID, or embedded H2 (no install needed)

Build & Run

# Linux / macOS
./gradlew bootRun

# Windows
gradlew.bat bootRun

Tests:

./gradlew test        # Linux/macOS
gradlew.bat test       # Windows

Choosing a database

The default Spring profile is mariadb. To run against a different DB, set spring.profiles.active to one of the profiles below (connection settings for each profile live in src/main/resources/application.yml). A local MariaDB/PostgreSQL container can be started directly from the docker-compose.yml at the repository root.

Profile DB
mariadb (default) MariaDB
postgres PostgreSQL
mysql MySQL
mssql Microsoft SQL Server
cubrid CUBRID
h2 Embedded H2 — runs immediately from a local file (./data/h2/yona), no Docker/server install
java -jar yona.jar --spring.profiles.active=postgres

# Try it with zero setup (H2)
java -jar yona.jar --spring.profiles.active=h2

Integration tests are verified against all 5 server DBs using real Docker containers (Testcontainers); H2 is embedded and needs no container. To run tests against a single DB (never run two or more at once — the gradle build output directory gets corrupted; always run one at a time):

./gradlew test -Dyona.it.db=postgres   # mariadb|postgres|mysql|mssql|cubrid|h2

Deployment configuration (especially on Windows)

Where physical storage lives on disk (git bare repos, svn repos, git-lfs objects, attachment uploads) is controlled by the 4 settings below. The defaults are Unix absolute paths in the form /tmp/yona/..., so when operating on Windows you must reconfigure these to Windows paths.

Setting key Default Purpose
yona.git.base-dir /tmp/yona/git Git bare repository root
yona.svn.base-dir /tmp/yona/svn SVN repository root
yona.lfs.base-dir /tmp/yona/lfs Git LFS object storage root
yona.upload.base-dir ${yona.data:data}/uploads (relative) Attachment upload root

How to change these settings

  1. Set directly in application.yml (the most reliable way)

    yona:
      git:
        base-dir: "D:/yona-data/git"
      svn:
        base-dir: "D:/yona-data/svn"
      lfs:
        base-dir: "D:/yona-data/lfs"
      upload:
        base-dir: "D:/yona-data/uploads"
    

    Windows paths can be written with forward slashes (/) too — Java accepts both separators. If you use backslashes, YAML escaping requires doubling them (\\), so forward slashes are recommended.

  2. Pass as command-line arguments at runtime (to vary per deployment without touching application.yml)

    java -jar yona.jar --yona.git.base-dir=D:\yona-data\git --yona.svn.base-dir=D:\yona-data\svn --yona.lfs.base-dir=D:\yona-data\lfs --yona.upload.base-dir=D:\yona-data\uploads
    

    Passing JVM system properties with -D (java -Dyona.git.base-dir=D:\... -jar yona.jar) works the same way.

  3. Environment variables — under Spring Boot's relaxed binding rules, the environment variable corresponding to yona.git.base-dir is YONA_GIT_BASEDIR (the hyphen is simply dropped, not replaced with an underscore like other YONA_* settings). This is easy to get wrong, so option 1 (yml) or option 2 (command-line arguments) is recommended.

Prerequisites for using Fork (hard-link cloning) on Windows

Project Fork does not physically copy the repository — it clones via filesystem hard links (ProjectServiceImpl.cloneHardLinkedRepository). For this to work correctly:

  • yona.git.base-dir (and yona.svn.base-dir) must live entirely within a single NTFS volume (drive). Hard links cannot cross drives, so Fork fails between different drives (no copy fallback — this is intentional).
  • The storage location must be NTFS. External disks formatted as FAT32/exFAT, and some network drives, don't support hard links at all, so Fork fails there.

Server settings

  • LDAP: the ldap section of application.yml
  • Social login (OAuth2): the spring.security.oauth2 section of application.yml
  • WebAuthn (passkeys): yona.security.webauthn.relying-party-id/relying-party-name in application.yml — you must reconfigure these to match your deployment domain (the default is localhost).
  • Two-factor authentication (TOTP) encryption key: you must set the YONA_TOTP_ENCRYPTION_PASSWORD/YONA_TOTP_ENCRYPTION_SALT environment variables before deploying to production. The defaults are placeholder values committed to source control (yona-totp-dev-only-password, etc.) — leaving them as-is in production means every user's TOTP secret is encrypted with a key anyone can read from the repo, so two-factor authentication provides no real protection. Booting without setting these logs a [SECURITY WARNING] TOTP encryption key is still the committed placeholder default error, which your deployment pipeline should monitor for (TotpEncryptionKeyGuard).
  • SSH (Git/Mercurial access, SSH key registration): see SSH: system sshd integration (Korean only for now).
  • GPG commit signature verification, deploy keys, and API tokens/OAuth apps need no extra setup — they're enabled by default and available directly from each user's settings screens.

Google Analytics

  • The Google Analytics tracking script is actually implemented, same as legacy (GlobalModelAttributeAdvice populates a sendYonaUsage model attribute, and templates/site/layout.html renders the GA script based on that value).

  • Unlike legacy (application.send.yona.usage = true, on by default), the default here is off (false). To enable it, set the following to true in application.yml.

    yona:
      analytics:
        send-usage: true
    

Migration

  • Provides GitHub project import into this repository (MigrationService, MigrationApiController). Enable it via the github.client.id / github.client.secret / github.allow.migration settings.
  • The original Yona's separate backup/migration tool, Yona Export, has not yet been ported to this repository (the Kotlin/Spring port) — see docs/parity/index.md for status.

Contribution

  • The branch for contributions is next (main is a stale old snapshot — all active development happens on next, which is also the repository's default branch).
  • Fork the repository, work on top of the next branch, then send a pull request to the next branch.

Operations guide

legacy Yona kept English docs at docs/*.md and Korean docs at docs/ko/*.md. yona keeps that same split: this section lists the English set (same filenames/locations as legacy), rewritten for yona. The Korean set lives under docs/guide/ — see the 운영 가이드 section above (it's reorganized slightly differently, e.g. install docs merged into one file, so the two sets aren't a strict 1:1 file mirror).

User manual: legacy's docs/userManual/ was English-only, so it's ported here at the same location — docs/userManual/TOC.md. (The duplicate projectSetting/projectSettings folders from a legacy typo were merged into one, projectSetting/.)

Technical docs: legacy's docs/technical/ (English) and docs/ko/technical/ (Korean) were two different, non-overlapping sets of files. Only the English set is mirrored here at the same location — docs/technical/ (markdown, mailbox, watch, label-typeahead, name-validation). The Korean set's 11 additional topics (access control, JS module conventions, uploader/webhook internals, etc.) only ever existed in Korean, both in legacy and here — see docs/guide/technical/README.md.

For a systemd unit example and DB tuning samples for running this as a standing service, see support-script/.

Design specs, vision docs, and release notes from legacy Yona (including its Yobi/nFORGE predecessors) are preserved verbatim under docs/legacy-reference/.

Code structure overview

docs/parity/index.md, docs/TEMPLATE_BACKLOG.md, and docs/coverage/index.md record porting progress against legacy yona and deliberately preserved differences.

Documentation convention: docs/parity/, docs/coverage/, and docs/golden/ follow the docs/yona-wiki/ style (index = table only, details = individual files). When logging a new ticket/batch/finding, don't append narrative under the index table — create a new file in the relevant directory (tickets/.md, batches/.md, findings/.md, etc.) and add just a table row + link to the index.

License

yona is provided under the Apache License 2.0, the same license as the original Yona/Yobi project. See NOTICE for third-party component notices and AUTHORS for the original project's contributor list.

Frequently asked questions

Is yona free to use?

yona is open source under the Apache-2.0 licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does yona do?

Project Hosting SW

What is yona written in?

yona is primarily written in Kotlin. Its source is publicly available at https://github.com/yona-projects/yona, and it has 501 GitHub stars.