Chienomi

【ConoHaアドベントカレンダー 2019】 高性能レンタルサーバー ConoHa WINGを本格的に使い倒す

開発::web

  • TOP
  • Articles
  • 開発
  • 【ConoHaアドベントカレンダー 2019】 高性能レンタルサーバー ConoHa WINGを本格的に使い倒す

※ この記事はConoHa Advent Calendar 6日目の記事として書かれたものです。

今年もやって参りましたこのシーズン。

これがChienomi初見という人もいるだろうから、改めてご挨拶。

「パソコンのなんでも屋さん」「ご高齢者の方の携帯電話の使い方指導からLinuxカーネルの話まで」でおなじみ Mimir Yokohama代表の「はるかみ」です。

さて、アドベントカレンダーでやろうと思っていたネタは実は他にあったのだけど、10月にやった内容がなかなかおもしろそうだったので、それを今年のアドベントカレンダーにすることにした。

(ちなみに、もともと何をやろうと思っていたかというと、ConoHa VPSでSaaS展開するために並列高速化する話とか)

この記事は前提として、Manjaro Linux上で行っており、Linux環境を使用し、またLinux環境における操作に対してある程度習熟していることを想定しているが、 Windowsユーザーであっても”Git for Windows”を導入し、Git Bashを使うことでほぼ同様の操作で行うことができる。

PureBuilder SimplyはWindows環境で使用する場合、MSYSまたはCygwinを使用することを想定しており、Git Bashを使うことはとても推奨される。Gitを利用してデプロイするセクションもあるので、Windowsの場合どのみちGit for Windowsが必要であり、Git for Windowsを導入することでこの記事の前提条件がまとめて揃うことになる。

内容的な全体の難易度は「やや易しい」程度で、初心者には難しい面もあるかと思うが、手順を詳細に示し、解説を加えているので、じっくり取り組めば初心者でもクリアできるだろう。 総合的には初心者〜初級者向けの内容ではあるが、あまり知られていないトリックや情報も紹介する。

また、この記事は「レンサバ側の人」(レンサバでFTPとか使ってウェブページを公開する程度のレベルの人)がシステム的にサーバーを利用する手引き(シェルやコマンドラインを使って快適にサーバー管理をする手引き)であると同時に、「VPS側の人」(VPSを構築・運用できる程度の人)がWINGで少ないストレスでウェブ及びメールを運用するための手引きでもある。

普段のChienomiとは違い基礎部分の解説も(全面ではないが)設けたので、VPSなんて全然わかんないからWING使っているんだという人も安心して読んでほしい。 普段VPSを使っていて、WINGに興味があるという人にとっても、退屈な部分はいくらかあったとしても、退屈な内容ではないはずだ。

Conoha WINGについて

ConoHa WINGは2018年にデビューしたGMOインターネットが展開するレンタルサーバーである。

従来、ConoHaという名前でVPSサービスを展開していたが、それに追加する形で「速度」をウリにしたレンタルサーバーサービスであるWINGを追加した。 これに伴い、従来のConoHaはConoHa VPSと呼ばれるようになり、ConoHaという名称はサービス名ではなく、事業名/ブランド名になったようだ。

ConoHa WINGは速度面にメリットがあり、実際にWordPressを動かすとかなり速い。 なかなか高性能なVPSであるConoHa VPSと比べても若干高性能なハードウェアを使用しており、ConoHa VPSの安価なプランでは512MBや1GBといったメモリ容量であることから、各インスタンスに256GBのメモリを搭載するWINGのほうが安定して高速に動作する。

レンタルサーバーとしてはリッチな性能を持つというだけでなく、様々な面で使い勝手が良い。 SSHログインが可能であったり、扱いやすいDNSがあったり、あるいはcronが利用可能であったりと全体的に使いやすさに優れている。 使いにくい点といえば、メールのエイリアス機能がなく、メールボックスを作らないといけない上に、転送設定もしづらいことぐらいだ。

レンタルサーバーで要件を満たす場合でも操作の自由度のなさから避けたいという心理も働くが、VPSを利用するスキルを持った人にとっても高性能で使いやすいレンタルサーバーだと言えるだろう。

速度面ではさすがにCDNを使うのと比べると遅く、静的コンテンツを前提とする場合はやや遅い気がするが(おそらくサーバー設定上のパス解析の関係だろう)、それでもレンタルサーバーとしてはだいぶ速い方である。

メールエイリアス

メールエイリアスの話はちょっと難しくなれが、一般的なメールサーバーでは非常に簡単な書式で配送可能なメールアドレスを増やすことができる。

その配送は

  • ユーザー(メールボックス)に配信
  • 他のメールアドレスへ転送
  • プログラムへパイプ

の3種類。

複数のドメインを扱うバーチャルドメインにおいても、やや書き方が違うもののほぼ同様に使うことができる。

もうひとつ、拡張アドレスというものもある。これは、「アカウント部(@より前の部分)の特定の文字以降をメールボックスから除外する」というもの。 一般的には+で、例えばharuka+my@example.comというメールを受け取ったexample.comメールサーバーは、haruka+myアカウントのメールボックスではなく、harukaアカウントのメールボックスに配送するということである。 この機能はGMailでも利用可能で、ConoHa WINGについても全く明示されていないものの、+によって拡張アドレスが利用可能。 ただ、+つきのアドレスは弾くフォームが多い(+を弾いているのではなく、正当なメールアドレスを無効だとして拒否するフォームが多い)ので、実用性はあまり高くないだろう。

で、メールエイリアスの話に戻るが、このために自分でメールサーバーを管理しているとメールアドレスを増やすのはすごく簡単なことなのだが、ConoHa WINGの場合、メールボックスを領域の確保、パスワードの設定も含めて作成し、その上で転送アドレスを設定する必要がある。 これがレスポンスがそこまでいいわけではないインターフェイスということもあり、結構しんどいし、めんどくさい。 特に転送のほうはまとめて書けるわけでもない上に、設定に柔軟性があまりなくてめんどくさいのだ。

ちなみに、ConoHa WINGには「ローカル配送」という設定項目があるが、これはPostfixの設定の経験がある人向けに言うと、mydestinationから当該ドメインを除外するというものであり、このメールエイリアスには関係がない。

SSH周りの話

SSHとは

SSHはリモートログインのためのプロトコル、あるいはそのためのソフトウェアの名称である。

SSHは経路の暗号化と、非常に強力な認証機能を持っている。 恐らく現状において最も信用できる認証機構だろう。

通常はコマンドラインシェルを獲得するために使用するが、プロキシ、ポートフォワード、ソケット変換、セキュアトンネルなどなど、その用途はめちゃくちゃ幅広いソフトウェアでもある。

サブプロトコル(サブシステム)としてSFTPがあり、これを利用してFTPクライアント(例えばFileZillaやWinSCPなど)からアクセスすることもできる。 ちなみに、FTPとSFTPはプロトコル的な互換性は全くなく、FTPがテキストプロコトルなのに対しSFTPはSSHそのものに類似したバイナリプロトコルだったりと似てすらいない。また、提供するソフトウェアもFTPがFTPサーバーなのに対してSFTPはSSHサーバーなので(少なくとも経路としてSSHを必須とするので)全く違うのだが、クライアント的には同じように使えるようにすることが多いようだ。

Windows 10にはOpenSSHが搭載されており、標準でSSHを利用することができる。

ConoHa WINGのSSH

ConoHa WINGではConoHa VPS同様にコンソールからSSH鍵の登録が可能になっている。

ConoHa VPS同様、ここから登録できるのはECDSAまでで、ED25519鍵が登録できない。 ぜひ早くED25519鍵に対応して欲しいものだ

ちなみに、サーバー側は普通にED25519に対応しており、あくまでコントロールパネルからはED25519鍵が登録できないというだけである。だから、ED25519鍵を作って~/.ssh/authorized_keysに登録すればED25519鍵でログインできる。 ED448をいち早く理解せよとは言わないので、せめてED25519には対応しておいてほしいところ。

SSH鍵の登録

まずは鍵を作る。ECDSAで

% ssh-keygen -t ecdsa -f ~/.ssh/conoha-wing-acal_ecdsa  
Generating public/private ecdsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/haruka/.ssh/conoha-wing-acal_ecdsa.
Your public key has been saved in /home/haruka/.ssh/conoha-wing-acal_ecdsa.pub.
The key fingerprint is:
SHA256:qIdBFPRLUAgSW4v4iXYuV88YsJx9NPvLsMX/jMc/Mhw haruka@hydrangea
The key's randomart image is:
+---[ECDSA 256]---+
|o.oo=+.          |
|.= o.o           |
|+ ... oo         |
| o.o=..oo        |
|..o=.+ooS        |
|. o .+* o    E   |
| . oo..+ +  o .  |
|  o  .  = o o* . |
|       . o ooo+..|
+----[SHA256]-----+

あとは「+SSH KEY」「インポート」だ。

ECDSA公開鍵を「インポート」で登録

登録したSSH鍵を開くと接続情報が載っている。 (ちなみに、このサーバーはこの記事が掲載された時点で存在しないので、既にアクセスできない)

接続情報を確認

これに従って次のようなエントリを~/.ssh/configに書く。 Windowsでもホームフォルダ以下同様の位置(%HOMEPATH%\.ssh\config)である。

Host wing-adv
  HostName www49.conoha.ne.jp
  User c5853005
  Port 8022
  IdentityFile ~/.ssh/conoha-wing-acal_ecdsa
  ServerAliveCountMax 3
  ServerAliveInterval 10
  IdentitiesOnly yes

あとは普通にSSHで入れるはずだ。

