Dashlit 서버 이사 노트

맥에서 사용하던 Dashlit 북마크를 coolify 서비스로 이동할 수 있다.

Dashlit 서버 이사 노트

맥에서 혼자 사용하던 Dashlit를 외부 서버로 옮기는 과정을 정리합니다. 핵심은 데이터폴더를 그대로 옮기는 것이 목표입니다.

한눈에 보기: 바꿀 것 세 가지

무엇맥에서서버에서이유
데이터 폴더 경로/Users/heesung/Desktop/Docker_volumes/dashlit/data/opt/dashlit/data맥 경로는 서버에 없습니다.
JWT_SECRETPortainer에 저장된 값똑같은 값값이 바뀌면 로그인이 모두 풀립니다.
파일 주인 번호501:20 (heesung:staff)10001:10001 (dashlit)앱이 10001번으로 실행되기 때문입니다.

501:20은 맥의 첫 사용자 기본값입니다. 맥 터미널에서 id를 치면 내 번호를 확인할 수 있습니다.


개념 정리

컨테이너

앱 하나와 그 앱에 필요한 것을 통째로 담은 상자(도시락통)입니다. 상자는 언제 버리고 새로 만들어도 됩니다. 그래서 중요한 데이터는 상자 밖에 따로 보관합니다.

이미지와 태그

이미지(컨테이너를 찍어내는 틀)는 ghcr.io/codewec/dashlit, 뒤의 :main은 태그(틀의 버전 이름표)입니다. :main은 받을 때마다 최신판으로 바뀔 수 있습니다. 이사 직후 문제가 생기면 원인을 가리기 어려우니 쓰던 버전을 적어 두세요.

볼륨 (바인드 마운트)

컴퓨터의 폴더를 상자 안에 연결하는 통로(상자에 서랍을 꽂는 것)입니다. 왼쪽:오른쪽에서 왼쪽이 바깥 폴더, 오른쪽이 상자 안 위치입니다. 이사할 때는 왼쪽만 바꾸면 됩니다.

환경변수

앱을 켤 때 건네주는 설정 메모입니다. ${DASHLIT_JWT_SECRET}은 "실제 값은 다른 곳에 적어 뒀다"는 표시입니다. Portainer는 스택의 Environment variables 칸, 직접 실행하면 같은 폴더의 .env 파일에 값을 넣습니다.

JWT_SECRET

JWT(로그인 출입증)에 찍는 도장을 만드는 비밀 열쇠입니다. 열쇠가 바뀌면 예전 출입증이 모두 가짜로 취급됩니다. 맥에서 쓰던 값을 그대로 가져가세요.

소유권 (UID / GID)

리눅스는 파일 주인을 이름이 아니라 번호로 기억합니다(UID는 사람 번호, GID는 모둠 번호). 파일 주인 번호와 앱의 번호가 맞아야 앱이 파일에 쓸 수 있습니다. heesung, dashlit 같은 이름은 사람이 보기 좋게 붙인 별명일 뿐입니다.

맥에서 괜찮았던 이유

맥의 Docker Desktop은 폴더를 연결할 때 번호 차이를 알아서 맞춰 줍니다(통역사 역할). 리눅스 서버에는 이 통역사가 없습니다. 그래서 서버에서는 번호를 직접 맞춰야 합니다.

chown

파일 주인 번호를 바꾸는 명령(change owner, 이름표 바꿔 달기)입니다. -R은 폴더 안의 파일까지 전부 바꾸라는 뜻입니다. chmod 777(아무나 쓰게 문 열어 두기)은 바깥에 공개하는 서비스에서는 위험하니 쓰지 않습니다.

리버스 프록시와 HTTPS

리버스 프록시(건물 안내 데스크)는 바깥 손님을 받아 안쪽 앱으로 안내합니다. 여기서 HTTPS(봉투에 넣어 보내는 편지)를 맡으면 로그인 정보가 암호화됩니다. Caddy, Nginx Proxy Manager, Cloudflare Tunnel이 대표적입니다.

DISABLE_PASSWORD_REGISTRATION

true면 새 회원가입을 막습니다. 인터넷에 공개하면 아무나 계정을 만들 수 있게 되니 꼭 켜 둡니다.

맥의 @ 표시

drwxr-xr-x@의 @는 맥만 쓰는 숨은 메모(확장 속성, 예: 인터넷에서 받은 파일 표시)가 붙어 있다는 뜻입니다. 리눅스는 이 메모를 모릅니다. 포장할 때 COPYFILE_DISABLE=1과 --no-xattrs를 함께 붙여 메모를 빼고 보냅니다.


그림으로 보는 소유권 문제

