Synology NAS에서 SynoCommunity 패키지로 Gitea를 운영하고 있었는데, 보안 취약점 관련 이슈를 확인하면서 Gitea를 1.26.2-29에서 1.27.1-30으로 업데이트하게 됐다.

 

내 환경은 다음과 같다.

DSM        : 7.3.2
Gitea 기존 : 1.26.2-29
Gitea 신규 : 1.27.1-30
Architecture: x86_64

Gitea HTTP Port : 8418
Gitea SSH Port  : 202

Reverse Proxy:
Cloudflare → Nginx Proxy Manager → Gitea
 

DB는 PostgreSQL 15.4 Docker 컨테이너를 사용하고 있다.


1. Gitea 업데이트 패키지 확인

SynoCommunity spksrc에 Gitea 1.27.1 업데이트 PR이 올라와 있었고, 아직 정식 저장소 배포 전이라 GitHub Actions의 artifact를 이용해 테스트했다.

PR:

 
SynoCommunity/spksrc #7383 gitea: update from v1.26.2 to v1.27.1
 

GitHub Actions에서 내 NAS에 맞는:

Build (x64-7.1)
 

artifact를 다운로드했다.

압축을 풀면 다음 SPK가 나온다.

gitea_x64-7.1_1.27.1-30.spk
 

 


2. 업데이트 전 백업

실서비스 데이터가 있는 환경이기 때문에 먼저 Gitea를 중지했다.

 
sudo synopkg stop gitea
 

상태 확인:

 
sudo synopkg status gitea
 

기존 Gitea 데이터 위치를 확인했다.

설정 파일:

/volume1/@appdata/gitea/conf.ini
 

Repository:

 
[repository]
ROOT = /volume1/git/kwah
 

LFS:

 
[lfs]
PATH = /volume1/git/lfs
 

DB:

 
[database]
DB_TYPE = postgres
HOST = 192.168.0.4:65432
NAME = gitea
USER = kwah
 

Git 데이터 전체 크기는 약 2.3GB였다.

 
sudo du -sh /volume1/git
 
2.3G /volume1/git
 

백업 디렉터리를 생성했다.

 
sudo mkdir -p /volume1/backup/gitea-20260812
 

Gitea AppData 백업:

 
sudo tar -czpf \
  /volume1/backup/gitea-20260812/gitea-appdata.tar.gz \
  /volume1/@appdata/gitea
 

Repository 및 LFS를 포함하여 /volume1/git 전체도 백업했다.

 
sudo tar -czpf \
  /volume1/backup/gitea-20260812/gitea-git-data.tar.gz \
  /volume1/git
 

3. PostgreSQL DB 백업

처음에는 NAS에 설치된 pg_dump를 사용했는데 다음 오류가 발생했다.

pg_dump: server version: 15.4
pg_dump version: 11.11

pg_dump: aborting because of server version mismatch
 

NAS에 설치된 PostgreSQL client가 11.11이고 DB 서버는 PostgreSQL 15.4였기 때문이다.

다행히 PostgreSQL 자체를 Docker로 운영하고 있었다.

 
docker ps
 
postgres:15.4
 

따라서 PostgreSQL 컨테이너 내부의 pg_dump를 사용했다.

 
docker exec postgres \
  pg_dump -U kwah -d gitea -Fc \
  > /volume1/backup/gitea-20260812/gitea-db.dump
 

여기서 주의할 점이 하나 있다.

처음에는 다음처럼 -t를 사용했다.

 
docker exec -t postgres ...
 

그런데 -Fc는 PostgreSQL Custom Binary Format이기 때문에 TTY를 거쳐 리다이렉션하면 파일이 손상될 가능성이 있다.

따라서 DB dump를 파일로 받을 때는 docker exec -t가 아니라 그냥 docker exec를 사용했다.

백업 검증:

 
cat /volume1/backup/gitea-20260812/gitea-db.dump | \
  docker exec -i postgres pg_restore -l | head -20
 