% ssh wing-adv
The authenticity of host '[www49.conoha.ne.jp]:8022 ([150.95.219.89]:8022)' can't be established.
ECDSA key fingerprint is SHA256:vunfVW4aKAx5wcrUF1GQ9VBN/wjU+GACCvq7bzjxQa8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes 
Warning: Permanently added '[www49.conoha.ne.jp]:8022,[150.95.219.89]:8022' (ECDSA) to the list of known hosts.
Attempting to create directory /home/c5853005/perl5
[c5853005@web0049 ~]$ 

Bashを改善する

しかしログインするとこんな感じである

ConoHa WINGのデフォルト環境

実に寂しい。 シェルの画面をはじめて見る人は「そんなもんか」と思うかもしれないが、sshを実行しているローカルプロンプト(私の手元のマシンの表示)と比べるとなんとも貧しいというか、まず色がない。

ConoHaにログインした際に使用されるシェルは “Bash” といって、Linuxにおいては標準的なシェルである。 Linuxer、あるいはUnixerの諸兄諸姉にとっては極めて馴染み深いものだ。

設定を見てみると、.bashrc

# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions

.bash_profile

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

/etc/bashrc

# /etc/bashrc

# System wide functions and aliases
# Environment stuff goes in /etc/profile

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

# are we an interactive shell?
if [ "$PS1" ]; then
  if [ -z "$PROMPT_COMMAND" ]; then
    case $TERM in
    xterm*|vte*)
      if [ -e /etc/sysconfig/bash-prompt-xterm ]; then
          PROMPT_COMMAND=/etc/sysconfig/bash-prompt-xterm
      elif [ "${VTE_VERSION:-0}" -ge 3405 ]; then
          PROMPT_COMMAND="__vte_prompt_command"
      else
          PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
      fi
      ;;
    screen*)
      if [ -e /etc/sysconfig/bash-prompt-screen ]; then
          PROMPT_COMMAND=/etc/sysconfig/bash-prompt-screen
      else
          PROMPT_COMMAND='printf "\033k%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
      fi
      ;;
    *)
      [ -e /etc/sysconfig/bash-prompt-default ] && PROMPT_COMMAND=/etc/sysconfig/bash-prompt-default
      ;;
    esac
  fi
  # Turn on parallel history
  shopt -s histappend
  history -a
  # Turn on checkwinsize
  shopt -s checkwinsize
  [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
  # You might want to have e.g. tty in prompt (e.g. more virtual machines)
  # and console windows
  # If you want to do so, just add e.g.
  # if [ "$PS1" ]; then
  #   PS1="[\u@\h:\l \W]\\$ "
  # fi
  # to your custom modification shell script in /etc/profile.d/ directory
fi

if ! shopt -q login_shell ; then # We're not a login shell
    # Need to redefine pathmunge, it get's undefined at the end of /etc/profile
    pathmunge () {
        case ":${PATH}:" in
            *:"$1":*)
                ;;
            *)
                if [ "$2" = "after" ] ; then
                    PATH=$PATH:$1
                else
                    PATH=$1:$PATH
                fi
        esac
    }

    # By default, we want umask to get set. This sets it for non-login shell.
    # Current threshold for system reserved uid/gids is 200
    # You could check uidgid reservation validity in
    # /usr/share/doc/setup-*/uidgid file
    if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
       umask 022
    else
       umask 022
    fi

    SHELL=/bin/bash
    # Only display echos from profile.d scripts if we are no login shell
    # and interactive - otherwise just process them to set envvars
    for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            if [ "$PS1" ]; then
                . "$i"
            else
                . "$i" >/dev/null
            fi
        fi
    done

    unset i
    unset -f pathmunge
fi
# vim:ts=4:sw=4

おまけ。

$ ls -l /etc/bash_completion.d/
total 56
-rw-r--r-- 1 root root 56178 Oct 31  2018 git

これはちょっと使いにくすぎる。せめてArch LinuxのBash環境を導入してあげよう。

Arch Linuxを使っているのなら話はだいぶ簡単。 次のコマンドはローカルから実行

% cat /etc/bash.bashrc ~/.bashrc | ssh wing-adv 'cat > .bashrc.local'

で、.bashrcで読むようにする。 WING上で

[c5853005@web0049 ~]$ echo '. ~/.bashrc.local' >> .bashrc

Arch Linuxじゃない人のために.bashrc.localの中身はこの通り

#
# /etc/bash.bashrc
#

# If not running interactively, don't do anything
[[ $- != *i* ]] && return

[[ $DISPLAY ]] && shopt -s checkwinsize

PS1='[\u@\h \W]\$ '

case ${TERM} in
  xterm*|rxvt*|Eterm|aterm|kterm|gnome*)
    PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND; }'printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'

    ;;
  screen*)
    PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND; }'printf "\033_%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
    ;;
esac

[ -r /usr/share/bash-completion/bash_completion   ] && . /usr/share/bash-completion/bash_completion
#
# ~/.bashrc
#

[[ $- != *i* ]] && return

colors() {
    local fgc bgc vals seq0

    printf "Color escapes are %s\n" '\e[${value};...;${value}m'
    printf "Values 30..37 are \e[33mforeground colors\e[m\n"
    printf "Values 40..47 are \e[43mbackground colors\e[m\n"
    printf "Value  1 gives a  \e[1mbold-faced look\e[m\n\n"

    # foreground colors
    for fgc in {30..37}; do
        # background colors
        for bgc in {40..47}; do
            fgc=${fgc#37} # white
            bgc=${bgc#40} # black

            vals="${fgc:+$fgc;}${bgc}"
            vals=${vals%%;}

            seq0="${vals:+\e[${vals}m}"
            printf "  %-9s" "${seq0:-(default)}"
            printf " ${seq0}TEXT\e[m"
            printf " \e[${vals:+${vals+$vals;}}1mBOLD\e[m"
        done
        echo; echo
    done
}

[ -r /usr/share/bash-completion/bash_completion ] && . /usr/share/bash-completion/bash_completion

# Change the window title of X terminals
case ${TERM} in
    xterm*|rxvt*|Eterm*|aterm|kterm|gnome*|interix|konsole*)
        PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/\~}\007"'
        ;;
    screen*)
        PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/\~}\033\\"'
        ;;
esac

use_color=true

# Set colorful PS1 only on colorful terminals.
# dircolors --print-database uses its own built-in database
# instead of using /etc/DIR_COLORS.  Try to use the external file
# first to take advantage of user additions.  Use internal bash
# globbing instead of external grep binary.
safe_term=${TERM//[^[:alnum:]]/?}   # sanitize TERM
match_lhs=""
[[ -f ~/.dir_colors   ]] && match_lhs="${match_lhs}$(<~/.dir_colors)"
[[ -f /etc/DIR_COLORS ]] && match_lhs="${match_lhs}$(</etc/DIR_COLORS)"
[[ -z ${match_lhs}    ]] \
    && type -P dircolors >/dev/null \
    && match_lhs=$(dircolors --print-database)
[[ $'\n'${match_lhs} == *$'\n'"TERM "${safe_term}* ]] && use_color=true

if ${use_color} ; then
    # Enable colors for ls, etc.  Prefer ~/.dir_colors #64489
    if type -P dircolors >/dev/null ; then
        if [[ -f ~/.dir_colors ]] ; then
            eval $(dircolors -b ~/.dir_colors)
        elif [[ -f /etc/DIR_COLORS ]] ; then
            eval $(dircolors -b /etc/DIR_COLORS)
        fi
    fi

    if [[ ${EUID} == 0 ]] ; then
        PS1='\[\033[01;31m\][\h\[\033[01;36m\] \W\[\033[01;31m\]]\$\[\033[00m\] '
    else
        PS1='\[\033[01;32m\][\u@\h\[\033[01;37m\] \W\[\033[01;32m\]]\$\[\033[00m\] '
    fi

    alias ls='ls --color=auto'
    alias grep='grep --colour=auto'
    alias egrep='egrep --colour=auto'
    alias fgrep='fgrep --colour=auto'
else
    if [[ ${EUID} == 0 ]] ; then
        # show root@ when we don't have colors
        PS1='\u@\h \W \$ '
    else
        PS1='\u@\h \w \$ '
    fi
fi

unset use_color safe_term match_lhs sh

alias cp="cp -i"                          # confirm before overwriting something
alias df='df -h'                          # human-readable sizes
alias free='free -m'                      # show sizes in MB
alias np='nano -w PKGBUILD'
alias more=less

xhost +local:root > /dev/null 2>&1

complete -cf sudo

# Bash won't get SIGWINCH if another process is in the foreground.
# Enable checkwinsize so that bash will check the terminal size when
# it regains control.  #65623
# http://cnswww.cns.cwru.edu/~chet/bash/FAQ (E11)
shopt -s checkwinsize

shopt -s expand_aliases

# export QT_SELECT=4

# Enable history appending instead of overwriting.  #139609
shopt -s histappend

#
# # ex - archive extractor
# # usage: ex <file>
ex ()
{
  if [ -f $1 ] ; then
    case $1 in
      *.tar.bz2)   tar xjf $1   ;;
      *.tar.gz)    tar xzf $1   ;;
      *.bz2)       bunzip2 $1   ;;
      *.rar)       unrar x $1     ;;
      *.gz)        gunzip $1    ;;
      *.tar)       tar xf $1    ;;
      *.tbz2)      tar xjf $1   ;;
      *.tgz)       tar xzf $1   ;;
      *.zip)       unzip $1     ;;
      *.Z)         uncompress $1;;
      *.7z)        7z x $1      ;;
      *)           echo "'$1' cannot be extracted via ex()" ;;
    esac
  else
    echo "'$1' is not a valid file"
  fi
}

# better yaourt colors
export YAOURT_COLORS="nb=1:pkg=1:ver=1;32:lver=1;45:installed=1;42:grp=1;34:od=1;41;5:votes=1;44:dsc=0:other=1;35"
改善されたBash

だが、言語の指定がないので、追加する。

export LANG=ja_JP.UTF-8
export LC_ALL=ja_JP.UTF-8

