Ubuntu

Https요청 Ubuntu + Ngnix + SSL(Certbot) + Gitea

washble2 2026. 2. 23. 02:39

 

여기에서 했던 것을 토대로 작업했습니다.

아래 링크와 환경이 달라서 삽질을 많이 해서 삽질 부분 기록을 위해 적습니다.

https://blog.naver.com/washble2/224014563831

 

[ASP.Net Core] Nginx를 사용한 Linux에 서버 배포

[사용 버전] - Linux ubuntu 24.04.2 LTS - ASP.Net 9.0.3 Linux에 ASP.Net을 배포하는 방식...

blog.naver.com

 

 

시작전 외부접속의 80, 443포트를 서버의 80, 443포트를 포트 포워드 해두셔야합니다.

 

 

1. ngix설치

# nginx 설치
$ sudo apt update
$ sudo apt install nginx -y

 

 

 

2. certbot으로 ssl 인증서 발급

(아래의 명령어를 작동시키기 전에 아래 추가 설명글을 봐주세요)

# Certbot 설치
$ sudo apt install certbot python3-certbot-nginx -y

# 도메인 인증서 발급
$ sudo certbot --nginx -d {domain.com}
# 예시) sudo certbot --nginx -d washble2.tistory.com -d www.washble2.tistory.com

# 자동 갱신 확인
$ sudo systemctl status certbot.timer

 

 

nginx를 처음 설치 하면 그대로 도메인 인증서 발급을 받아도 된다는 글을 봤지만 일단 그 전에 확인해두면 좋은것 들이 있습니다.

일단 방화벽nginx설정파일 gitea의 app.ini파일 입니다.

 

아래 링크를 보면 자세하게 나오지만 따로 제가 삽질한 부분에 대해서 알려드리며 설정을 봐보도록 하겠습니다.

https://docs.gitea.com/administration/reverse-proxies

 

Reverse Proxies | Gitea Documentation

General configuration

docs.gitea.com

 

1) 방화벽을 확인해주세요!

ubuntu에는 ufw, firewall, iptables등의 방화벽이 있습니다.

여기서 사용하고있는 방화벽의 80번과 443번 포트를 열어주어야 합니다.

# ufw 사용확인
$ sudo ufw status
# 443, 80 포트 열기
$ sudo ufw allow 443/tcp
$ sudo ufw allow 80/tcp


# firewall 사용확인
$ sudo firewall-cmd --state
# 443 포트 열기
$ sudo firewall-cmd --permanent --add-service=https
$ sudo firewall-cmd --reload
# 80 포트 열기
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload


# iptables 사용확인
$ sudo iptables -L -n -v
# 443, 80포트 열기
$ sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

 

 

2) nginx 설정 파일 확인

# nginx 설정파일 들어가기
$ sudo vim /etc/nginx/sites-available/default


# nginx 설정파일의 기본형태
server {
    listen 80;
    server_name example.com www.example.com;

    location / {
        # 아직 SSL 적용 전이므로 그냥 기본 응답만
        root /var/www/html;
    }
}

# listen 80;
# 80번 포트 사용

# server_name example.com www.example.com;
# 본인의 도메인 이름 => 도메인은 IP연결(A)에 하시면 됩니다.

# location / {
# 주소의 들어오는 경로

# root /var/www/html;
# 아직 SSL 적용 전이므로 그냥 기본 응답만

 

 

 

3) gitea의 ROOT_URL을 반드시 도메인에 맞추세요!

# 컨테이너 확인
$ sudo docker ps

# gitea에 해당하는 컨테이너에 접속
$ sudo docker exec -it {gitea 컨테이너 이름} /bin/bash

# 컨테이너 내부 설정 파일 열기(일반적인 경로)
$ vi /data/gitea/conf/app.ini

# server 섹션에 ROOT_URL을 본인 도메인으로 변경
[server]
ROOT_URL = https://example.com/
# 컨테이너 나가는 방법 exit + enter 또는 ctrl + shift + d

# 컨테이너 재실행
$ sudo docker restart {gitea 컨테이너 이름}

 

 

※ 만약 제대로 안 될 경우 TXT(SPF)로 인증서를 얻을 수 있습니다.

# Certbot 실행 (DNS 인증 모드)
$ sudo certbot certonly --manual --preferred-challenges=dns -d example.com -d www.example.com

# certonly → 인증서만 발급, 자동 설치는 하지 않음
# --manual → 수동 모드
# --preferred-challenges=dns → DNS-01 챌린지 사용
# -d → 인증받을 도메인 지정



