SSD Nodes Learn Hosting plans →
가이드 Matt Connor작성자 Matt Connor

LinkBreeze 직접 호스팅: Docker Compose 구축 가이드

LinkBreeze를 VPS에 배포하는 방법을 알아봅니다. Docker Compose와 Caddy를 활용한 설정, SQLite 데이터 관리, 그리고 안정적인 서비스 운영을 위한 이미지 태그 고정 및 트래킹 설정 등 실무적인 구축 과정을 상세히 설명합니다.

LinkBreeze란 무엇인가

LinkBreeze는 직접 호스팅하는 Linktree 대안 서비스입니다. 하나의 Docker 컨테이너로 공개용 링크 페이지와 관리자 대시보드를 모두 제공하며, 모든 상태 정보는 단일 SQLite 파일에 저장됩니다. 이 프로젝트는 MIT 라이선스를 따르며 TypeScript와 Next.js로 작성되었습니다. 컨테이너 이미지는 Docker Hub의 omnirise/linkbreeze와 GHCR의 ghcr.io/manak-hash/linkbreeze를 통해 배포됩니다. 서비스를 실행하려면 VPS, 해당 VPS를 가리키는 A 레코드가 설정된 도메인, 80번 및 443번 포트 개방, 그리고 Docker Compose 플러그인이 포함된 Docker Engine이 필요합니다.

이 가이드는 저장소에서 공식적으로 지원하는 배포 방식, 즉 자체적으로 인증서를 발급받는 리버스 프록시 뒤에서 Docker Compose를 실행하는 방법을 다룹니다. 또한 무엇이 서비스 중단을 유발하는지도 설명합니다. 링크 페이지는 타인이 클릭하는 공개 URL이므로, 서비스가 중단되면 클릭을 유도할 수 없기 때문입니다.

본격적인 시작에 앞서, 이 프로젝트가 매우 초기 단계임을 명확히 인지하시기 바랍니다.

LinkBreeze는 공개 프로필 링크용으로 충분히 성숙했습니까?

2026년 8월 기준으로 GitHub 저장소는 178개의 별, 17개의 포크, 1명의 관리자를 보유하고 있었습니다. 첫 번째 태그된 릴리스인 v1.0.0은 2026년 7월 1일에 작성되었습니다. 이는 수년이 아닌 수개월 된 프로젝트입니다.

2026년 10월 11일, 관리자의 GitHub 계정과 저장소 모두 404 오류를 반환했습니다. 변경 로그에는 GitHub 계정 공개 범위 문제가 언급되어 있으며, 소스 코드는 여전히 프로젝트 공식 GitLab 미러인 gitlab.com/omnirise00/linkbreeze에 공개되어 있고 이미지는 Docker Hub에 있습니다.

차트LinkBreeze tagged releases per week, v1.0.0 to v1.4.1
이 차트의 데이터
[
  {
    "week": "2026-06-29",
    "releases": 3,
    "cumulative": 3
  },
  {
    "week": "2026-07-06",
    "releases": 3,
    "cumulative": 6
  },
  {
    "week": "2026-07-13",
    "releases": 1,
    "cumulative": 7
  },
  {
    "week": "2026-07-20",
    "releases": 2,
    "cumulative": 9
  },
  {
    "week": "2026-07-27",
    "releases": 3,
    "cumulative": 12
  },
  {
    "week": "2026-08-03",
    "releases": 2,
    "cumulative": 14
  },
  {
    "week": "2026-08-10",
    "releases": 4,
    "cumulative": 18
  },
  {
    "week": "2026-08-17",
    "releases": 1,
    "cumulative": 19
  },
  {
    "week": "2026-08-24",
    "releases": 1,
    "cumulative": 20
  },
  {
    "week": "2026-08-31",
    "releases": 0,
    "cumulative": 20
  },
  {
    "week": "2026-09-07",
    "releases": 0,
    "cumulative": 20
  },
  {
    "week": "2026-09-14",
    "releases": 1,
    "cumulative": 21
  },
  {
    "week": "2026-09-21",
    "releases": 1,
    "cumulative": 22
  }
]

v1.0.0 이후 이 프로젝트는 2026년 9월 23일 v1.4.1까지 22개의 릴리스를 13주에 걸쳐 배포했습니다. 릴리스 속도는 둔화되었습니다. 8월 14일까지 17개의 릴리스가 이루어졌으나, 2026년 10월 11일 기준으로 v1.4.1 이후 태그된 릴리스는 없습니다.

