Files
sam-docs/dev/deploys/ops-manual/09-security.md
권혁성 987030f24c docs: [ops] 서버 계정 관리 문서 업데이트
- 09-security: 서버 계정 관리 섹션 신규 추가 (Linux/MySQL 계정 현황, 생성 절차, 잠금/해제)
- 09-security: SSH 인증 정책 정리 (패스워드 허용, root 외부 접근 차단)
- 01-server-overview: 3개 서버 사용자 정보 업데이트 (hskwon/pro/kkk)
- 01-server-overview: 운영 DB 사용자 테이블에 pro, kkk 추가
2026-03-16 10:20:07 +09:00

9.5 KiB

9. 보안 관리

목차로 돌아가기


서버 계정 관리

Linux 계정 현황

계정 이름 sam-dev sam-prod sam-cicd 비고
hskwon 권혁성 sudo, users sudo, users, webservice sudo, users, webservice 개발팀장
pro 김보곤 develop, sudo, users pro, sudo, users, webservice (잠금) pro, sudo, users, webservice (잠금) 개발실장
kkk 강영보 develop, sudo, users pro, sudo, users, webservice (잠금) pro, sudo, users, webservice (잠금) 개발자 (2026-03-13 생성)

MySQL 계정 현황

계정 sam-dev sam-prod sam-cicd 비고
hskwon ALL . (auth_socket) ALL . (auth_socket) ALL . (auth_socket) 개발팀장
codebridge - sam, sam_stage, sam_stat, codebridge - 앱 사용자
pro chandj, sam, samdb codebridge, sam, sam_stage, sam_stat (잠금) codebridge, gitea, sam, sam_stage, sam_stat (잠금) 개발실장
kkk chandj, sam, samdb codebridge, sam, sam_stage, sam_stat (잠금) codebridge, gitea, sam, sam_stage, sam_stat (잠금) 개발자 (2026-03-13 생성)
sam_backup - - (운영 DB에서 원격 접근) sam, sam_stat (원격 백업) CI/CD 백업

신규 계정 생성 절차

# 1. 개발서버 (전체 권한)
ssh sam-dev "sudo useradd -m -s /bin/bash -G develop,sudo,users -c '이름' 계정명"
ssh sam-dev "echo '계정명:비밀번호' | sudo chpasswd"

# 2. 운영/CICD (잠금 상태로 생성)
ssh sam-prod "sudo useradd -m -s /bin/bash -G pro,sudo,users,webservice -c '이름' 계정명"
ssh sam-prod "echo '계정명:비밀번호' | sudo chpasswd"
ssh sam-prod "sudo usermod -L 계정명"    # Linux 잠금

ssh sam-cicd "sudo useradd -m -s /bin/bash -G pro,sudo,users,webservice -c '이름' 계정명"
ssh sam-cicd "echo '계정명:비밀번호' | sudo chpasswd"
ssh sam-cicd "sudo usermod -L 계정명"    # Linux 잠금

# 3. DB 계정 — 개발 (활성)
ssh sam-dev "mysql -u root -p'<비밀번호>' -e \"
CREATE USER '계정명'@'localhost' IDENTIFIED BY '비밀번호';
GRANT ALL PRIVILEGES ON chandj.* TO '계정명'@'localhost';
GRANT ALL PRIVILEGES ON sam.* TO '계정명'@'localhost';
GRANT ALL PRIVILEGES ON samdb.* TO '계정명'@'localhost';
FLUSH PRIVILEGES;\""

# 4. DB 계정 — 운영/CICD (잠금)
ssh sam-prod "sudo mysql -e \"
CREATE USER '계정명'@'localhost' IDENTIFIED BY '비밀번호';
GRANT ALL PRIVILEGES ON codebridge.* TO '계정명'@'localhost';
GRANT ALL PRIVILEGES ON sam.* TO '계정명'@'localhost';
GRANT ALL PRIVILEGES ON sam_stage.* TO '계정명'@'localhost';
GRANT ALL PRIVILEGES ON sam_stat.* TO '계정명'@'localhost';
ALTER USER '계정명'@'localhost' ACCOUNT LOCK;
FLUSH PRIVILEGES;\""

