27 days ago

VPS linode
64bit, OS: Ubuntu 16.04 LTS

Update system

apt update && apt upgrade

Install docker

apt install docker.io

Start docker

systemctl start docker
systemctl enable docker

pull docker image we need

docker pull imhang/kcp-shadowsocks-docker

run image for test

docker run -p 443:443 -p 443:443/udp -p 9443:9443/udp --rm -it imhang/kcp-shadowsocks-docker

download mac client from github
kcptun

run kcptune client command is

./client_darwin_amd64 -r “yourvps:9443" -l ":8388" --crypt none --key 123456 --mtu 1400 --parityshard 0 --nocomp false

run ssr client with

PORT 443
PASSWORD 123456
METHOD   chacha20
SS_TIMEOUT  600

Now we need to run the server as service

docker run -d --restart=always -e "SS_PORT=443" -e "SS_PASSWORD=123456" -e "SS_METHOD=chacha20" -e "SS_TIMEOUT=600" -e "KCP_PORT=9443" -e "KCP_MODE=fast" -e "MTU=1400" -e "SNDWND=1024" -e "RCVWND=1024" -p 443:443 -p 443:443/udp -p 9443:9443/udp --name ssserver imhang/kcp-shadowsocks-docker

and client command become

./client_darwin_amd64 -r "45.79.215.97:9443" -l ":8388" --crypt none --key 123456 --mtu 1400 --parityshard 0 --nocomp false --sndwnd 1024 --rcvwnd 1024
 
3 months ago

deploy process for a new ubuntu 16.04 64bit

part I setup linux machine for secure reason

verify root account

$ ssh root@remote
$ exit

ssh to remote with local pub key

$ ssh-copy-id root@remote

login again without password

add new user doudouappadmin

$ adduser doudouappadmin

$ adduser doudouappadmin sudo

$ exit

verify with doudouappadmin

$ ssh doudouappadmin@remote
$ exit

login with pub key without password

$ ssh-copy-id doudouappadmin@remote

login with doudouappadmin to disable root login

$ sudo vim /etc/ssh/sshd_config

edit

PermitRootLogin no

make change effect

$ sudo systemctl restart sshd
$ exit

PartII update system and basic lib

$ ssh doudouappadmin@remote

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo dpkg-reconfigure tzdata

Geographic aera - Asia
Time zone - Shanghai

support multilanguage

$ sudo locale-gen zh_TW zh_TW.UTF-8 zh_CN.UTF-8 en_US.UTF-8

用vi编辑器打开

$vim ~/.bashrc

在空白处新增行

export LC_ALL="en_US.UTF-8"

执行

$ source ~/.bashrc

install basic application and lib

$ sudo apt-get install build-essential git-core curl libssl-dev libreadline5 libreadline-gplv2-dev zlib1g zlib1g-dev libcurl4-openssl-dev libxslt-dev libxml2-dev libffi-dev git vim

install RVM

$ \curl -sSL https://get.rvm.io | bash

then run

$ source ~/.rvm/scripts/rvm

install Ruby

$ rvm install 2.3.1

confirm ruby

$ rvm list

setup ruby china mirror

$ gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
$ gem sources -l
*** CURRENT SOURCES ***

https://gems.ruby-china.org
## confirm there is only one gems.ruby-china.org
$ gem install bundler

install RMagick

$ sudo apt-get install imagemagick
$ sudo apt-get install libmagickwand-dev
$ gem install rmagick

install Passenger

install Passenger

$ gem install passenger

install Nginx and merge Passenger

$ rvmsudo passenger-install-nginx-module

选择Ruby & NodeJS

再选择选项1. Yes: download, complie and install Nginx for me. (recommended)

选择安装目录, 可以直接按回车,使用默认安装目录[/opt/niginx]

start nginx

$ git clone git://github.com/jnstq/rails-nginx-passenger-ubuntu.git
$ sudo mv rails-nginx-passenger-ubuntu/nginx/nginx /etc/init.d/nginx
$ sudo chown root:root /etc/init.d/nginx