Zshを使う

grml-zsh-config

だが、これではまだ十分に使いやすい環境とは言えない。 やはり強力で便利なシェルであるZshが使いたい。

ZshはBashとは比べ物にならないほど強力なシェルである。 Zshがどのように強力であるかを説明するのは長くなりすぎて難しいが、とりあえずTABを連打すればなんとかなるあたりが超強力である。個人的には多段補完とかコンテキスチュアル補完とかメニュー補完とかどこでも使えるmodifierとか拡張グロブとかグロブクオリファイアとかヒストリ展開とか多彩過ぎるヒストリのたどり方とかがやばいと思っている。

一応、ConoHa WINGにはZsh自体は載っている。 これはとても素晴らしいことだ。

だが、.zshrc

#
# .zshrc is sourced in interactive shells.
# It should contain commands to set up aliases,
# functions, options, key bindings, etc.
#

autoload -U compinit
compinit

#allow tab completion in the middle of a word
setopt COMPLETE_IN_WORD

## keep background processes at full speed
#setopt NOBGNICE
## restart running processes on exit
#setopt HUP

## history
#setopt APPEND_HISTORY
## for sharing history between zsh processes
#setopt INC_APPEND_HISTORY
#setopt SHARE_HISTORY

## never ever beep ever
#setopt NO_BEEP

## automatically decide when to page a list of completions
#LISTMAX=0

## disable mail checking
#MAILCHECK=0

# autoload -U colors
#colors

/etc/zshrc

#
# /etc/zshrc is sourced in interactive shells.  It
# should contain commands to set up aliases, functions,
# options, key bindings, etc.
#

## shell functions
#setenv() { export $1=$2 }  # csh compatibility

# Set prompts
PROMPT='[%n@%m]%~%# '    # default prompt
#RPROMPT=' %~'     # prompt for right side of screen

# bindkey -v             # vi key bindings
# bindkey -e             # emacs key bindings
bindkey ' ' magic-space  # also do history expansion on space

# Provide pathmunge for /etc/profile.d scripts
pathmunge()
{
    if ! echo $PATH | /bin/grep -qE "(^|:)$1($|:)" ; then
        if [ "$2" = "after" ] ; then
            PATH=$PATH:$1
        else
            PATH=$1:$PATH
        fi
    fi
}

_src_etc_profile_d()
{
    #  Make the *.sh things happier, and have possible ~/.zshenv options like
    # NOMATCH ignored.
    emulate -L ksh


    # from bashrc, with zsh fixes
    if [[ ! -o login ]]; then # We're not a login shell
        for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            . $i
        fi
        done
        unset i
    fi
}
_src_etc_profile_d

unset -f pathmunge _src_etc_profile_d

/etc/zprofile

#
# /etc/zprofile and ~/.zprofile are run for login shells
#

PATH="$PATH:$HOME/bin"
export PATH

_src_etc_profile()
{
    #  Make /etc/profile happier, and have possible ~/.zshenv options like
    # NOMATCH ignored.
    #
    emulate -L ksh

    # source profile
    if [ -f /etc/profile ]; then
        source /etc/profile
    fi
}
_src_etc_profile

unset -f _src_etc_profile

ちょっと使いにくすぎる。 それに、どのみちWING上ではchshvipwなど、デフォルトシェルを変更する手段が効かないので1、だったらZshを手動で呼び出して使いやすいように、思いっきりカスタマイズしてしまおう。

まずは優れたZsh設定であるgrml-zsh-configの導入だ。 ConoHa WINGにはwgetがあり、なおかつ.zshrcは上書きしても問題ないようなものであるため、いきなり導入してしまう。

$ wget -O .zshrc https://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
--2019-10-30 16:13:12--  https://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
Resolving git.grml.org (git.grml.org)... 83.246.69.172, 2a02:790:1:12::4
Connecting to git.grml.org (git.grml.org)|83.246.69.172|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://git.grml.org/?p=grml-etc-core.git;a=blob_plain;f=etc/zsh/zshrc;hb=HEAD [following]
--2019-10-30 16:13:14--  https://git.grml.org/?p=grml-etc-core.git;a=blob_plain;f=etc/zsh/zshrc;hb=HEAD
Reusing existing connection to git.grml.org:443.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/plain]
Saving to: '.zshrc'

    [    <=>                                ] 126,085      148KB/s   in 0.8s   

2019-10-30 16:13:15 (148 KB/s) - '.zshrc' saved [126085]

ユーザー設定も。

$ wget -O .zshrc.local  https://git.grml.org/f/grml-etc-core/etc/skel/.zshrc
--2019-10-30 16:14:21--  https://git.grml.org/f/grml-etc-core/etc/skel/.zshrc
Resolving git.grml.org (git.grml.org)... 83.246.69.172, 2a02:790:1:12::4
Connecting to git.grml.org (git.grml.org)|83.246.69.172|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://git.grml.org/?p=grml-etc-core.git;a=blob_plain;f=etc/skel/.zshrc;hb=HEAD [following]
--2019-10-30 16:14:22--  https://git.grml.org/?p=grml-etc-core.git;a=blob_plain;f=etc/skel/.zshrc;hb=HEAD
Reusing existing connection to git.grml.org:443.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/plain]
Saving to: '.zshrc.local'

    [ <=>                                   ] 10,404      --.-K/s   in 0.001s  

2019-10-30 16:14:23 (13.4 MB/s) - '.zshrc.local' saved [10404]

これだけでも割と満足できる結果が得られるだろう。だが、これはまだまだ序の口だ。

grml式 Zsh

powerlevel9k

次はPoewrlevel9kを導入しよう。

Powerlevel9kは、Powerlineのような華やかで多機能なプロンプトを提供してくれるテーマエンジンだ。 Powerlineと違ってZsh専用であり、Powerlineと比べると要件が低くやや軽い。

まずは導入先を用意する。

% mkdir ~/.local
% mkdir ~/.local/zsh

幸いにもConoHa Wingにはgitがある。 というわけで、Gitを使って導入だ。

% git clone https://github.com/bhilburn/powerlevel9k.git ~/.local/zsh/powerlevel9k

.zshrc.localに書き足そう。 prompt offはなくても動くかもしれない。ちなみに、promptというコマンドはgrml-zsh-configによって提供されている関数。

% echo "prompt off" >> ~/.zshrc.local
% echo "source ~/.local/zsh/powerlevel9k/powerlevel9k.zsh-theme" >> ~/.zshrc.local
Zsh Powerlevel9k

さらに私は好みでこんな感じで~/.zshrc.localに書き足している。 Vimだとコメントの扱いのせいでコピペするとごっそりコメントになってしまって面倒なので、ローカルのエディタで書いて、SSHとcatを組み合わせるほうが楽。 ちなみに、ユーザー部分の色はConoHaの色をイメージしている(256色なので完全には再現できない)。

##### USE EXTENDED_GLOB #####
setopt EXTENDED_GLOB
setopt AUTO_CONTINUE

##### SET LANGUAGE #####

export LANG=ja_JP.UTF-8
export LC_ALL=ja_JP.UTF-8

###################
##### VI Mode #####
###################

setopt vi
export KEYTIMEOUT=1

########################
##### POWERLEVEL9k #####
########################

POWERLEVEL9K_MODE=awesome-fontconfig
POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(vi_mode user ssh host dir newline)
POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status background_jobs command_execution_time vcs ram)
zle-keymap-select() {
  zle reset-prompt
  zle -R
}
zle -N zle-keymap-select
POWERLEVEL9K_SHORTEN_STRATEGY=truncate_from_right
POWERLEVEL9K_SHORTEN_DIR_LENGTH=5
POWERLEVEL9K_SHORTEN_DELIMITER=".."

# Colorize
POWERLEVEL9K_OS_ICON_BACKGROUND="white"
POWERLEVEL9K_OS_ICON_FOREGROUND="blue"
POWERLEVEL9K_DIR_HOME_FOREGROUND="white"
POWERLEVEL9K_DIR_HOME_SUBFOLDER_FOREGROUND="white"
POWERLEVEL9K_DIR_DEFAULT_FOREGROUND="white"
POWERLEVEL9K_USER_DEFAULT_BACKGROUND=081
POWERLEVEL9K_USER_DEFAULT_FOREGROUND=015
POWERLEVEL9K_USER_ROOT_BACKGROUND=red
POWERLEVEL9K_USER_ROOT_FOREGROUND=black
POWERLEVEL9K_USER_SUDO_BACKGROUND=051
POWERLEVEL9K_USER_SUDO_FOREGROUND=052
POWERLEVEL9K_USER_ICON="\uF415"
POWERLEVEL9K_ROOT_ICON="#"
POWERLEVEL9K_SUDO_ICON="\uF09C"
POWERLEVEL9K_VI_MODE_NORMAL_FOREGROUND=051
POWERLEVEL9K_VI_MODE_INSERT_FOREGROUND=168
POWERLEVEL9K_VCS_CLEAN_BACKGROUND=147
POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND=174
POWERLEVEL9K_VCS_MODIFIED_BACKGROUND=139
POWERLEVEL9K_VCS_CLEAN_FOREGROUND=black
POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND=black
POWERLEVEL9K_VCS_MODIFIED_FOREGROUND=black

viキーバインドにしているので注意してほしい。 Vimmerではない多くのユーザーはviモードにはしないほうが良いだろう。

Powerlevel9kを設定

なお、Powerlevel9kを表示するためにはローカル側(端末側)にAwesomeフォントが必要になる。 WidnowsのMSYS環境ではCicaフォントを使うのが楽。Cicaを導入してMinTTYのフォントをCicaにする。Linux環境ではCicaだけだとちょっと足りないので、Awesome(Powerline)フォントがどのみち必要。

