−25%

Windows 연간 결제, 10월 31일까지. 요금제 보기

EQVPS
시작하기

Alpine Linux VPS 설정 방법: apk, doas, OpenRC와 방화벽

새 Alpine Linux 3.21 VPS의 첫 단계: 업데이트하고 재부팅하기, 실제로 로그인할 수 있는 doas 사용자 만들기, root와 비밀번호 SSH 로그인 끄기, ufw 추가, cron과 매일 업데이트 켜기. ufw가 막지 못하는 Docker 포트도 다룹니다.

Alpine Linux는 저희가 제공하는 가장 작은 이미지입니다. 저희 서버에서 새로 설치한 Alpine 3.21은 유휴 상태에서 RAM 55 MB와 디스크 153 MB를 사용했고, Ubuntu 24.04는 313 MB와 2.7 GB를 사용했습니다. 그 대가로 익숙한 도구를 포기해야 합니다. Alpine은 apt 대신 apk, sudo 대신 doas, systemd 대신 OpenRC, glibc 대신 musl을 씁니다.

아래 단계는 Debian이나 Ubuntu에서 하는 첫 10분을 Alpine에 맞게 옮긴 것입니다. 게시 전에 모든 명령을 저희 Alpine 3.21 이미지에서 실행했고, 그중 두 가지에서 처음에 막혔습니다. 대시보드의 비밀번호로 root로 로그인하세요.

1. 업데이트하고 한 번 재부팅하기

apk update && apk upgrade
uname -r
ls /lib/modules

서버는 처음 부팅할 때 이미 사용 가능한 업데이트를 설치했기 때문에, apk upgrade는 보통 할 일이 거의 없습니다. 대신 마지막 두 줄을 보세요. 첫 업데이트에서 새 커널이 들어왔다면, 실행 중인 커널(uname -r)의 모듈은 더 이상 디스크에 없습니다. 모듈을 불러오는 작업은 재부팅할 때까지 모두 실패합니다. 저희 테스트 서버에서는 방화벽 설치 중 ERROR: Couldn't determine iptables version이 출력되었습니다. 두 버전이 다르면 지금 재부팅하세요.

reboot

테스트 서버는 1분이 안 되어 다시 올라왔습니다.

2. 로그인할 수 있는 사용자 만들기

adduser -D deploy
passwd deploy
adduser deploy wheel

passwd를 건너뛰지 마세요. adduser -D는 비밀번호 없이 계정을 만들고, Alpine은 이를 잠긴 계정으로 표시하며, sshd는 잠긴 계정을 올바른 키가 있어도 거부합니다. 저희 테스트에서 유일한 단서는 /var/log/messages에 있던 다음 한 줄이었습니다.

User deploy not allowed because account is locked

비밀번호는 나중에도 필요합니다. doas가 묻는 것이 바로 이 비밀번호입니다.

서버를 주문할 때 SSH 키를 추가했다면 root의 authorized_keys에 들어 있습니다. 새 사용자에게 복사하세요.

install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
install -m 600 -o deploy -g deploy /root/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys

아직 키가 없나요? 내 컴퓨터에서 키를 만들고 공개 키를 /home/deploy/.ssh/authorized_keys에 붙여 넣으세요.

3. doas가 비밀번호를 묻게 하기

Alpine은 sudo 대신 doas를 쓰며, 저희 이미지에서는 이미 wheel 그룹에 허용되어 있습니다. /etc/doas.d/wheel.conf의 규칙은 permit nopass :wheel이어서, wheel의 구성원은 아무것도 입력하지 않고 root가 됩니다. 비밀번호를 묻고 몇 분 동안 기억하도록 바꾸세요.

echo 'permit persist :wheel' > /etc/doas.d/wheel.conf

이제 doas apk add nano는 Ubuntu의 sudo apt install nano처럼 작동합니다.

4. SSH: 키만 허용, root 금지

