
때는 2026년 1월 9일..
저렴한 가격에 홈 서버를 구매/설치 해놓고 사실 그동안 제대로 활용하지 못하고 있었습니다.
매일 아침 10시에 코인마켓캡 Fear&Greed 지표를 보내주는 봇을 돌리는 서버 정도로만 사용하고 있었죠..

요즘 어딜가도 AI, Agent 등 이야기가 나오고 있고 개인적으로도 관심이 많이 생겨서
"그럼 그냥 내 홈 서버에 24시간 돌아가는 개인 AI 비서를 하나
만들어보자."
라는 생각이 들었습니다.
(사실 예전에 오픈클로를 한번 셋업해보긴 했지만 성능이슈로 버렸습니다)
시간도 꽤 지났고, Openclaw 2.0이 출시되었다는 소식!! (실제 2.0은 아니고 자잘한 버그 고치다 보니 여기저기 건든곳이 많아서 이정도면 버전2 아니야? 라는 네이밍이라고는 합니다 )
그 소식과 AI 성능도 이전에 비하면 훨씬 향상되었기 때문에, OpenClaw를 홈서버에 올려보기로 했습니다.
최종적으로 만들고 싶은 구조는 대충 이런 느낌입니다.
Discord
↓
OpenClaw Gateway
↓
Agent
↓
OpenAI GPT
↓
Web Search / Tools / Memory ...
일단 이번 글에서는
Docker로 OpenClaw Gateway를 띄우고 → OpenAI를 연결하고 → Discord에서
대화할 수 있는 상태까지
만들어보겠습니다.
그리고 역시나 한 번에 되지는 않았습니다.
OpenClaw를 서버에 직접 설치할 수도 있지만 저는 가능하면 홈 서버에 이것저것 설치해서 환경을 더럽히고 싶지 않았습니다.
또 나중에 OpenClaw를 지우거나 버전을 바꾸기도 편할 것 같아서 Docker로
구성하기로 했습니다.
그런데...
docker --version
Docker부터 없었습니다.
Docker 공식 저장소를 추가해서 설치해줍니다.
sudo apt update
sudo apt install -y ca-certificates curl
Docker 저장소의 GPG key를 등록합니다.
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
Docker apt repository를 추가합니다.
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
패키지 목록을 다시 읽고 Docker를 설치합니다.
sudo apt update
sudo apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
설치 확인.
docker --version
docker compose version
이렇게 Docker는 설치됐습니다.
Docker 명령어를 실행할 때마다 sudo를 붙이는 건 귀찮습니다.
그래서 현재 사용자를 docker 그룹에 추가했습니다.
sudo usermod -aG docker $USER
여기서 옵션은
-a : 기존 그룹은 유지하면서 append
-G : supplementary group 지정
이라는 뜻입니다.
즉 현재 사용자를 기존 그룹에서 빼지 않고 docker 그룹에도 추가합니다.
적용하려면 로그아웃 후 다시 로그인해야 합니다.
다시 접속한 다음
docker ps
를 실행해서 sudo 없이 정상적으로 동작하는지 확인했습니다.
참고로
docker그룹은 사실상 root에 가까운 권한을 가질 수 있으므로
아무 서버에서나 막 추가하는 건 좋지 않습니다. 제 경우 개인 홈 서버라
편의성을 위해 이렇게 구성했습니다.
💡 docker 그룹은 무엇인가?
Linux에는 사용자마다 소속 그룹(group)이라는 개념이 있습니다.
예를 들어 현재 사용자가 어떤 그룹에 속해 있는지 확인하려면:
groups
를 사용할 수 있습니다.
Docker를 설치하면 일반적으로 docker라는 그룹이 만들어지고, 이 그룹에 속한 사용자는 Docker socket에 접근할 수 있습니다.
그래서:
sudo usermod -aG docker $USER
를 실행합니다.
각 부분을 뜯어보면:
sudo
└── 관리자 권한으로 실행
usermod
└── 사용자 계정 정보를 수정
-a
└── append
기존 supplementary group을 유지
-G docker
└── docker 그룹을 supplementary group으로 추가
$USER
└── 현재 로그인한 사용자
즉 한마디로:
“현재 사용자를 기존 그룹에서 빼지 말고 docker 그룹에도 추가해줘.”
라는 뜻입니다.
특히 -a가 중요합니다.
실수로:
sudo usermod -G docker $USER
처럼 -a 없이 사용하면 기존 supplementary group 목록을 의도치 않게 변경할 수 있으므로 주의해야 합니다.
이제 본론입니다.
OpenClaw 저장소를 clone 합니다.
cd ~
git clone https://github.com/openclaw/openclaw.git
cd openclaw
OpenClaw는 Docker 이미지를 직접 build할 수도 있는데, 홈 서버에서 굳이 소스 전체를 build하지 않고 공식 pre-built image를 사용했습니다.
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
그리고 setup script 실행.
./scripts/docker/setup.sh
이 스크립트가 생각보다 많은 일을 해줍니다.
대충
Docker image 준비
↓
OpenClaw onboarding
↓
Gateway 설정
↓
Agent workspace 생성
↓
인증 설정
↓
Docker Compose Gateway 실행
까지 이어집니다.
setup script를 실행하면 터미널에서 onboarding이 시작됩니다.
처음에는 보안 관련 안내가 나옵니다.
OpenClaw Agent는 단순 챗봇이 아니라 파일이나 Shell 같은 실제 시스템
도구에 접근할 수 있기 때문에 이런 경고가 나오는 것 같습니다.
개인 홈 서버에서 제가 직접 사용하는 환경이므로 내용을 확인하고
진행했습니다.

