← 전체 글로 돌아가기

웹 개발

systemd 서비스에 WorkingDirectory를 적어야 했던 이유

systemd로 Node 앱을 띄울 때 상대 경로 파일을 못 찾아서 고친 설정 노트다.

로그에 나온 에러

Node 앱을 systemd 서비스로 등록했는데 로컬 실행에서는 문제없던 파일 읽기가 서버에서만 실패했다. 에러는 대략 이런 모양이었다.

Error: ENOENT: no such file or directory, open './data/config.json'

처음에는 파일 권한을 의심했다. ls -l로 봐도 파일은 있었고, 서비스 계정도 읽을 수 있었다. 놓친 부분은 실행 위치였다.

왜 터미널 실행과 달랐나

터미널에서는 프로젝트 폴더에 들어간 뒤 실행했다.

cd /srv/my-app
node server.js

하지만 systemd는 내가 생각한 폴더에서 실행해 주지 않는다. 앱 코드에 상대 경로가 있으면 현재 작업 디렉터리에 따라 결과가 달라진다.

수정한 유닛 파일

나는 서비스 파일에 WorkingDirectory를 명시했다.

[Unit]
Description=My Node App
After=network.target

[Service]
User=app
WorkingDirectory=/srv/my-app
ExecStart=/usr/bin/node server.js
Restart=always
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

변경 후에는 데몬 설정을 다시 읽고 상태를 확인했다.

sudo systemctl daemon-reload
sudo systemctl status my-app --no-pager

같이 확인한 항목

이 문제를 보면서 아래도 같이 점검했다.

  • ExecStart에 적은 Node 경로가 실제로 존재하는지
  • 서비스 계정이 프로젝트 폴더를 읽을 수 있는지
  • .env를 쓴다면 EnvironmentFile 경로가 맞는지
  • 로그가 journalctl -u 서비스명에 남는지

메모

상대 경로는 작은 프로젝트에서는 편하지만, 서비스로 띄우는 순간 실행 위치가 숨어 있는 의존성이 된다. 다음부터는 파일 경로를 다룰 때 WorkingDirectory를 정하거나, 코드에서 절대 경로 기준을 분명히 잡기로 했다.