Project

General

Profile

Actions

機能 #83

open

機能 #63: 新チケットver1

環境づくり

Added by K Okuda 13 days ago. Updated 4 days ago.

Status:
新規
Priority:
通常
Assignee:
Start date:
09/07/2025
Due date:
% Done:

0%

Estimated time:
Spent time:
Actions #1

Updated by K Okuda 12 days ago

python インストール
pip インストール
fastApi インストール(uvicorn付き)
postgres インストール
letsEncrypt インストール

psycopg[binary](PostgreSQL用Pythonドライバ)
alembic(DBマイグレーションを使うなら)
passlib[bcrypt](パスワードハッシュ用)
python-dotenv(環境変数を .env で管理するなら)
Pillow(プロフィール画像をサーバーで再エンコードするなら)

Actions #2

Updated by K Okuda 12 days ago

1) OSパッケージ
# 基本
sudo dnf -y update
sudo dnf -y install python3 python3-pip

# python3-venvはoracle linuxのためスキップ

# PostgreSQL(AppStreamの例:v15を使う)
sudo dnf -y module reset postgresql
sudo dnf -y module enable postgresql:15
sudo dnf -y install postgresql-server

# Certbot(Let’s Encrypt)
sudo dnf -y install oracle-epel-release-el$(rpm -E %rhel)
sudo dnf -y install certbot


PostgreSQLの初期化・起動(必要なら)

sudo /usr/bin/postgresql-setup --initdb
sudo systemctl enable --now postgresql

2) 仮想環境を作成して有効化
python3 -m venv /opt/myapp/.venv
source /opt/myapp/.venv/bin/activate
python -m pip install --upgrade pip

3) Pythonパッケージ(アプリ用)
# FastAPI 本体+Uvicorn(推奨オプション込み)
pip install fastapi "uvicorn[standard]"

# PostgreSQL ドライバ(psycopg v3)
pip install "psycopg[binary]"

# 追加(必要に応じて)
pip install alembic              # マイグレーションを使うなら
pip install "passlib[bcrypt]"    # パスワードハッシュにbcryptを使うなら
pip install python-dotenv        # .env で環境変数を管理するなら
pip install Pillow               # 画像の再エンコードをサーバーでやるなら
Actions #3

Updated by K Okuda 12 days ago

# (入っていたら)抜ける
deactivate 2>/dev/null || true

# 古いvenvは不要なら削除(消したくない場合はスキップ)
sudo rm -rf /opt/myapp/.venv

# 新しく作る(ホーム配下)
mkdir -p ~/myapp
python3 -m venv ~/myapp/.venv
source ~/myapp/.venv/bin/activate
python -m pip install --upgrade pip

pip install fastapi "uvicorn[standard]" "psycopg[binary]" \
    alembic "passlib[bcrypt]" python-dotenv Pillow

which uvicorn
python -c "import fastapi,psycopg,PIL,uvicorn; print('OK')"


# 起動

/opt/myapp/.venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000
# または ~/myapp/.venv/bin/uvicorn ...
Actions #4

Updated by K Okuda 5 days ago · Edited

ここまでやったこと(時系列)

VPSにSSH接続:鍵は作成済み。VS Code Remote-SSH はユーザー名の指定でつまずき、対処方針を共有。

Python系の導入:python3/pip はOSにあり。
仮想環境は当初 /opt/myapp/.venv を想定 → 最終的に ~/myapp/.venv を使う方針に整理(sudo不要で安全)。

パッケージの導入(一部rootにも入ったが最終的にvenvで実施する想定):
FastAPI、Uvicorn、psycopg[binary]、(必要に応じて)Alembic、Passlib[bcrypt]、python-dotenv、Pillow。

アプリ雛形の作成:
main.py を用意(/media を /srv/app/media にマッピング、/health エンドポイント追加)。
権限エラーはディレクトリ所有者の修正で解消。

静的領域の用意:/srv/app/media 作成・権限付与。

起動確認の準備:uvicorn main:app --host 0.0.0.0 --port 8000 で動かす方針、
ポート衝突時の確認コマンド(ss/lsof/fuser)も共有。

DNS設定:サブドメイン→VPSのAレコードを設定済み。ただしまだ未反映。
反映待ちのテストは hosts で一時紐づけする方法まで共有。

Let’s Encrypt:DNSが通ったら certbot で取得→Uvicornを443で常駐、更新フックで再起動の方針まで共有。
(まだ実行はしていない想定)