edit nginx server 档(只有 Ubuntu 16+ 需要)

$ sudo vim /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/opt/nginx/logs/nginx.pid
ExecStartPre=/opt/nginx/sbin/nginx -t
ExecStart=/opt/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target

restart Nginx

$ sudo /etc/init.d/nginx restart

Nginx

browser http://xx.xx.xx.xx to verify nginx

install rails 5.0.3

$ gem install rails -v 5.0.3

install nodejs

$ sudo apt-get install npm

install PostgreSQL

$ sudo apt-get install postgresql postgresql-contrib libpq-dev
$ gem install pg

update postgres password
login psql

$ sudo -u postgres psql

update postgres password

\password postgres

leave by

\q

let Rails know to connect db with the account

# sudo vim /etc/postgresql/9.5/main/pg_hba.conf

update all md5 to peer and save and run

$ sudo /etc/init.d/postgresql reload

镜像文件到此为止

让远端机器可以去 github 拉档案

$ ssh doudouappadmin@remote

生成ssh key

$ key ssh-keygen

查看pub key

$ more ~/.ssh/id_rsa.pub

去Github的仓库里,项目里面贴到 Settins -> Deploy keys
去远端机测试

$ ssh -T git@github.com

deploy cap if there is no cap 当前已经使用cap了。没有cap的进行如下

使用 Capistrano 部署项目

修改 Gemfile,加入以下内容

group :development do
gem "capistrano", "~> 3.4"
gem "capistrano-rvm"
gem "capistrano-rails"
end
$ bundle install

然后执行

$ cap install

修改 config/deploy.rb

lock '3.6.1'  # 每个人按自己的默认版本,不一定要是"3.6.1"

set :application, 'vidopk'

set :repo_url, 'git@github.com:jiezhon/videopk.git'  # 这里填的是每个人自己的repo地址



set :deploy_to, "/home/doudouappadmin/videopk"

注: 这里示例项目为videopk,也是Gitup的仓库名

如果有图片,视频需要存在其他的云存储服务器,关于云存储的密钥文件application.yml用linkded_files实现从shared目录下读取

set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml', 'config/application.yml')

修改 Capfile

require "capistrano/rvm"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
require "capistrano/passenger"

修改config/deploy/production.rb
加上一行,配置server和user

server "1.1.1.1", user: "doudouappadmin", roles: %w{app db web}, my_property: :my_value

在远端生成档案
执行

$ cap production deploy:check

远端服务器配置

在远端机的shared目录下的设定档

$ vim database.yml
production:
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
database: videopk_production
username: postgres
password: YOURPASSWORD
$ vim secrets.yml

在本机上执行

$ rake secret

产生密钥
然后贴到远端机的

$ vim shared/config/secrets.yml
production:

  secret_key_base: 上面产生的那串密钥

配置upyun存储的相关密钥

$vim application.yml
production:
  UPYUN_OPERATOR_ID: "11"
  UPYUN_OPERATOR_PASSWORD: "11"
  UPYUN_BUCKET: "11"
  UPYUN_HOST: "http://11.b0.upaiyun.com"

正式 deploy

执行

$ cap production deploy

第一次会卡在 bundle install 比较久,并且第一次deploy会失败,因为 production db 还没创建
出错信息为 “FATAL: database "videopk_production" dose not exist”
创建DB

到最新的release目录下面

$ cd videopk/released/xxxxxxxx
RAILS_ENV="production" bundle exec rake db:create

再跑一次 cap production deploy

设定 Nginx

$ sudo vi /opt/nginx/conf/nginx.conf
    server {
        listen       80;
        server_name  dd.doudouapp.com;

        root /home/doudouappadmin/videopk/current/public;
        passenger_enabled on;
        client_max_body_size 30M;
    }

重开Nginx