sshd는 /etc/ssh/sshd_config.d/의 파일을 이름 순서대로 읽고, 각 설정마다 처음 찾은 값을 사용합니다. 저희 이미지에서 첫 파일은 00-eqvps.conf이며, 첫날 접속할 수 있도록 root와 비밀번호 로그인을 허용합니다. 내용을 바꾸세요.

cat > /etc/ssh/sshd_config.d/00-eqvps.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
EOF
sshd -t && rc-service sshd restart
sshd -T | grep -E '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication) '

Alpine에서는 세 번째 줄이 중요합니다. 이미지는 PAM을 쓰는 OpenSSH 빌드를 사용하며, 처음 두 줄만 있을 때 테스트 서버는 여전히 keyboard-interactive 로그인을 제공했습니다. 세 줄을 모두 넣으면 키 없이 로그인하려는 시도는 다음 결과를 받습니다.

Permission denied (publickey).

root 세션은 열어 두세요. 두 번째 터미널에서 ssh deploy@YOUR.SERVER.IP가 되는지(NAT 요금제라면 -p와 대시보드의 개인 포트를 붙이세요), 그리고 doas id가 비밀번호를 받아들이는지 확인하세요.

5. 방화벽: ufw

ufw는 community 저장소에 있으며, 저희 이미지에서는 이 저장소가 켜져 있습니다.

apk add ufw
ufw limit 22/tcp
ufw --force enable
rc-update add ufw default
ufw status

limit은 SSH를 허용하지만 연달아 많은 연결을 여는 쪽은 늦춥니다. 여기서 rc-update가 중요한 이유는, runlevel에 추가하지 않으면 OpenRC가 재부팅 후 방화벽을 시작하지 않기 때문입니다. 재부팅 후 저희 서버는 Status: active 상태로 돌아왔습니다. NAT 요금제에서는 SSH를 포트 22에 그대로 두세요. 개인 외부 포트가 서버 안의 22번으로 전달됩니다. 전용 IPv4가 있는 요금제라면 필요할 때 웹 포트를 여세요(ufw allow 80/tcp, ufw allow 443/tcp). 나머지는 ufw 가이드에 있습니다.

6. cron과 매일 업데이트 켜기

새 Alpine 서버에서는 cron이 아예 돌지 않습니다. 켜세요.

rc-update add crond default
rc-service crond start

Alpine의 root crontab은 이미 /etc/periodic/daily에 있는 모든 것을 02:00에 실행합니다. 그곳에 업데이트 스크립트를 넣으세요.

cat > /etc/periodic/daily/apk-upgrade <<'EOF'
#!/bin/sh
apk upgrade --update-cache --no-progress >> /var/log/apk-auto.log 2>&1
EOF
chmod +x /etc/periodic/daily/apk-upgrade
run-parts --test /etc/periodic/daily

마지막 명령은 cron이 실행할 스크립트 목록을 보여 주며, 만든 스크립트가 목록에 있어야 합니다. 이렇게 하면 3.21의 수정 사항을 계속 받습니다. 다음 Alpine 릴리스로 넘어가는 것은 별도의 수동 작업입니다. 커널 업데이트는 여전히 재부팅이 필요하니, 1단계의 uname -r / ls /lib/modules 확인을 가끔 반복하세요.

7. 표 하나로 보는 OpenRC

systemd를 안다면, 바뀌는 것은 대부분 다음과 같습니다.

작업systemdAlpine (OpenRC)
서비스 시작systemctl start nginxrc-service nginx start
부팅 시 시작systemctl enable nginxrc-update add nginx default
상태systemctl status nginxrc-service nginx status
실행 중인 것systemctl list-unitsrc-status
시스템 로그journalctl/var/log/messages

8. Docker, 그리고 ufw가 막지 못하는 포트

Alpine은 시스템 자체가 거의 방해하지 않아서 Docker 호스트로 좋습니다.

apk add docker docker-cli-compose
rc-update add docker default
rc-service docker start
docker run --rm hello-world