いま出来る状態

~/myapp/.venv(推奨のvenv)を有効化すればFastAPI/Uvicorn等を使える状態。

main.py と /srv/app/media の準備はOK(所有者は自分)。

DNSは未反映なので、IP:8000 なら疎通確認可能。

次にやること(順番)

アプリを起動して動作確認

仮想環境を有効化 → uvicorn main:app --host 0.0.0.0 --port 8000

ブラウザで http://<VPSのIP>:8000/health が {"ok": true} になるか確認。

404や接続不可なら、FWで 8000/tcp を一時開放、ss -ltnp | grep ':8000' で待受確認。

DNSの反映確認

手元で nslookup <サブドメイン>/dig +short <サブドメイン> → VPSのIPが返るまで待つ。

早く確かめたい場合は一時的に hosts へ追記して http://<サブドメイン>:8000/health を確認。

HTTPS化(DNSが通ってから)

certbot certonly --standalone -d <サブドメイン> で証明書取得。

取得後、Uvicornを443で常駐(systemd化 & AmbientCapabilities=CAP_NET_BIND_SERVICE)。

certbot.timer 有効化+更新フックで systemctl restart myapp。

最終確認:https://<サブドメイン>/health

(任意)VS Code Remote-SSH

~/.ssh/config に User okuda と IdentityFile を明記して myvps で接続。

この流れでまずIPベースで稼働確認→DNS反映→HTTPS常駐まで持っていけます。

Actions #5

Updated by K Okuda 4 days ago

概要

FastAPI を HTTPS(:443) で常駐運用まで構築。

SELinux/権限エラーを解消。

Let’s Encrypt の自動更新 → アプリ再起動まで実装。

対象ドメイン:test.igovote.net

実施内容

アプリ配置
アプリコードを /opt/myapp/main.py に統一。動作確認用に /health を用意。
※ 静的配信(/media)は未設定。

証明書取得(Let’s Encrypt)
certbot certonly --standalone -d test.igovote.net -m <実メール> --agree-tos -n

systemd サービス作成
初回起動で 203/EXEC / Permission denied が発生 → 後述の対処で解消。

起動失敗の解消

venv を /opt/myapp/.venv に作成(/home 配下の venv 実行をやめる)。

ExecStart を /opt/myapp/.venv/bin/python -m uvicorn に統一。

AmbientCapabilities=CAP_NET_BIND_SERVICE を付与(非 root で 443 バインド)。

証明書を /etc/ssl/myapp/ へコピー(okuda:okuda、640)、restorecon 実施。

起動確認
ログで Uvicorn running on https://0.0.0.0:443 を確認。
/health は GET 200(curl -i https://test.igovote.net/health)。
※ curl -I(HEAD)は 405 が正しい挙動。

証明書の自動更新

deploy hook:/etc/letsencrypt/renewal-hooks/deploy/10-myapp-reload.sh
(更新後に /etc/ssl/myapp/ へ再コピー → systemctl restart myapp)

自作 systemd タイマー:
certbot-renew.service(oneshot), certbot-renew.timer(毎日実行)

--dry-run と hook 手動実行で再起動動作を確認済み。

最終構成

コード:/opt/myapp/main.py(静的配信なし)

仮想環境:/opt/myapp/.venv

サービス:/etc/systemd/system/myapp.service

User=okuda / WorkingDirectory=/opt/myapp

ExecStart=/opt/myapp/.venv/bin/python -m uvicorn main:app --host 0.0.0.0 --port 443 --ssl-certfile /etc/ssl/myapp/fullchain.pem --ssl-keyfile /etc/ssl/myapp/privkey.pem --workers 2

AmbientCapabilities=CAP_NET_BIND_SERVICE

証明書(アプリが読むコピー):/etc/ssl/myapp/{fullchain.pem, privkey.pem}(okuda:okuda 640)
※ 元は /etc/letsencrypt/live/test.igovote.net/(root 管理)

自動更新:certbot-renew.timer 有効、deploy hook で鍵コピー&再起動

主要なトラブルと対処

Could not import module "main" → コードを /opt/myapp に統一、WorkingDirectory も一致させ解消。

203/EXEC / Permission denied → venv を /opt へ、python -m uvicorn 方式、AmbientCapabilities 付与で解消。

certbot 登録エラー → 実メール指定で解消。

Actions

Also available in: Atom PDF