ssh sam-cicd "sudo mysql -e \"
CREATE USER '계정명'@'localhost' IDENTIFIED BY '비밀번호';
GRANT ALL PRIVILEGES ON codebridge.* TO '계정명'@'localhost';
GRANT ALL PRIVILEGES ON gitea.* TO '계정명'@'localhost';
GRANT ALL PRIVILEGES ON sam.* TO '계정명'@'localhost';
GRANT ALL PRIVILEGES ON sam_stage.* TO '계정명'@'localhost';
GRANT ALL PRIVILEGES ON sam_stat.* TO '계정명'@'localhost';
ALTER USER '계정명'@'localhost' ACCOUNT LOCK;
FLUSH PRIVILEGES;\""

계정 잠금/해제

# Linux 잠금 해제
sudo usermod -U 계정명

# Linux 잠금
sudo usermod -L 계정명

# MySQL 잠금 해제
sudo mysql -e "ALTER USER '계정명'@'localhost' ACCOUNT UNLOCK;"

# MySQL 잠금
sudo mysql -e "ALTER USER '계정명'@'localhost' ACCOUNT LOCK;"

SSH 키 관리

SSH 인증 정책

서버 패스워드 인증 root 외부 접근 SSH 키 비고
sam-dev 허용 차단 허용 개발서버
sam-prod 허용 차단 허용 운영서버
sam-cicd 허용 차단 허용 CICD서버

일반 계정은 패스워드 접근 허용, root는 외부 접근 완전 차단 (PermitRootLogin no)

# SSH 설정 확인
sudo grep -E "^(PasswordAuthentication|PermitRootLogin|PubkeyAuthentication)" /etc/ssh/sshd_config
# 현재 설정:
#   PasswordAuthentication yes
#   PermitRootLogin no   # root 외부 접근 완전 차단
#   PubkeyAuthentication yes

[운영] 공개키 관리

cat /home/hskwon/.ssh/authorized_keys

# 새 공개키 추가
echo "새_공개키_내용" >> /home/hskwon/.ssh/authorized_keys

# SSH 설정 변경 후 반드시 재시작
sudo systemctl restart sshd

[CI/CD] 공개키 관리

cat /home/hskwon/.ssh/authorized_keys
echo "ssh-ed25519 AAAA... user@host" >> /home/hskwon/.ssh/authorized_keys
chmod 600 /home/hskwon/.ssh/authorized_keys

[CI/CD] Jenkins SSH 키

# 경로: /var/lib/jenkins/.ssh/id_ed25519
# 공개키는 운영서버/개발서버 hskwon authorized_keys에 등록됨
sudo cat /var/lib/jenkins/.ssh/id_ed25519.pub

# 연결 테스트
sudo -u jenkins ssh -i /var/lib/jenkins/.ssh/id_ed25519 hskwon@211.117.60.189 "hostname && date"
sudo -u jenkins ssh -i /var/lib/jenkins/.ssh/id_ed25519 hskwon@114.203.209.83 "hostname && date"

# known_hosts 갱신 (호스트 키 변경 시)
sudo -u jenkins ssh-keygen -R 211.117.60.189
sudo -u jenkins ssh-keyscan -H 211.117.60.189 >> /var/lib/jenkins/.ssh/known_hosts

UFW (방화벽) 관리

[운영] 규칙

포트 허용 범위 용도
22 Anywhere SSH
80 Anywhere HTTP
443 Anywhere HTTPS
9100 110.10.147.46 only node_exporter
3306 110.10.147.46 only MySQL 백업

[CI/CD] 규칙

포트 허용 범위 용도
22 Anywhere SSH
80 Anywhere HTTP
443 Anywhere HTTPS

[개발] 규칙

포트 허용 범위 용도
22 Anywhere SSH
80 Anywhere HTTP
443 Anywhere HTTPS
3000 Anywhere Gitea

MySQL(3306), Apache(8080), Next.js(3001) 등은 외부 차단됨

공통 명령어

# 규칙 확인
sudo ufw status numbered

# 규칙 추가
sudo ufw allow from IP주소 to any port 포트번호

