Dive into Ofuton

お布団に飛び込もう

お一人様インスタンスを建てたドン

今話題のマストドンのお一人様インスタンスを建てました

don.crakac.com

さくらのVPS 1コア512MBプランで今のところ動いていますが、いつ死ぬかはわかりません。

メモリは常にswap使っててかなりヤバそうな雰囲気だけど、CPUはかなり遊んでいるのでなんかいい方法ないかなーと思う次第です。

tigで新規ファイルが表示が出来なくなったので、設定を追加したら直った

tigとは?

Introduction · Tig

ターミナル上で使えるgitクライアント。gitのコマンドをガシガシ打っていくよりタイプ数も減るし見やすいので便利。

最近なぜか新しいファイルを表示してくれなくなったのでチョット不便だった。

環境

やったこと

/usr/local/etc/tigrc に以下の行を追加

set status-show-untracked-files = yes

f:id:crakac:20170720221810p:plain

無事表示されるようになった。めでたしめでたし。

github.com

DateUtilsでいい感じに時刻表示

Mastodonクライアントを作っていて、API叩いて降ってくる時刻の形式が "2017-07-17T12:24:30.721Z"となっているのでこれを上手いこと表示する。

val format = "yyyy-MM-dd'T'HH:mm:ss.SSS";
val sdf = SimpleDateFormat(format, Locale.getDefault())
val time = sdf.parse(source).time + TimeZone.getDefault().rawOffset
return DateUtils.getRelativeTimeSpanString(time, System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS)

こういう感じにするとちょうどいい感じになる

stackoverflow.com

DateUtils | Android Developers

TabLayoutでナウいUI

いつの間にか公式でいい感じのタブUIが楽に作れるようになってた。

material.io

Lollipop出始めの頃は全然公式でライブラリとかがなくて、PagerSlidingTabStripとか使ってたけど、今は公式で結構いい感じに提供されてるのね。

material.io

ドキュメントとかの調査は大事だなあと感じる。

いい感じにActionbarをスクロールに追従させるやつ https://guides.codepath.com/android/handling-scrolls-with-coordinatorlayout

API level 21以上(Lollipop以降)ならListViewでもいい感じに出来る。

stackoverflow.com

listView.isNestedScrollingEnabled = true

SwipeRefreshLayoutを使うと、ListViewが空っぽのときスクロールできない。EmptyViewをセットしておくと動いた。

AndroidStudio+Kotlinのアップデートで詰まった話

環境


2ヶ月ぶりにAndroidStudioを起動したら、Kotlinのバージョンが1.1.2-3から、1.1.3-2に上がっていたので上げてみたところビルドが通らなくなった。 どうやら自分以外にも遭遇している人がいたみたい。 stackoverflow.com

で、回答にこういうことが書いてあった。 gist.github.com

don’t use kapt { generateStubs true } } at all, it will not work with kapt3

書いてあったのでこれ削除した。

ついでにbuildtoolsやらsupportlibraryやらのバージョンも上げてみたら、supportlibraryがないよと怒られた。

developer.android.com

いつの間にやらSDK toolsからインストールするんじゃなくてmavenから落っことしてくるスタイルになったみたい。

allprojects {
    repositories {
        jcenter()
        maven {
            url "https://maven.google.com"
        }
    }
}

多分これで動いた。(他にもガチャガチャしたのでそれはちゃんと覚えてない)

