
미니PC 홈서버 구축하기 (1) -(SER8, Ubuntu 24 세팅) 에 이어서 작성한다.
현재 내 PC 와 네트워크 구성은 아래와 같다.
나중에 구조를 약간 변경할 예정이지만, 일단 접속만 되는지 확인하고 개념을 정리한 후에 다른 구조로 적용해보자.

일단 내 미니PC 에서 띄운 간단한 Springboot 서버를 메인 PC 에서 접속해보자.
그러기 위해선 모뎀에서 빠져나와 미니PC 에 연결된 네트워크의 public(공인) IP 주소를 알아야 한다.
private (사설) IP 로는 접근하지 못한다. 왜냐?
지금 미니PC 와 메인PC 는 같은 공유기로부터 나오지 않았기 때문에 서로 다른 네트워크라고 봐도 무방하므로 내부적으로만 접근 가능한 private IP 로는 접근이 되지 않는다.
미니PC 는 리눅스 환경이므로, 아래 명령어로 public IP 주소를 알 수 있다.
curl ifconfig.me

출력된 public IP 를 123.123.123.123 이라고 가정해보자.
그러면 외부에서 해당 IP 에 별다른 보안 설정 없이도 바로 접속이 가능하다.
왜냐? 모뎀은 단순히 LAN 포트를 매핑시켜주는 역할만 하기 때문이다.
그러면 메인 PC 에서 curl 명령어로 미니PC 의 공인IP:포트/endpoint 로 접속이 되는지 확인해보자.

접속이 잘 되는 것을 볼 수 있다.
다만 이는 보안은 둘째치고, 한 가지 함정이 숨어있다.
바로 IP 가 계속 바뀐다는 점인데, 이를 명령어로 확인해보자.
ip a
>>
...
2: enp1s0: ...
inet 123.123.123.123/24 brd 123.123.123.255 scope global dynamic noprefixroute enp1s0
...
ip a 명령어의 응답에서 공인 IP 설정이 어떻게 되어있는 지 보면, dynamic 이라는 키워드가 보인다.
이는 내 IP 가 동적으로 계속 변한다는 것을 의미하는데, 이는 내 가정용 인터넷 회선이 자체가 동적으로 할당시켜서 보내준다는 것이다.
이는 DHCP 라고 칭하고, 이를 어떻게 해결할 것인가와 보안적인 부분도 같이 개념을 바로잡고 넘어가보려고 한다.
짧게 요약하자면, 아래 내용을 1. 사전지식 에서 설명하고자 한다.
내 인터넷 회선은 일반 가정용이다.
속도는 100Mbps 일 뿐더러, 고정 IP 와 같은 서비스는 지원하지 않는다.
그러면 동적,고정 IP 는 무엇이면서 DHCP 는 무엇이냐?
DHCP(Dynamic Host Configuration Protocol)는 네트워크 내 장치가 자동으로 IP 주소를 할당받도록 하는 프로토콜이다.
가정용 인터넷 회선에서는 ISP(인터넷 서비스 제공업체)가 동적 IP를 제공하며, 이는 일정 시간이 지나면 변경된다.
동적 IP(Dynamic IP): ISP가 사용 가능한 IP를 자동으로 할당하며 일정 시간이 지나면 변경됨.
일반 가정용 인터넷에서 기본적으로 제공됨.
고정 IP(Static IP): 변하지 않는 IP 주소로, 서버 운영 등에 필요하지만 일반적으로 유료 서비스로 제공됨.
동적 IP 문제를 해결하기 위해 DDNS(Dynamic DNS) 를 사용하면 변경된 IP를 자동으로 도메인과 연결하여 접속할 수 있다.
프록시 서버는 클라이언트와 인터넷 사이에 위치하여 요청을 대신 처리하는 서버이다.
홈 서버 운영 시, 일반적으로 Nginx 를 띄워 가장 앞단에서 SSL 인증 및 로드밸런싱을 통해 리버스 프록시의 역할을 한다.
또한 내 서버에서 직접적으로 리버스 프록시를 운영하고 싶지 않다면,
Cloudflare 와 같은 외부의 프록시 서버를 사용하는 것도 방법이다.
Cloudflare 자체적으로 DDos, 해킹 방어를 지원하므로 내가 운용할 PC에 웹 서버를 운영한다면 좋은 선택이지만, 해당 PC에 웹 서버를 띄우지 않는다면 굳이 사용할 필요가 없다.
만약 적용한다면 Cloudflare 프록시 서버 외의 다른 IP 로부터의 접근은 막아둘 필요가 있다.
다만 나의 경우엔 미니PC 에 웹 서버를 띄우지 않고 MySQL, Kafka, Redis, Elasticsearch 등 DB 성격을 지닌 것들만 운영할 것이기 때문에 Cloudflare 와 같은 외부 프록시 서버는 사용하지 않을 예정이다.
위 툴들은 외부 서버에서 접근이 가능해야 되는 상황이라, 접근하는 것은 SSH 터널링으로만 접속할 수 있게 구성하려한다.
웹 서버는 외부 Oracle Cloud 서버에 띄우고, 그 안에는 Nginx 를 통한 SSL 인증과 로드밸런싱 및 Cloudflare 프록시도 적용하는 것을 나중에 작성할 예정이다.
아래는 내가 앞으로 구성할 환경을 간단하게 요약한 그림이다.
미니PC 는 DB 나 형상관리 용도로만 사용할 것이지만,
다른 개발자가 접근할 것을 생각해 VPN 은 제외하고 포트는 열어두는 대신 SSH 접속만 허용할 예정이다.
화살표 이외 다른 방식의 접근은 방화벽으로 인해 접근이 실패될 것이다.
(해상도가 깨지니 새 탭에서 이미지 열기 로 확인하자.)