이 내용을 두 가지 별개의 사실로 이해하십시오. 관리자는 활동 중이며 버그는 며칠 내로 수정됩니다. 그러나 스키마와 기본 설정은 여전히 변경되고 있으므로, 배포 후 방치한 인스턴스는 작성 중인 코드와 크게 달라질 것입니다.

라이선스는 최악의 상황으로부터 사용자를 보호합니다. MIT 라이선스, 컨테이너 이미지, 그리고 로컬 디스크의 SQLite 파일 조합은 개발이 중단되더라도 현재 상태로 계속 실행될 수 있음을 의미합니다. 하지만 보안 수정 사항을 더 이상 받지 못하는 공개 웹 애플리케이션은 시간이 지남에 따라 위험 요소가 될 수 있습니다. 이 서비스를 배포할 때는 지속적인 업데이트를 계획하고, 아래의 백업 루틴을 첫날부터 정상적으로 작동하도록 유지하십시오.

이미지 태그를 고정하고 latest를 사용하지 마십시오

현재 릴리스 워크플로우는 버전당 두 개의 태그를 Docker Hub와 GHCR로 푸시합니다. 하나는 latest이며, 다른 하나는 푸시된 그대로의 git 태그로 v가 포함됩니다. 따라서 릴리스 v1.4.1에 고정해야 할 태그는 docker.io/omnirise/linkbreeze:v1.4.1입니다. v1.4.0 이전 릴리스는 다르게 태그가 지정되었습니다. 워크플로우에서 v를 제거했으므로, 해당 릴리스는 GHCR에만 ghcr.io/manak-hash/linkbreeze:1.2.7와 같은 순수 숫자로 존재합니다. 릴리스에 맞지 않는 형식으로 태그를 작성하면 Docker는 해당 태그가 푸시된 적이 없으므로 manifest unknown 오류를 보고합니다. 현재 README에서 기본 풀 경로로 사용하는 Docker Hub에는 latest 및 v1.4.1만 존재합니다.

latest는 계속 변하므로 태그를 고정해야 합니다. 위 차트의 주기에서 latest에 대해 docker compose pull을 수행하는 것은 사용자가 이용 중인 페이지를 검토 없이 업그레이드하는 것과 같습니다. 태그를 고정하면 파일을 수정할 때 업그레이드가 수행됩니다.

이미지에 관해 한 가지 더 말씀드릴 점이 있습니다. v1.4.0부터는 linux/amd64 및 linux/arm64을 위한 멀티 아키텍처 매니페스트 리스트이며, 각각 네이티브 러너에서 빌드됩니다. x86이 아닌 ARM VPS에서 실행하면 동일한 태그가 arm64 빌드를 가져오므로 서버에서 별도로 컴파일할 필요가 없습니다. v1.3.2까지의 릴리스는 linux/amd64용으로만 게시되었으며, 32비트 arm/v7 보드는 의도적으로 제외되었습니다. 따라서 이전 버전을 고정하거나 32비트 보드를 사용하면 no matching manifest 오류가 발생합니다.

Caddy를 활용한 LinkBreeze 배포 및 자동 TLS 설정

Caddy는 Let's Encrypt로부터 인증서를 직접 요청하고 갱신하므로, TLS(Transport Layer Security)를 위해 별도의 인증서 설정 단계를 거칠 필요가 없습니다. 전체 배포는 한 디렉터리에 있는 세 개의 파일로 구성됩니다.

먼저 시크릿을 생성합니다.

mkdir -p ~/linkbreeze && cd ~/linkbreeze
printf 'SECRET_KEY=%s\n' "$(openssl rand -hex 32)" > .env
chmod 600 .env

SECRET_KEY은 관리자 세션 쿠키에 서명하고 분석용 방문자 해시를 솔팅(salting)하며, v1.4.0 버전부터는 저장된 2단계 인증(TOTP) 시크릿을 암호화하는 키를 도출하는 데도 사용됩니다. 저장소에 게시된 compose 파일은 기본값을 ${SECRET_KEY:-changeme-in-production}로 설정하므로, 이 단계를 건너뛰면 프로젝트의 공개 저장소에 노출된 세션 서명 키로 인스턴스가 실행됩니다. 나중에 변경하면 로그아웃 처리되고 분석용 솔트가 초기화되므로, 첫 실행 전에 반드시 설정하십시오.

