라즈베리파이 첫 부팅 완전 자동화 — firstrun.sh로 WiFi·계정·SSH 한 번에 세팅
안녕하세요, 천상나타입니다.
지난 글에서 SD 슬롯 고장난 라즈베리파이를 카드리더 USB 부팅으로 살린 얘기를 했는데요, 부팅이 된 건 시작에 불과했습니다. 이번엔 그 다음 벽 — 첫 부팅 설정을 콘솔 타이핑 한 글자 없이 자동화한 얘기입니다.
헤드리스로 파이를 켜려면 WiFi·계정·SSH·키보드가 부팅과 동시에 세팅돼야 하는데, 최신 Raspberry Pi OS 이미지에서 인터넷에 도는 방법의 절반이 먹히지 않았어요. 최종적으로는 커널 부팅 시점에 스크립트를 강제로 실행시키는 systemd.run 메커니즘으로 해결했습니다.
안 먹혔던 것들부터 정리
먼저 실패 기록이에요. 다 "공식 문서에 나오는 방법"이라고 돌아다니는 것들인데, 제가 받은 최신 이미지(2026-10-06 trixie arm64)에서는 이랬습니다:
1. wpa_supplicant.conf를 부팅 파티션에 넣기 — 고전적인 방법인데 파일을 읽기는 읽는데 WiFi가 연결되지 않았습니다. 최신 이미지는 네트워크를 NetworkManager로 관리하는데 wpa_supplicant 경로는 레거시라 무시되거나 충돌했어요.
2. network-config (cloud-init 형식) — 이것도 완전히 무시됐습니다. network-config는 netplan 형식으로 쓰는 건데, 이 이미지에는 그걸 NetworkManager로 변환해주는 파이프라인이 없어서 파일이 통째로 안 읽혔어요. 부팅 후 열어보면 그대로 남아있습니다.
3. 콘솔에서 수동 입력 — 부팅이 되니 콘솔에 키보드 꽂고 직접 치자고 했는데, 이것도 못 했습니다. 새 이미지는 키보드 레이아웃이 UK가 기본값이라 @가 Shift+2에 없거든요. WiFi 비밀번호에 @가 들어있어서 애초에 입력 자체가 불가능했습니다. loadkeys us도 알파벳만 있는 명령이라 칠 수는 있는데, 이걸로 바꾼 건 세션 한정이라 재부팅하면 또 UK로 돌아갔어요.
4. SSID 대소문자 — nmcli dev wifi connect를 쳐도 계속 인증 실패. 원인은 SSID가 SK_WiFiGIGA5872_2.4G인데 SK_WIFIGIGA5872_2.4G로 치고 있었던 것. WiFi 목록에 보이는 이름이라서 틀린 줄도 몰랐습니다 — 스캔 목록의 SSID는 표시되는 대로인데, 연결할 때는 대소문자까지 정확히 맞아야 하더라고요.

해결책: firstrun.sh + systemd.run
결국 방법은 하나였습니다 — 부팅 파티션에 스크립트를 넣고, 부팅 과정에서 강제로 실행되게 만드는 것. Raspberry Pi Imager의 "사용자 지정 설정"이 내부적으로 쓰는 메커니즘과 동일한 방식입니다.
구조는 이렇습니다:
1단계 — 부팅 파티션에 firstrun.sh 작성
맥에서 SD카드(부팅 디스크)를 꽂아 /boot/firmware에 스크립트를 씁니다. 이 안에 하고 싶은 모든 설정을 담아요:
#!/bin/bash
# WiFi 국가코드 → rfkill 해제 → WiFi 프로파일 생성 → 접속
raspi-config nonint do_wifi_country KR
rfkill unblock wifi
nmcli radio wifi on
nmcli connection add type wifi con-name home \
ifname wlan0 ssid "SK_WiFiGIGA5872_2.4G" \
wifi-sec.key-mgmt wpa-psk wifi-sec.psk "비밀번호"
nmcli connection up home
# 키보드 US 레이아웃 영구 변경
raspi-config nonint do_configure_keyboard us
# 콘솔 자동 로그인 + SSH 활성
raspi-config nonint do_boot_behaviour B2
raspi-config nonint do_ssh 0
# 결과 기록 (부팅 후 확인용)
nmcli device status > /boot/firmware/firstrun-done.txt
ip a >> /boot/firmware/firstrun-done.txt
# 자기 자신 삭제 (한 번만 실행되게)
rm -f /boot/firmware/firstrun.sh
핵심은 do_wifi_country KR을 먼저 실행하는 거예요. 국가코드가 설정되기 전엔 wlan0이 unavailable로 rfkill에 막혀있어서 WiFi 설정을 뭘 해도 안 됩니다. 이 순서 하나로 제가 겪은 대부분의 "안 되는 이유"가 해소됐어요.
2단계 — cmdline.txt에 3줄 추가
같은 부팅 파티션의 cmdline.txt 끝에 이걸 붙입니다:
systemd.run=/boot/firmware/firstrun.sh
systemd.run_success_action=reboot
systemd.unit=kernel-command-line.target
systemd.run=경로— 해당 파일을 부팅 중 실행systemd.run_success_action=reboot— 성공하면 자동 재부팅 (설정이 깨끗한 상태로 다시 기동)systemd.unit=kernel-command-line.target— 네트워크 없어도 도달하는 아주 이른 부팅 단계에서 실행. 나중 단계를 지정하면 스크립트가 의존하는 서비스가 안 떠있을 수 있어서 이 단계를 고릅니다
3단계 — 꽂고 전원만 켠다
이후엔 아무것도 안 합니다. 파이가 1차 부팅에서 스크립트를 실행하고, 자동으로 재부팅한 뒤, 2차 부팅에서는 WiFi가 자동 연결된 상태로 올라옵니다. 스크립트는 자기 자신을 삭제해서 한 번만 돌고요.

