title


Raspberry Pi
[WEBサーバ][English]
  • リモートアクセス用で、公開サーバ目的ではないです。
  • 外部からのアクセスはランダムに決めたポート番号だけをRaspberry Piへポートフォワーディングし、Basic認証+SSL通信をする。
  • LAN内部からは通常どおりポート80でアクセスし、バーチャルホスト設定でポート番号ごとに別々のサイトを表示する。
  • MySQL、Apache、PHPは、セキュリティを考慮してソースから最新版をインストールする。
[MySQL]
  • ソースコードのダウンロード
    
    pi@raspberrypi ~ $ git clone https://github.com/mysql/mysql-server.git
    
  • Cursesが入ってないとcmakeがエラーになるので入れておく。
    
    pi@raspberrypi ~ $ sudo apt-get install libncurses5-dev
    
  • bisonが入ってないとcmakeがエラーになるので入れておく。
    
    pi@raspberrypi ~ $ sudo apt-get install bison
    
  • cmakeする。バージョンは5.7.9。boostライブラリのディレクトリ定義をしないとエラーになる。downloadイネーブルにしておかないとエラーになる。
    
    pi@raspberrypi ~ $ cd mysql-server/
    pi@raspberrypi ~/mysql-server $ mkdir release
    pi@raspberrypi ~/mysql-server $ cd release/
    pi@raspberrypi ~/mysql-server/release $ cmake .. -DDOWNLOAD_BOOST=1 -DWITH_BOOST=./boost -DENABLE_DOWNLOADS=1 -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci
    
  • gccバージョンが4.6(4.6.2)だとmakeでlf_alloc-pin.cでエラーが出る。でも4.8(4.8.2)にすると今度はitem_geofunc_setops.ccでエラーが出る。4.7(4.7.2)だとok。
    
    pi@raspberrypi ~ $ sudo apt-get install gcc-4.7
    pi@raspberrypi ~ $ sudo apt-get install g++-4.7
    pi@raspberrypi ~ $ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.7 47 --slave /usr/bin/g++ g++ /usr/bin/g++-4.7 --slave /usr/bin/gcov gcov /usr/bin/gcov-4.7
    pi@raspberrypi ~ $ sudo update-alternatives --config gcc
    alternative gcc (/usr/bin/gcc を提供) には 3 個の選択肢があります。
    
      選択肢    パス            優先度  状態
    ------------------------------------------------------------
      0            /usr/bin/gcc-4.8   48        自動モード
    * 1            /usr/bin/gcc-4.6   46        手動モード
      2            /usr/bin/gcc-4.7   47        手動モード
      3            /usr/bin/gcc-4.8   48        手動モード
    
    現在の選択 [*] を保持するには Enter、さもなければ選択肢の番号のキーを押してください: 2
    update-alternatives: /usr/bin/gcc (gcc) を提供するために 手動モード で /usr/bin/gcc-4.7 を使います
    pi@raspberrypi ~ $ gcc -v
    ...
    gcc version 4.7.2 (Debian 4.7.2-5+rpi1)
    
  • makeする。6時間かかりました。
    
    pi@raspberrypi ~/mysql-server/release $ make
    
  • インストールする。
    
    pi@raspberrypi ~/mysql-server/release $ sudo make install
    
  • 設定ファイル/usr/local/mysql/my.cnfを作成する。
    mysqldはmy.cnfファイルを以下の順で捜索します。
    /etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf
    一方、後で/etc/init.d/へコピーする/usr/local/mysql/support_files/mysql.serverでは$basedir/my.cnfを使うようなので、$basedir(=/usr/local/mysql)に入れておいて、/etc/mysql/にリンクファイルを置くことにします。
    
    [client]
    port            = 3306
    socket          = /var/run/mysqld/mysqld.sock
    default-character-set=utf8
    
    [mysqld]
    user            = mysql
    pid-file        = /var/run/mysqld/mysqld.pid
    socket          = /var/run/mysqld/mysqld.sock
    port            = 3306
    basedir         = /usr/local/mysql
    datadir         = /usr/local/mysql/data
    tmpdir          = /tmp
    character-set-server=utf8
    skip-character-set-client-handshake
    bind-address            = 127.0.0.1
    
  • 初期化する。initializeで暫定パスワードが表示されるので記録する。
    
    pi@raspberrypi ~/mysql-server/release $ groupadd mysql
    pi@raspberrypi ~/mysql-server/release $ useradd -r -g mysql mysql
    pi@raspberrypi ~/mysql-server/release $ cd /usr/local/mysql
    pi@raspberrypi /usr/local/mysql $ sudo chown -R mysql .
    pi@raspberrypi /usr/local/mysql $ sudo chgrp -R mysql .
    pi@raspberrypi /usr/local/mysql $ sudo bin/mysqld --initialize --user=mysql
    ...
    2015-XX-XXTXX:XX:XX.XXXXXXZ X [Note] A temporary password is generated for root@localhost: **********
    pi@raspberrypi /usr/local/mysql $ sudo bin/mysql_ssl_rsa_setup
    pi@raspberrypi /usr/local/mysql $ sudo chown -R root .
    pi@raspberrypi /usr/local/mysql $ sudo chown -R mysql data
    pi@raspberrypi /usr/local/mysql $ sudo cp support-files/mysql.server /etc/init.d/mysql
    pi@raspberrypi /usr/local/mysql $ sudo update-rc.d mysql defaults
    pi@raspberrypi /usr/local/mysql $ sudo service mysql start
    
  • PATHに/usr/local/mysql/binを追加する。/home/pi/.profile
    
    if [ -d "/usr/local/mysql/bin" ] ; then
        PATH="/usr/local/mysql/bin:$PATH"
    fi
    
  • Password変更。Initializeで記録したパスワードを入れて、新しいパスワードに変更する。
    
    pi@raspberrypi ~ $ mysqladmin -p -u root password
    Enter password:
    New password:
    Confirm new password:
    Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
    pi@raspberrypi ~ $
    
  • 動作確認とユーザー追加。
    
    pi@raspberrypi ~ $ mysqlshow -p -u root
    Enter password:
    +--------------------+
    |     Databases      |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sys                |
    +--------------------+
    pi@raspberrypi ~ $ mysql -p -u root
    Enter password:
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 2
    Server version: 5.7.9 Source distribution
    
    Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql> create user 'apache'@'localhost';
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> grant select,insert,update,delete on *.* to 'apache'@'localhost';
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> create database home;
    Query OK, 1 row affected (0.00 sec)
    
    mysql> use `home`
    Database changed
    mysql> create table `personal` ( `id` int(10) default NULL, `name` char(100) default NULL );
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> quit
    Bye
    pi@raspberrypi ~ $ mysql -u apache home
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 23
    Server version: 5.7.9 Source distribution
    
    Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql> insert into personal
        -> values ('10', 'name');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from personal;
    +------+------+
    | id   | name |
    +------+------+
    |   10 | name |
    +------+------+
    1 row in set (0.00 sec)
    
