さくらのレンタルサーバーでPython3最新を利用する(202501時点)

## はじめに

- さくらのレンタルサーバーで最新のPython3を利用したい
- 複数Pythonバージョンの切り替えができるように導入したい
- こちらは2025/1の状況になり、今後のさくら側のアップデートで状況は変わるはず

## さくらのレンタルサーバ状況

- さくらのレンタルサーバFreeBSD13にはPython2.7と3.8がインストールされている、旧仕様のFreeBSD11ではPython2.7のみになる
- FreeBSD13サーバにはOpenSSL1.1.1kがインストールされているがPythonのビルド時にこちらを検出できずインストール済みのOpenSSLを使ってPythonをビルドできない(後述)
  - Python3.10以降ではOpenSSL1.1.1以降を必要とする(Python3.9までは古いOpenSSL1.0.xでもビルド可能)

https://help.sakura.ad.jp/rs/2251/?article_page=2#heading-1

> 3.8.x
> ※旧仕様の一部サーバは、2.7.xです。

## Python環境の構築方法

当初の目的に書いた

- 各種バージョン切り替え
- 最新版を入れる

するための手順を記載していく。

### pyenvインストール

バージョン環境の切り替えのために必要。pyenvの環境設定は次の記事を参照のこと

https://qiita.com/umekichinano/items/11d87902883871981ef4

なお、Python3.9等でFreeBSDインストール済みのOpenSSL1.0.xでも良い場合は下記のOpenSSLのビルドやpyenvのオプション指定は不要で通常の`pyenv install -v 3.9.19`で利用可能。

### OpenSSLのビルド

さくらのFreeBSD13では`/usr/bin/openssl`として1.1.1kが入っているが原因はさておき(後述)Pythonがこちらを検出できずビルドできない。この対応としてOpenSSLの最新版3.x.xあるいは1.1.1Xをソースからビルドしてこちらを利用する。
下記例ではインストール先のパスを`$HOME/local`としたがどちらでも良い。OpenSSLビルド時のキモとなる点は、

- `--openssldir=/etc/ssl`でFreeBSDの標準のCAバンドルを参照すること
- `install_sw`で証明書関連やドキュメントはインストールせずバイナリーのみをローカルにインストール

OpenSSLバージョンはこれを書いている時点の最新3.4.0にしているが任意のバージョンに置き換えること

ソースを展開して

```sh
mkdir -p $HOME/local/src
cd $HOME/local/src/
curl -LO https://github.com/openssl/openssl/releases/download/openssl-3.4.0/openssl-3.4.0.tar.gz
tar xvfpz openssl-3.4.0.tar.gz 
cd openssl-3.4.0
```

オプションを指定してビルドしローカルにバイナリーをインストール

```sh
./config --prefix=$HOME/local/openssl/3.4.0 --openssldir=/etc/ssl
make
make install_sw
```

これで`~/local/openssl/3.4.0`に実行ファイルやライブラリ等が入り`/etc/ssl`に置かれた証明書バンドルや設定を参照するOpenSSL環境が出来あがる。

```sh
LD_LIBRARY_PATH=$HOME/local/openssl/3.4.0/lib \
~/local/openssl/3.4.0/bin/openssl version
```

```sh
OpenSSL 3.4.0 22 Oct 2024 (Library: OpenSSL 3.4.0 22 Oct 2024)
```

### Pythonのビルド

上記OpenSSLの場所を指定しビルド

```sh
CONFIGURE_OPTS="--with-openssl=$HOME/local/openssl/3.4.0 \
--with-openssl-rpath=auto" \
pyenv install -v 3.13.1
```

少なくともこちらの方法で、

- 3.10.16
- 3.11.11
- 3.12.8

もビルド可能。

動作確認としては、

`import ssl`したり、

```sh
$ ~/.pyenv/versions/3.13.1/bin/python
Python 3.13.1 (main, Jan 17 2025, 11:13:16) [GCC 9.4.0] on freebsd13
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 3.4.0 22 Oct 2024'
>>> 
```

次のコードでHTTPSを利用したコードが動けばとりあえず動いているはず

```python
import urllib.request

with urllib.request.urlopen('https://dummyjson.com/products/1') as response:
   html = response.read()
   print(html)
```

このPython3.13環境にPoetryを入れて、とりあえず

- Flask + Flask-CORS
- FastAPI + Pydantic V1 + a2wsgi

をCGIとして動作させることができた。(ハロワレベル）

さくらのレンタルサーバでFastAPIを動かしてみた方法についてはこちらの記事を参照のこと

https://qiita.com/hkato/items/b28120f441ee47bd0608

## さくらOpenSSL1.1.1kが使えない原因？

正確にはわからないが恐らくここら辺だと思う。

さくらのレンタルサーバFreeBSD13には次のOpenSSLがインストールされている

| path                         | version                   | pkg-config |
| ---------------------------- | ------------------------- | -----------|
| /usr/bin/openssl             | 1.1.1k                    | なし        |
| /usr/local/bin/openssl       | 1.0.2-chacha (1.0.2k-dev) | あり        |
| /usr/local/bin/openssl-0.9.8 | 0.9.8zh                   | なし        |

しかしpkg-configに対応しているのは1.0.2のみである。恐らくこれによりOpenSSL1.1.1のバイナリーは存在しているのにPython側のビルドで探すことができず失敗するものと思われる。
openssl.pcを手書きしてPKG_CONFIG_PATHで指定するなどして本当か検証できるかと思うがやってない。

なお私は現在新仕様のFreeBSD13にアップデートしたが、旧仕様のFreeBSD11ではOpenSSLは1.0.2oであった。過去試した記録ではFreeBSD11版でもOpenSSL3.xを個別にローカルインストールし、そちらを参照すればPython3.10以降も今回と同じことは可能であった。

## まとめ

- さくらFreeBSD13にインストール済みOpenSSL1.1.1はPythonから利用できないので個別にOpenSSLをローカルビルドする（証明書等はOSのデフォルトを参照で）
  - FreeBSD11の場合はOpenSSL1.0.2aなのでOpenSSLのビルドは必須
- 上記ビルドしたOpenSSLをPythonビルド時に指定する(`--with-openssl`および`--with-openssl-rpath`オプション)