$ sudo /etc/init.d/nginx restart

迁移数据盘

$ sudo disk -l

Device     Boot Start      End  Sectors Size Id Type
/dev/vdb1        2048 41943039 41940992  20G 83 Linux
$ sudo mkdir /data
$ sudo mount /dev/vdb1 /data
$ sudo chown -R postgres:postgres /data/pkdata
#### only if you want to init a disk
$ sudo su - postgres 
$ /usr/lib/postgresql/9.5/bin/initdb -D /data/pkdata
$ exit
### 
$ sudo /etc/init.d/postgresql stop
$ sudo su - postgres
$ /usr/lib/postgresql/9.5/bin/pg_ctl -D /data/pkdata -l logfile start
$ exit
 
4 months ago

rails 5.0, devise 4.0
thanks for gist
and devise gem override controller

Part I: Add api

$git branch api_v1
$git checkout api_v1
$rails generate controller api/v1/battles

and copy battles_controller to the new file with some additional code

class Api::V1::BattlesController < ApplicationController
  before_action :authenticate_user!, only: [:follow_left_video, :unfollow_left_video, :follow_right_video, :unfollow_right_video]
  before_action :find_battle, only: [:follow_left_video, :unfollow_left_video, :follow_right_video, :unfollow_right_video]

  def index
    respond_to :json
    @battle = Battle.recent.first

and create file battles.json.jbuilder under app/view/api/v1/battles with content

if @battle.present?
  json.extract! @battle, :id, :title, :description, :left_video_id, :right_video_id
else
  return "no battle"
end

and add new content in route.rb

  namespace :api do
    namespace :v1 do
      resources :battles do
        member do
          post :follow_left_video
          post :unfollow_left_video
          post :follow_right_video
          post :unfollow_right_video
        end

    # resources :videos do
    #   resources :video_comments, only: [:new, :create]
    # end
      resources :battle_comments, only: [:new, :create]
      end
    end
  end

we can test it by input xxx.xx/api/v1/battles.json in browser.

$ git add .
$ git commit -m"api done"
$ git checkout master

Part II: add json login based on devise

Step 1: override devise

from devise gem devise gem override controller

$ git checkout master
$ git branch override_devise
$ git checkout override_devise
$ rails generate devise:controllers users

update devise content in route.rb

Rails.application.routes.draw do
  devise_for :users, controllers: {
    sessions: 'users/sessions'
  }
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root 'battles#index'

test it now, the user management should still work like before.

Step2 add new gem simple_token_authentication

# Gemfile
gem 'simple_token_authentication', '~> 1.0' # see semver.org

and add one more attribute for user model

$ bundle install
$ rails g migration add_authentication_token_to_users "authentication_token:string{30}:uniq"
$ rails db:migrate

add following code to user.rb in model
on top of user.rb

# app/models/user.rb

class User < ActiveRecord::Base
  acts_as_token_authenticatable
  # Note: you can include any module you want. If available,
  # token authentication will be performed before any other
  # Devise authentication method.
  #
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :invitable, :database_authenticatable,
         :recoverable, :rememberable, :trackable, :validatable,
         :lockable

  # ...

on bottome of user.rb

   def reset_authentication_token!
     self.authentication_token = generate_authentication_token("")
     self.save
   end
 
  private
  def generate_authentication_token(token_generator)
    loop do
      token = Devise.friendly_token
      break token unless User.where(authentication_token: token).first
    end
  end

terst login and logout again, should still work well.

now update app/controllers/users/sessions_controllers.rb