Telemetry는 굳이 필요하지 않아서
No thanks
를 선택했습니다.
Setup mode는
QuickStart
를 선택했습니다.
QuickStart에서 Gateway 기본값은 다음과 같이 잡았습니다.
Gateway port : 18789
Gateway auth : Token
Tailscale : Off
첫 번째 Agent 이름은 그냥 기본값인
main
을 사용했습니다.
나중에는
main
dev
research
처럼 Agent를 나눠서 Discord 채널별로 연결해볼 생각입니다.
OpenClaw의 재미있는 점이 단순히 AI 하나를 실행하는 게 아니라 하나의
Gateway 아래에 여러 Agent를 구성할 수 있다는 점입니다.
모델 Provider는 OpenAI를 선택했습니다.
API Key를 별도로 발급해서 사용하는 방식도 있지만 저는 기존 ChatGPT/Codex
계정을 이용하는 OAuth 방식을 사용했습니다.
ChatGPT Login
을 선택했고, 다음과 같은 메세지가 나왔습니다

https://auth.openai.com/oauth/authorize?response_type=code&client_id=app_~~
제 홈 서버 환경은 CLI 환경이었기 때문에, OAuth URL을 복사하여 제 PC 에서 따로 접속을 했습니다.
URL을 통해 OpenAI 로그인을 했는데,

?
당황했습니다.
알고보니 저 리다이렉트 된 주소 http://localhost:1455/auth/callback~~~ 를 전체 복사하여 CLI 환경에 붙여넣기 하라고 하더군요..
(한국인 특 : 설명서 안읽음)
기본 모델은 설치 과정에서
openai/gpt-5.6-sol
로 일단 설정을 했고,
모델 선택 화면에서는 그대로
Keep current
를 선택했습니다.
그 다음 실제 completion을 한번 날려서 인증과 모델 접근이 정상인지
테스트하는 화면이 나옵니다.
Test AI access now with a live completion?
Yes
실제 요청 하나까지 성공하는 걸 확인했습니다.

홈 서버에 SSH 접속을 해서 OpenClaw에게 말을 거는것은 너무나도 귀찮은 일이기 때문에 메신저를 활용하려고 했고, Discord를 선택했습니다.

(discord 관련 패키지를 설치할까요?에서 계속 no 를 선택했던 뻘짓이 남아있네요)
Discord (Bot API)