앱 번호 10001은 맥에서 docker exec dashlit id로 확인한 값입니다. 결과는 uid=10001(dashlit) gid=10001(dashlit)이었습니다.

이사 순서


0 Tailscale 사용자라면 ACL부터 확인

Tailscale 관리 콘솔 · Access controls

ACL(누가 어느 기기의 몇 번 문으로 갈 수 있는지 적은 출입 명단)에 새 서버가 없으면 연결이 조용히 버려집니다. 오류 메시지 대신 타임아웃만 나서 원인을 찾기 어렵습니다. 옮기기 전에 "맥 → 새 서버 22번" 허락부터 넣어 두세요.

1 맥에서 준비물 확인

맥 터미널 · 완료앱 번호는 10001로 확인했습니다. Portainer 스택 화면에서 DASHLIT_JWT_SECRET 값도 복사해 둡니다.

docker exec dashlit id

2 앱을 멈추고 데이터 포장

맥 터미널켜진 채로 복사하면 데이터가 반쯤 저장된 상태로 담길 수 있습니다. 반드시 먼저 멈춥니다.

docker stop dashlit
cd ~/Desktop/Docker_volumes
COPYFILE_DISABLE=1 tar --no-xattrs -czf dashlit-data.tgz -C dashlit data

설명:
COPYFILE_DISABLE=1은 ._ 찌꺼기 파일을, --no-xattrs는 맥 숨은 메모(확장 속성)를 빼고 포장합니다. 둘 다 있어야 서버에서 경고 없이 풀립니다.
마지막에 data는 하위폴더 입니다. 여러개의 폴더가 있다면 스페이스바(뛰어쓰기)로 구별하시면됩니다. data data1 temp1

3 서버로 보내고 풀기

맥 → 서버
scp(파일 택배)로 서버에 보낸 뒤, 서버에서 폴더를 만들고 풉니다.

# 맥에서 
# ssh key를 사용하지 않는다면 scp dashlit-data.tgz 접속아이디@서버주소:/tmp/
scp -i ~/.ssh/키파일 dashlit-data.tgz 접속아이디@서버아이피:/tmp/

# 서버에서
sudo mkdir -p /opt/dashlit
sudo tar --warning=no-unknown-keyword -xzf /tmp/dashlit-data.tgz -C /opt/dashlit

다 풀렸는지는 파일 개수로 확인합니다. 맥과 서버의 숫자가 같으면 됩니다.

# 서버
find /opt/dashlit/data | wc -l
# 맥
find ~/Desktop/Docker_volumes/dashlit/data | wc -l

4 폴더권한 맞추기

서버 터미널

파일 주인을 앱 번호 10001로 바꿉니다. ls -ln(이름 대신 번호로 보기)에서 10001 10001이 보이면 성공입니다.

sudo chown -R 10001:10001 /opt/dashlit/data
ls -ln /opt/dashlit/data

5 새로운 스텍에 올리기 (Coolify)

개인적으로 여러 서비스 중에서 coolify 서비스를 이용합니다. casaos도 좋긴하지만 외부 서비스로는 업데이트도 빠르고 만족합니다. coolify 에서 caddy를 이용합니다.

기존 Portainer 에서 사용하던 Stack의 내용을 활용한다.

services:
  app:
    container_name: dashlit
    image: ghcr.io/codewec/dashlit:main
    restart: unless-stopped
    environment:
      - JWT_SECRET=${DASHLIT_JWT_SECRET}
      - DISABLE_PASSWORD_REGISTRATION=true
    healthcheck:
      - disable: true
    volumes:
      - /opt/dashlit/data:/data  # 바뀜: 서버 경로

coolify 에서 주의할것은 Port 부분이다.

ports:를 남겨 두면 서버의 해당번호 문이 실제로 열립니다. 지금은 OCI 보안 목록에 4530 규칙이 없어 밖에서 못 들어오지만, Docker로 연 포트는 서버 iptables의 REJECT 줄을 거치지 않습니다. 나중에 보안 목록을 넓게 열면 그대로 노출되니 지워 두는 게 깔끔합니다.

중간에 보면 ${DASHLIT_JWT_SECRET} 부분의 내용을 Portainer Stack ENV에서 가져와야한다. 이부분 안넣으면 동일한 서비스로 복사가 안된다.

6 이동성공 확인하자

서버 터미널

아래 명령의 결과가 비어 있으면 권한 문제가 없는 것입니다. 그다음 브라우저로 접속해 기존 계정으로 로그인되는지 봅니다.

docker logs dashlit 2>&1 | grep -iE 'permission denied|EACCES'

이후 coolify 에서 입력한 도메인과 기존 로그인으로 확인하자.

▲