[Apache2]
  • ソースコードはWindows上でダウンロード。http://httpd.apache.org/ FTPでRaspberry piに置いて解凍する。
    
    pi@raspberrypi ~/apache2 $ tar xvfz httpd-2.4.17.tar.gz
    
  • Apache Portable Runtime libraryというのが必要。APRとAPR-util。http://apr.apache.org/ FTPでRaspberry piに置いてsrclibの下にapr、apr-utilというディレクトリを作成してそれぞれ解凍する。
    
    pi@raspberrypi ~/apache2/httpd-2.4.17/srclib/apr $ tar xvfz apr-1.5.2.tar.gz
    pi@raspberrypi ~/apache2/httpd-2.4.17/srclib/apr $ mv -i apr-1.5.2/* .
    pi@raspberrypi ~/apache2/httpd-2.4.17/srclib/apr-util $ tar xvfz apr-util-1.5.4.tar.gz
    pi@raspberrypi ~/apache2/httpd-2.4.17/srclib/apr-util $ mv -i apr-util-1.5.4/* .
    
  • configure実行。MPMは、PHPのサイトでしきりにスレッドを使うなと書かれているので、preforkを選べるように --enable-mpms-shared=allを入れておく。
    
    pi@raspberrypi ~/apache2/httpd-2.4.17 $ ./configure --enable-modules=all --enable-mods-shared=all --with-included-apr --enable-mpms-shared=all
    
  • makeする。MySQLと違って進捗率表示が無いが30分くらいで完了。
    
    pi@raspberrypi ~/apache2/httpd-2.4.17 $ make
    
  • インストールする。
    
    pi@raspberrypi ~/apache2/httpd-2.4.17 $ sudo make install
    
  • /usr/local/apache2/conf/httpd.conf
    
    ServerRoot "/usr/local/apache2"
    Listen 80
    Listen xxxxx # ポートフォワーディング用
    LoadModule mpm_prefork_module modules/mod_mpm_prefork.so # マルチプロセッサモジュールをスレッド使わないpreforkとする。
    LoadModule authn_core_module modules/mod_authn_core.so
    LoadModule authz_host_module modules/mod_authz_host.so
    LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
    LoadModule authz_user_module modules/mod_authz_user.so
    LoadModule authz_core_module modules/mod_authz_core.so
    LoadModule access_compat_module modules/mod_access_compat.so
    LoadModule auth_basic_module modules/mod_auth_basic.so
    LoadModule reqtimeout_module modules/mod_reqtimeout.so
    LoadModule filter_module modules/mod_filter.so
    LoadModule mime_module modules/mod_mime.so
    LoadModule log_config_module modules/mod_log_config.so
    LoadModule env_module modules/mod_env.so
    LoadModule headers_module modules/mod_headers.so
    LoadModule setenvif_module modules/mod_setenvif.so
    LoadModule version_module modules/mod_version.so
    LoadModule ssl_module modules/mod_ssl.so
    LoadModule unixd_module modules/mod_unixd.so
    LoadModule status_module modules/mod_status.so
    LoadModule autoindex_module modules/mod_autoindex.so
    LoadModule dir_module modules/mod_dir.so
    LoadModule alias_module modules/mod_alias.so
    LoadModule php5_module        modules/libphp5.s
    <IfModule unixd_module>
    User xxxxxxx # 専用アカウント。DocumentRoot下以外のアクセス権を与えない。
    Group xxxxxxx
    </IfModule>
    
    <IfModule dir_module>
        DirectoryIndex index.html index.htm index.php
    </IfModule>
    
    <Files ".ht*">
        Require all denied
    </Files>
    
    <Files "*.log">
        Require all denied
    </Files>
    
    ErrorLog "logs/error_log"
    LogLevel warn
    
    <IfModule log_config_module>
        LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
        LogFormat "%h %l %u %t \"%r\" %>s %b" common
        <IfModule logio_module>
          # You need to enable mod_logio.c to use %I and %O
          LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
        </IfModule>
    </IfModule>
    
    <IfModule mime_module>
        TypesConfig conf/mime.types
        AddType application/x-compress .Z
        AddType application/x-gzip .gz .tgz
    </IfModule>
    
    SSLRandomSeed startup builtin
    SSLRandomSeed connect builtinSSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
    SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4
    SSLHonorCipherOrder on
    SSLProtocol all -SSLv3
    SSLProxyProtocol all -SSLv3
    SSLPassPhraseDialog  builtin
    SSLSessionCache shmcb:/usr/local/apache2/logs/ssl_scache(512000)
    SSLSessionCacheTimeout  300
    
    Include conf/extra/httpd-vhosts.conf # バーチャルホスト設定は別ファイル
    
    <FilesMatch \.php$>
        SetHandler application/x-httpd-php
    </FilesMatch>
    
  • /usr/local/apache2/conf/extra/httpd-vhosts.conf
    バーチャルホスト設定。起動時の「AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message」は無視。
    
    <VirtualHost 192.168.1.10:80>
            ServerAdmin メールアドレス
            DocumentRoot /home/www
            <Directory />
                    Options FollowSymLinks
                    AllowOverride None
            </Directory>
            <Directory /home/www/>
                    Options FollowSymLinks
                    AllowOverride None
                    Order allow,deny
                    allow from all
            </Directory>
            ErrorLog "logs/error0.log"
            LogLevel warn
            CustomLog "logs/access0.log" combined
    </VirtualHost>
    
    <VirtualHost 192.168.1.10:xxxxx>
            ServerAdmin xxxxxxx
            DocumentRoot /home/www/pi
            SSLEngine on
            SSLCertificateFile /usr/local/apache2/conf/ssl/server.crt
            SSLCertificateKeyFile /usr/local/apache2/conf/ssl/server.key
            <Directory />
                    Options FollowSymLinks
                    AllowOverride None
            </Directory>
            <Directory /home/www/pi>
                    SSLrequireSSL
                    Options FollowSymLinks
                    AllowOverride None
                    Order allow,deny
                    allow from all
                    AuthUserFile /home/www/pi/.htpasswd
                    AuthGroupFile /dev/null
                    AuthName "INPUT ID and PASSWORD"
                    AuthType Basic
                    require valid-user
            </Directory>
    
            ErrorLog "logs/error.log"
            LogLevel warn
    
            CustomLog "logs/access.log" combined
    </VirtualHost>
    
[SSL]
  • 証明書の作成
    
    pi@raspberrypi /usr/local/apache2/conf $ sudo chmod 777 ssl
    pi@raspberrypi /usr/local/apache2/conf/ssl $ openssl genrsa -des3 2048 > server.key
    Generating RSA private key, 2048 bit long modulus
    .........................................+++
    ........+++
    e is 65537 (0x10001)
    Enter pass phrase:
    Verifying - Enter pass phrase:
    pi@raspberrypi /usr/local/apache2/conf/ssl $ openssl req -new -key server.key > server.csr
    Enter pass phrase for server.key:
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [AU]:JP
    State or Province Name (full name) [Some-State]:Tokyo
    Locality Name (eg, city) []:xxxxx
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Private
    Organizational Unit Name (eg, section) []:Home
    Common Name (e.g. server FQDN or YOUR name) []:外部IPアドレス
    Email Address []:xxxxxxxxxx
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    pi@raspberrypi /usr/local/apache2/conf/ssl $ openssl x509 -in server.csr -days 3650 -req -signkey server.key > server.crt #証明書を作成します。
    Signature ok
    subject=/C=JP/ST=Tokyo/L=*****/O=Private/OU=Home/CN=***.***.***.***/emailAddress=*@*.*.*
    Getting Private key
    Enter pass phrase for server.key:
    pi@raspberrypi /usr/local/apache2/conf $ sudo chmod 700 ssl
    