정상적으로 다음과 같이 출력됐다.

Archive created at ...
dbname: gitea
TOC Entries: 1118
Format: CUSTOM

Dumped from database version: 15.4
Dumped by pg_dump version: 15.4
 

최종 백업:

gitea-appdata.tar.gz    약 5.8M
gitea-git-data.tar.gz  약 1.9G
gitea-db.dump           약 1.1M
 

4. Gitea 1.27.1 설치

DSM 패키지 센터에서:

패키지 센터
→ 수동 설치
→ gitea_x64-7.1_1.27.1-30.spk
 

를 선택해 기존 Gitea 위에 업데이트했다.

업데이트 후 버전 확인:

 
sudo synopkg version gitea
 
1.27.1-30
 

시작:

 
sudo synopkg start gitea
 

상태:

 
sudo synopkg status gitea
 
status: running
 

프로세스도 정상적으로 올라왔다.

 
ps auxww | grep '[g]itea'
 
sc-gitea ... /volume1/@appstore/gitea/bin/gitea web \
  --port 8418 \
  --pid /volume1/@appdata/gitea/gitea.pid
 

5. 그런데 Gitea 초기 설정 화면이 나타남

업데이트 자체는 완료됐는데 gitea에 접속하니 기존 Gitea가 아니라 신규 설치 화면이 나타났다.

DB 설정도 기존 PostgreSQL이 아니라 기본 MySQL 값이 나타났고 Repository 경로 역시 기존 설정과 달랐다.

기존 설정이 사라진 것인지 확인했다.

 
sudo head -40 /var/packages/gitea/var/conf.ini
 

그런데 기존 설정은 정상적으로 살아 있었다.

 
APP_NAME = kwah-git
RUN_USER = sc-gitea
RUN_MODE = prod

[repository]
ROOT = /volume1/git/kwah

[server]
SSH_DOMAIN = git.kwah.dev
DOMAIN = git.kwah.dev
ROOT_URL = https://git.kwah.dev/
HTTP_PORT = 8418
SSH_PORT = 202

[database]
DB_TYPE = postgres
HOST = 192.168.0.4:65432
NAME = gitea
USER = kwah
 

INSTALL_LOCK도 정상적으로 설정되어 있었다.

 
[security]
INSTALL_LOCK = true
 

즉 설정 내용 자체의 문제는 아니었다.


6. 실제 Gitea가 읽는 설정 파일 확인

Gitea CLI에서 기본 설정 경로를 확인했다.

 
sudo -u sc-gitea \
  /volume1/@appstore/gitea/bin/gitea help
 

결과:

WorkPath:
  /volume1/@appstore/gitea/bin

CustomPath:
  /volume1/@appstore/gitea/bin/custom

ConfigFile:
  /volume1/@appstore/gitea/bin/custom/conf/app.ini
 

즉 현재 Gitea가 기본적으로 읽는 설정 파일은:

/volume1/@appstore/gitea/bin/custom/conf/app.ini
 

였다.

실제 내용을 확인했다.

 
sudo cat \
  /volume1/@appstore/gitea/bin/custom/conf/app.ini
 

내용은 고작 이것뿐이었다.

 
[server]
LOCAL_ROOT_URL = http://localhost:8418/
 

반면 기존 설정 전체는:

/volume1/@appdata/gitea/conf.ini
 

에 있었다.

두 파일을 비교하면 거의 전체 설정이 빠진 상태였다.

 
sudo diff -u \
  /volume1/@appdata/gitea/conf.ini \
  /volume1/@appstore/gitea/bin/custom/conf/app.ini
 

7. 기존 conf.ini를 app.ini로 복원

먼저 새로 생성된 app.ini를 백업했다.

 
sudo cp \
  /volume1/@appstore/gitea/bin/custom/conf/app.ini \
  /volume1/@appstore/gitea/bin/custom/conf/app.ini.bak
 

