Ubuntu 20.04 LTS にGeoDjango+wsgi+Apacheを設定

# はじめに

Ubuntu上に、GIS(地理空間情報）を扱えるGeoDjango+PostGIS環境と、Apacheにmod-wsgi経由でアクセスする様に設定した手順の備忘録を兼ねたメモです。

## 環境

```
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.2 LTS"
```

## インストールソフト

* Apahce 2.4.41
* Python ~~3.9~~  3.8.10
* Django 3.2.6
* PostgreSQL 12.7
* PostGIS 3.1.1

**Python-3.9だと、mod_wsgiまわりの変更が面倒なので、3.8系を利用**
 
# 環境構築

## 必要なパッケージのインストール

お約束の更新後、apache、GDALなどをaptでインストール

```
sudo apt update
sudo apt upgrade
sudo apt install git apache2 apache2-dev gdal-bin libgdal-dev
```

## 文字コード設定

コンソールを日本語化する場合

```
sudo apt -y install language-pack-ja language-pack-ja-base ibus-mozc
sudo localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"
```

## ssh

/etc/ssh/sshd_configの以下の箇所を修正。portの変更は念のため。

```/etc/ssh/sshd_config
Port 32722
PermitRootLogin no
PasswordAuthentication no
ClientAliveInterval 30
```

**秘密公開鍵でsudoできるユーザでログインできること**を確認してからsshdをrestart

## ファイヤーウォールの設定

ufw を使いました。

```
＄ sudo ufw status
Status: inactive
$ sudo ufw default deny
$ sudo ufw allow 22/tcp
$ sudo ufw allow 80/tcp
$ sudo ufw allow 443/tcp
$ sudo ufw allow 8000/tcp    # テスト用
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere                  80/tcp                     ALLOW       Anywhere                  
443/tcp                    ALLOW       Anywhere                  
8000/tcp                   ALLOW       Anywhere                  
22/tcp (v6)                ALLOW       Anywhere (v6)             
80/tcp (v6)                ALLOW       Anywhere (v6)             
443/tcp (v6)               ALLOW       Anywhere (v6)             
8000/tcp (v6)              ALLOW       Anywhere (v6)             
```

## Python 3.8 ~~3.9~~

~~デフォルトが python-3.8 だったので、aptを使って、python-3.9 を導入。~~
デフォルトの3.8を利用。

```
sudo apt install python3.8 python3.8-dev python-is-python3 -y
```

ちなみに、3.9を入れる場合は下の通りで、apacheからPython3.9を使う様にする必要あり。

```
$ sudo apt install python3.9 python3.9-dev -y
$ sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1
$ sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2
$ sudo update-alternatives --config python3
  [snip] # Python3.9を選択
$ sudo apt install python-is-python3   # python だけで python3 を起動
$ python -V
Python 3.9.0+
```

## Apache

### バージョン等の秘匿

```/etc/apache2/conf-available/security.conf
ServerTokens Prod
#### Add
# Hide Header Server Apache
Header unset Server
# Hide Header X-Powered-By
Header unset X-Powered-By
```

### 文字コード設定

Apacheの設定ファイル/etc/apache2/envvarsで、利用する文字コードに修正。ここでは ja_JP.UTF-8に統一

```/etc/apache2/envvars
#export LANG=C
export LANG="ja_JP.UTF-8"
```

### 設定の確認と再起動

Apacheの設定を確認して再起動

```
$ sudo a2enmod headers 　#　headerモジュールの追加
$ apachectl configtest
Syntax OK
$ sudo systemctl restart apache2
```

## Django

pip を使って導入。

```
$ sudo apt install python3-pip
$ sudo pip install --upgrade pip    # pip 自身を更新
$ sudo pip install django django-environ
$ python -m django --version   # djangoのバージョン確認
3.2.3
```

あらかじめ requirements.txt でリストを用意しておいてあれば、一気にインストールできる。

```
$ sudo pip install -r requirements.txt
```

## PostgreSQL+PostGIS

PostgraSQLデータベースと、そのGIS拡張のPostGISをインストール。

```
$ apt install postgresql postgis gdal-bin
$ ps auxww | grep postgresql  #データベース起動されていることを確認
```

データベースにアクセス

```
$ sudo -u postgres psql
[sudo] password for foo: 
psql (12.7 (Ubuntu 12.7-0ubuntu0.20.04.1))
postgres=# 
```

USERとデータベースを作成し、PostGIS化

```
postgres=# CREATE USER testuser WITH PASSWORD 'password';
CREATE ROLE
postgres=# CREATE DATABASE testdb OWNER = testuser TEMPLATE = template0 ENCODING = 'UTF8';
postgres=# \c testdb
You are now connected to database "testdb" as user "postgres".
testdb=# CREATE EXTENSION postgis;
CREATE EXTENSION
testdb=# SELECT PostGIS_Version();
            postgis_version            
---------------------------------------
 3.0 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
```

## Djangoの設定

### Djangoプロジェクト

既存の動作するDjnagoプロジェクト一式を任意の場所、例えば /var/www/djnago 以下に配置する。
なければ、[こちらのDjango初期プロジェクト](https://qiita.com/yasushi00/items/3c944a4f63b132054b41#django%E5%88%9D%E6%9C%9F%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88) などを参考に、あらかじめDjangoプロジェクトを作成しておく。

### Dｊangoの設定

必要に応じて設定ファイル setting.py の以下の部分などを修正。

```
# PostGIS
INSTALLED_APPS = [ 
    'django.contrib.admin', 
    'django.contrib.auth',  
    'django.contrib.contenttypes',
    'django.contrib.sessions', 
    'django.contrib.messages', 
    'django.contrib.staticfiles', 
    'django.contrib.gis',         # 追加：GIS機能
    ’test',                       # 追加：作成したプロジェクト
]       
# データベースの設定
    'default': {
        'ENGINE': 'django.contrib.gis.db.backends.postgis',
        'HOST': 'localhost',    # DBホスト
        'NAME': 'postgisdb',    # データベース名
        'USER': 'postgis',      # DBユーザ名
        'PASSWORD': 'passwords', # DBパスワード
    }
# テスト用
ALLOWED_HOSTS = ["*"]           
```

### 管理ユーザの追加

```
$ sudo ./manage.py createsuperuser
```
### データベースのマイグレーション

```
$ ./manage.py migrate
```

## djangoの動作確認

テストサーバを実行し、トップページが表示されることを確認。
Pythonライブラリが足りない場合は、pip でインストールする。

```
$ ./manage.py runserver
$ curl http://localhost:8000
```

## wsgi設定

### インストール

```
$ sudo apt install libapache2-mod-wsgi-py3
$ sudo a2enmod wsgi   #これは不要だった
$ sudo pip install mod-wsgi mod-wsgi-httpd
```

### django.conf

以下の内容のapachの設定ファイル /etc/apache2/sites-available/django.conf を作成。
サーバのホスト名が、example.com Djnagoプロジェクトが test で一式を /var/www/test に配置した場合

```
<VirtualHost *:80>
    ServerName example.com 

    #Demon process for multiple virtual hosts
    WSGIDaemonProcess example.com python-path=/var/www/test/:/usr/local/lib/python3.8/dist-packages processes=2 threads=5

    #Pointing wsgi script to config file
    WSGIScriptAlias / /var/www/test/test/wsgi.py
    WSGIProcessGroup example.com

    #Your static files location
    Alias /static/ "/var/www/test/static/"
    <Location "/media">
        SetHandler None
    </Location>
    <LocationMatch "\.(jpg|gif|png|js|css)$">
        SetHandler None
    </LocationMatch>
    <Directory /var/www/test/ >
        WSGIProcessGroup example.com
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>
```

設定ファイルを有効化して、apacheをリロード

```
$ sudo a2ensite django
$ sudo systemctl reload apache2
```

DNSにホストを登録していればcertbotによるSSL設定も可能

```
$ sudo apt install certbot python3-certbot-apache 
$ sudo a2enmod ssl   # SSLモジュールの有効化
$ sudo certbot   # 表示される順に入力していけばOK
```

Apacheの設定を確認して再起動

```
$ apachectl configtest
Syntax OK
$ sudo systemctl restart apache2
```## 動作確認

任意のブラウザで、http://example.com にアクセスし表示を確認。


# 参考

* https://qiita.com/yasushi00/items/3c944a4f63b132054b41
* https://manual.sakura.ad.jp/vps/os-packages/ubuntu20.html