[PHP]
  • ソースコードはWindows上でダウンロード。http://php.net/downloads.php FTPでRaspberry piに置いて解凍する。
    
    pi@raspberrypi ~/php $ tar xvfz php-5.6.15.tar.gz
    
  • libxml2-devが入ってないとconfigureがxml2-configエラーになるので入れておく。
    
    pi@raspberrypi ~ $ sudo apt-get install libxml2-dev
    
  • configure実行。
    
    pi@raspberrypi ~/php/php-5.6.15 $ ./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-mysqli --enable-mbstring
    
  • makeする。40分くらいで完了。
    
    pi@raspberrypi ~/php/php-5.6.15 $ make
    
  • インストールする。
    
    pi@raspberrypi ~/php/php-5.6.15 $ sudo make install
    
  • php.iniをコピー
    
    pi@raspberrypi ~/php/php-5.6.15 $ sudo cp -i php.ini-production /usr/local/lib/php.ini
    
  • php.iniを以下変更。
    
    session.save_path = "/var/session"
    mbstring.internal_encoding = UTF-8
    mbstring.http_input = UTF-8
    mbstring.http_output = UTF-8
    mbstring.substitute_character = "?";
    
[cron]
  • 監視用にアクセスログを定期的にDocumentRootへコピーします。*.logは直接閲覧は出来ないようにしています。
    
    # /etc/cron.d/accesslog
    
    # Copy accesslog every 30 minutes
    05,35 *     * * *     root   cp /usr/local/apache2/logs/access.log /home/www/pi/xxxxx.log; chmod 666 /home/www/pi/xxxxx.log
    06,36 *     * * *     root   cp /var/log/user.log /home/www/pi/xxxxx.log; chmod 666 /home/www/pi/xxxxx.log
    