diff --git build.gradle build.gradle
index dfc6deb..be0b64b 100644
--- build.gradle
+++ build.gradle
@@ -1,12 +1,12 @@
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
 
 buildscript {
-    ext.kotlin_version = '1.1.2-3'
+    ext.kotlin_version = '1.1.3-2'
     repositories {
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.3.1'
+        classpath 'com.android.tools.build:gradle:2.3.3'
         classpath 'com.google.gms:google-services:3.0.0'
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 
@@ -18,6 +18,9 @@ buildscript {
 allprojects {
     repositories {
         jcenter()
+        maven {
+            url "https://maven.google.com"
+        }
     }
 }
 
diff --git mobile/build.gradle mobile/build.gradle
index 1397a1a..722bab0 100644
--- mobile/build.gradle
+++ mobile/build.gradle
@@ -2,16 +2,17 @@ apply plugin: 'com.android.application'
 apply plugin: 'kotlin-android'
 
 android {
-    compileSdkVersion 25
-    buildToolsVersion "25.0.3"
+    compileSdkVersion 26
+    buildToolsVersion "26.0.0"
     defaultConfig {
         applicationId "com.crakac.ofutodon"
         minSdkVersion 21
-        targetSdkVersion 25
+        targetSdkVersion 26
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
     }
 
@@ -47,32 +48,27 @@ dependencies {
     androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
         exclude group: 'com.android.support', module: 'support-annotations'
     })
-    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
-    compile 'com.android.support:appcompat-v7:25.3.1'
-    compile 'com.android.support:support-v4:25.3.1'
-    compile 'com.android.support:design:25.3.1'
-    compile 'com.android.support:support-annotations:25.3.1'
-    compile 'com.android.support.constraint:constraint-layout:1.0.2'
+    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+    compile 'com.android.support:appcompat-v7:26.0.0-beta2'
+    compile 'com.android.support:support-v4:26.0.0-beta2'
+    compile 'com.android.support:design:26.0.0-beta2'
+    compile 'com.android.support:support-annotations:26.0.0-beta2'
-    compile 'com.jakewharton:butterknife:8.5.1'
+    compile 'com.jakewharton:butterknife:8.7.0'
-    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
-    kapt 'com.jakewharton:butterknife-compiler:8.5.1'
+    annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0'
+    kapt 'com.jakewharton:butterknife-compiler:8.7.0'
 }
 
-kapt {
-    generateStubs = true
-}
-
 repositories {
     mavenCentral()
 }

SNSに投稿した時間を可視化したい

Why

  • 最近はやりのマストドンにかなり時間を取られているので、なんとかして自分の時間を取り戻したい。
  • 睡眠時間を間接的に記録したい
  • なんか作りたい
  • GitHubの草みたいにしたい

How

進捗

概ね出来てきた。 f:id:crakac:20170628230146p:plain

GitHubっぽい表は、cal-heatmapを使用

ActiveRecordで、1分毎の投稿を集計して返す

Status.select("count(*) as toots, date_trunc('min', tooted_at) as t").where(user_id: id).where(tooted_at: start..stop).group('t')

↑の結果をJSONにして、ブラウザなりに返す

render json: stats.map{|s| [s.t.to_i, s.toots]}.to_h

困りどころ

cal-heatmapが表示用のJSONを取得するとき、こういう感じのパラメータが飛んでくるが、

start=2017-06-27T13:00:00.000Z&stop=2017-06-28T12:59:00.000Z

上述のselect文だと最後のマス目のcount()が合わない。2017-06-28T12:59:00.000Zからの一分間で投稿されていた場合はカウントできなくなるから。

毎回countするよりは、集計結果を別テーブルにして、ユーザーがSNSへの投稿を取得するのと同じタイミングで更新していくのがいいんだろうなという気持ちではある。

今読んでるもの

PostgreSQLのEXPLAINの読み方https://www.postgresql.jp/document/8.3/html/using-explain.html

さくらのVPS(Ubuntu16.04LTS)を借りてからSSHのポートを変更してローカルから接続するまで

TL;DR:

  • sshdがListenするポートは複数指定できるので、まずは追加してチェックしてから22番を削除するとよい
  • ufwは使わずiptablesだけでやる
    • というかufwでポートを開けようとしても開いてなさそう
  • iptablesの設定はサーバー再起動すると消えるのでなんとかする
    • iptables-persistentをインストールする(要検証)
    • /etc/iptables/iptables.rulesを直接いじる(本当にこれで大丈夫なのか?)

iptablesについてはiptables-persistentの方がいいと思います。インストールするだけみたいなので。

参照したところ

iptablesの設定方法 – さくらのサポート情報
iptablesによるパケットフィルタリング

コマンド群

# 作業用ユーザ作成
adduser USER_NAME

# sudo出来るようにする
gpasswd -a USER_NAME sudo

# ssh ポート変更、rootログイン不可、パスワードログイン不可などにする
vi /etc/ssh/sshd_config
# 設定反映
service sshd restart #bash補完だとsshdじゃなくてsshしか出なかったのはなんでだろう。

# ufwは止める
ufw disable

# iptables (さくらのヘルプより。あくまで参考例と但し書があるが、とりあえず使う)
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport $YOUR_SSH_PORT -j ACCEPT
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT

# iptablesの設定確認(今回の環境だと再起動で消し飛ぶのでなんとかする。)
iptables-save 

# 以下のどちらか
apt-get install iptables-persistent(未検証)
vi /etc/iptables/iptables.rules #iptables-saveで出てきた内容 or 上記iptablesコマンド群を書く

# 作業用ユーザssh公開鍵をおく
su USER_NAME #sshでログインしたいユーザに切り替える
cd
mkdir .ssh
echo "PUBLIC_KEY" > .ssh/authorized_keys
chmod 600 .ssh/authorized_keys
chmod 700 .ssh
exit

# rebooooooooooooooot!!!!!
reboot

これでたぶんいけるとおもいます。

以下おまけ

こういう記事は前にも書いてて 、そんなに変わってないやろバリバリーと同じように設定してたらハマったと言う話。 4年経ってると変わるんだね…。

環境

ローカル MacBook Pro (Retina, 13-inch, Mid 2014)

さくらのVPS
ゾーン 石狩第1ゾーン
メモリ 512 MB
ストレージ SSD 20 GB
CPU 1コア
お値段 685円/月

メモリ1GBあたりの値段は1GB, 2GBの方が安いけど今は性能は必要ないし困ったときに上げられるのがVPSの利点なのであまり考えないことにしよう。浮いたお金(281円)

なぜVPS

  • マストドンが流行っているから
  • そろそろサーバーがほしいから
  • rootが取れるから
  • 最悪管理画面からリセットできるから
  • やろうと思えばなんでも出来るから
  • 勉強にちょうどいいから
  • 色々作って公開したいから

色々理由はあるけど、時間的、金銭的、精神的余裕を最近取り戻してきたというのと、SoftSkillsという本を読んだことがきっかけ(日本語版Amazonリンク)。

VPSを借りる

さくらのVPSは先に書いたとおり、4年前にも借りたことがあった。 当時全く不満がなかったと記憶しているので、今回もさくらもVPSにした。 また、さくらの人がMastodon会議に出ていることと、世界最大のMastodonインスタンスmstdn.jpの足回りを支えているということを聞いてさくらインターネットに好意を持ったから。人間は感情的な生き物だからしかたないね。

OSインストー

OSはCentOS6/7、Ubuntu14.04LTS, 16.04LTS、その他いくつか選べるようになっていた。どちらかでなければいけない理由もないのでちょっとだけ馴染みがあるUbuntuにした。 ボタンポチポチするだけでOSのインストールが終わるVPS素晴らしい。

WebコンソールからSSHの設定をする

さくらのVPS(Ubuntu16.0.4LTS)の管理ユーザの名前が、rootではなくubuntuであると気付くまでにムダに時間がかかってしまった。 思い込み、視野狭窄、こういうものがバグを取りづらくしているんだなと身をもって学んだ。

疲れた

こういう記事見つけた。なんでこないだは見つからなかったの…もうだめ眠いよパトラッシュ… iptables の設定を保持する(iptables-save と iptables-restore)