Raspberry PI4 でNextCloudを構築

概要

Dropbox,OneDrive,GoogleDrive,Boxなど色々アカウントを作って
便利に使っているのですが,無料アカウントだと容量が少ないのがネックとなります。
4つ持っていてもすぐに一杯になり,iPhone,iPadと連携して使う分にはすぐに
いっぱいになります。

そこで,オープンソースのNextCloudをRaspberryPIに入れて自宅でディスクストレージ
を構築することにします。

RaspberryPIの準備

RaspberryPI

先日たまたま秋葉原で見つけて購入したRaspberryPI4の4Gメモリ版を流用します。
Windows10を入れて使っていたのですが,如何せん重いのと,リモートで使うのには
不便なので,ここで一旦Linux化することにします。

raspbian os

Macを使っているのですが,公式サイトから,Raspberry Pi Imagerをダウンロードし
インストールします。SDカードを挿して,Raspberry Pi Imagerを起動,CHOOSE OSメニューの
otherからRaspberry Pi OS Liteを選択しインストールします。
ちなみにSDカードは32Gのものを使いましたが,OS入れただけだと2G程度の使用量です。

update

おきまりのアップデートをします

sudo apt udpate -y
sudo apt upgrade -y

リモート設定

sshログインできるように設定します

sudo raspi-config

3 Interface OptionsからP2 SSHを選択し YESを選択

ifconfig

このコマンドでIPアドレスを調べてリモートからログインできるようになりました

固定IPアドレス

固定にしないと面倒なので固定IPにします

sudo vi /etc/dhcpcd.conf
interface eth0
static ip_address=192.168.10.102/24
static routers=192.168.10.1
static domain_name_servers=192.168.10.1 8.8.8.8

こんな感じで追加しreboot

NextCloud

インストール

こちらを参考にインストールします。
インストールにはsnapというパッケージ管理システムを利用します。このコマンド一発で,MySQLなど必要なものが全てインストールから設定まで行ってくれます。

sudo apt install snapd
sudo snap install nextcloud

ルータの設定

外部からアクセスする関係上,ルータに穴を開けます。
80と443をこのRaspberryPIのIPアドレスにマッピングします

ダイナミックDNS

固定IPアドレスならば気にする必要ないのですが,プロバイダによってはダイナミックIPアドレスの場合があるので,SofteatherVPNをインストールした時に,設定したダイナミックDNSのホスト名を使用します。
vpn0000000000.softether.netといった感じのやつですね。

ユーザ追加

管理者を追加します。sudoでやるとパスエラーが出たので,Rootになってから実行しました

sudo su -
nextcloud.manual-install sammy password

エラーがいっぱい出ましたが,無事終了

ERROR: ld.so: object '/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
Nextcloud was successfully installed

Trusted Domains

sudo su -
nextcloud.occ config:system:get trusted_domains

先ほど設定したドメイン名も

nextcloud.occ config:system:set trusted_domains 1 --value=vpn00000000.softether.net
ERROR: ld.so: object '/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
System config value trusted_domains => 1 set to string vpn00000000.softether.net

仕上げ

SSLの設定

外部からアクセスするのでLet’s Encryptの無料SSLを入れます。

sudo su -
nextcloud.enable-https lets-encrypt
In order for Let's Encrypt to verify that you actually own the
domain(s) for which you're requesting a certificate, there are a
number of requirements of which you need to be aware:

1. In order to register with the Let's Encrypt ACME server, you must
   agree to the currently-in-effect Subscriber Agreement located
   here:

       https://letsencrypt.org/repository/

   By continuing to use this tool you agree to these terms. Please
   cancel now if otherwise.

2. You must have the domain name(s) for which you want certificates
   pointing at the external IP address of this machine.

3. Both ports 80 and 443 on the external IP address of this machine
   must point to this machine (e.g. port forwarding might need to be
   setup on your router).

Have you met these requirements? (y/n) y

yを入力します

Please enter an email address (for urgent notices or key recovery): 

メールアドレスを入力しEnter

Please enter your domain name(s) (space-separated): 

先ほど設定したダイナミックDNSのホスト名を入力