class Users::SessionsController < Devise::SessionsController
  # before_action :configure_sign_in_params, only: [:create]
  skip_before_action :verify_authenticity_token, if: :json_request?


  def json_request?
    request.format.json?
  end
  # GET /resource/sign_in
  # def new
  #   super
  # end

  # POST /resource/sign_in
  def create
    if json_request?
      email = params[:email] if params[:appid]
      password = params[:password] if params[:appsecret]

      id = User.find_by(email: email).try(:id) if email.presence

      # Validations
      if request.format != :json
        render status: 406, json: { message: 'The request must be JSON.' }
        return
      end

      if email.nil? or password.nil?
        render status: 400, json: { message: 'The request MUST contain the user email and password.' }
        return
      end

      # Authentication
      user = User.find_by(email: email)

      if user
        if user.valid_password? password
          user.reset_authentication_token!
          # Note that the data which should be returned depends heavily of the API client needs.
          render status: 200, json: { email: user.email, authentication_token: user.authentication_token, id: id }
        else
          render status: 401, json: { message: 'Invalid email or password.' }
        end
      else
        render status: 401, json: { message: 'Invalid email or password.' }
      end
    else
      #if json_request? == false
      super
    end
  end

  # DELETE /resource/sign_out
  def destroy
    if json_request?

      # Fetch params
      user = User.find_by(authentication_token: params[:user_token])

      if user.nil?
        render status: 404, json: { message: 'Invalid token.' }
      else
        user.authentication_token = nil
        user.save!
        render status: 204, json: nil
      end
    else
      super
    end
  end

  # protected

  # If you have extra params to permit, append them to the sanitizer.
  # def configure_sign_in_params
  #   devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute])
  # end
end

now we support json login, following is test code in python

import requests
rooturl = "https://lin-rails-tt-myrual.c9users.io"
loginRes = requests.post(rooturl+ "/users/sign_in.json", params={'appid':'app123', 'appsecret':'333', 'email':'admin@test.com', 'password':'123456'})
print(loginRes.text)

Step3 merge json api and simple token

git add .
git commit -m"json login done"
git merge api_v1

test all web browser login and json login again.

now we add protect to api/v1/battles controller

class Api::V1::BattlesController < ApplicationController
  #before_action :authenticate_user!, only: [:follow_left_video, :unfollow_left_video, :follow_right_video, :unfollow_right_video]
  before_action :find_battle, only: [:follow_left_video, :unfollow_left_video, :follow_right_video, :unfollow_right_video]
  #acts_as_token_authentication_handler_for User, fallback: :none
  acts_as_token_authentication_handler_for User , only: [:index, :show, :follow_left_video, :unfollow_left_video, :follow_right_video, :unfollow_right_video]

  def index

and verify in browser again, we should see error now.

now it is time to verify with python code

import requests
rooturl = "https://lin-rails-tuto2-myrual.c9users.io"
failedRes = requests.get(rooturl+"/api/v2/battles.json")
print(failedRes.text)
loginWithoutAppidRes = requests.post(rooturl+ "/users/sign_in.json", params={'appsecret':'333', 'email':'admin@test.com', 'password':'123456'})
print(loginWithoutAppidRes.text)
raw_input()

loginRes = requests.post(rooturl+ "/users/sign_in.json", params={'appid':'app123', 'appsecret':'333', 'email':'admin@test.com', 'password':'123456'})
print(loginRes.text)
auth_token = loginRes.json()['authentication_token']
successRes = requests.get(rooturl+ "/api/v2/battles.json", params={'appid':'app123', 'appsecret':'333', 'user_email':'admin@test.com', 'user_token':auth_token})
print(successRes.text)
raw_input()
failedRes = requests.get(rooturl+"/api/v2/battles.json")
print(failedRes.text)

now the url /api/v1/battles.json is protected

 
4 months ago

感谢

https://gorails.com/guides/free-ssl-with-rails-and-nginx-using-let-s-encrypt

linode ubuntu 16.04.02 安装let’s encrypt

首先这个版本的ubuntu没有add-apt-repository,所以要先安装相关的包

sudo apt-get install software-properties-common python-software-properties

然后安装certbot

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot

假设rails 运行在 /home/doudouappadmin/videopk/current/public