SSH 터널링은 보안이 취약한 네트워크에서 암호화된 터널을 통해 데이터를 전송하는 기술이다. 원격 서버에 안전하게 접속하거나 프록시 역할을 수행할 때 유용하다.
예제: 로컬에서 원격 서버의 8080 포트에 접근하는 SSH 터널 설정
# 원격 서버의 SSH 포트가 2222일 때,
ssh -L 8080:localhost:8080 -p 2222 user@remote-server
위 명령어를 실행하면, 로컬 PC에서 localhost:8080으로 접근할 때 원격 서버의 8080 포트로 연결된다.
앞서 설명한 것과 같이, 외부에서 미니PC 에 접근할 때 SSH 로만 접근하도록 설정할 예정이다.
VPN(Virtual Private Network)은 공용 네트워크에서 안전하게 내부 네트워크에 접근할 수 있도록 하는 기술이다.
WireGuard, OpenVPN 등을 사용하면 외부에서 내부 네트워크로 안전하게 접속할 수 있다.
VPN을 사용하면 공인 IP 없이도 내부 네트워크의 장치에 접속 가능하고, 네트워크 보안을 강화할 수 있다.
다만 크리티컬한 단점은 VPN 이라는 벽을 거쳐오므로 통신속도가 느려지고, 뿐만 아니라 클라이언트도 VPN 을 설정해야 진입할 수 있다.
그러므로 내부적으로 특정 클라이언트에만 통신을 허용하고 싶을 때 적용하는 것이 일반적이다.
방화벽(Firewall)은 네트워크 보안을 위해 특정 트래픽을 차단하거나 허용하는 역할을 한다.
리눅스에서 ufw(Uncomplicated Firewall) 설정 예제
ufw 는 iptables 를 편하게 사용하기 위한 것으로 Ubuntu, Debian 기반에서 동작하니 참고하자.
sudo ufw default deny incoming # 모든 인입 차단 (기본값)
sudo ufw allow 22/tcp # 22포트(기본은 SSH) 허용
sudo ufw allow 80/tcp # HTTP 허용
sudo ufw allow 443/tcp # HTTPS 허용
sudo ufw allow from 192.168.1.100 to any port 8080 # 192.168.1.100 에서만 8080포트 허용
sudo ufw allow from 192.168.1.200 to any port 8080
192.168.1.200 에서도 8080포트 허용
sudo ufw allow from 192.168.1.0/24 to any port 80 # 192.168.1.0~255 범위에서만 80포트(HTTP) 허용
sudo ufw enable # 방화벽 활성화
sudo ufw status # 방화벽 설정 확인
# 만약 방화벽 설정을 삭제하고 싶다면
# 방화벽 설정을 넘버링으로 확인
sudo ufw status numbered
# 출력 예시
Status: active
To Action From
-- ------ ----
[ 1] 8080/tcp ALLOW IN Anywhere
[ 2] 8080/tcp (v6) ALLOW IN Anywhere (v6)
# [ 2] 삭제
sudo ufw delete 2
방화벽을 설정하여 불필요한 포트와 IP는 차단하고, 필수적인 것만 개방해야 보안이 강화된다.
앞서 보여준 전체 도식에서 Cloudflare, Oracle Cloud 관련 설정은 제외하고 미니PC 설정에만 집중한다.
우선 모뎀에 직접 연결하는 것 말고, 미니PC 를 공유기에 연결해보자.
변경한 LAN 구성은 아래와 같다.