これでとりあえずはインストール完了です。

その他

そのほかとして

  • Apacheの設定をhttpからhttpsへのリダイレクト
  • linuxのApplicationFireWall設定など

いろいろセキュリティ絡みが残っているのですが,それはまた別の話。。。

wordpressのエラー

2,3日前に,以前作成したWordpressのサイトが,
エラーで入れなくなったと連絡がありました。

さくらインターネットで運用しているのですが,サポートに連絡しても
埒が開かないので,こちらにヘルプ依頼が。

確かに,Wordpressのログインができないようになっています。
仕方がないので,SSHログインしてみたところ, dead.letter  が。

この問題を解決しようとする際、以下の情報を聞かれるかもしれません。
WordPress バーション5.8.1
現在のテーマ: Spacious (バージョン 1.9.4)
現在のプラグイン: Contact Form 7 (バージョン 5.5.1)
PHP バージョン5.6.40

エラー詳細
===============
エラータイプ E_PARSE が wp-content/plugins/contact-form-7/admin/includes/welcome-panel.php ファイルの 9 行目で発生しました。 エラーメッセージ: syntax error, unexpected 'print' (T_PRINT), expecting identifier (T_STRING)

こんなエラーが出てました。どうやらプラグインの自動アップデートでやられたようです。
ContactForm7なのでたくさん使われているはずなのに,それほど大きな問題になっていないのはなぜ?

調べたところどうやら,これが原因。

さくっと,welcome-panel.phpを修正し

Line 9: Rename function to public function _print()
Line 223: Rename to $column->_print();

動きました。

どうやら,このサイトはphp5.6で運用していたのが原因かもしれません。
このあとPHP7.4にアップデートしておきました。

ジョブスケジューラのエラー

大学のスパコンはジョブ管理システム PBSによってジョブスケジュールを行なっているのですが,
最近変わったのか,Pythonで並列処理をしようとするとなぜかエラーが出るようになりました。

エラー

=>> PBS: job killed: ncpus 20.8 exceeded limit 16

コード


import os
from mpi4py import MPI
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
name = MPI.Get_processor_name()

import csv
source=[]
target=[]
with open("test.csv","r",encoding="utf-8") as f:
    cdata=csv.reader(f,delimiter=",")
    for i,items in enumerate(cdata):
        if i==0:
            continue
        source.append(items[0])
        target.append(items[1])

data_lst=[]
for src,tgt in zip(source,target):
    data_lst.append((src,tgt))

# http://muscle199x.blog.fc2.com/blog-entry-70.html?sp
def split_list(lst, n):
    list_size = len(lst)
    a = list_size // n
    b = list_size % n
    return [lst[i * a + (i if i < b else b):(i + 1) * a + (i + 1 if i < b else b)] for i in range(n)]

from transformers import MT5ForConditionalGeneration, MT5Model, MT5EncoderModel, T5Tokenizer

tokenizer = T5Tokenizer.from_pretrained("google/mt5-base")
model = MT5ForConditionalGeneration.from_pretrained("google/mt5-base")
if rank == 0:
    data = split_list(data_lst, size)
else:
    data = None

def calc(my_data):
    res=[]

    for src,tgt in my_data:
        inputs = tokenizer.encode("summarize: " + src, return_tensors='pt', max_length=512, truncation=True)
        summary_ids = model.generate(inputs, max_length=50, min_length=10, length_penalty=5., num_beams=2)
        summary = tokenizer.decode(summary_ids[0])
        res.append((src,tgt,summary))
    return res

my_data = comm.scatter(data, root=0)

for r in range(comm.size):
    if rank == r:
        print("scatter.[%d] %d" % (rank, len(my_data)))
    comm.Barrier()

my_res = calc(my_data)
def flatten(l):
    try:
        return ([item for sublist in l for item in sublist])
    except:
        import traceback
        traceback.print_exc()
        print(l)

# gather
res = MPI.COMM_WORLD.gather(my_res, root=0)

if rank == 0:
    res=flatten(res)
    for src,tgt,summary in res:
        print(f"source:{src}")
        print(f"target:{tgt}")
        print(f"summary:{summary}")
        print("-----")