sudo letsencrypt certonly --webroot --webroot-path /home/doudouappadmin/videopk/current/public --renew-by-default --email lilin@myrual.me --text --agree-tos  -d dd.doudouapp.com

然后编辑nginx配置文件来启用ssl

sudo vim /opt/nginx/conf/nginx.conf

打开ssl 相关内容
然后

server {
    listen       443 ssl;
    server_name  dd.doudouapp.com;

    ssl_certificate      /etc/letsencrypt/live/dd.doudouapp.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/dd.doudouapp.com/privkey.pem;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    root /home/doudouappadmin/videopk/current/public;
    passenger_enabled on;
    client_max_body_size 30M;
}

然后用ngix 校验一下语法

sudo nginx -t
 
5 months ago

万维刚-放诸古今皆准的权力规则 提供了一个观察方法,解释了很多现象。

唯一令人难受的是指出了一个事实,人类是愚蠢的,短视的,有理想但是不承认现实的人是会头破血流的,而且是活该。

 
5 months ago

如果在做重要选择的时候心里不平静,那么这个选择极有可能是错误的。
不平静可能来自于消极的东西,
比如对某个人的不满意(比如老板,或者同伴),某个事情的不满意(某个决策),现状的不满意(无进展,受限制)。

不平静也可能来自于积极的东西,
对某个人的特别喜欢(有个人魅力),某个事情的高度看好(很牛的概念和趋势),某个特别大的推动因素(手握充沛的资金或者某种资源)。

想一想,什么更重要?

 
6 months ago

右派写了一篇被左派认定恐穆的英文内容。
左派写了一个辟谣内容,引用了一个据说客观的英文研究报告,并得出恐穆毫无根据的结论。
霍炬在朋友圈分享了左派的这篇文章,并支持该结论。
TK在微博批评了这篇文章的漏洞。
左派不服,直接反击。
TK在微博继续批评了这次反击的漏洞。

针对这个事情发表意见的还有老赵(右),StephanieYR(左)。

这是一次对我来说很特殊的事件。TK和霍炬都是我认为很厉害的人。这次竟然有两个相反的观点。
我以很次的英文水平读了一下英文研究报告,我的结论是无神论者(大部分中国人以及共产党员)和犹太人在33年后会非常不利。

那么问题来了,为什么我们无法面对现实,为什么我们会那么相信我们过去的想法,我们为什么会受过去的选择的影响。

 
6 months ago

时间投资刚刚有一篇文章
http://mp.weixin.qq.com/s/hnj-pJVbOusBn2GIuVJDXA

李笑来刚刚在得到专栏里面写了一篇 最简单的安全投资策略是什么

民间还有类似的话,男怕入错行。

想要获得长周期下的持续(增长/回报)都需要遵循两个原则:

  1. 选择一个持续快速增长的事情(个股,行业,事业)。
  2. 持续的在这个行业积累。

但是遵循这两个原则需要克服人类与生俱来的一些生物本能:

  1. 要更多:个股/行业/职业 很多很多,符合持续快速增长很少很少的。
  2. 要更快:你必须认识到10个月才能生个孩子,你至少以年为时间单位来思考。不能猴急。

关于行业说说具体的举例子。

我2002年毕业,进入电子行业做电视机,具体工作写软件。
随着电子行业的发展,眼看着电视芯片供应商从欧美高大上切换到联发科,我后来离开了电视行业,进入了智能卡行业,然后是平淡的6年。
6年之后我终于离开传统的电子行业,算是进入了互联网行业。

一起做电视的朋友中有一个机械专业毕业的,和我一起写软件,做了两年多电视软件以后进入了手机软件开发,那还是欧美高大上芯片供应商的时代。
但是很快联发科的方案就横扫了市场,这哥们就换了工作做Android App开发,做了一年以后又成为了iOS app 开发,然后进了糯米团,年薪大概50万左右。早早在北京买了房。

我和朋友相比,智商一样,学历一样,毕业院校水平一样,第一份工作一样,仅仅是因为第二份工作所在的行业不同,他的收入和就业选择就比我好了很多。