docker-compose.yml를 작성합니다.

services:
  linkbreeze:
    image: docker.io/omnirise/linkbreeze:v1.4.1
    restart: unless-stopped
    volumes:
      - linkbreeze-data:/app/data
    environment:
      - DATABASE_PATH=/app/data/linkbreeze.db
      - SECRET_KEY=${SECRET_KEY}
      - BASE_URL=https://links.example.com
    networks:
      - linkbreeze-net

  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config
    networks:
      - linkbreeze-net

networks:
  linkbreeze-net:

volumes:
  linkbreeze-data:
  caddy-data:
  caddy-config:

BASE_URL은 선택 사항이지만 설정하는 것이 좋습니다. 애플리케이션에 실제 공개 주소를 알려주어, 위조된 Host 헤더가 포함된 요청이 들어와도 애플리케이션이 타인의 도메인으로 링크를 생성하지 못하도록 방지합니다.

그 옆에 본인의 도메인을 사용하여 Caddyfile를 작성합니다.

links.example.com {
    encode zstd gzip
    reverse_proxy linkbreeze:3000
}

Caddy는 기본적으로 프록시 요청에 X-Forwarded-For 및 X-Forwarded-Proto를 설정하며, 분석 기능은 이에 의존합니다. 서비스를 시작합니다.

docker compose up -d
docker compose ps
docker compose logs -f caddy

docker compose ps를 실행하면 LinkBreeze 컨테이너가 healthy 상태로 표시되어야 합니다. 이미지 자체에 헬스체크인 wget --spider -q http://127.0.0.1:3000/api/health이 포함되어 있으므로 별도로 추가할 필요는 없습니다. 저장소의 Caddy 예제에 있는 헬스체크를 그대로 복사하지 마십시오. 해당 예제는 curl을 호출하는데, 이 이미지는 node:22-alpine 기반으로 빌드되어 busybox wget만 포함하고 curl은 없기 때문입니다. 해당 컨테이너는 페이지를 완벽하게 제공하면서도 unhealthy 상태를 보고할 수 있습니다.

브라우저에서 https://links.example.com을 엽니다. 첫 방문 시 /setup의 설정 마법사로 이동하며, 여기서 단일 관리자 계정을 생성합니다. 이후 대시보드는 /dashboard에서, 로그인 폼은 /login에서 이용할 수 있습니다. 해당 계정은 이 인스턴스 전용이며 애플리케이션 내에 SSO(Single Sign-On) 연동 기능은 없습니다. 따라서 호스팅 중인 다른 서비스와 동일한 계정으로 대시보드에 로그인하려면 자체 호스팅 Authentik과 같은 전방 인증 프록시를 앞단에 배치해야 합니다.

compose 파일이 수행하지 않는 작업에 유의하십시오. 포트 3000을 외부로 노출하지 않습니다. 오직 Caddy만이 공개 인터페이스에서 수신 대기합니다. Compose 파일 문법이 생소하다면 VPS를 위한 Docker Compose 기초에서 이 파일이 전제로 하는 내용을 다루고 있으며, 이미 다른 프록시를 사용 중이라면 Nginx, Caddy 및 Traefik 비교에서 변경 사항을 확인할 수 있습니다. 저장소는 Certbot을 사용하는 Nginx, Traefik 및 Cloudflare 터널에 대한 작동 예제를 제공합니다.

데이터가 저장되는 위치와 백업에 포함되어야 할 내용

DATABASE_PATH은 /app/data/linkbreeze.db을 가리킵니다. 업로드된 아바타와 링크 썸네일은 그 옆의 /app/data/uploads에 기록됩니다. 두 항목 모두 linkbreeze-data이라는 이름의 볼륨에 저장되므로, 백업 단위는 데이터베이스 파일 단독이 아닌 볼륨 전체가 되어야 합니다. 업로드 디렉터리 없이 파일만 복원하면 페이지의 모든 이미지가 404 오류를 반환하게 됩니다.

그 외의 모든 데이터는 실제로 해당 데이터베이스 내에 존재합니다. 여기에는 페이지, 링크, 설정, 테마, 이메일 구독자 및 분석 데이터 행이 포함됩니다.

컨테이너를 중지한 상태에서 복사본을 생성하십시오:

docker compose stop linkbreeze
docker compose cp linkbreeze:/app/data ./backup-$(date +%F)
docker compose start linkbreeze