これで実行スクリプトはこんな感じ

#!/usr/bin/bash
#PBS -N sample
#PBS -j oe 
#PBS -l select=1:ncpus=64:mpiprocs=64
#PBS -q SINGLE
NPROCS=`cat $PBS_NODEFILE|wc -l`
cd ${PBS_O_WORKDIR}
mpirun -np ${NPROCS} python mt5.py

解決方法

ここにありました。

簡単に解決するためには,Pythonコードの一番上に


import os
os.environ["MKL_NUM_THREADS"] = "1"
os.environ["NUMEXPR_NUM_THREADS"] = "1"
os.environ["OMP_NUM_THREADS"] = "1"

これを入れるだけ。Numpyを呼ぶ前に呼ぶ必要があるので,シェルスクリプトで呼んでもいいですし,Pythonの一番上で環境変数に設定してやってもいいです。

備忘録,JAISTのスパコン使い方

Jaistには3つスパコンがあります。
学生でもどれも自由に使えます。
この辺りが他の大学と違うところでしょうか?

今回はつい最近と言っても1年くらい経ちますが,リニューアルされた
スパコンKagayakiでのPythonでのMPIの使い方。

公式にはPythonはサポートしてません。

Anaconda

いろいろ試したのですが,これが一番。
スーパーユーザ権限がないのでローカルにインストールし,パスを設定します。

