- 관리자 표: 칸의 줄바꿈 금지를 풀고 화면 폭을 넓혀, 긴 파일 이름이 있어도 펼쳤을 때 버튼이 표 밖으로 밀리지 않게 함 - 이메일 내보내기 기능 제거 (버튼, mailTemplate 설정, 문구, 문서) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Dodo Transfer
사내에서 쓰는 셀프 호스팅 파일 전달 서비스입니다. 파일을 올리면 링크가 만들어지고, 받는 사람은 링크로 내려받습니다. 계정 없이 쓰고, 비밀번호와 보관 기간으로 접근을 관리합니다.
PsiTransfer(BSD-2-Clause)를 바탕으로 화면과 동작을 새로 만들었습니다. 출처와 라이선스를 보세요.
기능
올리는 사람
- 파일을 화면 어디에든 끌어다 놓거나, 붙여넣기(Ctrl+V)로 추가하고, 올리기 전에 썸네일과 미리보기로 확인
- 큰 파일도 조각으로 나누어 올리고, 연결이 끊기면 이어서 올림 (tus)
- 보관 기간: 1회 다운로드 / 1일 / 3일 / 5일 / 7일 버튼, 그 외는 목록에서 선택
- 비밀번호는 필수 (1회 다운로드만 예외). 무작위 비밀번호 생성 버튼
- "인증된 사용자는 비밀번호 없이 다운로드": 업로드 로그인 상태인 사내 사용자는 링크를 열 때 비밀번호를 묻지 않고, 외부 수신자는 비밀번호를 입력
- 완료 후 "링크와 비밀번호 복사", QR 코드 버튼
- "내 업로드": 이 브라우저에서 올린 링크를 다시 보기 (비밀번호는 저장하지 않음)
- 업로드 로그인은 한 번 하면 7일 유지되고, 사용할 때마다 연장
받는 사람
- 만료일과 남은 시간 표시, 파일별 다운로드와 전체 받기(zip, tar.gz)
- 브라우저가 표시할 수 있는 파일(이미지, PDF, 동영상, 오디오, 텍스트·코드)은 목록의 썸네일과 모달 미리보기로 확인 (새 창을 열지 않음). 미리보기는 다운로드로 집계되지 않음
- 1회 다운로드: 한 번 받으면 삭제됨. 미리보기와 썸네일은 제공하지 않음
관리자 (/admin)
- 올라온 파일 조회, 검색, 정렬, 미리보기, 다운로드, 삭제 (파일 단위, bucket 단위)
- 서비스 이름, 로고, 하단 저작권 표기 변경 (저장하면 모든 화면에 바로 적용)
그 밖에: 라이트/다크 모드(브라우저 설정을 따름), 모바일 화면, 다국어(기본 한국어와 영어, 브라우저 언어를 따름),
웹훅, 도커 상태 확인(/healthz).
빠르게 시작하기
도커를 권장합니다. 자세한 내용은 docs/deployment-docker.md를 보세요.
git clone https://git.dodo-lab.kr/blue2rai/DodoTransfer.git
cd DodoTransfer
cp .env.example .env # 관리자와 업로드 비밀번호를 정합니다
docker compose -f compose.example.yaml up -d --build
http://localhost:3377/sharing/에 접속합니다 (예시 compose는 /sharing 하위 경로로 서비스합니다).
데이터는 컨테이너의 /data 볼륨에 저장됩니다. 업로드한 파일과 관리자 설정(이름, 로고)이 모두 여기에 있으므로,
이 볼륨만 유지하면 컨테이너를 다시 만들어도 모두 그대로입니다.
설정
모든 설정은 PSITRANSFER_ 접두사의 환경변수로 바꿀 수 있습니다. 자주 쓰는 것은 다음과 같습니다.
전체 목록은 docs/configuration.md에 있습니다.
| 환경변수 | 설명 |
|---|---|
PSITRANSFER_UPLOAD_PASS |
업로드 비밀번호. 없으면 누구나 올릴 수 있음 |
PSITRANSFER_ADMIN_PASS |
관리자 비밀번호. 없으면 /admin이 없음 |
PSITRANSFER_BASE_URL |
하위 경로로 서비스할 때 (/sharing) |
PSITRANSFER_RETENTIONS |
보관 기간 목록 (JSON) |
PSITRANSFER_QUICK_RETENTIONS |
버튼으로 보일 보관 기간 (쉼표로 구분) |
PSITRANSFER_DEFAULT_RETENTION |
처음 선택돼 있는 보관 기간 (초) |
PSITRANSFER_REQUIRE_BUCKET_PASSWORD |
비밀번호 필수 여부 (기본 true, 1회 다운로드는 예외) |
PSITRANSFER_MAX_AGE |
어떤 파일도 이 시간(초)이 지나면 삭제 |
PSITRANSFER_MAX_FILE_SIZE, PSITRANSFER_MAX_BUCKET_SIZE |
크기 제한 (바이트) |
PSITRANSFER_TRUST_PROXY |
리버스 프록시 뒤에서 실제 IP를 로그에 남김 |
PSITRANSFER_APP_NAME |
서비스 이름의 기본값 (관리자 설정이 우선) |
이름과 로고
기본은 Dodo Transfer와 임의로 만든 도도새 아이콘입니다. 관리자 페이지(/admin > 설정)에서 이름, 로고, 하단
표기를 바꿀 수 있고, 코드를 고치거나 다시 빌드할 필요가 없습니다. 아진산업 로고 파일은
docs/brand/ajin-logo.png에 있습니다. 자세한 내용은
docs/layout-customization.md를 보세요.
로그인과 보안
- 업로드 로그인: 업로드 비밀번호로 로그인하면 서버가 서명된 토큰을 발급해 브라우저에 보관합니다. 비밀번호는 저장하지 않고, 서버에도 로그인 상태를 저장하지 않으므로 컨테이너를 다시 시작해도 유지됩니다. 업로드나 관리자 비밀번호를 바꾸면 모든 토큰이 무효가 됩니다.
- bucket 비밀번호: 서버에는 argon2 해시로만 저장됩니다.
- 파일 주소:
files/<bucket>++<무작위 UUID>형태이고, 목록을 받을 때(비밀번호 확인 후)만 알 수 있습니다. - 미리보기: 서버가 파일 이름의 확장자로 형식을 정하고 허용 목록에 있는 것만 인라인으로 내려줍니다 (HTML은 제외).
스크립트가 실행되지 않도록 응답에
sandboxCSP와nosniff를 붙입니다. - 관리자 다운로드: 비밀번호 헤더를 보낼 수 없는 일반 링크 대신 60초 동안만 유효한 서명 링크를 씁니다.
- 종단 간 암호화는 없습니다. 전송 구간 암호화는 nginx의 HTTPS로 처리하세요 (예시).
개발
Node.js 24 이상이 필요합니다.
npm ci # 서버 의존성
npm --prefix app ci # 프론트엔드 의존성
npm run build # app/src를 public/app으로 빌드
NODE_ENV=dev npm run dev # 개발 서버 (config.dev.js 사용, 관리자 비밀번호 admin)
npm test # 단위 테스트와 통합 테스트
| 위치 | 내용 |
|---|---|
app.js, config.js |
시작과 설정 |
lib/endpoints.js |
화면 껍데기, 다운로드, 업로드 라우트 |
lib/admin.js |
관리자 API (파일 관리, 설정) |
lib/auth.js, lib/settings.js, lib/mime.js |
로그인 토큰, 이름과 로고 설정, 미리보기 형식 |
lib/db.js, lib/store.js, lib/tusboy/ |
파일 인덱스와 만료, 저장소, tus 업로드 |
app/ |
프론트엔드 (Vue 3, Vite, Pinia) |
lang/ |
화면 문구 (en.js가 기본, ko.js가 한국어) |
plugins/ |
웹훅 |
docs/ |
문서, 설계 기록(DESIGN.md), 디자인 목업(mockup/) |
디버그 로그는 DEBUG=psitransfer:* npm start로 볼 수 있습니다.
참고
- 전체 받기(zip, tar.gz)는 이어받기를 지원하지 않습니다. 파일 하나씩 받으면 이어받기가 됩니다.
- 동영상과 오디오는 코덱에 따라 브라우저에서 재생되지 않을 수 있습니다 (예: H.265). 그때는 다운로드를 안내합니다.
- 예전 PsiTransfer가 저장한
/data는 그대로 쓸 수 있습니다. 이전 파일에는 썸네일이 없어 아이콘으로 표시됩니다.
출처와 라이선스
이 프로젝트는 Christoph Wiechert의 PsiTransfer를 바탕으로 합니다. 원본의 라이선스(BSD 2-Clause)와 저작권 고지는 LICENSE에 그대로 유지합니다.