그리고 기존 설정을 복사했다.

 
sudo cp \
  /volume1/@appdata/gitea/conf.ini \
  /volume1/@appstore/gitea/bin/custom/conf/app.ini
 

권한 확인:

 
ls -l /volume1/@appstore/gitea/bin/custom/conf/app.ini*
 
-rw------- sc-gitea synocommunity app.ini
-rw------- root     root           app.ini.bak
 

Gitea를 다시 시작했다.

 
sudo synopkg start gitea
 

NAS 내부에서 확인:

 
curl -v http://127.0.0.1:8418/
 

정상적으로:

HTTP/1.1 200 OK
<title>KWAH</title>
Version: 1.27.1
 

이 출력되었다.

기존 DB와 Repository가 정상적으로 복구됐다.

다만 이 Gitea는 설치한 지 오래된 인스턴스라 /volume1/@appdata/gitea/conf.ini가 과거 SynoCommunity 패키지에서 생성한 구조인지, 내가 예전에 직접 커스텀했던 설정 구조인지는 확실하지 않다.

따라서 이 현상이 모든 1.26.2 → 1.27.1 업데이트에서 발생한다고 단정할 수는 없다.


8. Repository clone / push 확인

Mac에서 기존 Repository를 새로 clone했다.

 
git clone http://git.kwah.dev/lee.git
 

정상적으로 clone 됐다.

remote: Enumerating objects: 953, done.
remote: Counting objects: 100% (953/953), done.
remote: Total 953
 

테스트 파일을 추가하고 commit:

 
git add .
git commit -m "push test"
 

push:

 
git push
 

정상적으로:

main -> main
 

까지 완료됐다.

따라서 다음 항목은 정상 동작하는 것을 확인했다.

기존 Repository 인식
HTTP Clone
Commit
HTTP Push
PostgreSQL 기존 데이터
기존 사용자/Repository
 

9. Git 사용 중 redirect 경고

처음 clone을 다음과 같이 HTTP로 했다.

 
git clone http://git.kwa.dev/lee.git
 

그런데 Gitea 설정은:

 
ROOT_URL = https://git.kwah.dev/
 

이기 때문에 Git에서:

warning: https://git.kwah.dev/... 로 리다이렉트
 

라는 메시지가 나왔다.

문제는 아니었다.

애초에 HTTPS URL을 사용하면 된다.

 
git clone https://git.kwah.dev/lee.git
 

기존 Repository라면:

 
git remote set-url origin \
  https://git.kwah.dev/lee.git
 

로 수정할 수 있다.


10. Gitea의 detected web site URL 경고

로그인 후 다음 경고도 나타났다.

The detected web site URL is "http://git.kwah.dev/",
it's unlikely matching the site config.

Mismatched app.ini ROOT_URL or reverse proxy
"Host/X-Forwarded-Proto" config might cause wrong URL links...
 

app.ini에는 이미:

 
ROOT_URL = https://git.kwah.dev/
 

가 설정되어 있었다.

내 구조는:

Browser
  ↓ HTTPS
Cloudflare
  ↓
Nginx Proxy Manager
  ↓ HTTP :8418
Gitea
 

NPM의 기본 proxy 설정을 확인했다.

 
docker exec npm \
  cat /etc/nginx/conf.d/include/proxy.conf
 

내용:

 
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;

proxy_pass $forward_scheme://$server:$port$request_uri;
 

Cloudflare SSL 모드를 확인해보니 Flexible이었다.

즉 실제 구조는:

Browser ── HTTPS ──> Cloudflare ── HTTP ──> NPM ── HTTP ──> Gitea
 

Cloudflare → NPM 구간이 HTTP이므로 NPM의:

 
$scheme
 

값은 http가 된다.

그래서 Gitea가 실제 URL을:

http://git.kwah.dev/
 

로 감지한 것이다.


11. NPM Advanced에서 X-Forwarded-Proto를 강제로 지정해봤지만