$ cat ~/.bashrc
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('~/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "~/anaconda3/etc/profile.d/conda.sh" ]; then
        . "~/anaconda3/etc/profile.d/conda.sh"
    else
        export PATH="~/anaconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<

実行コード 

mpi.py


#!/bin/env python
# coding:utf-8

from mpi4py import MPI
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
name = MPI.Get_processor_name()
print(f"size={size},rank={rank},name={name}")

mpi.sh

. ~/.bashrc
if [ ! -d venv ];then
    python -m venv venv
fi
. venv/bin/activate
LOG=${0%.*}.log
pip install -r requirements.txt > $LOG

mpirun -np 4 python mpi.py > mpi.log 2>&1

デフォルトではCSHなのでCSHでキックコードを作成し,中ではBashを使います

PBS_mpi.sh

#PBS -N mpi
#PBS -j oe 
#PBS -l select=1
#PBS -q SINGLE


source /etc/profile.d/modules.csh

module purge
module load openmpi
module load intel


cd ${PBS_O_WORKDIR}

bash mpi.sh

実行

$ qsub PBS_mpi.sh

結果

$ cat mpi.log
size=4,rank=1,name=spcc-250
size=4,rank=3,name=spcc-250
size=4,rank=0,name=spcc-250
size=4,rank=2,name=spcc-250

さくらインターネットのメーリングリストFML4で添付ファイル禁止

ちょっと,苦労したのでメモ

さくらインターネットのメーリングリストはfml4を使用している。
このメーリングリストでの設定ファイルは,各メーリングリストごとのconfig.phで行う。

ちなみに,config.phをいじると,コントロールパネルから設定を変更すると上書きされてしまうので注意

% cd ~/fml/spool/ml/メーリングリスト名/

config.phに追記。最後の1;の直上に書く

$USE_DISTRIBUTE_FILTER = 1;
$DISTRIBUTE_FILTER_HOOK .= q#
    if ($e{'Body'} =~ /filename=.*/i) {
        return 'Do not post messages with attachments';
    }
#;

要は,filename属性があったときには拒否するということ

ネットで調べた下記方法では,HTMLメールまでおかしくなってしまうので,NG

&ADD_CONTENT_HANDLER('multipart/.*','text/plain','allow');
&ADD_CONTENT_HANDLER('multipart/.*','text/html','strip');
&ADD_CONTENT_HANDLER('multipart/.*','*./.*','strip');

いろいろ調べてしまった。

LinkstationにDebianを導入し,Timemachineサーバにする

LS-V1.5TLというBuffaloのNASをずいぶん前に買ったのですが,あまり活用ができていなかったので,
Linuxを入れることにしました。

元々のNASのファームウエアにもTimemachineサーバはついているのですが,もう古いマシンなので壊れても
いいという感じでLinux化し遊ぶことに。

Linux化

こちらの記事がわかりやすいです。
一度分解し,HDDを取りだすのが面倒ですが,それさえ終われば,快適なLinux化ができます。
当然のように,分解の際にほぼ全てのつめを折ってしまいましたが気にしない。

timemachine

手順などはあちらこちらに書いているのですが

avahi

ここを参考に,avahiをインストールします。debianのパッケージがあるのでそのまま使います

sudo apt install avahi-daemon

設定はこんな感じ

/etc/avahi/services/timemachine.service




 %h
 
   _smb._tcp
   445
 
 
   _adisk._tcp
   dk0=adVN=TimeMachine,adVF=0x82
 

samba

sambaをインストールします。Samba上で使うみたいです

sudo apt install samba

sambauser

timemachineとユーザを作ります

sudo adduser timemachine
sudo password -a timemachine
sudo smbpasswd timemachine

timemachine directory

バックアップ用ディレクトリを作成します

sudo mkdir /mnt/timemachine
sudo chown -R timemachine:timemachine /mnt/timemachine

smb.conf

ここでポイントは,通常のSambaユーザとは別にし,Finderなどからはいじれないようにします。
同時にアクセスするとエラーになるための回避です。

[TimeMachine]
   path = /mnt/timemachine
   browsable = yes
   writeable = yes
   create mode = 0664     #tried turning this off, no fix
   directory mode = 0777  #tried turning this off, no fix
   vfs objects = catia fruit streams_xattr
   fruit:aapl = yes
   fruit:time machine = yes
   #guest ok = yes
   fruit:time machine max size =1T  #tried turning this off, no fix
   inherit acls = yes

restart

リスタートします

sudo /etc/init.d/smbd restart
sudo /etc/init.d/avahi-daemon restart

これで使えると思います。

Mac OS 11.4でpip pdftotext

M1Macで何故か素直に入らなかったのでメモ

環境

  • M1 Mac book Air
  • OS: 11.4
  • python: Intel miniconda3
  • python version:3.8.5

手順

brewでPdftotextを入れる

brew install pdftotext

~/.zshrcに追加

export C_INCLUDE_PATH=/opt/homebrew/Cellar/poppler/21.05.0/include:$C_INCLUDE_PATH
export CPATH=$C_INCLUDE_PATH
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/opt/homebrew/Cellar/poppler/21.05.0/lib # どうもこれは効かないらしい

pipでpdftotextライブラリを入れる 

pip install pdftotext --global-option=build_ext --global-option="-L/opt/homebrew/Cellar/poppler/21.05.0/lib"

M1 MacでのPython

M1 Mac book Air 購入したのですが,なかなか使いこなすにはハードルが高そうです。
特に,Pythonのモジュール類がうまく動かないものが多いです。

いろいろ書かれていますが,結論としては,Rosetta2を使うのが一番という結論。

brewのPythonを使うパターン

これは,ディープラーニング系のライブラリが全く入りません。
自分でGitHubからソースコード持ってきてインストールできるものもあるのですが
かなり厳しいです。

pyenvを使うパターン

brewと同様

miniforgeを使うパターン

これはarm用のライブラリもあるのですが,全部はない模様。。

rosetta2でminiconda

これが簡単ですね

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O ~/miniconda.sh
./miniconda.sh

これでIntelと同様に使えます。多少遅くなっているのでしょうが気にしない

vimでJSONのフォーマット

大きく分けてふた通りあるみたいだ。

jqを使うパターン

ubuntuの場合

apt install jq

macの場合

brew install jq

外部コマンドとして,VIMから起動する

:%!jq

pythonを使うパターン

こちらはpythonが入っていればvimから

:%!python -m json.tool

どうもvimrcで自動フォーマットする方法は見つからなかった?

beep音削除

microsoft terminalからubuntuへsshログインしたとき、BEEP音がうるさいのを削除する設定

csh

~/.cshrcに以下を追加

set nobeep

bash

~/.inputrcに以下を追加

set bell-style none

vim

~/.vimrcに以下を追加

set vb t_vb=