また、WindowsユーザーはMSYS(Git for Windowsのもの含む)ならば問題ないが、標準のCMD.EXEやPowershellでは表示がおかしなことになってしまう。 まだプレビュー版だが、Windows StoreからWindows Terminalを入手するという方法もある。これは将来的にWindowsに標準搭載される予定のものだ。こちらはフォント設定が可能で、Powerlevel9kを適切に表示することができる。

さらなるプラグイン

さらにFish2のようにZshでシンタックスハイライトしてくれるzsh-syntax-highlightingを入れてみよう。

これは、コマンドや文字列、クォートされた文字列、展開される値、ファイルなどをハイライトしてくれる。コマンドやファイルが存在するかどうかもわかるので便利だ。 この機能はFishに備わっているものだが、Zshでもこのプラグインを使うことで実現できる。

% git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ~/.local/zsh/zsh-syntax-highlighting
% echo "source ~/.local/zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ~/.zshrc.local
Zsh Syntax Highlighting

PureBuilder Simplyで作って、Gitでデプロイ

PureBuilder Simplyとは

PureBuilder Simplyは私が開発する、静的ウェブドキュメントへの事前生成ジェネレータである。同様のソフトウェアとしてはJykillやPelicanがある。だが、それらよりも扱いやすく簡単であり、静的なHTMLファイルやCSS、CGIアプリケーションなどをマージしたプロジェクトを簡単に作ることができる、まさにConoHa WINGにぴったりのソフトウェアである。

PureBuilder Simplyについての詳細は既に記事として公開されている。 そちらも参考にして欲しい。

このChienomiを含め、私が公開しているサイトはすべてPureBuilder Simplyを使用しており3、うち4サイトはConoHa WING上で動作している (それ以外はConoHa VPS上で動作している)。

Gitでデプロイする

基本的にはその記事で詳しく書いてあるので、そちらに従って作って欲しい。 そう、まるでPureBuilder Simplyで作るかのような流れで書き出していながら、その部分は別記事に丸投げである。

ここではまずローカル側のドキュメント環境は出来上がった(公開可能なビルドまで終わっている)として先に進める。 ちなみに、PureBuilder Simplyの動作としてはそのままサーバーにコピーすれば使えるようなHTMLファイルを組み上げることだから、別にPureBuilder Simplyを使っていなくても、HTMLファイルとか画像ファイルとか、とにかくサーバーに上げる前の状態のファイルを揃えばこれ以降の内容はそのまま適用できる。

この状態では、そのままウェブサーバー上で公開することができるドキュメントが出来上がっている状態なので、単純にコピーすれば良いのだが、コピーは時間がかかり、ドキュメントが増えると手間も増えて煩わしくなる。しかもなぜかConoHa WINGにはrsyncがない。今すぐrsyncを導入してほしい

ないものは仕方ないので、Gitを使ってデプロイするようにしよう。 まずはWING上でリポジトリを作る

% mkdir ~/.local/websites
% git init --bare ~/.local/websites/example.git

ConoHa WING上には~/.public_html/<ドメイン名>というページ公開用の領域があり、エラーページが用意されているが、とりあえずこれは消して、リポジトリにする。

% cd ~/.public_html
% rm -rf example.conohawing.com
% git clone ~/.local/websites/example.git example.conohawing.com

このままでは訪問者が.gitディレクトリ内にアクセスできてしまう。 ConoHa WINGはサーバーはNginxであるものの、.htaccessファイルを利用することができるようになっている。 これは、コントロールパネル上から編集することが可能だ。

ConoHaコントロールパネルで.htaccessを編集

ここに

<Files ".*">
  deny from all
</Files>

と書いておけばドットディレクトリに対するアクセスを拒否することができる。 (スクリーンキャプチャではFilesMatchを使っているけれど、別に必要なかった…)

あるいは、.gitディレクトリ内に.htaccessファイルを作り

deny from all

と書いても構わない。

つづいてローカル側でpushできるようにする。 ここでは~/Documents/websites/exampleが全体のドキュメントルートであり、 ~/Documents/websites/example/SourceがPureBuilder Simplyドキュメントルート、~/Documents/websites/example/Buildがビルド先だとしよう。

% cd ~/Documents/websites/example/Build
% git init
% git add -A
% git commit -m "Initial commit."

.git/configにこんな感じで書いておこう。

[remote "wing"]
        url = ssh://wing-adv/home/c5853005/.local/websites/example.git

そしたらpush

% git push wing master

今度はリモートで更新

% cd ~/public_html/example.conohawing.com
% git pull

自動デプロイするようにしてもいいけれども、PureBuilder Simplyの場合git pullするタイミングでドキュメントが更新されるため、自動デプロイするようにしてしまうと記事の予約投稿ができなくなることからあまりお勧めはしない。 なお、ConoHa WINGではcronとatが利用可能である。

~/bin/update-websiteみたいな感じでBashスクリプトにしておくと楽。

cd ~/public_html/example.conohawing.com
git pull

次回以降はビルドとテストが終わったら、ビルドディレクトリで

% git add -A
% git commit -m "Update website."
% git push wing master

みたいな感じにすればサーバーに送るところまでできる。 実行可能なシェルスクリプトにしていればさらに

% ssh wing-adv bin/update-website

とかやれば一気。この一連の処理を手元のシェルスクリプトやシェル関数にしておいてもいい。 Buildディレクトリ上で行うことを考えれば、関数よりはシェルスクリプトのほうがいいだろう。

#!/bin/bash
build_dir="$HOME/Documents/website/example/Build"
cd $build_dir
if git add -A && git commit -m "Update website" && git push wing master && ssh wing-adv bin/update-website
then
  echo "Deploy succeeded."
else
  echo "Deploy failed."
  exit 1
fi

ここでひとつ注意点がある。Zshの場合は.zshenvという非対話的環境で読み込むべき設定ファイルというのがあるのだが、Bashにはそうしたファイルがない。 ConoHa WINGはログインシェルを変更する方法がなく、最初から$PATHに入っているディレクトリには書き込めない。

そのため、ログイン後は実行できる~/bin以下のスクリプトがSSHコマンドとしては実行できない。

ちなみに、~/.pam_environmentというファイルを使ってオーバーライドすることもできるのだが、ConoHa WINGではこれが使用されない。さらに、 ConoHa WINGでは(systemd-timerを含めて)Systemd関連コマンドが一切使えなくなっているので、Systemdを使う方法も効かない

ではこれを実行するにはどうすればよいか。例えば

ssh wing-adv ~/bin/update-website

としてしまうと、~/を解決するのはローカル環境なのでリモートとは違う値になってしまう。

そこでポイントはログイン後のディレクトリだ。

ssh wing-adv pwd

のようにすればわかるが、特別な条件がつかなければログイン直後はホームディレクトリになる。 そのため、~/にいる状態が起点になることから~/bin/update-websiteを表すのにbin/update-websiteという表現が可能である。

サーバー側アップデートをシェルスクリプトにするのは、何も指先を節約するためだけではない。 デプロイ時に発動すべきhookを書くのにも適している。 例えばChienomiの場合は、PureBuilder Simplyと連携した検索機能を使用しており、このインデックスの更新をデプロイ時に行っている。

CGI

CGIとは

CGIは環境変数と標準出力を使ったwebアプリケーションのインターフェイス。 古典的なもので、最近はあまり使われていない(とかいいながら、WordPressが結構な確率でPHP-cgiだったりするけど)。

PHPだとCGIだろうがCGIでなかろうが「CGIとは違う」みたいな謎の風潮があったせいで、CGIと呼ばないから、それ以前のPerlが普通だった頃にCGIが使われていた印象になっていて、CGI=Perlと思っている人も結構いる。でも、実際は前述の通り。

「イマドキCGI(笑)」みたいに言う人もいるかもしれないけれども、小さいアプリケーションを動かす上ではインターフェイス周りの面倒を見なくていいCGIは非常に楽で建設的。

Shebang

ConoHa WINGではperlは/usr/bin/perlでPHPもusr/bin/phpなんだけど、Rubyは/usr/local/bin/rubyで、Pythonも/usr/local/bin/python

なかなかイマドキの環境でRubyやPythonが/usr/local/bin以下に入っていることってないと思う。 そのせいでShebang行が開発環境とWINGで異なってしまうかもしれない。

Shebangのメカニズムについては、ここここで解説しているけれども、単純に

#!ruby

って書いとけばOK。Pythonの場合も

#!python

で良い。

…で、済まないのがConoHa WINGのCGI。 何が起きるかは「狂えるCGI」を参照

この条件に合わせるには非常に筋の悪い/usr/bin/env rubyを使うのが一番無難という… (なお、ConoHa WINGは/bin -> /usr/bin というシンボリックリンクになっている)

ちなみに、Shebang及びenv(1)についてある程度知識がある人のために話しておくと、env(1)の本来の使い方である環境変数のセットをShebangで行うことはできない。なぜならば、Shebangにおいて取れる引数はひとつだけだからだ。

第一歩

とりあえずBashでやってみる。 必要なのは

  • ドキュメントルート以下のどこかに置くこと(ConoHa WINGの場合ディレクトリ制限などは特にない)
  • 拡張子を.cgiにすること
  • Shebang行をちゃんと書くこと
  • 実行権限を与えること(chmod 755)

というわけで、こんな感じ。

#!/usr/bin/bash

cat <<EOF
Status: 200 OK
Content-Type: text/plain; charset=UTF-8

こんにちは世界
EOF

これで動作する。 Statusというヘッダーフィールドは見慣れないかもしれないが、これはCGI 1.1で策定されたCGIのResponse Fieldsである

CGIのヘッダーとしてはHTTPヘッダーを含めることもできる。CGIから生成する可能性のあるヘッダーとしては、キャッシュ関連、クッキー関連、認証関連などだろうか。 手書きでContent-Lengthヘッダーを送るのはトラブルの元なのでオススメしない。

Ruby CGI