# 규칙 삭제
sudo ufw delete 규칙_번호

# 변경사항은 즉시 적용 (재시작 불필요)

주의: SSH (22/tcp) 규칙 삭제 금지

# 변경 전 백업 (CI/CD)
sudo ufw status numbered > /tmp/ufw-backup-$(date +%Y%m%d).txt

SSL 인증서 관리

# 인증서 만료일 전체 확인
sudo certbot certificates

# 자동 갱신 타이머 확인
sudo systemctl status certbot.timer

# 새 도메인 인증서 발급
sudo certbot --nginx -d 새도메인 --email develop@codebridge-x.com

# 수동 갱신
sudo certbot renew

# 인증서 삭제
sudo certbot delete --cert-name 도메인명

fail2ban 관리

# jail 상태 확인
sudo fail2ban-client status
sudo fail2ban-client status sshd

# IP 차단 해제
sudo fail2ban-client set sshd unbanip IP주소

# jail 재시작
sudo fail2ban-client restart sshd

화이트리스트 설정

현재 설정:

서버 ignoreip
운영 127.0.0.1/8, 110.10.147.46 (CI/CD)
CI/CD 127.0.0.1/8, 211.117.60.189 (운영)
개발 127.0.0.1/8, 110.10.147.46 (CI/CD), 211.117.60.189 (운영)
# /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 110.10.147.46 211.117.60.189

# 변경 후
sudo systemctl restart fail2ban

[운영] .env 파일 보안

주의: .env 권한은 반드시 640 (-rw-r-----)이어야 합니다. PHP-FPM은 www-data 사용자(webservice 그룹)로 실행되므로 그룹 읽기 권한이 필요합니다. 600으로 설정하면 PHP-FPM이 .env를 읽지 못해 전체 서비스 500 에러가 발생합니다. (실제 장애 사례: 2026-03-03, 08-troubleshooting.md 참조)

# 권한 확인 (640이어야 함 — 소유자 rw + 그룹 r)
ls -la /home/webservice/api/shared/.env
ls -la /home/webservice/mng/shared/.env
ls -la /home/webservice/sales/.env

# 권한 수정
chmod 640 /home/webservice/api/shared/.env
chmod 640 /home/webservice/mng/shared/.env
chmod 640 /home/webservice/sales/.env

vi 편집 시 권한 변경 방지

vi로 파일을 편집하면 새 파일로 교체되면서 권한이 600으로 초기화될 수 있습니다. 이를 방지하기 위해 서버 계정의 ~/.vimrc에 아래 설정을 추가합니다:

# 원본 파일에 직접 덮어쓰기 (권한 유지)
echo "set backupcopy=yes" >> ~/.vimrc

적용 현황 (2026-03-03):

  • sam-prod: hskwon, pro 계정 적용 완료
  • sam-cicd: hskwon, pro 계정 적용 완료

[운영] Redis 보안

Redis는 127.0.0.1에만 바인딩되어 외부 접근 불가.

redis-cli config get bind    # "127.0.0.1 ::1"
grep "^bind" /etc/redis/redis.conf

[운영] MySQL 사용자 관리

# 사용자 목록
sudo mysql -e "SELECT user, host, plugin FROM mysql.user;"

# 비밀번호 변경
sudo mysql -e "ALTER USER 'codebridge'@'localhost' IDENTIFIED BY '새_비밀번호'; FLUSH PRIVILEGES;"

# 외부 접근 사용자 확인
sudo mysql -e "SELECT user, host FROM mysql.user WHERE host != 'localhost';"

[CI/CD] Jenkins 보안

  • Jenkins Credentials에서만 민감 정보 관리
  • Jenkinsfile에 직접 비밀번호 기재 금지
  • 관리자: hskwon
  • 사용자 추가: Jenkins 관리 > Users > Create User

[CI/CD] Gitea 접근 제어

  • 회원가입 비활성화 (DISABLE_REGISTRATION = true)
  • 로그인 필수 (REQUIRE_SIGNIN_VIEW = true)
  • API 토큰 기반 인증
  • 사용자 추가: CLI 또는 관리자 웹 UI