맥 세 대를 하나처럼 — Tailscale + SSH + 홈서버 구축기

포트포워딩 없이 맥 3대를 하나의 네트워크로 연결한 경험

DevOps
2026년 3월 11일

맥을 세 대 쓰고 있습니다. 집에서 쓰는 메인 맥북프로, 이동할 때 들고 다니는 맥북에어, 그리고 24시간 켜두는 맥미니. 처음에는 맥북 두 대에서 개발 환경을 동기화하려고 했는데, 도커 컨테이너, 로컬 DB, 환경변수, 터미널 설정까지 맞추려면 결국 양쪽 다 셋팅을 해야 했습니다.

그래서 방향을 바꿨습니다.

개발 환경은 메인 맥북프로에만 두고, 에어는 화면이랑 키보드 역할만 하자.

어디서든 맥북프로에 SSH로 붙어서 작업하면 됩니다. 맥미니는 디스코드 봇이나 자동화 서비스처럼 24시간 떠있어야 하는 것들을 돌리는 홈서버 역할입니다.

전체 구조

핵심 개념은 씬 클라이언트입니다.

맥북에어 (이동용, 씬 클라이언트)
    └── SSH ──→ 맥북프로 (메인 개발 환경)

맥미니 (24시간 홈서버)
    ├── Docker (디스코드 봇, n8n 등)
    └── GitHub Actions 배포 대상

전체를 Tailscale로 연결

에어는 화면과 키보드 역할만 하고, 코드 실행, 도커, 빌드는 전부 맥북프로에서 일어납니다. 카페에서 에어로 작업해도 맥북프로 환경 그대로 쓸 수 있습니다. 맥미니는 개발용이 아니라 서비스 운영용입니다.

Tailscale — 어디서든 연결해주는 핵심 도구

집 밖에서 홈 네트워크에 접근하려면 보통 포트포워딩을 생각합니다. 하지만 포트포워딩은 설정이 번거롭고, 포트를 인터넷에 열어두면 외부 봇들이 24시간 두드립니다. 보안적으로도 좋지 않습니다.

Tailscale은 이 문제를 깔끔하게 해결해줍니다. WireGuard 기반의 메시 VPN인데, 설정이 앱 깔고 로그인하면 끝입니다. 장비끼리만 통신하는 구조라 포트를 인터넷에 전혀 열지 않습니다.

Tailscale 설치 (macOS)
brew install tailscale
sudo brew services start tailscale
sudo tailscale up

세 대 모두 설치하고 같은 계정으로 로그인하면 자동으로 연결됩니다.

Tailscale 상태 확인
tailscale status
# 100.112.x.x   macbookpro   chahyunwoo@  macOS
# 100.64.x.x    macmini      chahyunwoo@  macOS
# 100.78.x.x    macbookair   chahyunwoo@  macOS

이제 어디서든, 카페 와이파이에서든, 테더링 중이든 Tailscale IP로 서로 접근 가능합니다. 같은 공유기에 물려있지 않아도 됩니다.

Tailscale은 무료 플랜에서 장비 100대까지 지원합니다. 개인 용도로는 충분합니다.

SSH 키 설정

비밀번호 없이 접속하려면 SSH 키를 등록해야 합니다.

SSH 키 생성 + 등록
# 키 생성 (이미 있으면 생략)
ssh-keygen -t ed25519 -C "your@email.com"
 
# 각 장비에 공개키 등록
ssh-copy-id chahyunwoo@100.112.x.x   # 맥북프로
ssh-copy-id hyunwoo@100.64.x.x       # 맥미니

그리고 ~/.ssh/config에 별칭을 등록하면 IP를 외울 필요가 없습니다.

~/.ssh/config
Host macpro
  HostName 100.112.x.x
  User chahyunwoo
  IdentityFile ~/.ssh/id_ed25519
 
Host macmini
  HostName 100.64.x.x
  User hyunwoo
  IdentityFile ~/.ssh/id_ed25519

이제 ssh macpro, ssh macmini 한 줄로 접속됩니다.

VS Code Remote SSH — 에어에서 프로처럼 개발

여기서 한 단계 더 나갑니다. 터미널 SSH만으로도 충분하지만, VS Code의 Remote SSH 익스텐션을 쓰면 에어에서 맥북프로의 파일 시스템에 직접 접근해서 개발할 수 있습니다.

Cmd + Shift + PRemote-SSH: Connect to Hostmacpro 선택하면 연결됩니다. 터미널도 맥북프로 터미널이고, 코드 실행도 맥북프로에서 됩니다. 에어는 말 그대로 모니터 역할입니다.

에어의 배터리도 훨씬 오래갑니다. 무거운 작업은 전부 맥북프로에서 일어나니까요.

맥미니 홈서버 설정

맥미니를 24시간 서버로 쓰려면 몇 가지 설정이 필요합니다.

정전 후 자동 시작

시스템 설정 → 일반 → 전원 → 정전 후 자동으로 시작 체크. 정전이 되더라도 전원이 복구되면 맥미니가 자동으로 부팅됩니다.

잠자기 방지

잠자기 완전 비활성화
sudo pmset -a sleep 0

서버는 잠자면 안 됩니다. 이 설정으로 디스플레이가 꺼져도 시스템은 계속 깨어있습니다.

원격 로그인

시스템 설정 → 일반 → 공유 → 원격 로그인 활성화. 이걸 켜야 SSH 접속이 됩니다.