RubyにはCGIという、脳みそがとろけそうなくらい便利なライブラリ(1000%くらい誇張)がある。 これを使えば誰でも簡単にCGIスクリプトが書けるようになる。

基本的にはCGI#[]でフォームフィールドの値を得ることができ、あるいはCGI#paramsでHashに変換することができる。 また、CGIに関連する環境変数はdowncase化したメソッドとして定義されており、$HTTP_*という環境変数はHTTP_を除いてdowncase化したメソッドになっている。

もっともその辺りの話は公式ドキュメントが十分にわかりやすい

出力周りの話は例としてはあまりちゃんと書いていないけれど、CGI#outの引数として色々とヘッダーに書くことを渡せるようになっている。 これは、CGI#headerで同様に呼び出すとヘッダーとして出力する文字列が得られる。 出力するcontent bodyはブロックの戻り値の文字列。

#!/usr/bin/env ruby
require 'cgi'

cgi = CGI.new
name = cgi["name"]

cgi.out("status" => "OK",
        "type" => "text/plain",
        "charset" => "UTF-8",
        "language" => "ja") do
  "こんにちは、世界!"
end

CGI出力にはeRubyが便利。 erbコマンドはないけれど、ERBライブラリ自体はあるので、普通に使える。ただし、erbコマンドがない(erubyコマンドもない)ため、CGIフィルタ機能として使うことはできない。

ERBライブラリの使い方が従来のものは明確に廃止予定になっているので要注意。 ConoHa WING上のRubyは

ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]

だった。(ちょっと古いな…)

#!/usr/bin/env ruby
require 'cgi'

ERB_TEMPLATE = <<EOF
<html>
  <title><head><%= @title %></head></title>
  <body>
    <ul>
% @menu.each do |i|
      <li><%= i %></li>
% end
    </ul>
  </body>
</html>
EOF

cgi = CGI.new()
erb = ERB.new(ERB_TEMPLATE, "%<>")
@title = sprintf("Hello, %s", cgi["name"])
@menu = %w(apple grape orange)

cgi.out("status" => 200, "type" => "text/html", "charset" => "UTF-8") do
  erb.result(binding)
end

Ruby Rack CGI

なに? CGIはやだ? Rackがいい?

世の中Rackなんて某アプリケーションフレームワーク(マイナス検索で除外されたくないので具体名は書かない)で使ってるだけでちゃんと自分で使う人間がいなくてまともにドキュメントもないのに、よくぞ言ったえらいぞ。

というか、そもそもRackは中間層にあるインターフェイスであり、それよりもサーバー側のインターフェイスの差異を吸収することが目的だから、もちろんCGIでもRackできる

#!/usr/bin/env ruby

require 'rack'

class HelloWorld
  def call(env)
    param_info = env.inspect
    [200, {"Content-Type" => "text/plain"}, ["Hello, wolrd!", "", param_info].join("\n")]
  end
end

Rack::Handler::CGI.run HelloWorld.new

ただ、この場合インターフェイスをcgi.rbからrackに替えているだけではある。 でも、Rackで書いておけばCGIじゃなくなってもそれ自体はそのまま使えるというメリットがあって、意外と悪くない。

とはいえ、CGIで動かすレベルの規模でRackのほうが嬉しいケースってあまりなくて、むしろcgi.rbのほうが色々話が早かったり… Rackを使う理由が移植性以外にあまり思い浮かばない。

rhtml (eRuby) したい

PHPのようにロジックをテンプレート中に埋め込めるeRuby。 PHPと比べて非常に柔軟で強力なので、静的HTMLの中に動的要素を埋め込むのに極めて適している。

(もっとも、PureBuilder Simplyみたいな動的構成ツールを使っていると全く使わないけど)

ConoHa WINGのApacheはmod_actionがあるので、.htaccess

AddType application/x-httpd-eruby .rhtml
Action application/x-httpd-eruby /cgi-bin/eruby.cgi

みたいに書いておく。Actionのパスはドキュメントルートからのパス。

これだけでいけるみたいなことが書いてあったりするけど、そうはいかない。単純にやるとリクエストされたファイルがわからない。 方法は色々あるけれど、$PATH_TRANSLATEDを使うのが最も手っ取り早い。

require 'erb'

if File.exist?(ENV["PATH_TRANSLATED"])
  puts "Status: 200 OK"
  puts "Content-Type: text/html"
  puts
  ERB.new(File.read(ENV["PATH_TRANSLATED"]), "%<>").run
else
  puts "Status: 404 Not Found"
  puts "Content-Type: text/plain"
  puts
  puts "404 NOT FOUND"
end

より高速なErubiを使いたい場合、gem install --user erubiしてからこんな感じ。

require '/home/cXXXXXXXX/.gem/ruby/2.5.0/gems/erubi-1.9.0/lib/erubi.rb'

if File.exist?(ENV["PATH_TRANSLATED"])
  puts "Status: 200 OK"
  puts "Content-Type: text/html"
  puts
  puts eval(Erubi::Engine.new(File.read(ENV["PATH_TRANSLATED"])).src)
else
  puts "Status: 404 Not Found"
  puts "Content-Type: text/plain"
  puts
  puts "404 NOT FOUND"
end

RubyGems

Rubyの場合、パッケージはgemというコマンドを用いて追加、アップデートなどを行うことができる。 これによってより多彩なライブラリを使用したプログラミングができるのだが、前節の例にてファイルを具体的に指定してロードしていることからもわかるとおり、ConoHa WINGでは素直にgemが利用できない。

これは、CGIスクリプトがApacheのSuEXEC環境で呼ばれており、ユーザーに関してはそのユーザーになっているのだが、$HOMEが設定されていないためGemのパスがおかしなことになってしまい、ユーザーローカルなライブラリがロードできない。

以前なら環境変数$GEM_HOMEを設定してから(もしくは$HOMEを設定してから)require 'rubygems'すればよかったのだが、現在はそもそもrubygemsがロードされた状態でRubyが起動するためこの方法も効かない。

解決方法その1。 CGIをラッパースクリプトにする。

#!/usr/bin/zsh

export HOME="/home/cXXXXXXXX"

exec ruby $HOME/cgi/foo.rb

これでfoo.rbを本体にすればOK。 話はシンプルだが、CGIスクリプトひとつごとにラッパースクリプトを書かなければならない。

その2。汎用のラッパースクリプトを書く。 まずはラッパースクリプト側。

export HOME="home/cXXXXXXXX"

exec ruby "$1"

CGI側はこんな感じになる。

#!/usr/bin/zsh /home/cXXXXXXXX/.local/bin/cgiwrap.zsh
#!ruby

# ここから本体コード

これは#!rubyと書いておかないと「Rubyスクリプトがないよ」と言われてしまう。ruby -xする必要はないらしい。

ラッパースクリプトはひとつでいいが、Shebangがなかなか汚いのと、 そのせいでエディタが適切に認識しなかったりする(少なくともVimはちゃんと認識してくれる)のでだいぶお勧めしにくい。

あるいは出だしを

#!/usr/bin/zsh /home/cXXXXXXXX/.local/bin/cgiwrap.zsh
# -*- mode: ruby -*-
# vim: ft=ruby :
#!ruby

# ここから本体コード

とやればだいぶ緩和されるかもしれない。

ConoHa WINGではシンボリックリンクは無効なので、シンボリックリンクを使って共通化する方法は使えない。 ハードリンクを使うことはできるが、この場合Gitでの管理は困難になるだろう。やるとしたらGitの管理外で行うことになる。

CGIアプリケーションに必要・便利なツール

curl

HTTP通信において非常に便利なツールとなるcurl(1)はインストールされている。 なので、hookとしてDiscrodやSlackなどにメッセージを投げるのは比較的容易。 また、WINGの素の環境からでは17個もパッケージをインストールする必要があるRubyGemsのDiscordrbも利用可能。

あんまりDiscordrbでWebhookする情報がないので(いや、GitHubにはちゃんと書いてあるけど)、ここで用例。

require 'discordrb/webhooks'

client = Discordrb::Webhooks::Client.new("WebhookのURL")
client.execute do |builder|
  builder.content = "こんにちはこんにちは"
  builder.username = "WING bot"
end

curlでも同じ感じでいける。(エンコーディングなしの力技)

curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"username":"WING bot","content":"こんにちはこんにちは"}' 'WebhookのURL'

外部にリクエストを出せるため、他のサーバーと連携できてだいぶ幅が広がる。

mailx

USB Mailからの流れを持つMailx。 RHEL7ではhairloom-mailxが採用されており、Arch LinuxではS-nailが採用されている。

S-nailはエンコーディングなどをうまく処理してくれるため、S-nailだといいなぁ、と思ったのだけど、なんと mailxがない!!!!

もう最悪。すごい面倒。嫌になる。

というか、

lrwxrwxrwx 1 root root 15 Jul 29 12:21 /bin/Mail -> ../../bin/mailx

これミスってんじゃない??

いくらなんでもsendmailを直接叩くというのはダサすぎるので、RubyならMailライブラリを使おう。 まずはgem install --user mailでライブラリをインストール。

% gem install --user mail
Fetching: mini_mime-1.0.2.gem (100%)
WARNING:  You don't have /home/c5096736/.gem/ruby/2.5.0/bin in your PATH,
      gem executables will not run.
Successfully installed mini_mime-1.0.2
Fetching: mail-2.7.1.gem (100%)
Successfully installed mail-2.7.1
Parsing documentation for mini_mime-1.0.2
Installing ri documentation for mini_mime-1.0.2
Parsing documentation for mail-2.7.1
Installing ri documentation for mail-2.7.1
Done installing documentation for mini_mime, mail after 14 seconds
2 gems installed
gem install --user mail  14.34s user 1.44s system 97% cpu 16.267 total

あとはこんな感じ。

#!/usr/bin/env ruby

require 'mail'