저희 서버에서는 다운로드를 포함해 12초가 걸렸습니다. Docker 데몬이 실행되자 사용 메모리는 57 MB에서 124 MB로 늘었습니다.

Alpine만의 문제는 아닌 함정이 있습니다. Docker는 자체 방화벽 규칙을 씁니다. ufw가 SSH만 허용하는 상태에서 nginx를 -p 8080:80으로 시작했더니, 서버 밖에서 포트 8080으로 접속할 수 있었습니다. ufw는 막지 않았습니다. 컨테이너를 같은 서버의 리버스 프록시로만 접근하게 하려면 localhost에 게시하세요.

docker run -d -p 127.0.0.1:8080:80 nginx:alpine

어떤 요금제를 고를까

Alpine은 RAM 거의 전부를 여러분의 소프트웨어에 남겨 둡니다. Nano 요금제(2 vCPU, 1 GB, 15 GB, 월 $3)면 작은 서비스나 컨테이너 몇 개에 충분합니다. NAT 요금제이므로 SSH는 개인 포트로 들어옵니다. 포트 80과 443을 인터넷에 열어야 한다면 Nano-IP가 월 $8에 전용 IPv4를 제공합니다. 더 무거운 Docker 스택에는 월 $5에 2 GB인 Micro가 있습니다.

Alpine 3.21은 Alpine VPS 페이지에 있으며 VPS의 모든 Linux 요금제에서 선택할 수 있습니다. 결제는 Base, Ethereum, Polygon 네트워크의 USDT, USDC, ETH로 하며 신분증이나 카드가 필요 없습니다.

자주 묻는 질문

Alpine은 왜 Ubuntu나 Debian보다 훨씬 작은가요?

glibc 대신 musl, 기본 명령에 BusyBox, systemd 대신 OpenRC를 쓰기 때문입니다. 저희 서버에서 새로 설치한 Alpine 3.21은 유휴 상태에서 RAM 55 MB와 디스크 153 MB를 사용했습니다. Ubuntu 24.04는 313 MB와 2.7 GB를 사용했습니다.

키가 맞는데도 새 사용자가 "account is locked"를 받는 이유는 무엇인가요?

adduser -D는 비밀번호 없이 계정을 만들고, Alpine은 이를 잠긴 계정으로 표시합니다. 그러면 sshd는 올바른 키가 있어도 그 사용자를 거부합니다. 로그에는 "User deploy not allowed because account is locked"가 남습니다. passwd로 비밀번호를 설정하면 키 로그인이 작동합니다.

Alpine에서 SSH 터널이 작동하지 않는 이유는 무엇인가요?

Alpine의 기본 /etc/ssh/sshd_config는 AllowTcpForwarding no로 되어 있어 ssh -L 포워딩이 거부됩니다. 터널이 필요하면 이 파일에서 값을 yes로 바꾸고 rc-service sshd restart를 실행하세요.

제 프로그램이 Alpine에서 실행되나요?

Alpine 저장소에 있는 것은 모두 실행되고, 어떤 베이스 이미지로 만든 Docker 컨테이너도 실행됩니다. glibc용으로 빌드된 리눅스 바이너리는 musl에서 시작되지 않는 경우가 많습니다. Alpine이나 musl용 빌드를 찾거나 Docker 안에서 실행하세요. gcompat 패키지는 일부 단순한 glibc 바이너리에 도움이 됩니다.

Alpine에는 어떤 요금제면 충분한가요?

월 $3인 1 GB Nano 요금제로 충분하고도 남습니다. 시스템 자체는 약 55 MB만 씁니다. 포트 80과 443을 인터넷에 열어야 한다면 전용 IPv4가 있는 월 $8의 Nano-IP를 선택하세요.

댓글

아직 댓글이 없습니다. 첫 번째가 되세요.

댓글 남기기

댓글은 표시되기 전에 검토됩니다.