README에 conda/systemd/Apache 설치 문서 추가

- Miniconda(ncue) 기반 설치/실행 및 systemd 예시 추가
- Apache ProxyPass 설정 및 503 트러블슈팅 절차 정리
- Flask DB pool lazy 생성으로 임포트 단계 장애(503) 완화

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dsyoon
2026-02-08 09:05:47 +09:00
parent 9fe71ad6a4
commit f2119ed8da
2 changed files with 196 additions and 37 deletions

160
README.md
View File

@@ -16,33 +16,166 @@ python3 -m http.server 8000
그 후 브라우저에서 `http://localhost:8000`으로 접속합니다.
## 서버(Node) + PostgreSQL 사용자 저장
## 백엔드(Flask) + PostgreSQL 사용자 저장
로그인 후 사용자 정보를 `ncue_user`에 저장하고(Upsert), 로그인/로그아웃 시간을 기록하며,
`/api/config/auth`로 Auth0 설정을 공유하려면 백엔드 서버가 필요합니다.
현재 백엔드는 **Python Flask(기본 포트 8023)** 로 제공합니다. (정적 HTML/JS는 그대로 사용 가능)
1) 의존성 설치(Python)
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
2) 테이블 생성
### 1) DB 테이블 생성(서버에서 1회)
```bash
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f db/schema.sql
```
3) 서버 실행
### 2) 실행 방법 A: (로컬/간단) venv로 실행
```bash
python flask_app.py
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
PORT=8023 python flask_app.py
```
### 3) 실행 방법 B: (운영/권장) Miniconda 환경 `ncue` + gunicorn + systemd
#### B-1) 최초 1회 설치
```bash
cd /path/to/home
conda activate ncue
python -m pip install -r requirements.txt
python -m pip install gunicorn
```
#### B-2) 단독 실행(테스트)
```bash
conda activate ncue
cd /path/to/home
gunicorn -w 2 -b 127.0.0.1:8023 flask_app:app
```
확인:
```bash
curl -s http://127.0.0.1:8023/healthz
curl -s http://127.0.0.1:8023/api/config/auth
```
#### B-3) systemd 서비스(예시)
`/etc/systemd/system/ncue-flask.service`:
```ini
[Unit]
Description=NCUE Flask API (gunicorn)
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/path/to/home
# miniconda 경로는 설치 위치에 맞게 수정하세요.
ExecStart=/bin/bash -lc 'source /opt/miniconda3/etc/profile.d/conda.sh && conda activate ncue && gunicorn -w 2 -b 127.0.0.1:8023 flask_app:app'
Restart=always
RestartSec=3
# .env 대신 systemd Environment로 주입(권장)
Environment=DB_HOST=ncue.net
Environment=DB_PORT=5432
Environment=DB_NAME=ncue
Environment=DB_USER=ncue
Environment=DB_PASSWORD=REPLACE_ME
Environment=TABLE=ncue_user
Environment=AUTH0_DOMAIN=ncue.net
Environment=AUTH0_CLIENT_ID=g5RDfax7FZkKzXYvXOgku3Ll8CxuA4IM
Environment=AUTH0_GOOGLE_CONNECTION=google-oauth2
Environment=ADMIN_EMAILS=dosangyoon@gmail.com,dsyoon@ncue.net
Environment=PORT=8023
[Install]
WantedBy=multi-user.target
```
적용/재시작:
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now ncue-flask
sudo systemctl restart ncue-flask
sudo systemctl status ncue-flask --no-pager
```
로그 확인:
```bash
sudo journalctl -u ncue-flask -n 200 --no-pager
```
### 4) Apache 설정(정적은 Apache, `/api/*`만 8023 프록시)
필요 모듈(Ubuntu/Debian):
```bash
sudo a2enmod proxy proxy_http headers
sudo systemctl reload apache2
```
가상호스트 예시:
```apacheconf
<VirtualHost *:80>
ServerName ncue.net
DocumentRoot /path/to/home
<Directory /path/to/home>
Require all granted
</Directory>
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
ProxyPass /api/ http://127.0.0.1:8023/api/
ProxyPassReverse /api/ http://127.0.0.1:8023/api/
ProxyPass /healthz http://127.0.0.1:8023/healthz
ProxyPassReverse /healthz http://127.0.0.1:8023/healthz
</VirtualHost>
```
적용:
```bash
sudo apachectl -t && sudo systemctl reload apache2
```
### 5) 503(Service Unavailable) 트러블슈팅 체크리스트
브라우저 콘솔에서 503이 뜨면 대부분 **Apache가 127.0.0.1:8023 백엔드로 프록시했는데 백엔드가 응답을 못하는 상태**입니다.
- 백엔드가 살아있는지:
```bash
curl -i http://127.0.0.1:8023/healthz
curl -i http://127.0.0.1:8023/api/config/auth
```
- 서비스 로그:
```bash
sudo journalctl -u ncue-flask -n 200 --no-pager
```
- Apache 프록시 로그:
- Ubuntu/Debian: `/var/log/apache2/error.log`
- RHEL/CentOS: `/var/log/httpd/error_log`
> 참고: `flask_app.py`는 DB가 일시적으로 죽어도 앱 임포트 단계에서 바로 죽지 않도록(DB pool lazy 생성) 개선되어,
> “백엔드 프로세스가 안 떠서 Apache가 503”인 케이스를 줄였습니다.
기본적으로 `.env``ADMIN_EMAILS`에 포함된 이메일은 `can_manage=true`로 자동 승격됩니다.
### (선택) 역프록시/분리 배포
@@ -83,3 +216,6 @@ update ncue_user set can_manage = true where email = 'me@example.com';
- 내보내기: 현재 화면 기준 링크를 JSON으로 다운로드합니다.
- 가져오기: 내보내기 JSON(배열 또는 `{links:[...]}`)을 다시 불러옵니다.
## 설치 방