# Certbot이 TXT 레코드 값 제시
Please deploy a DNS TXT record under the name:
_acme-challenge.example.com
with the following value:
abc123def456gh789ijklmnopqrstuvwxyz


# DNS 관리 콘솔에서 TXT 레코드 추가
# 도메인 관리 서비스에 접속해서 _acme-challenge.example.com 이름으로 TXT레코드 추가
# 값은 Certbot이 제시한 문자열 abc123def456gh789ijklmnopqrstuvwxyz을 그대로 입력


# DNS 레코드 반영되었는지 확인
$ nslookup -q=TXT _acme-challenge.example.com
# Certbot이 제시한 값이 보이면 정상


# Certbot 계속 진행
# DNS 레코드가 반영된 후, Certbot 터미널에서 Enter를 눌러 진행
# → 인증 성공 시 /etc/letsencrypt/live/example.com/ 경로에 인증서가 생성


# 인증서 정보 확인
$ sudo certbot certificates

# 제대로 인증됐을 때 뜨는 내용
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: yumyumttok.p-e.kr
    Serial Number: 6f778.....aa2d
    Key Type: ECDSA
    Domains: example.com www.example.com
    Expiry Date: 2025-12-21 09:27:41+00:00 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 

 

 

 

3. 인증서 자동갱신

Certbot의 장점입니다.

# [자동갱신 설정]
# crontab을 실행해줍니다.
$ sudo crontab -e

# crontab을 처음 켠다면 루트 사용자용 crontab이 없어서 새로 만들기 위해 편집기를 선택하라는 안내가 나옵니다.
# 원하는 편집기의 숫자를 넣고 Enter를 눌러 주시면 됩니다.
no crontab for root - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.basic
  3. /usr/bin/vim.tiny
  4. /bin/ed


# 편집기가 열리면 맨 아래에 아래의 내용을 추가하고 저장해줍니다.
# 매일 자정에 인증서를 자동으로 갱신하도록 예약한다는 내용입니다.
0 0 * * * certbot renew --quiet


# 설정이 잘 되었는지 확인
$ sudo crontab -l

# cron서비스가 작동중인지 확인
$ sudo systemctl status cron
# 아래와 같이 active (running)이 뜨면 제대로 작동하는 것 입니다.
Active: active (running) since Wed 2025-09-17 10:24:05 UTC; 5 days ago

# crontab 갱신 테스트
# $ sudo certbot renew --dry-run

 

 

 

4. 인증서 적용

1) nginx 설정

server {
        # listen 80;
        listen [::]:443 ssl;
        listen 443 ssl;

        # SSL configuration
        #
        # listen 443 ssl;
        # listen [::]:443 ssl;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        ssl_certificate /etc/letsencrypt/live/{도메인}/fullchain.pem;
        # ex) ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/{도메인}/privkey.pem;
        # ex) ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;


        # location /.well-known/acme-challenge/ {
        #       root /var/www/html;
        # }

        # root /var/www/html;

        # Add index.php to the list if you are using PHP
        # index index.html index.htm index.nginx-debian.html;

        server_name {도메인} www.{도메인};
        # ex) server_name example.com www.example.com

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                # try_files $uri $uri/ =404;
                
                # 대용량 파일을 업로드를 위한 설정
                # 없으면 "413 Request Entity Too Large" 오류가 발생할 수 있음
                client_max_body_size 512M;
                
                proxy_pass {컨테이너 실행 로컬 주소};
                # ex) proxy_pass http://127.0.0.1:3000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $http_connection;
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
        }


        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}
}

server {
    listen 80;
    server_name {도메인} www.{도메인};
    # ex) server_name example.com www.example.com
    return 301 https://$host$request_uri;
}

 

 

2) nginx 재실행

# nginx 문법확인
$ sudo nginx -t

# nginx 재실행
$ sudo systemctl reload nginx
# 실행된 nginx가 없으면 재실행 불가 => nginx 실행
$ sudo systemctl start nginx 또는 $ sudo systemctl restart nginx

# nginx 상태확인
$ sudo systemctl status nginx 또는 $ sudo journalctl -xeu nginx
# journalctl가 더 자세히 확인

# nginx 로그 확인
# 에세스 로그
$ sudo tail -f /var/log/nginx/access.log
# 에러 로그
$ sudo tail -f /var/log/nginx/error.log

 

 

 

'Ubuntu' 카테고리의 다른 글

Docker에 설치된 Gitea에 systemd 설정  (0) 2026.02.24