이제는 메인PC, 미니PC, Wi-fi 모두 공유기에서 관리하므로
미니PC 에서 연 포트를 메인PC, Wi-fi 에서 접속이 가능해야 한다.
미니PC 에서 private IP 정보를 확인해보자.
...
2: enp1s0: ...
inet 172.30.1.26/24 brd 172.30.1.255 scope global dynamic noprefixroute enp1s0
...
172.30.1.26 이라는 내부 IP 정보가 확인되었다.
아래와 같이 미니PC 에서 8080 포트에 swagger endpoint 를 띄워 로컬에서 접속이 가능한 것을 보인다.

해당 private IP 와 8080 포트를 메인PC, Wi-fi 로 연결한 핸드폰에서도 확인해보자.
동일 공유기에서 나온 메인PC 에서 private IP 에 접속

모바일에서 공유기의 Wi-fi 를 사용해 private IP 에 접속

같은 공유기 내에서는 private IP 로 통신됨을 알았으니,
이제는 외부에서도 접속할 수 있게 DDNS 와 포트포워딩을 설정해보자.
KT 공유기를 기준으로 설명한다.
일반적으로 KT 공유기의 내부 접속 주소는 172.30.1.254 이다.
접속하면 아래와 같은 화면이 노출되는데, 여기서 기본값은

로그인하면 아래와 같이 비밀번호를 변경해야만 앞으로도 계속 사용할 수 있다.

변경이 완료되면 아래와 같은 공유기 기본 정보가 나타난다.
여기서 IP 할당방식이 DHCP 이고, 임대시간이 3600초 라고 표시되는 것을 보아 1시간마다 동적 IP 로 할당됨을 알 수 있다.

장치설정 > 트래픽 관리에서 포트포워딩을 테스트해보자.
포트포워딩 설정을 하지 않은 상태에서는 동적 public IP 로 접속해도 모든 포트를 막고 있으므로 접속이 되지 않는다.
아래 캡처에 설명한 예시는 외부에서 8080 포트로 접속할 때,
172.30.1.26 이라는 private IP 주소를 가진 네트워크에 8080 포트로 매핑하겠다는 뜻이다.
보안 상 외부 포트를 내부 포트와 다르게 설정하는 것이 안전하다.
특히 SSH 와 같은 기본 22포트를 그대로 사용하면 외부에서 접속이 그만큼 쉬워진다.
여기서는 테스트용이므로 일단 진행해본다.

그러면 이제 외부에서는 동적 public IP 로 private IP:8080 에 접속할 수 있게 되었다.
# 접속 대상 PC 에서 동적 public IP 확인
curl ifconfig.me
위에서 얻은 동적 public IP 를 가지고 모바일에서 wi-fi 없이 접속이 가능한지 확인해보자.