결과 확인은 firstrun-done.txt로
스크립트 마지막에 nmcli device status와 ip a 출력을 파일로 남기게 해뒀습니다. 부팅 후 SD카드를 다시 맥에 꽂으면 /boot/firmware/firstrun-done.txt에서 실행됐는지, WiFi가 잡혔는지, IP가 뭔지 바로 보여요. 이 파일이 없으면 스크립트가 실행 안 된 것(cmdline 패치 확인), 있으면 안에 결과가 기록돼 있습니다.
실제로 이 파이는 이 방식으로 한 번에 성공했습니다 — 부팅 후 화면에 My IP address is 192.168.45.209가 찍혀서 확인했고, 그 뒤 SSH로 접속해서 나머지 세팅(정적 IP, 공개키)을 마무리했어요.
왜 이게 다른 방법보다 확실한가
wpa_supplicant.conf나 network-config는 부팅 시스템이 읽어주기를 바라는 방식입니다 — 이미지 버전이 바뀌면 그 "읽어주는 코드" 자체가 사라지거나 바뀔 수 있어요(실제로 그랬고요). 반면 systemd.run은 커널 부팅 시점에 systemd가 실행하는 거라 이미지 내용물과 무관하게 동작합니다. Raspberry Pi Imager가 이 방식을 쓰는 이유도 같습니다 — 확실하니까요.
정리
헤드리스 파이 첫 부팅 자동화는 인터넷 팁이 오래된 이미지 기준이 많아서 함정이 많습니다. 제 결론은:
wpa_supplicant.conf·network-config는 이미지마다 다르게 동작 → 신뢰 금지firstrun.sh+systemd.run조합이 Imager와 동일한 메커니즘이라 버전에 관계없이 동작- 스크립트 안에서
do_wifi_country→rfkill unblock→ WiFi 프로파일 생성 순서로 — 국가코드가 첫 단추 - 결과는
firstrun-done.txt로 남겨서 성공 여부를 부팅 후에도 확인 가능하게
다음 글에서는 이렇게 살린 파이에서 셀레니움 크롤링을 VNC 화면으로 실시간 확인한 세팅을 다룹니다 — headless인데 눈으로 브라우저가 움직이는 걸 볼 수 있는 구성이에요.
'IT > Linux' 카테고리의 다른 글
| 라즈베리파이에서 셀레니움 크롤링을 눈으로 보기 — VNC + 가상 디스플레이 세팅 (0) | 2026.11.15 |
|---|---|
| SD 슬롯이 고장난 라즈베리파이 살리기 — 카드리더 USB 부팅으로 우회한 후기 (0) | 2026.11.15 |
| Linux 환경에서 VI 에디터 없이 사용하는 방법 (0) | 2023.04.04 |
| 리눅스 iptables 포트포워딩 간략 정리 (port foward) (0) | 2018.10.17 |
| 리눅스 자주 쓰는 명령어 alias주기(톰켓 실시간 로그 출력) (0) | 2018.03.12 |