[index.php]
  • カメラ画像、映像は監視プログラムがDocumentRoot下へ作成します。
  • ファイルを検索し、存在するファイルへリンクを張ります。
  • cronでコピーされたログファイルから、前回のアクセスと、エラーログがあれば表示します。
  • /home/www/pi/index.php
    
    <?php
    
    date_default_timezone_set("Asia/Tokyo");
    $work =<<<HTM1
    <html>
    <head>
    <title>HOME</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <center>
    <img src="000.jpg"><br>
    
    HTM1;
    
    print($work);
    printf("%s<br>\n", date("F d Y H:i:s.", filemtime("000.jpg")));
    
    $access = fopen("xxxxx.log", "r");
    if($access){ 
      $preip="";
      while ($line = fgets($access)) { 
        $logarray1 = preg_split("/\"/", $line);
        $logarray2 = preg_split("/[\s,]+/", $line);
        if($preip != $logarray2[0] && substr($logarray2[0],0,7)!="192.168"){
          $work=sprintf("%s %s %s", substr($logarray2[3],1), $logarray2[0],$logarray1[count($logarray1)-2]);
          $work=htmlspecialchars($work);
        }
        $preip = $logarray2[0];
      } 
      print($work);
      print("<br>\n");
    } 
    fclose($access);
    
    $userlog = fopen("xxxxx.log", "r");
    if($userlog){
      while ($line = fgets($userlog)) {
        if(stristr($line,"Error")!=FALSE){
          $work=htmlspecialchars($line);
          print($work);
          print("<br>\n");
        }
      }
    }
    fclose($userlog);
    
    $filename="000.3gp";
    
    for ($i=0;$i<20;$i++){
      $filename = sprintf("%03d.3gp", $i);
      if( file_exists($filename) ){
        printf("<a href='%s'>%s</a>(%s %dKB)<br>\n", $filename, $filename, date("m/d H:i:s.", filemtime($filename)), filesize($filename)/1024);
      }
    }
    
    for ($i=0;$i<20;$i++){
      $filename = sprintf("%03d.avi", $i);
      if( file_exists($filename) ){
        printf("<a href='%s'>%s</a>(%s %dKB)<br>\n", $filename, $filename, date("m/d Y H:i:s.", filemtime($filename)), filesize($filename)/1024);
      }
    }
    
    $work =<<<HTM2
    </center>
    </body>
    </html>
    HTM2;
    
    print($work);
    
    ?>