디스코드 봇 토큰을 발급하는 방법도 알려주네요.
제 Bot token을 입력해 주었고 전체 채널에서 동작하게 하는 건 싫어서 접근 정책은
Allowlist
로 설정했습니다.
OpenClaw에서는 Discord 서버와 채널을 다음과 같이 지정할 수 있습니다.
guildId/channelId
Discord에서 개발자 모드를 켜면 서버 ID와 채널 ID를 복사할 수 있습니다.
저는 개인 Discord 서버의 사장실이라는 채널 하나만 허용했습니다.
구조는 대충 이런 느낌입니다.
Discord Server
│
├── 일반 채널
│ └── OpenClaw 접근 X
│
└── #사장실
└── OpenClaw 접근 O
실제 config에는 다음과 비슷하게 들어갑니다.
{
"channels": {
"discord": {
"enabled": true,
"token": "<DISCORD_BOT_TOKEN>",
"groupPolicy": "allowlist",
"guilds": {
"<GUILD_ID>": {
"channels": {
"<CHANNEL_ID>": {
"enabled": true
}
}
}
}
}
}
}
당연하지만 Discord Bot Token은 비밀번호나 마찬가지이므로 GitHub에
올리거나 블로그에 노출하면 안 됩니다.
온보딩 마지막쯤 이런 메시지가 나왔습니다.
Systemd user services are not available inside this container.
Gateway not detected yet.
Start now:
openclaw gateway run
순간
"엥? 설치 실패했나?"
했는데 Docker 환경이라 그런 것이었습니다.
컨테이너 안에서는 systemd user service를 설치하는 방식이 아니라 Docker
Compose가 Gateway 프로세스를 관리합니다.
setup script가 끝까지 실행되고 나니
Starting gateway
Container openclaw-openclaw-gateway-1 Started
Container openclaw-openclaw-gateway-1 Running
으로 정상 실행됐습니다.
설정 위치도 출력됩니다.
Config: /home/fcsd/.openclaw
Workspace: /home/fcsd/.openclaw/workspace
설치가 끝났으니 Gateway가 실제로 살아있는지 확인했습니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
exec openclaw-gateway \
sh -lc 'node dist/index.js gateway health --token "$OPENCLAW_GATEWAY_TOKEN"'
docker compose exec : 현재 실행 중인 container 안에서 명령 실행openclaw-gateway : 명령을 실행할 서비스gateway health : Gateway health checkOPENCLAW_GATEWAY_TOKEN : Gateway 인증에 사용하는 token결과는
Gateway Health
OK (5ms)
Discord: blocked
Gateway는 정상인데...
Discord가 blocked?
여기서 첫 번째 삽질이 시작됩니다.
온보딩에서 Discord와 allowlist까지 설정했지만 Bot Token 연결도
확인해주었습니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
run --rm openclaw-cli \
channels add \
--channel discord \
--token '<DISCORD_BOT_TOKEN>'
<DISCORD_BOT_TOKEN>에는 Discord Developer Portal에서 발급받은 실제 Bot
Token을 넣으면 됩니다.
docker compose run --rm은 OpenClaw CLI용 일회성 container를 실행하고
명령이 끝나면 container를 제거합니다.
등록 결과:
Added Discord account "default".
채널 목록도 확인합니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
run --rm openclaw-cli \
channels list
결과:
Chat channels:
- Discord default: installed, configured, enabled
오?
그럼 된 건가?
다시 Health Check.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
exec openclaw-gateway \
sh -lc 'node dist/index.js gateway health --token "$OPENCLAW_GATEWAY_TOKEN"'
그런데 여전히
Discord: blocked
...
channels status --probe로 원인 찾기단순히 channels list만 봐서는 왜 막혀있는지 알 수 없었습니다.
그래서 실제 Gateway와 Discord 연결 상태까지 확인해봤습니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
run --rm openclaw-cli \
channels status --probe
결과:
Gateway reachable.
- Discord default:
enabled,
configured,
error: Gateway websocket closed: 4014,
running,
disconnected,
bot:@김비서,
intents:content=disabled,
health:blocked,
works,
audit ok
여기서 범인이 거의 보입니다.
Gateway websocket closed: 4014
intents:content=disabled
그래도 정확한 원인을 확인하기 위해 Gateway 로그도 봤습니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
logs --tail=200 openclaw-gateway
--tail=200은 Gateway 로그의 마지막 200줄만 출력합니다.
그리고 로그에서 아주 친절하게 알려줍니다.
Discord Message Content Intent is disabled;
bot may not respond to channel messages.
gateway websocket closed code=4014
reason=Disallowed intent(s).
missing privileged gateway intents.
아하!
OpenClaw 문제가 아니라 Discord Bot 설정 문제였습니다.
Discord Developer Portal에서 Bot 설정으로 이동했습니다.
Discord Developer Portal
↓
Application
↓
Bot
↓
Privileged Gateway Intents
↓
MESSAGE CONTENT INTENT
MESSAGE CONTENT INTENT를 ON으로 변경했습니다.
저는 추후 사용자/Role 기반 제어도 해볼 수 있어서
SERVER MEMBERS INTENT도 같이 켜두었습니다.
설정을 바꿨으니 Gateway를 재시작합니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
restart openclaw-gateway
그리고 바로 probe를 날렸는데...
Gateway not reachable at ws://127.0.0.1:18789
ECONNREFUSED
ㅋㅋ
또 안됩니다.
이번 문제는 별거 아니었습니다.
Gateway를 restart한 직후 바로 probe를 실행해서 아직 Gateway가 18789
포트를 열기도 전에 CLI가 접속을 시도한 것이었습니다.
잠깐 기다린 뒤 다시 Health Check.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
exec openclaw-gateway \
sh -lc 'node dist/index.js gateway health --token "$OPENCLAW_GATEWAY_TOKEN"'
이번에는
Gateway Health
OK (5ms)
Discord: configured
오케이 굿.
그리고 다시 Discord probe.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
run --rm openclaw-cli \
channels status --probe
최종 결과:
Gateway reachable.
- Discord default:
enabled,
configured,
running,
connected,
bot:@김비서,
token:***,
intents:content=limited,
works,
audit ok
드디어
running
connected
works
audit ok
가 떴습니다.
짜라란~
여기까지 구성하고 나면 제 홈 서버는 대충 다음과 같은 구조가 됩니다.
Discord
│
│ #사장실
▼
@김비서
│
▼
OpenClaw Gateway
│
├── main Agent
│
├── OpenAI OAuth
│ └── openai/gpt-5.6-sol
│
├── Codex Hosted Search
│
└── Workspace / Memory / Sessions
기존에는
홈 서버
↓
매일 아침
↓
CoinMarketCap Fear & Greed
↓
Telegram 전송
정도로만 사용하고 있었는데 이제는 24시간 켜져 있는 서버에 실제 AI
Agent가 하나 들어왔습니다.
이제 좀 홈 서버 산 보람이 생기는 것 같습니다.