SQLite 데이터베이스에 프로세스가 쓰기 작업을 수행하는 도중에 복사하면 트랜잭션이 완료되지 않은 상태로 캡처되어, 복사본이 손상된 파일로 열릴 수 있으므로 반드시 먼저 중지해야 합니다. 복사가 진행되는 동안 페이지는 오프라인 상태가 됩니다. 복원 작업은 이 과정을 역순으로 수행하면 됩니다:

docker compose stop linkbreeze
docker compose cp ./backup-2026-08-14/. linkbreeze:/app/data
docker compose start linkbreeze
docker compose logs -f linkbreeze

대시보드에서는 /api/backup에서 linkbreeze-backup-YYYY-MM-DD.json 형식으로 제공되는 JSON 내보내기 기능도 지원합니다. 여기에는 프로필, 링크와 섹션, 설정, 저장된 테마 및 사용자 지정 폰트 항목이 포함됩니다. 분석 기록, 이메일 구독자, 관리자 계정 또는 업로드된 파일은 포함되지 않으며, 이 파일을 복원하면 기존에 포함된 6개 테이블의 현재 행을 삭제한 뒤 파일의 데이터를 삽입합니다. 이 기능은 호스트를 이전하거나 편집 실수를 되돌리기 위한 설정 스냅샷으로 활용하십시오. 볼륨 복사본이 곧 백업입니다.

VPS에서 SQLite를 운영하는 다른 모든 경우와 마찬가지로 두 가지 저장소 규칙이 적용됩니다. SQLite의 잠금 기능은 네트워크 파일 시스템에서 신뢰할 수 없으며, 데이터 페이지가 손상된 후에야 이를 알게 될 수 있으므로 데이터베이스는 반드시 로컬 디스크에 유지하십시오. 또한 이름이 지정된 볼륨 대신 호스트 바인드 마운트를 사용하는 경우, 먼저 호스트 디렉터리의 소유권을 변경(chown)하십시오. 컨테이너는 node:22-alpine 내의 uid 1000인 비루트(non-root) node 사용자로 실행되므로, 루트 권한으로 생성된 디렉터리에는 쓰기 권한이 없습니다. 이 경우 애플리케이션이 데이터베이스를 열 수 없어 컨테이너가 시작 시 종료됩니다. Compose에서 이름이 지정된 볼륨과 바인드 마운트 비교에서 해당 내용을 자세히 다룹니다.

분석 도구와 동의 배너가 필요 없는 이유

이 기능이야말로 다른 곳에서 무료로 얻을 수 있는 페이지를 굳이 직접 호스팅하는 이유를 정당화합니다.

분석 도구는 쿠키를 사용하지 않습니다. 방문자에게 쿠키가 설정되지 않으며, 공개 페이지에서 타사 스크립트가 로드되지 않습니다. 방문자는 IP 주소, 사용자 에이전트 문자열, 솔트(salt)를 SHA-256으로 해싱한 뒤 16자리 16진수로 자른 값으로 식별됩니다. 솔트 자체는 현재 UTC 날짜와 SECRET_KEY을 해싱한 값이므로 UTC 자정에 변경되며, 어제의 해시값으로 오늘의 방문자를 추적할 수 없습니다. 원본 IP 주소는 데이터베이스에 기록되지 않습니다.

클릭 수는 서버에서 집계됩니다. 공개 페이지의 모든 http 링크는 자신의 도메인에 있는 /go/<id>을 가리키며, 이 경로가 클릭을 기록한 뒤 실제 목적지로 302 리다이렉트 응답을 보냅니다. 따라서 JavaScript가 비활성화된 환경이나 백그라운드 요청을 차단하는 인앱 브라우저에서도 클릭 집계가 정상적으로 작동합니다. 페이지 뷰는 /api/track를 통해 기록됩니다.

두 가지 예외 사항을 알아두어야 합니다. 유효한 관리자 세션이 포함된 요청은 건너뛰므로, 페이지를 직접 편집할 때 조회수가 증가하지 않습니다. 알려진 크롤러 사용자 에이전트 또한 집계에서 제외됩니다.

동의 관련 사항: 독자의 기기에는 아무것도 저장되지 않으며, 쿠키 배너가 허가를 요구하는 대상은 독자의 기기에 저장되는 쿠키입니다. 독자가 거주하는 지역에 따라 법적 의무가 달라질 수 있으므로 확인이 필요하지만, 여기에는 공개해야 할 추적 쿠키가 없으며 데이터를 수신하는 제3자도 없습니다.

