웹 개발
systemd 환경 변수가 쉘과 다를 때 만든 Node 배포 설정 노트
SSH에서는 되는데 서비스로만 실패한 Node 앱의 환경 변수와 WorkingDirectory 설정 노트입니다.
터미널과 서비스의 실행 환경은 달랐다
SSH에서 npm start를 실행하면 정상인데 서비스로 올리면 DB 연결 오류가 났다. .env 권한부터 의심했지만, 서비스는 내 로그인 쉘의 환경 변수와 현재 디렉터리를 물려받지 않는다. nvm을 설치했다는 사실도 서비스가 그 Node 경로를 안다는 뜻은 아니었다.
실행 기준을 파일에 적었다
서비스 정의에 사용자, 작업 경로, 환경 파일, 실행 명령을 명시했다. 특히 WorkingDirectory가 없을 때 상대 경로 업로드 폴더가 프로젝트 밖에 생긴 경험이 있다.
[Service]
User=deploy
WorkingDirectory=/srv/myapp/current
EnvironmentFile=/srv/myapp/shared/app.env
ExecStart=/usr/bin/npm run start
Restart=on-failure
환경 파일은 쉘 스크립트처럼 export를 붙이지 않고 한 줄에 한 값으로 두었다.
NODE_ENV=production
DATABASE_URL=postgresql://app:[email protected]:5432/app
NEXT_PUBLIC_SITE_URL=https://example.com
비밀값은 저장소나 서비스 정의 본문이 아니라 권한을 제한한 별도 파일에 뒀다. 전체 환경을 로그로 출력하는 디버그 코드는 확인 뒤 제거했다.
확인 기준
터미널의 printenv가 맞아도 끝내지 않는다. 서비스 로그에서 시작 오류를 보고, 실행 중인 앱의 헬스 URL을 요청한다. 설정을 바꾼 뒤에는 서비스 정의를 다시 읽도록 한 다음 확인한다.
남긴 메모
systemd가 불친절한 것이 아니라 쉘과 분리된 재현 가능한 실행 환경을 만든다. 이후에는 배포 문제에서 User, WorkingDirectory, EnvironmentFile, ExecStart 네 줄을 먼저 본다.