접속이 잘 되는 것을 볼 수 있다.
그러면 특정 포트를 열어야지만 접속할 수 있는 것을 알았으니,
1시간마다 동적으로 IP 가 계속 변하는 불편함을 DDNS 로 해결해보자.
KT 공유기에서 지원하는 DDNS no-ip, dyndns 네임서버만 지원한다.
현재 no-ip 계정이 핸드폰이 바뀌어 2차인증이 막혔고, dyndns 는 무료 서비스가 중단되었다.
그래서 duckdns 를 사용해 dns 를 매핑하고, 일정 주기마다 특정 스크립트를 실행해 내 공인 ip 를 duckdns 에 매핑하는 과정을 거치고자 한다.
아래 duckdns 에 진입하고 로그인한다.
https://www.duckdns.org/
이후 recapcha 를 클릭하면 아래와 같은 화면이 출력된다.
sub domain 란에 만들고 싶은 서브도메인을 작성한다.

그러면 아래와 같이 도메인이 특정 public ip 와 매핑됐음을 알 수 있다.

그러면 해당 도메인으로 접속해보자.

접속은 잘 됐지만, 내 public IP 가 언제 바뀔지 모른다.
이를 해결하기 위해 일정 주기마다 특정 스크립트를 실행해보자.
https://www.duckdns.org/install.jsp
에서 linux cron 을 선택하고 설명을 따라가면 된다.

잠깐 설명하자면 아래와 같다.
mkdir ~/duckdns
cd ~/duckdns
vi duck.sh
echo url="https://www.duckdns.org/update?domains=${도메인}&token=${토큰}&ip=" | curl -k -o ~/duckdns/duck.log -K -
chmod 700 duck.sh
# crontab 진입
crontab -e
# 아래 내용은 1분마다 duck.sh 를 수행하겠다는 의미
*/1 * * * * ~/duckdns/duck.sh >/dev/null 2>&1
주기는 각자 알아서 설정하면 되고, 나의 경우엔 1분마다 설정했다.
log 파일은 ~/duckdns/duck.log 에 저장되므로 여기서 확인 가능하다.
기본적으로 외부로부터의 접속을 공유기가 전부 차단하고, 포트포워딩으로 특정 포트만 열면서 매핑하도록 해준다.
그럼에도 방화벽을 설정해주어야 하는 이유가 뭘까?
Zero Trust 라는 용어를 살펴보자.
기본적으로 보안이라는 것은 외부로부터의 무분별한 접근을 막는 것을 기본 원칙으로 한다.
하지만 다음과 같은 상황을 상정해보자.
이런 경우에는 내부 네트워크라고 해도 안전한 상황이 아니다.
그래서 내부도 신뢰하지 않는다. 라는 의미에서 Zero Trust 라는 보안 용어가 나오게 된 이유이다.
또한 포트포워딩은 특정 IP 에 대해서만 허용하는 옵션이 없다.
방화벽은 Port 뿐 아니라 IP 도 제한할 수 있으므로, 방화벽 설정까지 하는 것은 옳은 선택이라고 할 수 있다.
그러면 방화벽 설정을 해보자.
우선 Docker 를 사용하는 환경이라면, 아래 옵션을 적용해 방화벽 설정이 올바르게 적용되도록 해야 한다.
# docker daemon 설정 진입
sudo vi /etc/docker/daemon.json
# 아래 내용 삽입
{
"iptables": false
}
# docker 재기동
sudo systemctl restart docker
1-8. 방화벽 에서 간략하게 설명했지만 명령어를 다시 확인해보자.
방화벽 설정이 변경될때마다 sudo ufw enable 또는 sudo ufw reload 를 적용해야 한다.
sudo ufw default deny incoming # 모든 인입 차단 (기본값)
sudo ufw allow 22/tcp # 22포트(기본은 SSH) 허용
sudo ufw allow 80/tcp # HTTP 허용
sudo ufw allow 443/tcp # HTTPS 허용
sudo ufw allow from 192.168.1.100 to any port 8080 # 192.168.1.100 에서만 8080포트 허용
sudo ufw allow from 192.168.1.200 to any port 8080
192.168.1.200 에서도 8080포트 허용
sudo ufw allow from 192.168.1.0/24 to any port 80 # 192.168.1.0~255 범위에서만 80포트(HTTP) 허용
sudo ufw enable # 방화벽 활성화
sudo ufw status # 방화벽 설정 확인
# 만약 방화벽 설정을 삭제하고 싶다면
# 방화벽 설정을 넘버링으로 확인
sudo ufw status numbered
# 출력 예시
Status: active
To Action From
-- ------ ----
[ 1] 8080/tcp ALLOW IN Anywhere
[ 2] 8080/tcp (v6) ALLOW IN Anywhere (v6)
# [ 2] 삭제
sudo ufw delete 2
SSH 는 기본적으로 22포트를 사용한다.
외부에서 접근하려면 22번 포트를 사용할 수 있게 열어주어야 하며, 접속을 당하는 PC에서는 SSH 접속 툴을 설치해주어야 한다.
# SSH 서버 설치 여부 확인
systemctl status ssh
# openssh 설치 (Ubuntu 기준)
sudo apt update && sudo apt install openssh-server -y
# openssh 시작 및 활성화
sudo systemctl enable ssh
sudo systemctl start ssh
# 실행 확인
systemctl status ssh
내 과정을 따라왔다면 이후 포트포워딩으로 외부 특정 포트 접근을 22포트로 매핑 및 open 하고, 방화벽도 open 해야 한다.
여기서 주의할점은 외부에서 SSH 접속 시 22포트를 그대로 사용하면 취약하므로 외부 접근 포트를 22말고 다른 포트로 매핑하자.
그러면 MobaXterm, Putty 등으로 SSH 접속이 가능해진다.
여기서 끝나도 되지만, 조금만 더 강화해보자.
외부에서 SSH 접속 시 아래 정보가 필요하다.
여기서 타인에게 위 정보들을 알려주었는데, 그 타인에게 접속을 그만하게 하고 싶다면 비밀번호를 변경하는 방법이 있다.
그런데 비밀번호를 매번 변경하는 것은 서버를 관리하는 입장에서 힘들 뿐 아니라, 보통 비밀번호는 다른 권한과 연계되어 있는 경우가 많으므로 외부에 노출되는 것은 보안 관점에서 좋은 방법은 아니다.
그래서, 비밀번호 대신 key 기반으로 접속하게 해보자.
나는 비밀번호를 유지하고, 나를 포함해 타인 모두 key 로만 SSH 접속 가능해야 한다.
기본적으로 로컬PC 에서 공개/비밀키를 생성한 후에,
로컬에는 비밀키를 사용해 접속하고 / 원격PC 에는 공개키를 등록해 해당 비밀키로 매칭되는 공개키로 인증되는 구조이다.