사용자들이 종종 놀라는 주의 사항이 하나 있습니다. SECRET_KEY을 교체하면 일일 솔트도 함께 변경되므로, 그 시점부터 모든 재방문자는 신규 방문자로 집계됩니다.

분석 데이터의 국가 열이 비어 있는 이유는 무엇입니까?

스택 내에서 국가 헤더를 설정하는 항목이 없기 때문입니다. LinkBreeze는 cf-ipcountry 및 x-vercel-ip-country와 같은 프록시 헤더를 통해 국가 정보를 확인합니다. Caddy나 Nginx 뒤에 있는 VPS 환경에서는 이러한 헤더가 존재하지 않으므로 국가 정보가 null로 기록되고 분석 결과가 비어 있게 됩니다. 컨테이너 내부에는 GeoIP 데이터베이스가 포함되어 있지 않습니다.

이 문제를 해결하는 방법은 두 가지입니다. 도메인 앞에 Cloudflare를 배치하면 프록시를 거치는 모든 요청에 cf-ipcountry이 추가됩니다. 또는 로컬 GeoIP 조회를 수행하여 직접 운영하는 리버스 프록시에서 해당 헤더 중 하나를 설정할 수 있습니다.

이와 관련된 더 심각한 함정이 있으니 확인이 필요합니다. 클릭 및 조회 핸들러는 클라이언트 주소를 읽을 때 먼저 X-Forwarded-For을 확인하고, 그다음 X-Real-IP을 확인하며, 두 헤더가 모두 없을 경우 0.0.0.0로 대체합니다. 프록시 없이 포트 3000을 인터넷에 직접 노출하면 모든 방문자가 동일한 값으로 해싱됩니다. 이 경우 고유 방문자 수는 항상 1로 표시되며, IP당 분당 60개 이벤트라는 속도 제한(rate limit)이 전체 방문자에게 한꺼번에 적용됩니다. 위에서 언급한 reverse_proxy 지시문을 사용하면 Caddy가 헤더를 자동으로 설정하므로 두 문제 모두 해결됩니다.

Linktree에서 가져오기 및 이전되지 않는 항목

대시보드의 마이그레이션 마법사는 공개 프로필 URL이나 내보낸 파일을 허용합니다. 이 마법사는 linktr.ee, bento.me, lnk.bio, tap.link, hopp.bio, beacons.ai, solo.to, linkfly, mssg.me, LittleLink 페이지와 일반적인 HTML 및 JSON 내보내기 형식을 인식합니다. Linktree나 Bento URL의 경우 해당 페이지에 포함된 __NEXT_DATA__ JSON을 읽어 들입니다. 정적 페이지의 경우 앵커 태그를 읽습니다.

이전되는 항목은 각 링크의 제목, URL, 설명, 이미지, 소셜 프로필 여부, 그리고 사용자의 표시 이름, 소개글, 아바타입니다. 데이터베이스에 기록하기 전에 발견된 링크 중 유지할 항목을 직접 선택할 수 있습니다.

이전되지 않는 항목은 분석 기록, 테마 및 레이아웃, 이메일 구독자, 게시 예약 날짜, 그리고 이전 플랫폼이 자체 로그인 뒤에 보관하는 모든 데이터입니다. 외관은 수동으로 다시 구성해야 하며, 기존 클릭 기록은 이전 서비스에 남는다는 점을 인지하십시오.

임포터는 브라우저가 아닌 서버에서 URL을 가져오므로 공개되지 않은 주소는 거부합니다. Private/local URLs are not allowed는 사용자가 내부 네트워크의 주소를 입력했음을 의미하며, 이러한 거부는 의도된 것입니다. 이 기능이 없다면 대시보드 접근 권한이 있는 누구나 사용자의 서버를 이용해 서버에서만 접근 가능한 내부 장비를 탐색할 수 있기 때문입니다. 그 외에 발생할 수 있는 메시지는 Only http and https URLs are allowed, Request timed out, Response too large입니다.

