Ubuntu 20.04のセットアップからDjangoのインストールまで

VPSにUbuntuをセットアップした際にいつもする作業をまとめました。今回はConoHaのVPSにUbuntu20.04をインストールしました。

Django、Django Channel, Django REST Frameworkをインストールするところまでです。

rootユーザーとしてサーバーへの接続後からの手順になります

新しいユーザーの登録

作業用に新しいユーザーを登録します。下記を実行すると新しいパスワードを聞かれます。Full Name, Room Number, Work Phone, Home Phone, Otherを聞かれますが空白で大丈夫です。

sudo adduser 【新しいユーザー名】
sudo usermod -aG sudo 【新しいユーザー名】

いったんログアウトして新しいユーザーとしてログインします

アップデートとアップグレード

sudo apt update
sudo apt upgrade
sudo reboot

vimとgitのインストール

最初にgitとvimをインストールするのが習慣になっています。

sudo apt update
sudo apt install vim git

サーバー上での.vimrcは必要最小限のシンプルなものに心がけています

nnoremap j gj
​​nnoremap k gk
​​set incsearch
​​set ignorecase
​​set smartcase
​​set hlsearch
​​nnoremap <ESC><ESC> :nohl<RETURN>
​​set expandtab
​​set shiftwidth=4
​​set tabstop=4
​​"noremap y "+y
​​set visualbell
​​set autoindent
​​
​​autocmd! BufNewFile,BufRead *.html set filetype=htmldjango
​​autocmd! BufNewFile,BufRead *.html set shiftwidth=2
​​
​​if has("autocmd")
​​  au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
​​endif

nginx(サーバー)

sudo apt install nginx

certbot

SSL認証のためにcertbotを使います。https://certbot.eff.org/の手順に従います。下記のような手順でした

sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot certonly --nginx
sudo certbot renew --dry-run

4行目のあと、メールアドレスや設定したいドメインを聞かれます。ドメインのDNS設定は済ませておいてください。成功するとメッセージの中に下記が表示されます。

Certificate is saved at: /etc/letsencrypt/live/ 【ドメイン名】/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/【ドメイン名】/privkey.pem

Django

Djangoをインストールする間にvenvで仮想環境をつくっています。

sudo apt install python3-venv
mkdir 【Djangoプロジェクト名】; cd 【Djangoプロジェクト名】
python3 -m venv venv
. venv/bin/activate
pip install django
django-admin startproject 【Djangoプロジェクト名】 .

Django: 言語・タイムゾーンの設定

...
LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'
...

Django: ローカル設定

サーバーだけで使う設定のために【Djangoプロジェクト名】/local_settings.pyを読み込むようにします。settings.pyの末尾に下記を追記します。

...
try:
    from .local_settings import *
except ImportError:
    pass

【Djangoプロジェクト名】/local_settings.py

SECRET_KEY = '【シークレットコードを入れてください】'
  
DEBUG = False

ALLOWED_HOSTS = ['【ドメイン名】']

Djangoはいったんここまでにしてデータベースをインストールします。

PostgreSQL

データベースにPostgreSQLをインストールします。postgisエクステンションも使います

sudo apt install postgresql-server-dev-12 postgresql-12-postgis-3
pip install psycopg2-binary
sudo su - postgres
createdb 【データベース名】 --encoding='utf-8' --locale=en_US.utf8 --template=template0
createuser -P 【データベース用ユーザー名】
psql
grant all privileges on database 【データベース名】 to 【データベース用ユーザー名】;
\q
psql 【データベース名】
create extension postgis;
\q
exit

3行目のあとパスワードを聞かれます

DATABASES = {
    "default": {
        "ENGINE": "django.contrib.gis.db.backends.postgis",
        "NAME": "【データベース名】",
        "USER": "【データベース用ユーザー名】",
        "PASSWORD": "【データベース用パスワード】",
        "HOST": "localhost",
        "PORT": "",
    }
}

Django Channelsのインストール

sudo apt install redis-server
pip install channels channels_redis daphne