# 로컬PC 에서 key 생성 (Windows cmd, Linux Terminal 모두 가능)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# 생성된 id_rsa.pub 이라는 공개키를 원격 서버의 ~/.ssh/authorized_keys 에 추가
# 이 작업은 원격 서버 관리자가 수행한다.
# 인증 권한 수정
chmod 600 ~/.ssh/authorized_keys
이후 아래 사항이 적용되지 않았다면 설정한다.
(2, 3번째 옵션은 선택이지만 하는 것을 권장한다.)
sudo vi /etc/ssh/sshd_config
PubkeyAuthentication yes # 공개 키 인증 활성화
PasswordAuthentication no # 비밀번호 로그인 비활성화 (보안 강화)
PermitRootLogin no # root 계정으로 SSH 접속 방지
# 수정 후 ssh 서버 재시작
sudo systemctl restart sshd
참고 :
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
명령어에서 "" 안의 부분은 공개키의 끝부분에 누구의 공개키인지 식별하기 위함이다.
PC 마다 모두 다른 비밀키로 인증해야되고, 그에 매칭되는 공개키는 서버에서 관리되어야 한다.
그래서 관리자는 ~/.ssh/authorized_keys 안의 식별자를 통해 접근 권한을 관리할 수 있게 되는 것이다.
일반적인 URI 의 형태는 아래와 같다.
서브도메인.2차도메인.최상위도메인/endpoint
여기서 /endpoint 앞부분까지를 host 라고 칭한다.
일반적인 네임서버에서 도메인을 임대할 때에는
2차도메인.최상위도메인 을 임대하고, 그 앞에 서브도메인은 내가 마음대로 지정할 수 있는 와일드카드 형태이다.
그런데 이번에 duckdns 에 DNS 를 요청할 때에는 구조가 조금 특이했다.
서브도메인만 내가 지정해 임대할 수 있고, 2차도메인과 최상위도메인은 duckdns.org 로 고정되어 있었다.
여기서 예상되는 문제점이 무엇이 있을까?
일반적인 host를 second.com 으로 IP1 에 매핑하고,
duckdns 에 요청한 DNS 가 sub.duckdns.org 으로 IP2 에 매핑했다고 가정하자.
일반적인 host 는
sub1.second.com 을 IP1:8081sub2.second.com 을 IP1:8082와일드카드 도메인 에서는 second.com 앞에 어떠한 서브도메인이 있든 IP1 으로 매핑하는 형태이기 때문이다.다만 duckdns 는 이미 sub 라고 고정되어 있어 내 서버에 특정 포트를 추가로 등록하고 싶으면 어떻게 해야되지 라는 생각이 들 수 있다.
이 역시 duckdns 도 sub.duckdns.org 앞에 어떠한 서브의 서브도메인이 붙었더라도 IP2 로 매핑하게 된다.
그러면 지금까지는 서브도메인명.duckdns.org:8080/$endpoint
이라는 URI 로 접속한 것 대신
서브-서브도메인명.duckdns.org:8080/$endpoint 으로 접속할 수 있게 Nginx 리버스 프록시를 활용해보자.
웹 서버를 띄우지 않을거라면 SSL 인증을 굳이 할 필요는 없다.
이 경우엔 Nginx 를 서브-서브도메인의 매핑 용도로만 사용하면 되니, SSL 인증을 하지 않을 사람은 2-4-1 만 하고 넘어가자.
리눅스 서버에 Nginx 를 설치해보자.
Oracle Cloud 프리티어 A1 인스턴스 생성 + 고정 public IP 생성
하고
도메인 구매, DNS 적용, SSL 인증, 신규 도메인 추가(가비아, Oracle Cloud)
에서의 nginx 설정을 다시 한 번 복습해보자.
80 포트를 예시로 들 예저잉니 포트포워딩, 방화벽에서 열어둔 상태여야 한다.
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx # 부팅 시 자동 시작 설정
sudo systemctl status nginx # Nginx 상태 확인
sudo lsof -i :80 # 80 포트에서 수신 대기 중인 프로세스 확인
curl -I http://localhost # 로컬 접속 확인
# 알아보기 쉽게 도메인명.conf 로 작성하자.
sudo vi /etc/nginx/sites-available/test.conf
# test.conf 에 아래 내용 삽입
server {
# HTTP 요청을 HTTPS로 리디렉션
listen 80;
server_name test.서브도메인명.duckdns.org;
location / {
# test.서브도메인명.duckdns.org 를 localhost:8080 으로 매핑
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# 심볼릭링크를 걸어야 적용된다.
sudo ln -s /etc/nginx/sites-available/test.conf /etc/nginx/sites-enabled/
# nginx 설정 확인
sudo nginx -t
# nginx 재기동
sudo systemctl restart nginx
이제 브라우저로 접속해보자.
서브도메인명.duckdns.org 로 접속한 모습

서브도메인명.duckdns.org:8080/$endpoint 로 접속한 모습

test.서브도메인명.duckdns.org/$endpoint 로 접속한 모습

이 때 Nginx 를 왜 적용했는지 이해해야 한다.
그냥 서브도메인명.duckdns.org:8080/$endpoint 으로 접속하면 되지 않냐? 라고 할 수 있다.
하지만 아래와 같은 이유로 리버스 프록시인 Nginx 를 적용했다.
그러면 Nginx 는 브라우저의 http(80), https(443) 요청만 처리하냐? -> 아니다. DB, 메시지 브로커, 기타 네트워크 서비스에 대한 로드 밸런싱이 가능하다.
SSL 인증은
도메인 구매, DNS 적용, SSL 인증, 신규 도메인 추가(가비아, Oracle Cloud)
에서 이미 다뤄봤지만 나의 경우엔 관리해야될 서버가 여러개이므로 다시 진행해보자.
Let's Encrypt 는 무료이면서 간편하게 설정이 가능하다.
다만 90일마다 갱신이 필요하므로 이는 아래에서 확인해보자.
# Let's Encrypt 를 적용하기 위한 certbot 설치
# nginx 에 적용할 것이므로 apache 버전을 설치하지 말 것.
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
# certbot 에 도메인 반영
# Nginx를 잠시 중지 (기존에 동작하던 SSL 인증이 있다면 잠시 멈추고 하자)
sudo systemctl stop nginx
# standalone 모드로 인증서 발급, 이메일 입력과 동의 과정이 있다.
sudo certbot certonly --standalone -d 도메인명나열
# Nginx 다시 시작
sudo systemctl start nginx
# nginx 설정 파일 업데이트
sudo vi /etc/nginx/sites-available/도메인명.conf
# 도메인명.conf 에 아래 내용 입력
# 이미 nginx 에서 자동으로 업데이트했지만 다시 작성한다.
# /etc/nginx/sites-available/도메인명.conf
server {
# HTTP 요청을 HTTPS로 리디렉션
listen 80;
server_name 도메인명;
return 301 https://$host$request_uri;
}
server {
# HTTPS 설정
listen 443 ssl;
server_name 도메인명나열;
# SSL 인증서 파일 경로
ssl_certificate /etc/letsencrypt/live/도메인명/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/도메인명/privkey.pem;
# SSL 설정 추가
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers HIGH:!aNULL:!MD5;
# 루트 디렉토리와 인덱스 파일 설정
root /var/www/html;
index index.html index.htm;
# 8080(예시) 포트로 프록시 설정
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
설정이 완료되었으면 nginx 를 재기동하자.
심볼릭을 위에서 설정했다면 굳이 다시 할 필요는 없다.
# 심볼릭 링크로 설정 파일을 활성화
sudo ln -s /etc/nginx/sites-available/도메인명.conf /etc/nginx/sites-enabled/
# nginx 설정 테스트
sudo nginx -t
# nginx 재시작
sudo systemctl restart nginx\
이제 http://test.서브도메인명.duckdns.org/endpoint 으로 입력했을 때,
https://... 으로 redirect 되면서 더 이상 안전하지 않음 표시가 뜨지 않는 것이 확인된다.

한 가지 설정이 더 남았다.
아까 Let's Encrypt 는 90일마다 갱신을 해줘야 한다고 얘기했는데, 이를 매번 확인할 수 없으므로 crontab 을 사용해 자동화해보자.
# crontab 설정 진입
crontab -e
# 아래 명령어를 적용한다.
0 3 * * * /usr/bin/certbot renew --quiet && /bin/systemctl reload nginx
# crontab 적용 확인
crontab -l
이 과정을 이해했다면,
도메인을 더 추가하고 SSL 인증을 받는 과정을 간단하게 처리할 수 있을 것이다.
위에서 우리는 단계적으로 차근차근 접근하다보니 8080 포트를 공유기 포트포워딩, 방화벽 설정에서 열어두었다.
하지만 마지막 단계에서 우리는 브라우저에서 8080 포트로 직접 접속하는 것이 아닌,
도메인명으로 접속한 뒤에 Nginx 리버스 프록시에서 8080 포트로 매핑하는 방식으로 변경했다.
그래서, 초반에 열어두었던 8080 포트를 공유기 포트포워딩, 방화벽에서 다시 닫아야한다.
물론 리버스 프록시 서버가 따로 있다면 말이 달라지지만, 우리는 그럴 돈과 자원이 없지 않은가..
필요한 부분만 설명했다고는 하지만 내용이 다소 길어 두서가 없을 수 있다.
설명이 부족했다면 얼마든 피드백을 주기 바란다.