이 세 가지만 설정하면 맥미니는 24시간 서버로 동작합니다. Tailscale이 설치되어 있으니 외출 중에도 ssh macmini로 접속 가능합니다.

Docker + CI/CD — GitHub Actions에서 맥미니로 자동 배포

맥미니에서 서비스를 운영하려면 Docker가 필요합니다. 저의 경우 디스코드 봇을 Docker Compose로 돌리고 있는데, 원래는 AWS Lightsail에서 운영하고 있었습니다. 근데 어차피 맥미니가 24시간 켜져있으니 거기로 옮기면 월 비용을 아낄 수 있었습니다.

문제는 CI/CD였습니다. AWS는 GitHub Actions에서 공인 IP로 SSH 접근이 가능했는데, 맥미니는 홈 네트워크 안에 있어서 외부에서 직접 접근이 안 됩니다. 여기서도 Tailscale이 답이었습니다.

Tailscale ACL + OAuth 설정

GitHub Actions 러너가 Tailscale 네트워크에 접속하려면 OAuth 클라이언트가 필요합니다. Tailscale 관리 콘솔에서 ACL에 tag:ci를 추가하고, OAuth 클라이언트를 생성합니다.

Tailscale ACL
{
  "tagOwners": {
    "tag:ci": ["autogroup:admin"]
  },
  "grants": [
    {"src": ["*"], "dst": ["*"], "ip": ["*"]}
  ]
}

생성된 Client ID와 Secret을 GitHub Repository Secrets에 등록합니다.

배포 워크플로우

.github/workflows/deploy.yml
deploy:
  runs-on: ubuntu-latest
  needs: test
  if: github.ref == 'refs/heads/main'
  steps:
    - name: Tailscale 연결
      uses: tailscale/github-action@v2
      with:
        oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
        oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
        tags: tag:ci
 
    - name: SSH 키 등록
      run: |
        mkdir -p ~/.ssh
        echo "${{ secrets.MACMINI_SSH_KEY }}" > ~/.ssh/id_ed25519
        chmod 600 ~/.ssh/id_ed25519
        ssh-keyscan -H 100.64.x.x >> ~/.ssh/known_hosts
 
    - name: 배포
      run: |
        ssh hyunwoo@100.64.x.x "cd ~/discord-bot && git pull origin main && docker compose up -d --build"

main 브랜치에 push하면 자동으로 테스트 → Tailscale 접속 → 맥미니에 배포가 됩니다.

Docker 키체인 문제

한 가지 주의할 점이 있습니다. SSH 세션에서 docker compose build를 실행하면 이런 에러가 납니다.

error getting credentials - err: exit status 1, out: `keychain cannot be accessed
because the current session does not allow user interaction`

Docker Desktop이 macOS 키체인에 인증 정보를 저장하는데, SSH 같은 원격 세션에서는 키체인에 접근할 수 없습니다. ~/.docker/config.json에서 credsStore를 제거하면 해결됩니다.

Docker 키체인 문제 해결
docker logout
cat > ~/.docker/config.json << 'EOF'
{
  "auths": {},
  "currentContext": "desktop-linux"
}
EOF
chmod 444 ~/.docker/config.json

chmod 444로 읽기 전용으로 만들어서 Docker Desktop이 재시작할 때 덮어쓰는 것을 방지합니다.

Docker Desktop UI에서 로그인이 필요한 경우 chmod 644로 권한을 다시 열어야 합니다.

Cloudflare Tunnel — 도메인 없이 HTTPS

맥미니에서 웹 서비스를 외부에 노출해야 할 때가 있습니다. 저의 경우 디스코드 봇의 웹폼 서버를 HTTPS로 제공해야 했는데, 도메인이 없었습니다.

Cloudflare Quick Tunnel을 쓰면 도메인 없이도 *.trycloudflare.com 주소로 HTTPS를 제공할 수 있습니다. Docker Compose에 사이드카 컨테이너로 넣으면 봇이 뜰 때 자동으로 터널이 생성됩니다.

docker-compose.yml
services:
  tunnel:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel --no-autoupdate --metrics 0.0.0.0:20000 --url http://bot:8000
 
  bot:
    build: .
    restart: unless-stopped
    depends_on:
      - tunnel

봇 컨테이너의 엔트리포인트에서 cloudflared의 metrics API(/quicktunnel)를 폴링해서 터널 URL을 자동 감지합니다. 터널 URL은 컨테이너가 재시작될 때마다 바뀌지만, 자동 감지니까 수동 설정이 필요 없습니다.

정리

이 구조의 핵심은 Tailscale입니다. 포트포워딩 없이, 복잡한 네트워크 설정 없이 앱 하나로 모든 장비가 하나의 네트워크처럼 연결됩니다.

  • 맥북에어 — 씬 클라이언트. 화면과 키보드만 담당
  • 맥북프로 — 메인 개발 환경. 코드, 도커, VPN 전부 여기서
  • 맥미니 — 24시간 홈서버. 봇, 자동화, CI/CD 배포 대상

장비를 늘려도 Tailscale에 추가하면 끝이고, Docker + CI/CD를 붙이면 홈서버에서 확장 가능합니다. AWS 같은 클라우드 비용도 아낄 수 있습니다.

맥을 여러 대 쓰고 있다면 한번 시도해볼 만한 구성입니다.

참고 자료

Tags:
TailscaleSSHmacOSHome ServerDocker