처음에는 NPM Advanced에 다음 설정을 추가해봤다.

 
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 https;
 

하지만 NPM이 자동 생성한 nginx 설정을 확인해보니 location / 내부에서 기본 설정이 다시 들어가고 있었다.

 
proxy_set_header X-Forwarded-Proto https;

...

proxy_set_header X-Forwarded-Proto $scheme;
 

Custom Location에서도 마찬가지로 동일 헤더가 중복됐다.

결국 이 설정 때문에 400 Bad Request가 발생했고, 추가했던 Advanced/Custom Location 설정을 제거하자 다시 정상 동작했다.

따라서 NPM이 자동 관리하는 Proxy Host에서는 무작정 proxy_set_header를 중복 추가하지 않는 것이 좋다.


12. 현재 상태

최종적으로 현재 상태는 다음과 같다.

Gitea       : 1.27.1-30
DSM         : 7.3.2
Architecture: x86_64

Gitea       : 정상
PostgreSQL  : 정상
Repository  : 정상
Clone       : 정상
Push        : 정상
NPM         : 정상
Cloudflare  : 정상
 

설정 파일은 현재 두 개가 존재한다.

실제로 Gitea가 읽는 파일:

/volume1/@appstore/gitea/bin/custom/conf/app.ini
 

기존 설정 파일:

/volume1/@appdata/gitea/conf.ini
 

현재는 기존 conf.ini 내용을 app.ini로 복사해서 사용하고 있으며, 기존 파일도 삭제하지 않고 보존하고 있다.

업데이트 전 백업 역시 당분간 유지할 예정이다.

/volume1/backup/gitea-20260812/
├── gitea-appdata.tar.gz
├── gitea-db.dump
└── gitea-git-data.tar.gz
 

정리

이번 작업에서 가장 중요했던 건 업데이트 전에 Repository와 DB를 따로 백업한 것이었다.

특히 Gitea처럼 DB와 Git Repository가 분리되어 있는 서비스는 단순히 패키지 디렉터리만 백업해서는 충분하지 않다.

최소한 다음 세 가지를 확보해두는 게 좋다.

1. Gitea 설정/AppData
2. Git Repository + LFS
3. Database dump
 

그리고 SynoCommunity 패키지를 오래 사용해온 환경이라면 업데이트 후에는 반드시:

 
gitea help
 

등으로 현재 Gitea가 실제 어떤 config 파일을 읽고 있는지 확인하는 것도 필요하다.

이번에는 기존 데이터가 사라진 게 아니라 기존 설정 파일과 새 Gitea가 읽는 설정 파일의 위치가 달라진 것이 핵심이었다.

결과적으로 1.27.1-30으로 업데이트한 뒤 기존 Repository의 clone/push까지 정상적으로 동작하는 것을 확인했다.

 

'etc' 카테고리의 다른 글

맥북에 Homebrew 설치  (0) 2025.01.21
Docker Desktop으로 Nginx 설치하기  (0) 2023.11.10
시놀로지 나스에 PostgreSQL 설치 및 외부 연결  (0) 2023.08.22
PowerMockup  (0) 2023.06.05
디자인 패턴과 프레임워크  (0) 2023.02.02

https://brew.sh 에 접속한다.

 

Homebrew 설치하기 옆에있는 Copy 아이콘을 클릭하여 선택한다.

터미널을 실행시킨다.

터미널에 해당 커맨드를 붙여넣는다.

 

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

계정 비밀번호를 입력한다.

 

엔터를 클릭하여 진행한다.

 

끝난뒤에 해당 커맨드를 입력한다.

echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/사용자이름/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"

 

Homebrew가 설치됐는지 해당 커맨드를 통해서 확인한다.

brew --version

 

 

 

 

구분 리스트 튜플 딕셔너리
구조 대괄호([]) 소괄호(()) 중괄호({}) 중괄호({})
중복여부 O O X 키: X
값: O
순서 O O X O
변경여부 O X O O
인덱스접근 O O X O