【Djangoプロジェクト名】/asgi.py

import os

from django.conf.urls import url
from django.core.asgi import get_asgi_application

# Fetch Django ASGI application early to ensure AppRegistry is populated
# before importing consumers and AuthMiddlewareStack that may import ORM
# models.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "【Djangoプロジェクト名】.settings")
django_asgi_app = get_asgi_application()

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter


application = ProtocolTypeRouter({
    # Django's ASGI application to handle traditional HTTP requests
    "http": django_asgi_app,

    # WebSocket chat handler
    "websocket": AuthMiddlewareStack(
        URLRouter([

        ])
    ),
})

【Djangoプロジェクト名】/settings.py

...

INSTALLED_APPS = [
    ...
    'channels',
    ...
]

...

ASGI_APPLICATION = "【Djangoプロジェクト名】.asgi.application"

【Djangoプロジェクト名】/local_settings.py

...
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("localhost", 6379)],
        },
    },
}

supervisorをインストールします

sudo apt install supervisor

/etc/supervisor/conf.d/asgi.conf

[fcgi-program:asgi]
# TCP socket used by Nginx backend upstream
socket=tcp://localhost:8000

# Directory where your site's project files are located
directory=/home/【Ubuntuのユーザー名】/【Djangoプロジェクト名】

environment=PATH="/home/【Ubuntuのユーザー名】/【Djangoプロジェクト名】/venv/bin:%(ENV_PATH)s"

# Each process needs to have a separate socket file, so we use process_num
command=daphne -u /run/daphne/daphne%(process_num)d.sock --fd 0 --access-log - --proxy-headers 【Djangoプロジェクト名】.asgi:application

# Number of processes to startup, roughly the number of CPUs you have
numprocs=4

# Give each process a unique name so they can be told apart
process_name=asgi%(process_num)d

# Automatically start and recover processes
autostart=true
autorestart=true

# Choose where you want your log to go
stdout_logfile=/var/log/supervisor/asgi.log
redirect_stderr=true

sudo mkdir /run/daphne/
sudo chown root.root /run/daphne/

/etc/nginx/sites-available/default

upstream channels-backend {
    server localhost:8000;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name 【ドメイン名】;

    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
    }

    location / {
        return 301 https://$server_name$request_uri;
        try_files $uri $uri/ =404;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ssl on;
    ssl_certificate      /etc/letsencrypt/live/【ドメイン名】/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/【ドメイン名】/privkey.pem;

    root /var/www/html;

    index index.html index.htm index.nginx-debian.html;

    server_name _;

    location / {
try_files $uri @proxy_to_app;
    }

    location ~ ^/(static|media)/ {
        root /home/【Ubuntuのユーザー名】/【Djangoプロジェクト名】/;
    }

    location @proxy_to_app {
proxy_pass http://channels-backend;
        # proxy_pass http://unix:/srv/platform/production/daphne.sock;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
    }
}
sudo supervisorctl reread
sudo supervisorctl update

今後、djangoの設定等を編集した際には下記を実行して反映させます

sudo supervisorctl restart asgi:*

nginxを読み直してサーバーが動くか確認します

sudo systemctl reload nginx

Not FoundになっていればOKです。

エラーログは/var/log/supervisor/asgi.logにあります。動作がおかしければチェックしてみてください

静的ファイル

すでにNginxで下記のように設定済です

...
location ~ ^/(static|media)/ {
    root /home/【Ubuntuのユーザー名】/【Djangoプロジェクト名】/;
}
...

Django側の設定をします。サーバー側のみで設定になりますので、local_setteings.pyに追記します。

from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
STATIC_ROOT = BASE_DIR / 'static'

確認のためにadmin画面にアクセスしてみます

python manage.py collectstatic
sudo systemctl reload nginx

Django REST FrameWork

pip install djangorestframework django-filter
INSTALLED_APPS = [
  ...
  'rest_framework',
  'django_filters',
  ...
]

初期設定値を記入します

...

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ],
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
...

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です