mail = Mail.new do
  from 'from@example.com'
  to 'to@example.net'
  subject "メールの送信テスト"
  body "日本語のメールです"
end

mail.delivery_method 

mail.deliver

なんとか許容範囲に収まっているだろうか。RubyGemsすら使えなかったら思わずWING―ツバサ―を窓から投げ捨てるところであった。

ImageMagick

ImageMagickはConoHa WINGに搭載されている。Rubyでcairoライブラリが使えないのでこれがないとグラフィックス操作がとても大変になってしまうから、あって本当によかった。

また、GraphicMagick(コマンド名gm)もある。

なお、Cairo自体は存在し、pango-viewを使ってテキストを画像化することもできる。

pango-view -q --text="Hello, World" -o out.png

FontConfig

FontConfig関連のプログラムは普通に一通り入っており、利用可能。 フォント自体は

% fc-list
/usr/share/fonts/dejavu/DejaVuSerif-Bold.ttf: DejaVu Serif:style=Bold
/usr/share/fonts/default/Type1/c059016l.pfb: Century Schoolbook L:style=Bold
/usr/share/fonts/dejavu/DejaVuSerif-Italic.ttf: DejaVu Serif:style=Italic
/usr/share/fonts/default/Type1/c059033l.pfb: Century Schoolbook L:style=Italic
/usr/share/fonts/default/Type1/p052024l.pfb: URW Palladio L:style=Bold Italic
/usr/share/fonts/default/Type1/d050000l.pfb: Dingbats:style=Regular
/usr/share/fonts/default/Type1/s050000l.pfb: Standard Symbols L:style=Regular
/usr/share/fonts/liberation/LiberationMono-Bold.ttf: Liberation Mono:style=Bold
/usr/share/fonts/default/Type1/n021003l.pfb: Nimbus Roman No9 L:style=Regular
/usr/share/fonts/default/Type1/a010013l.pfb: URW Gothic L:style=Book
/usr/share/fonts/default/Type1/n019003l.pfb: Nimbus Sans L:style=Regular
/usr/share/fonts/dejavu/DejaVuSansMono-BoldOblique.ttf: DejaVu Sans Mono:style=Bold Oblique
/usr/share/fonts/dejavu/DejaVuSansCondensed-Oblique.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Oblique,Oblique
/usr/share/fonts/dejavu/DejaVuSansCondensed-Bold.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Bold,Bold
/usr/share/fonts/dejavu/DejaVuSansMono.ttf: DejaVu Sans Mono:style=Book
/usr/share/fonts/default/Type1/a010033l.pfb: URW Gothic L:style=Book Oblique
/usr/share/fonts/default/Type1/a010015l.pfb: URW Gothic L:style=Demi
/usr/share/fonts/default/Type1/n022003l.pfb: Nimbus Mono L:style=Regular
/usr/share/fonts/default/Type1/n022024l.pfb: Nimbus Mono L:style=Bold Oblique
/usr/share/fonts/dejavu/DejaVuSansMono-Bold.ttf: DejaVu Sans Mono:style=Bold
/usr/share/fonts/default/ghostscript/putbi.pfa: Utopia:style=Bold Italic
/usr/share/fonts/default/Type1/b018012l.pfb: URW Bookman L:style=Light
/usr/share/fonts/liberation/LiberationMono-Italic.ttf: Liberation Mono:style=Italic
/usr/share/fonts/default/ghostscript/putri.pfa: Utopia:style=Italic
/usr/share/fonts/dejavu/DejaVuSans.ttf: DejaVu Sans:style=Book
/usr/share/fonts/default/Type1/n021024l.pfb: Nimbus Roman No9 L:style=Medium Italic
/usr/share/fonts/default/Type1/a010035l.pfb: URW Gothic L:style=Demi Oblique
/usr/share/fonts/default/Type1/p052023l.pfb: URW Palladio L:style=Italic
/usr/share/fonts/default/Type1/c059013l.pfb: Century Schoolbook L:style=Roman
/usr/share/fonts/default/Type1/n021004l.pfb: Nimbus Roman No9 L:style=Medium
/usr/share/fonts/default/Type1/b018035l.pfb: URW Bookman L:style=Demi Bold Italic
/usr/share/fonts/default/Type1/n022023l.pfb: Nimbus Mono L:style=Regular Oblique
/usr/share/fonts/dejavu/DejaVuSerifCondensed-BoldItalic.ttf: DejaVu Serif,DejaVu Serif Condensed:style=Condensed Bold Italic,Bold Italic
/usr/share/fonts/default/Type1/p052004l.pfb: URW Palladio L:style=Bold
/usr/share/fonts/dejavu/DejaVuSerifCondensed-Bold.ttf: DejaVu Serif,DejaVu Serif Condensed:style=Condensed Bold,Bold
/usr/share/fonts/default/Type1/n022004l.pfb: Nimbus Mono L:style=Bold
/usr/share/fonts/default/Type1/b018032l.pfb: URW Bookman L:style=Light Italic
/usr/share/fonts/dejavu/DejaVuSerif.ttf: DejaVu Serif:style=Book
/usr/share/fonts/dejavu/DejaVuSansMono-Oblique.ttf: DejaVu Sans Mono:style=Oblique
/usr/share/fonts/default/Type1/n019023l.pfb: Nimbus Sans L:style=Regular Italic
/usr/share/fonts/dejavu/DejaVuSans-Bold.ttf: DejaVu Sans:style=Bold
/usr/share/fonts/default/Type1/b018015l.pfb: URW Bookman L:style=Demi Bold
/usr/share/fonts/default/ghostscript/putb.pfa: Utopia:style=Bold
/usr/share/fonts/dejavu/DejaVuSerifCondensed.ttf: DejaVu Serif,DejaVu Serif Condensed:style=Condensed,Book
/usr/share/fonts/liberation/LiberationMono-Regular.ttf: Liberation Mono:style=Regular
/usr/share/fonts/default/Type1/n021023l.pfb: Nimbus Roman No9 L:style=Regular Italic
/usr/share/fonts/default/Type1/n019024l.pfb: Nimbus Sans L:style=Bold Italic
/usr/share/fonts/default/Type1/z003034l.pfb: URW Chancery L:style=Medium Italic
/usr/share/fonts/dejavu/DejaVuSerifCondensed-Italic.ttf: DejaVu Serif,DejaVu Serif Condensed:style=Condensed Italic,Italic
/usr/share/fonts/default/Type1/n019004l.pfb: Nimbus Sans L:style=Bold
/usr/share/fonts/default/ghostscript/putr.pfa: Utopia:style=Regular
/usr/share/fonts/dejavu/DejaVuSansCondensed.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed,Book
/usr/share/fonts/dejavu/DejaVuSerif-BoldItalic.ttf: DejaVu Serif:style=Bold Italic
/usr/share/fonts/dejavu/DejaVuSans-ExtraLight.ttf: DejaVu Sans,DejaVu Sans Light:style=ExtraLight
/usr/share/fonts/liberation/LiberationMono-BoldItalic.ttf: Liberation Mono:style=Bold Italic
/usr/share/fonts/dejavu/DejaVuSansCondensed-BoldOblique.ttf: DejaVu Sans,DejaVu Sans Condensed:style=Condensed Bold Oblique,Bold Oblique
/usr/share/fonts/dejavu/DejaVuSans-Oblique.ttf: DejaVu Sans:style=Oblique
/usr/share/fonts/default/Type1/n019044l.pfb: Nimbus Sans L:style=Bold Condensed
/usr/share/fonts/default/Type1/p052003l.pfb: URW Palladio L:style=Roman
/usr/share/fonts/default/Type1/c059036l.pfb: Century Schoolbook L:style=Bold Italic
/usr/share/fonts/default/Type1/n019063l.pfb: Nimbus Sans L:style=Regular Condensed Italic
/usr/share/fonts/default/Type1/n019064l.pfb: Nimbus Sans L:style=Bold Condensed Italic
/usr/share/fonts/dejavu/DejaVuSans-BoldOblique.ttf: DejaVu Sans:style=Bold Oblique
/usr/share/fonts/default/Type1/n019043l.pfb: Nimbus Sans L:style=Regular Condensed

という感じで日本語フォントがないので、ImageMagickやPangoを使って日本語のテキストを画像にする場合は日本語フォントを導入してあげる必要があるだろう。

Pandoc

Pandocが入っていると裏でHTMLにするのが楽なのだけど、さすがにない。

純Rubyで書かれたMarkdown処理ライブラリであるKramdownはRubyGemsで利用可能。

データベース関連

MySQL
mysql  Ver 14.14 Distrib 5.7.26, for Linux (x86_64) using  EditLine wrapper
PostgreSQL
psql (PostgreSQL) 9.2.24
sqlite

sqlite3として導入されている。 このおかげでかなりの数のアプリが動かせる。

3.7.17 2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668

ううううーーーん…最新版は3.30だからだいぶ古いな…

memcached

恐らく「あるけど切られてる」という感じ。アクセス権がないので使えない。

Redis

恐らく使えない。

MongoDB

使えない。

DBM

ndbmがなくて、RubyでDBMを使おうとするとGDBMが使われる。

GDBMがあるだけでも救いか。

QDBM

ない。

SDBM, PStore, YAMLStore

当然ながら使える (いずれもRuby自体で完結している)

KyotoCabinet

ない。

RubyGemsとその他の言語とライブラリ

gemを使うことはできるしgccも入ってはいるが、そもそも入っているソフトウェアが少ないため、あまり複雑な依存関係のソフトウェア(例えばPangoなど)を使用するのは難しい。 また、Java環境がなく、JavaでCGIを書くことはできないし、Javaを必要とするライブラリも使用できない。 その他入っているのは

  • Ruby
  • Perl
  • PHP
  • Python
  • GCC (c89 / c99 / cc / cpp / c++ / f95 (Fortran!))
  • Bash
  • Zsh
  • tcl (!!)