<문제상황>

Bootstrap을 통해서 <div>에 container-fluid 클래스를 추가했음에도, 좌우에 여백이 생기는 문제가 발생하였다.
CSS를 찾아보니 아래와 같이 설정되어 있었다.

      --bs-gutter-x: 1.5rem;

해결방법 1: css를 그냥 수정하는 방법

--bs-gutter-x라는 요소가 좌우 간격을 띄우는 역할을 했다.

.container-fluid {
      --bs-gutter-x: 0; /* container-fluid 설정 시에, 좌우에 공백생기는 걸 제거 */
}

해결방법 2: 클래스 추가

--bs-gutter-x가 gutter라는 것을 확인한 뒤에, gutter를 0으로 설정하는 클래스가 있는지 확인했다.
그리고, 해당<div>에만 g-0 클래스를 추가했다.

<div class="container-fluid g-0">
	/* 내용 */
</div>

 

  • 물리 계층(Physical Layer):
    • Ethernet: 네트워크 연결에 사용되는 가장 일반적인 물리 및 데이터 링크 계층 기술 중 하나
    • RS-232: 시리얼 통신에 사용되는 표준
    • V.35, V.90: 모뎀을 통한 데이터 전송 표준
  • 데이터 링크 계층(Data Link Layer):
    • Ethernet: 이더넷 프레임을 사용하여 데이터를 전송
    • PPP (Point-to-Point Protocol): 점대점 연결을 통해 데이터를 전송
    • IEEE 802.11: 무선 LAN (Wi-Fi) 표준
  • 네트워크 계층(Network Layer):
    • IP (Internet Protocol): 인터넷을 통한 데이터 패킷 전송의 주요 프로토콜
    • ICMP (Internet Control Message Protocol): 네트워크 장치 간의 오류 메시지 및 운영 정보를 전송
    • IGMP (Internet Group Management Protocol): 멀티캐스트 그룹 관리에 사용
  • 전송 계층(Transport Layer):
    • TCP (Transmission Control Protocol): 신뢰성 있는 연결 지향적 데이터 전송을 제공
    • UDP (User Datagram Protocol): 연결 없이 데이터를 전송하는 경량 프로토콜
  • 세션 계층(Session Layer):
    • NetBIOS (Network Basic Input/Output System): 네트워크 어댑터와 통신할 때 사용되는 서비스 및 프로토콜
    • RPC (Remote Procedure Call): 네트워크를 통해 다른 컴퓨터에 있는 프로그램이 실행될 수 있도록 함
  • 표현 계층(Presentation Layer):
    • SSL (Secure Sockets Layer): 데이터 암호화 및 복호화를 관리하여 안전한 데이터 전송을 보장
    • MIME (Multipurpose Internet Mail Extensions): 이메일을 통한 멀티미디어 데이터 전송 표준
  • 응용 계층(Application Layer):
    • HTTP (Hypertext Transfer Protocol): 웹 페이지 및 기타 데이터를 전송하는 데 사용됨
    • FTP (File Transfer Protocol): 파일 전송을 위한 프로토콜
    • SMTP (Simple Mail Transfer Protocol): 이메일 전송을 위한 프로토콜

 

출처) ChatGPT

'CS' 카테고리의 다른 글

보안 요소  (1) 2023.02.16
입력 데이터 검증 및 표현의 보안 약점  (0) 2023.02.16
C언어의 대표적인 표준 라이브러리  (0) 2023.02.16
소프트웨어 개발 프레임워크  (0) 2023.02.16
프로토콜의 종류  (0) 2023.02.16

자바스크립트의 속성 앞에 _(언더스코어)를 쓰는 이유는 이 속성이나 메서드가 비공개임을 나타내는 일반적인 방법이다.

자바스크립트는 자바나 다른 언어들과 달리 직접적으로 접근제어자를 사용할 수 없기 때문에, _(언더스코어)를 사용한다.

