機能 #83
open機能 #63: 新チケットver1
環境づくり
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 # 画像の再エンコードをサーバーでやるなら
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 ...
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常駐まで持っていけます。
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 登録エラー → 実メール指定で解消。