스크래핑은 타사의 마크업 구조에 의존합니다. 링크가 분명히 존재하는 페이지에서 마법사가 아무것도 찾지 못한다면, 해당 플랫폼이 파서 작성 이후 HTML 구조를 변경한 것입니다. 수정 사항을 기다리기보다 링크를 직접 추가하십시오. 프로필 페이지가 아닌 측정 가능한 단축 링크가 필요한 경우, Shlink와 같은 자체 호스팅 URL 단축기가 해당 역할을 수행하며 동일한 서버에서 원활하게 작동합니다.

고정된 배포 버전 업데이트

# edit the image tag in docker-compose.yml, then
docker compose pull
docker compose up -d
docker compose logs -f linkbreeze

컨테이너가 시작되면 스키마 마이그레이션이 자동으로 실행됩니다. 이를 되돌리는 공식적인 방법은 없으므로, 먼저 볼륨을 복사해 두어야 합니다. 되돌릴 수 없는 업그레이드는 이전 상태를 복구할 수 있을 때만 안전합니다.

대시보드는 더 최신 릴리스가 존재할 때 배너를 표시하도록 설계되었습니다. 릴리스된 버전은 프로젝트의 GitHub 저장소에서 작은 버전 파일을 가져와 확인하며, 최대 24시간에 한 번만 수행하고 인스턴스에 대한 정보는 전송하지 않습니다. 변경 로그에 따르면 v1.2.0에서 v1.4.0 버전은 404 응답을 반환하는 주소를 폴링하여 배너가 표시되지 않았으며, 2026년 10월 11일 기준으로도 해당 GitHub 파일은 여전히 404를 반환합니다. 변경 로그의 다음 미출시 항목에서는 확인 주소를 linkbreeze.omnirise.dev/latest-version.json로 변경합니다. 해당 변경 사항이 포함된 버전을 실행하기 전까지는 배너를 기다리지 말고 linkbreeze.omnirise.dev/changelog에서 변경 로그를 직접 확인하십시오. 현재 프로젝트 단계에서는 마이너 버전 업데이트로도 의존하고 있는 기본 설정이 변경될 수 있으므로, 태그를 변경하기 전에 릴리스 노트를 읽어보시기 바랍니다.

실패 유형 및 확인되는 메시지

manifest unknown (풀링 시). 태그 형식이 해당 릴리스와 맞지 않습니다. v1.4.0부터 태그는 v 형식을 유지하므로 :v1.4.1를 사용하십시오. v1.3.2까지의 GHCR 릴리스는 :1.2.7와 같은 단순 숫자 형식을 사용하며, Docker Hub에는 latest 및 v1.4.1만 존재합니다.

no matching manifest for linux/arm64/v8 in the manifest list entries. v1.4.0 이전의 릴리스를 고정(pin)했으며, 해당 버전은 amd64용으로만 배포되었습니다. arm64 빌드를 포함하는 v1.4.1로 고정 버전을 변경하십시오. 32비트 arm/v7 보드는 해당 플랫폼을 지원하지 않으므로 모든 릴리스에서 동일한 오류가 발생합니다.

페이지는 정상적으로 로드되지만 컨테이너가 unhealthy를 보고합니다. compose 파일의 헬스체크가 이미지에 포함되지 않은 curl를 호출하고 있습니다. 해당 설정을 삭제하고 이미지 자체의 wget 헬스체크가 실행되도록 하십시오.

Caddy가 인증서 오류를 반환하거나 아무것도 응답하지 않습니다. docker compose logs caddy를 확인하십시오. 일반적인 원인은 A 레코드가 아직 해당 VPS를 가리키지 않거나, 방화벽에서 80번 포트가 닫혀 있는 경우입니다. 80번 포트가 닫혀 있으면 Caddy가 도메인 소유권을 증명하기 위해 사용하는 ACME(자동 인증서 관리 환경) HTTP 챌린지가 차단됩니다.

고유 방문자 수가 1에서 멈춰 있습니다. 프록시가 X-Forwarded-For를 설정하지 않아 모든 방문자의 해시값이 동일하게 처리되고 있습니다.

어제까지는 정상이었으나 시작 직후 컨테이너가 종료됩니다. 명명된 볼륨(named volume)에서 호스트 바인드 마운트로 변경했다면, 데이터 디렉터리의 소유권이 root로 되어 있어 uid 1000으로 실행되는 애플리케이션이 데이터베이스 파일을 열 수 없는 상태입니다. 호스트 디렉터리의 sudo chown -R 1000:1000를 수행하십시오.