ES6 이후에 클래스가 생성됨에 따라서, #을 쓰는 방식으로 바뀌고 있다.

class Example {
    #privateField;

    constructor(value) {
        this.#privateField = value;
    }

    getPrivateField() {
        return this.#privateField; // 내부에서 접근 가능
    }
}

const obj = new Example(123);
console.log(obj.getPrivateField()); // 123 출력
console.log(obj.#privateField); // SyntaxError, 외부에서 접근 불가

 

출처) ChatGPT

'JavaScript > 개념정리' 카테고리의 다른 글

코드 순서의 (비)중요성  (0) 2023.06.07
return  (0) 2023.06.07
functions  (0) 2023.06.07
String  (0) 2023.06.07
자료형  (0) 2023.06.07
  • 모듈이란 특정 데이터들의 집합(파일)을 의미한다.
  • 모듈의 import(가져오기) 문법과 export(내보내기) 문법을 사용할 때, 모듈이라고 부를 수 있다.

module.js

export const hello = 'Hello World!'
  • module.js에서 다음과 같이 코드를 입력하고, export를 통해서, 내보내기를 한다.

main.js

import { hello } from './module.js'

console.log(hello) // 'Hello World!'
  • module.js를 받아오기 위해서는 import를 통해서 받아오기를 진행한다.
  • 변수로 선언했던 hello{} 사이에 넣어주고, 콘솔을 찍으면, module.js에서와 동일하게 Hello World!가 출력된다.

기본(default) 내보내기

  • 모듈에서는 값들을 내보낼 때, default(기본값), 객체, 함수 등을 export(내보내기) 할 수 있다.

module.js

export default defaultValue
  • export시에, default를 사용해서, 기본으로 보내는 값을 지정가능하다.

main.js

import value from './moudle.js'

console.log(value); // defaultValue
  • import시에, importfrom 사이에, 원하는 변수명을 입력한다.
  • 변수로 선언한 값을 conosle에 출력해보면, moudule.js에서 default값으로 선언한 defaultValue라고 나오는 걸 확인할 수 있다.

유명(named) 내보내기

module.js

export const str = "ABC"
const const arr = []
export function hello() {}
  • export시에, 함수, 배열, 객체, 변수등을 보내기가 가능하다.

main.js

import { str, arr, hello } from './module.js'

console.log(str); // 'ABC'
console.log(arr); // []
console.log(hello) // function hello()
  • import시에, {} 사이에, 변수명을 넣으면, 출력이 가능하다.

main.js

`import { str as alphabet } from './module.js'`

console.log(alphabet); // 'ABC'
  • 또한, as를 통해서 변수명을 다르게 변경할 수도 있다.

여러모듈 한번에 내보내기

moduleA.js

export const a = () => abc

moduleB.js

export const b = () => def

main.js

import { a } from './moduleA.js'
import { b } from './moduleB.js'

console.log(a()) //abc
console.log(b()) //def
  • 모듈을 합치지 않으면, 다음과 같이 작동하게 된다.
  • 하지만 모듈을 합치게 되면 다음과 같은 작용을 하게 된다.

moduleA.js

export const a = () => abc

moduleB.js

export const b = () => def

utils.js

export {a} from './moduleA.js'
export {b} from './moduleB.js'
  • moduleA와 moduleB를 바로 export(내보내기)한다.

main.js

import { a, b } from './utils.js'

console.log(a()) // abc
console.log(b()) // def
  • 그렇게 되면, 다음과 같이, console.log()에 동일한 결과값을 얻을 수 있다.

Docker Desktop을 실행한다.

상단의 Search에서 nginx를 검색한뒤에 Pull을 클릭한다.

Images 탭에 들어간 뒤에, Run을 클릭한다.

컨테이너 명을 입력하고, Host port80을 입력한뒤에 Run을 클릭한다.

브라우저에서 localhost를 검색하면, 적용이 완료된 걸 볼 수 있다.

+ Recent posts