入っていないのは

  • Node.js
  • Lua
  • Java
  • LLVM
  • Clisp/SBCL
  • ghc (Haskell)
  • Rust
  • Nim
  • DMD, GDC (D言語)
  • Csh, tcsh

などなどほとんど入ってない。

もうちょっとなんとかなりませんかね…?

レンタルサーバーなのだからすごく貧弱な環境でも仕方ないのかもしれないけど、いろいろもうちょっとなんとかして欲しい感がある。 もちろん、サーバー環境がRHEL7であることを踏まえて、必要なものをホームディレクトリ以下に書くこともできなくはないが4

もっとも、CGIのライブラリによる支援ということを考えると、現実的にはRuby, Perl, Python, PHPくらいしか考えられないため、CGIしか使えないんだからそんなもんさ、と思えなくはない。

CGI言語としてはC, Java, Lua, CLispあたりは普通に使われているから、ここらへんを使えるようにして欲しい感はあるけれども、少数派ではあろう。

特に機械語にコンパイルする系の言語の場合はなにもサーバー上でコンパイルしなければならないということもない。

また、必ずしもWING上で展開しているからといって、WING上でアプリケーションを動かさねばならないということもない。 サブドメインなり、別のドメインなりでConoHa VPS上で動作しているアプリケーションにリクエストしてもいいわけだ。むしろ、その手法は部分的にアプリケーションを使う手法を取る上ではやりやすいとすら言える。

WINGで動かせるアプリケーション

WordPressとEC-CUBEが公式でサポートされているようだけど、私が試した限り、さすがに(ManjaroやVivaldiのフォーラムで使われている)Discourseは使えないけど、Arch Linuxのforumで使われているFluxBBは使える。

ConoHa WINGの狂えるShebangとCGI

このセクションは検証・指摘なので、 このセクションの内容は他のセクションと比べて専門的で難易度が高い。

コマンドラインでコマンド名のときが一番わかりません

Shebangは#!rubyでいい。

…というのは常識の話で、ConoHa WINGだとこうはいかない

どういうことかというと、まず次のようなスクリプトを書いて実行権限を与える。

#!ruby

puts "Hello"
puts __FILE__.inspect
puts ARGV.inspect

普通はこうなる。実際私の環境でもこうなる。

% ./hello.cgi
Hello
"./hello.cgi"
[]

ところが、ConoHa WINGだとこうなる。

% ./hello.cgi
Traceback (most recent call last):
ruby: No such file or directory -- puts "Hello" (LoadError)
puts __FILE__.inspect
puts ARGV.inspect

なんじゃこりゃ…

まぁ、起きていることはわからないではないよ。 多分ARGV[0]としてラインターミネータまでじゃなくてEOFまで与えてるのでしょう。

…なんで?????

で、まぁ試しに絶対パスで与えてあげると正しく動作する。

% ./hello.cgi
Hello
"./hello.cgi"
[]

なるほど? では、Shebang行を

#!/usr/local/bin/ruby /home/c0000000/hello.cgi

のようにしたらどうか。

% ./hello.cgi
Hello
"/home/c5096736/hello.cgi"
["./hello.cgi"]

うん、間違ってはいない。 実際、

#!ruby /home/c0000000/hello.cgi

ならちゃんと動作する。 OK、じゃあそれなら…と思ったら、Nginx CGIだとこれも動作しない!!

$PATHから/usr/local/binが抜けているということもなく、

#!/usr/local/bin/ruby

puts "Content-Type: text/plain"
puts
pp ENV

とかやると$PATHは…おや? (一部隠しています)

...
 "PATH"=>"/usr/local/bin:/usr/bin:/bin",
 "QUERY_STRING"=>"",
 "REMOTE_ADDR"=>"****",
 "REMOTE_PORT"=>"27894",
 "REQUEST_METHOD"=>"GET",
 "REQUEST_SCHEME"=>"http",
 "REQUEST_URI"=>"/apps/env.cgi",
 "SCRIPT_FILENAME"=>"/home/c***/public_html/chienomi.org/apps/env.cgi",
 "SCRIPT_NAME"=>"/apps/env.cgi",
 "SERVER_ADDR"=>"127.0.0.1",
 "SERVER_ADMIN"=>"root@localhost",
 "SERVER_NAME"=>"chienomi.org",
 "SERVER_PORT"=>"8080",
 "SERVER_PROTOCOL"=>"HTTP/1.1",
 "SERVER_SIGNATURE"=>"",
 "SERVER_SOFTWARE"=>"Apache",
 "UNIQUE_ID"=>"****"}

はい? Apache???

Nginx→Apacheでファイルサーブ?

というわけで、ConoHa WINGはNginx CGI Handlerを使っているわけではなく、Apacheをlocalhost:8080で動作させて、CGIハンドラとして使っているらしい。 というか、CGIに関してはNginxをリバースプロキシとしてApacheにまわしているというのが正しい。実際、X_FORWARDED_*も入るようになっている。ただし、IPアドレスはX_FORWARDED_FORによってではなく、REMOTE_ADDRで取得できる。 挙動のおかしさはこのあたりから来ているのだろうか。

いや、でも直接実行したときにEOFまでをShebangだと認識するっていうのはこれ関係ないな…どうなってやがる…

というか、そもそも.htaccessを処理できるとか、静的ファイルのレスポンスが期待ほど速くない(ConoHa WINGのリソース条件ならもっともっと速いはず)とか、そこらへんを考えると静的ファイルをホストしてるのもApacheじゃないかなぁ。

つまり、Nginxが応答してくるけれども、Nginxは恐らくただのリバースプロキシであろうという予測。そこからアプリケーションサーバーにつなぐか(LiteSpeed LSAPIなど…)、もしくはApache送りか、という構造ではないだろうか。

Chienomiの計測

計測結果を見るとTTFB18msっていうのは、静的ファイル配信としては「まぁそんなもんかな」という気持ちになる。ただ、それでも「若干遅い」ので少しロスがある気がする。

Mimirの計測。こちらはConoHa VPS

ほとんどチューニングしていないNginxだけど、Mimir YokohamaのサイトはTTFBが6.68ms。こちらはメモリー量が厳しいこともあり、ちょっと安定しないのだけど、応答は速い。

しかしTTFBによる応答性よりも気になるのが、Initial connectionの長さ。VPSよりも高性能であるにも関わらずSSL部分でVPSよりかなり時間がかかっており、「んんんんん??」という気持ちになる。

問題を追求したいところではあるけれど、これ以上はサーバー構造の中身を見る必要があり、これをしようと思うとConoHaの中の人になるしかないので、一般ユーザーのために説明できるとしたら、

  • 本来Shebangは#!rubyとか書いておけば十分なもの
  • #!/usr/bin/env rubyっていうのはかなり無駄。筋の悪い書き方
  • ところがConoHa WINGでは挙動が変なので#!/usr/bin/env rubyって書くのが一番無難な方法
  • WINGでやるかVPSでやるかは無理のない段階でVPSに切り替えたほうがいいのは確か
  • 静的ファイル配信に関してはキャッシュ使わないとぶっちゃけ真の爆速とは言えない。静的ファイル配信でも可能ならキャッシュ使おう。コントロールパネルから設定できる。

というくらいか。

suexecとCGI

で、CGIの話に戻ると、要は引数があれば良いわけで、コマンドラインで実行する分には

#!ruby -rcgi

とか書けばちゃんと動作する。ただ、CGIとしてApache経由で実行した場合は

