소개

상황

라즈베리파이에서 자판기와 비슷한 것을 구현하기 위해 Electron을 프론트엔드로 사용하고 있다.

간편한 유지보수를 위해 Electron 프론트엔드에 자동 업데이트를 구현하려고, electron-builder에서 제공하는 업데이트 기능인 electron-updater 를 도입했다.

우선 나는 라즈베리파이OS (데비안 12 Bookworm), 라즈베리파이4B 기준으로 테스트했다.

문제점

다만 예상하지 못한 문제가 생겼다면, 업데이트를 받아오고 설치를 시도할 때마다 다음과 같은 창이 뜬다는 것이다.

글 작성자가 업로드 한 이미지

조금 찾아보니 이건 pkexec 라는 도구인데, 명령어 실행 권한을 가지고 있는 사용자로 명령어를 실행할 수 있도록 도와주는 도구라고 한다.

해결

시도 #1 - sudoer에 사용자 NOPASSWD 지정 (실패)

sudoer 파일에서 sudo 권한이 있는 사용자를 지정해줄 수 있는데, 원래 파일은 /etc/sudoers 에 위치한다. 이 파일을 보다 안전하게 수정하고 싶다면 visudo 명령을 이용해주면 된다.

# User privilege specification
root ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "@include" directives:
@includedir /etc/sudoers.d

기본 설정 이외에는 @includedir를 이용해 설정 파일을 나누어 관리하고 있는데, 이 디렉터리를 알아보자.

ls -l /etc/sudoers.d 명령을 실행했다.

-r--r----- 1 root root 36 Apr 29 2019 010_at-export
-r--r----- 1 root root 44 Jun 19 21:48 010_dpkg-threads
-r--r----- 1 root root 31 Jul 26 2023 010_global-tty
-r--r----- 1 root root 28 Jul 4 09:16 010_pi-nopasswd
-r--r----- 1 root root 211 Jun 7 23:10 010_proxy
-r--r----- 1 root root 1096 Jun 27 2023 README

여기에 010_pi-nopasswd 라는 파일이 있어 해당 파일을 열었더니

username ALL=(ALL) NOPASSWD: ALL

이처럼 이미 라즈베리파이 기본 유저에 대한 NOPASSWD 설정이 되어 있었다. 어쩐지 sudo에서 비밀번호를 입력한 적이 없더라니…

시도 #2 - pkexec를 비밀번호 없이 실행? (실패)

이 질문 글에서 동일한 문제를 확인했다. /usr/share/polkit-1/rules.d 폴더에 들어가니 dpkg 관련된 파일 org.dpkg.pkexec.update-alternatives.policy 가 있어 해당 파일을 수정했다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<policyconfig>
<vendor>The Dpkg Project</vendor>
<vendor_url>https://wiki.debian.org/Teams/Dpkg</vendor_url>
<icon_name>update-alternatives</icon_name>
<action id="org.dpkg.pkexec.update-alternatives">
<description>Run update-alternatives to modify system alternative selections</description>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">/usr/bin/update-alternatives</annotate>
</action>
</policyconfig>

여기 auth_admin_keepyes로 바꿔주었으나 변화는 없었다.

해결 - electron-updater 내부 sudo 명령어 수정

electron-updater 패키지의 BaseUpdater 파일을 보면 wrapSudo 라는 명령어를 sudo 커맨드로 말아주는 메소드가 있다.

이 메소드 중 다음과 같이 어떤 sudo wrapper(?)를 사용해야 하는지 구하는 코드가 있다.

const sudo = this.spawnSyncLog("which gksudo || which kdesudo || which pkexec || which beesu")

나는 어짜피 사용자에게 sudo 권한이 무조건 있고, sudo를 입력했을 때 터미널에서 별도의 비밀번호를 입력하는 인풋이 나오지 않는 환경에서만 업데이트가 이루어진다.

따라서 위 코드를 다음과 같이 바꿔준다.

const sudo = this.spawnSyncLog("which sudo")

라즈베리파이는 데비안 기반이라 electron-updater중에서도 DebUpdater를 사용한다. 해당 파일을 둘러보자.

보면 실제 설치가 일어나는 doInstall 이라는 메소드가 있다. 이걸 자세히 보자.

protected doInstall(options: InstallOptions): boolean {
const sudo = this.wrapSudo()
// pkexec doesn't want the command to be wrapped in " quotes
const wrapper = /pkexec/i.test(sudo) ? "" : `"`
const cmd = ["dpkg", "-i", options.installerPath, "||", "apt-get", "install", "-f", "-y"]
this.spawnSyncLog(sudo, [`${wrapper}/bin/bash`, "-c", `'${cmd.join(" ")}'${wrapper}`])
if (options.isForceRunAfter) {
this.app.relaunch()
}
return true
}

위 BaseUpdater에서 수정했던 wrapSudo를 이용하여 sudo를 이용해 명령을 실행하는데, sudo wrapper를 기준으로 구성되어 sudo를 사용하면 dpkg가 올바르게 동작하지 않는다.

파일 메소드를 조금 수정하여 간단하게 sudo dpkg -i <파일> || apt-get install -f -y 만 실행할 수 있도록 수정한다:

protected doInstall(options: InstallOptions): boolean {
const sudo = this.wrapSudo()
// pkexec doesn't want the command to be wrapped in " quotes
const wrapper = /pkexec/i.test(sudo) ? "" : `"`
const cmd = ["dpkg", "-i", options.installerPath, "||", "apt-get", "install", "-f", "-y"]
this.spawnSyncLog(sudo, cmd.join(" "))
if (options.isForceRunAfter) {
this.app.relaunch()
}
return true
}

이렇게 수정한 부분을 pnpm patch를 이용하여 패키지를 일일히 수정하지 않아도 모든 환경에서 반영될 수 있도록 했다.

태그
electron
raspberrypi
반응과 댓글 시스템은 Giscus에 의해 호스팅되며, 모든 대화는 GitHub에 저장됩니다.

출처가 명확하지 않은 내용을 신뢰하지 마세요. 글 작성자는 이로 인해 발생하는 책임을 지지 않습니다.

피드백 무엇이든 환영합니다 🤗

doda.devlicensegithubmade with ☕️

라즈베리파이에서 electron updater 비밀번호 입력 없이 업데이트하기 – 도다위키