OpenClaw를 Docker로 운영하면서 자주 사용할 것 같은 명령어도
정리해두겠습니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml ps
현재 Gateway container가 정상적으로 실행 중인지 확인합니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
logs -f openclaw-gateway
-f 옵션을 사용하면 실시간으로 로그를 따라갑니다.
최근 로그만 보고 싶다면
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
logs --tail=200 openclaw-gateway
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
restart openclaw-gateway
설정 변경 후 Gateway를 재시작할 때 사용합니다.
단, .env나 Compose environment 자체를 변경했다면 단순 restart가
아니라 container를 recreate해야 변경된 환경변수가 반영될 수 있습니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
up -d openclaw-gateway
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
exec openclaw-gateway \
sh -lc 'node dist/index.js gateway health --token "$OPENCLAW_GATEWAY_TOKEN"'
Gateway와 Channel의 기본 Health 상태를 확인합니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
run --rm openclaw-cli \
channels status --probe
Discord가 실제로 연결되어 있는지 확인할 때 굉장히 유용했습니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
run --rm openclaw-cli \
channels list
현재 등록된 Channel을 확인합니다.
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
run --rm openclaw-cli \
channels add \
--channel discord \
--token '<DISCORD_BOT_TOKEN>'
Discord Bot Token을 등록합니다.
설치 도중 다음과 같은 메시지도 한번 확인했습니다.
OpenClaw config identity changed while persisting the refreshed plugin registry
Run "openclaw doctor --fix"
이런 config/migration 관련 문제를 정리할 때는
docker compose -f /home/fcsd/openclaw/docker-compose.yml \
run --rm openclaw-cli \
doctor --fix
를 사용할 수 있습니다.
처음에는
"Docker 하나 띄우고 OpenAI 연결하면 끝나는 거 아닌가?"
라고 생각했는데 역시 이런 건 한 번에 되는 법이 없습니다.
특히 이번에 삽질했던 부분은
Discord: blocked
↓
Bot Token 문제인가?
↓
Allowlist 문제인가?
↓
channels status --probe
↓
4014 Disallowed intent(s)
↓
Message Content Intent 발견
↓
Gateway restart
↓
ECONNREFUSED
↓
아 그냥 아직 재시작 중이었구나...
↓
connected
였습니다.
그래도 OpenClaw CLI에서 상태와 로그를 꽤 자세하게 보여줘서 원인 찾는 것
자체는 어렵지 않았습니다.
현재는 main Agent 하나만 만들어놓은 상태인데 다음에는 여기서 조금 더
욕심을 내서
Discord
│
├── #사장실
│ └── main
│
├── #개발실
│ └── dev
│
└── #자료조사실
└── research
처럼 하나의 OpenClaw Gateway에 여러 Agent를 만들고 Discord 채널별로
Agent를 분리해볼 생각입니다.
그리고 dev Agent에는 개발에 필요한 Tool을 붙이고, research Agent에는
Web Search와 자료조사에 필요한 Tool을 붙여서 각자 역할을 나눠보려고
합니다.
단순히 ChatGPT를 Discord에서 사용하는 것과 달리,
내 서버에서 24시간 살아있고, 각자 Workspace와 Memory를 가지고, 실제
Tool을 사용할 수 있는 Agent를 만드는 것.
이게 OpenClaw를 설치해보고 싶었던 가장 큰 이유였습니다.
일단 오늘은 여기까지.
다음엔 진짜 비서처럼 부려먹어보겠습니다.