[Tue Nov 12 16:46:06.212682 2019] [cgi:error] [pid 55332] [client *:13520] AH01215: suexec policy violation: see suexec log for more details: /home/c****/public_html/cgitest.conohawing.com/apps/****.cgi
[Tue Nov 12 16:46:06.212946 2019] [cgi:error] [pid 55332] [client *:13520] End of script output before headers: ****.cgi

この通り。明示的に禁止されている感じかな。

まとめじみた所感とこぼれ話

なぜかあるQt

WINGに収録されているライブラリ、及びプログラムは基準が結構謎で、Qt関連のPerlライブラリが結構あったりする。 そしてそれ以上に、なぜかKDEライブラリがある(Phonon)。

管理者がKDE使いなのかな?

Gnome関連ライブラリはないものの、Gtk関連ライブラリはそれなりにある。

プライベート環境になっている

共有サーバーであるレンサバなんだけれど、GMOお手製のソフトウェアで仮想化されているそうで、見えるファイルが限られており、他のユーザーのファイルなどはそもそも見えなくなっている。

このため、感覚的にはroot権限のないVPSに近い感じ。

Ubuntuじゃないんかーい

ConoHaってホストはUbuntuって話だったと思うけれど、WINGはRHEL。しかも7。 そのおかげでソフトウェアが全体的に古い。バージョンが古いだけなら許せるけど、セキュリティfixが反映されてなかったりするのがたくさんあって辛い。

まぁ、レンサバですからね…

ConoHa VPSを使っているから、というのもあるけれど、ConoHa WINGがレンサバだということを忘れがちになる。

なにかと「自由がない」ことが気になるけれど、VPSではないので、レンサバ基準で考えれば自由があるほうなのかもしれない。

私はレンサバは近年あまりつかっていないのでレンサバ事情に疎いが、昔のことを思うと

  • FTPしかない。セキュアな方法(SFTPとか)もないし、SSHログインなんてとんでもない
  • だからとにかくコマンドが効かない。ひたすら手動でめんどくさい
  • 処理系がない(Perlしかない時代ののち、PerlかPHPの時代で…)
  • ライブラリがない。ライブラリつっこむのもPerlとかRubyとかで書かれてるのだけだから結構難儀する

みたいなのを思えば、まぁ自由度高いし使い勝手いいってことになるのかもしれない。

端末が使えて、rsyncがないから台無し感はあるにはあるけれどコマンドが打てて、もちろんSFTPもscpもできるし、 Gitも使えるし、入らないライブラリもあるけどユーザーローカルレベルでライブラリ入れられるし、 ついついVPSの感覚で「不自由だなぁ」なんて思ってしまうけれど、レンサバでこんなけいじれればむしろ驚異的、かもしれない。

レンサバという前提の上で言えば使いやすい

まずなにより

  • SSHログインできる
  • Zshがある

というのが大きい。これだけで使い勝手は天と地だ。もちろん、scpやSFTPも利用可能。

Zshが使えるためコマンドライン環境の使い勝手が良い。グローバルな設定ファイルをいじったり、プラグインパッケージを導入したりはできないが、ユーザーローカルにいじることはできる。

コマンド類はレンサバとしては充実しているほうで、基本的な利用においては非常にストレスなく使うことができる。

世の中にはレスポンスという概念が行方不明になっているクッソ遅くて使いにくくて操作できることがほとんどないウェブインターフェイスでしか操作できないというレンサバもあるので、VPSに慣れた身でも普通に使いやすいと感じる環境が揃っているのは素晴らしいことだ。

また、rsyncはないものの、Gitがあるので現代的なデプロイ手順がとれるのも大きい。 PureBuilder SimplyはGitやMercurialといった行指向のバージョン管理システムと非常に相性が良いので、これは嬉しいポイント。

RubyGemsやCPANも普通につかえて、ライブラリの導入にも比較的寛容。 このあたりはシェルが使えることの非常に大きな恩恵になっている。PaaSでも結構難しかったりするから、VPSに近い使い心地といえる。

レンサバでは未だにRubyが1.8だったりするところもある5ので、最新ではない(最新は2.6.5)とはいえ、まぁまぁ新しいのが入っていることは嬉しいこと。いや、2.5系の最新は2.5.7なんだけどね。 処理系が新しいということについては、そもそもWINGの稼働開始が新しくて、稼働してから変わってないって可能性もあるのでいささか不安ではある。

やはりサーバーの面倒を見なくてよいという部分は魅力的で、レンサバは性能が貧弱でちょっとしたことで他のユーザーの資源を逼迫してしまうことが普通にあることを考えれば、強力なインフラの上で動作するというのもまた魅力的。

また、 生ログが取れる という点も強調しておきたい。 設定でログを残す設定ができるようになっており、無期限で残すことも可能。 このログは、~/logs以下にファイルとして置かれ、自動的にデイリースナップショットも取れる。 これは一般的な形式(CLF)であり、GoAccessなどで解析することも容易である。 PureBuilder Simplyのような静的HTMLにビルドする方式の場合、webアプリケーションによってアクセスログを取るということができないので、この機能があるということは極めて重要である。

このあたりを含めて「VPSにする理由」の結構な部分をカバーできるというのがConoHa WINGの魅力だと思う。 条件によっては適合しないことは普通にあるのだけど、適合する環境を広げ、ストレスなく使えるようにする工夫が入っている。

レンサバとしての基本部分の話

VPSユーザーからすると、「自分で管理しなくていい」という点は大きくて、導入しなくて良い、維持しなくて良い、面倒見なくて良いというのは非常に大きな魅力だと言える。

まず使い勝手のいいDNSを挙げたい。 DNS系のコントロールパネルは非常に使いにくいことが多く、エントリが多いとうんざりするものだが、ConoHaはまとめて書ける上にレスポンスも良い。ただ、ConoHa WINGのみを使用する場合は自分で書く必要性が基本的にない。

サーバーがいじれないためにコンテンツキャッシュとExpiresヘッダのコントロールができることは非常に望ましい。 ただし、Expiresヘッダはその期間をコントロールできるようにはなっていない。6

BASIC認証が容易に書けることは、初心者のウェブ管理者には助かるだろう。

IPアドレスのアクセス制限が可能なことは、限定的ながら有用である。 動的な設定が必要な場合などはさすがに厳しいが。

Let’s EncryptによるSSLに対応している。これは非常に重要なことだろう。管理者権限がなければできないのだから。 SSL自体には対応していても、制限があることは珍しくない。だが、ConoHa WINGなら当たり前のようにHTTPS運用が可能。 また、www.つきドメインに対しても証明書をとってくれるようになっていて、リダイレクトではなく同じサイトを返すようになっている。(これはリダイレクトしてくれたほうが、本質的には良いはずだが)

今や自力での維持が難しくなったメール機能は一般的なメールサービスと同等に充実している。 もちろん、メールアドレスに制限はない。 変わったところでは、自動返信機能と、メーリングリスト機能がある。 メールマガジン機能はない。また、純粋なメールエイリアスとメールアドレス拡張がないことは、VPS管理者にとっては大きな不満だろう。

自分で運営するのと比べるとメール送達性は良いが、それでもメールが拒否されることはそれなりにある。 GMailやMail.ruのような大手サービスを使わない限り、今や確実な送達は期待できないだろう。

注意点として、メールアドレスを作ると「国外IPアドレス制限」がデフォルトでonになる。 これには注意を払わなければならない。

webメール機能もあり、Roundcubeのデザインをカスタマイズしたものになっている。 多分、スマートフォンからもいけるだろう。スマートフォン対応スキンが出てからスマートフォンでRoundcube使ったことないけど。

ログ機能とは別に、ConoHa WINGで提供されるアクセス解析機能もある。 表示件数が非常に少ないのであまり役には立たないが。

カスタムエラーページとか、基本的にレンサバで欲しい機能は網羅してあって、性能も良い。

なおwebフォントは月間75000PVで、リミットがかかるわけでもない仕様なので、ちょっと使いにくい。7

PHP前提?

「WordPressを速くする」という意識が強いようで、PHPだけはLiteSpeed LSAPIインスタンスとして動作させることが可能。Rubyから見ればFastCGIすらない環境なので、PHPだけ妙に優遇されている形。

そもそもWordPressにはコントロールパネルからのインストール機能があり、WordPress向けの機能も搭載しているあたり、非常に「WordPress指向」。 ただこれはConoHa WINGに限った話ではなく、レンサバはほとんどの場合WordPressが使われるので、大体どこもWordPressのことしか見ていない。現実的にはWordPress以外はアプリケーションが動かせないようなところもあるくらい。 あとは、WordPressのディレクトリがドキュメントルートになっちゃうとか。

それと比べればいくらか穏やかな仕様であり、柔軟ではある。

けれども、やっぱりPHP前提ではあって、Unicornが入っていたりはしないのでRuby使いとしては、そしてwebアプリケーションは自前で書いてる勢としては若干の不満はある。

お決まりの宣伝

「ちょっといくらなんでも難しすぎるよ」「こんな知識どこで身につけるのさ」とか思っているそこのアナタ!!!

Mimir YokohamaってステキなところではLinuxに関する知識が得られる家庭教師サービスがあるんだぜ!!! 千里の道も一歩から。様々なテクノロジーについて土台からしっかりと学ぶことができるMimir Yokohamaの授業を受ければみるみる地力が育ってこんな話がぽんぽん出てくるようになるのさ。 遠方でもリモート授業があるから安心サ☆

webアプリケーションの開発もやってるよ!! 価格的にも仕様的にも個人でもオーダーしやすいけど、オーダーの仕方や作業要領や可能な指定なんかが一般的なIT企業とは全然違うよ。

ついでに、サーバー管理を依頼したり、アドバイザーとしてサポートにつくこともできるよ。

さぁ、今すぐMimir Yokohamaをcheck it out!

ConoHa WINGに要望

  • 楽に書けるメールエイリアスが欲しい
  • rsync入れて!!!!!
  • mailx(特にS-nail)入れて!!!!!!!!!!
  • systemd-timerを許可してほしい (atはあるけどめんどくさい)
  • コントロールパネルからED25519鍵を登録させて!!!
  • GitだけじゃなくMercurialも入れて
  • ちゃんと言語系アップデートして欲しい。バージョンを上げろって話じゃなくて、脆弱性修正されたりしてるからせめてアップデートして
  • アクセス解析、せめて各20件くらいは出してほしい。できれば50件は見たい
  • レンサバでCGIだと、他に影響がなくパフォーマンス的にも良好で負担の少ないDBMは生命線なのでKyotoCabinet入れて

おまけ

本記事のここまでのサイズ

Chienomi始まって以来、恐らく最長の記事となった。


  1. 「デフォルトシェルを変更できないからカスタマイズする」というのは、デフォルトシェルとしてZshが使える場合、Zshをデフォルトシェルにするのであれば、カスタマイズすると環境によって、例えばコマンドプロンプトからとか、ウェブコンソールからといった条件で表示できなくて詰まってしまうというケースがある。だが、デフォルトでなく、わざわざzsh -lして呼び出して起動するのであればカスタマイズしたZshがうまく動かない環境ではBashを使えば良いという話になるからだ。↩︎

  2. 「ユーザーフレンドリーなシェル」らしいが、私には非常に使いにくく感じられる。なお、ConoHa WINGにはFishは搭載されていない。中の人がFish使いなんだし、入れてあってもおかしくないのに。↩︎

  3. 未公開のコミニュティサイトはDiscourseである。↩︎

  4. 私はその昔、まだレンタルサーバーでCGIしか使えなかった時代にRubyバイナリとライブラリをサーバー上においてRuby/CGIアプリケーションを動かしていたりした。↩︎

  5. Ruby1.8は2014-07-31にRuby 1.8.7がEOLとなっている。Ruby 1.8.0がリリースされたのは2003-08-04(!)であり、Ruby 1.9で大幅な非互換が発生したために(Windows XPのように)生き残ってしまった。↩︎

  6. 私の勘違いでなければ、コントロールパネルでExpiresを有効にすると、ドキュメントルートの.htaccessに書かれる形なので、これを編集してコントロールできるだろう。↩︎

  7. Chienomiの月間PVは12-20万程度。↩︎