추적 요청에 대해 HTTP 429 응답이 반환됩니다. /api/track 및 /go/<id>에 설정된 IP당 제한(throttle)에 도달했습니다. 방문자는 목적지로 정상적으로 리다이렉트되지만, 클릭 기록만 집계되지 않습니다.

FAQ

이 프로젝트는 아직 초기 단계입니다. 2026년 8월 기준 GitHub 저장소는 178개의 스타, 17개의 포크, 1명의 관리자를 기록했으며, 첫 번째 릴리스는 2026년 7월 1일에 배포되었습니다. 2026년 9월 23일 v1.4.1 버전까지 총 22개의 태그된 릴리스가 배포되었으며, 대부분 8월 중순 이전에 이루어졌으므로 동작 방식이 빠르게 변화해 왔습니다. 2026년 10월 11일 GitHub 계정은 404 오류를 반환했으나, GitLab 미러와 Docker Hub 이미지는 여전히 사용 가능합니다. MIT 라이선스와 로컬 SQLite 파일을 사용하므로 개발이 중단되어도 페이지는 계속 작동하지만, 보안 업데이트가 없는 공개 웹 애플리케이션은 위험 요소가 될 수 있습니다. 따라서 한 번 설치하고 끝나는 소프트웨어가 아니라 지속적으로 업데이트해야 하는 서비스로 간주하십시오.

어떤 LinkBreeze 이미지 태그를 사용해야 합니까?

docker.io/omnirise/linkbreeze:v1.4.1와 같은 버전 태그를 사용하고, 필요에 따라 의도적으로 변경하십시오. v1.4.0부터 릴리스 워크플로우는 latest와 v 접두사가 붙은 git 태그를 푸시합니다. 따라서 v이 없는 :1.4.1은 존재하지 않으며, Docker는 manifest unknown 오류를 반환합니다. v1.3.2 이전 릴리스는 이와 반대로 GHCR에 숫자만 있는 태그를 사용했습니다. v1.4.0부터는 linux/amd64 및 linux/arm64용 이미지가 빌드되므로, arm64 기반 VPS에서 별도의 로컬 빌드 없이 직접 가져올 수 있습니다.

LinkBreeze 분석에서 국가별 통계가 비어 있는 이유는 무엇입니까?

LinkBreeze는 cf-ipcountry 또는 x-vercel-ip-country과 같은 프록시 헤더에서 방문자의 국가 정보를 읽어오며, 자체적인 GeoIP 데이터베이스를 포함하고 있지 않습니다. Caddy나 Nginx 뒤에 있는 VPS는 해당 헤더를 설정하지 않으므로 국가 정보가 null로 저장됩니다. 도메인 앞에 Cloudflare를 배치하거나, 리버스 프록시에서 로컬 GeoIP 조회를 통해 해당 헤더 중 하나를 설정하도록 구성하십시오.

정확히 무엇을 백업해야 하며, 어떻게 복원합니까?

데이터베이스 파일뿐만 아니라 linkbreeze-data 볼륨 전체를 백업하십시오. /app/data/linkbreeze.db에는 모든 링크, 페이지, 설정, 구독자 및 분석 데이터가 저장되며, /app/data/uploads에는 페이지에서 참조하는 아바타와 썸네일 이미지가 저장됩니다. 컨테이너를 중지하고 docker compose cp linkbreeze:/app/data ./backup-$(date +%F)를 실행한 뒤 다시 시작하십시오. 복원하려면 디렉터리를 중지된 컨테이너에 다시 복사하고 컨테이너를 시작하면 됩니다. 대시보드에서 내보낸 JSON 파일은 프로필, 링크, 설정, 테마 및 폰트 항목에 대한 구성 스냅샷일 뿐이며, 분석 데이터나 이미지는 포함되어 있지 않습니다.

Linktree에서 가져오기를 하면 분석 데이터와 테마도 함께 이전됩니까?

아니요. 마이그레이션 마법사는 이전 공개 프로필에서 링크 제목, URL, 설명, 이미지와 표시 이름, 소개글, 아바타 정보만 읽어옵니다. 분석 기록, 테마, 이메일 구독자, 예약 게시 날짜는 이전되지 않습니다. 가져오기 후 테마 편집기에서 디자인을 다시 구성해야 하며, 클릭 기록은 기존 플랫폼에 그대로 남게 됩니다.

#linkbreeze#linktree-alternative#docker-compose#sqlite#self-hosting#analytics