关于投资说说我个人的例子。

基本上我一直是股市里面的失败者,没有赚过钱,后来读了很多书,也写过程序来搞投机,也尝试过仿真的股指期货。无一例外的失败。

在我灰心丧气很长一段时间以后,老婆要求做一些财务上的投资,虽然不愿意做,但是抱着亏了也认了的态度做了一些不一样的尝试。
就是长期小额定投。
剩下的难题是投什么。
我没有选择黄金,外汇,因为我不懂。
我选择了股票基金,因为懂一些。

选择的标准是
过去若干的大的上升波段,涨幅都能位于前50名的基金。

这个标准生效的假设是:

  1. 该基金的表现可以继续持续。
  2. 股市总体有上升。

按结果说:这次定投投了很久,赶上了一波大涨,然后我们因为买房卖掉了全部基金。算是回报非常好。

反思:

  1. 如果没有一波猛涨,这次投资的收益并不好。
  2. 如果没有买房的外部事件触发,就不会有如此好的收益。
  3. 那一波大涨中,该基金表现并不是最出色的。
 
7 months ago

黑客TombKeeper 曾说罗振宇贩卖的是智商提高的幻觉。 我想是的,我自己就喜欢这个感觉。其实这和人需要买书,杂志来读意思是一样的,都是让买的人以为自己智商提高了。

但是从最终结果看,真正通过读书能提高认识水平的人是人群中的少数,因为所有人都会喜欢恍然大悟的快感。但是只有行动才能让知识对生活真的产生影响,大脑在行动过程中需要挣扎一番才能让脑细胞重组,从而掌握这个知识。

彪悍一只猫在微信公众号一块听听上讲的普通人崛起的十大狠招里面讲了他读书的方法

  1. 我有没有真正理解作者所表达的内容?
  2. 理解以后我是不是也应该做点什么?
  3. 如果是要做点什么,结合自身实际,我该怎么去做?

李笑来说非虚构类的内容只看书。

都是一个意思,看一本书,如果真的要理解,行动,估计要花费几个月甚至几年。
那么就只能看真的有用的书籍了,好在真正有用的书其实不多。

那么是不是就不要订阅那么多收费专栏了呢?

NO!NO!NO!

我可以肯定的说,一定有些专栏是水的,一定有些讲座觉得不值,只是你很难提前预测,但是因此一个都不买,属于因噎废食。

一分钱都不浪费是做得到的么?

所以,要行动,要行动, 要行动。

写下来是第一步。
然后继续行动,继续行动,继续行动。

 
7 months ago

和菜头在微信公众号-槽边往事:《未来并非我所能见》里面有这样一个结语:

能够洞见未来的人的确有,比如:乔布斯。可惜,我不是。我也曾经想要知道未来的底牌是什么,好提前准备。但是,当未开把牌都摊开在我面前打的时候,我都根本没有意识到,更别说什么“采取主动”。

没有,没有洞见,没有提前准备。我做了我喜欢做的事情,没有得到也还在付出,我一直在错过未来,很努力都只能追上末班车。然后,这么追着追着,突然我就站在未来里了。

我读到这里,感到有点悲伤。因为我做了我喜欢的事情,有一些回报,但是依然不能足以让家人放心。也努力的想洞见未来,可惜直到今天也没有。

我猜测“然后,这么追着追着,突然我就站在未来里了”这一句是写出来让大家留有一点希望的,毕竟人都需要希望才能坚持下去。

可是,对大多数人来说,也就是我来说,失败是人生常态,只能不断的做自己喜欢的事情,不断的努力提高自己的价值,不断努力让自己更有用,是不是真的能站在未来,我想是可以的,但是我无法预计需要多长时间。

Joel Spolsky 和李笑来的经历都说明了一个道理,正确的价值观和方法论配合上有效的商业逻辑可以产生巨大的价值。