GeoIP installation for PHP on Ubuntu 16.04

Installing GeoIP Module On Apache2, Ubuntu 16.04

  1. 以下面這個指令尋找Geoip的相關程式:
    apt search geoip
    

    將會從相關的套件裡找到 libapache2-mod-geoip

  2. 進行套件安裝與更新
    apt update
    apt upgrade
    apt install geoip-bin geoip-database libapache2-mod-geoip libgeoip1
    

    新增後,會產生 /usr/share/GeoIP/ 目錄。

  3. 下載GeoIP資料庫
    cd /usr/share/GeoIP/
    ls
    rm GeoIP.dat
    wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
    gunzip GeoIP.dat.gz
    wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
    gunzip GeoLiteCity.dat.gz
    wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz
    gunzip GeoIPASNum.dat.gz
    

    在 /usr/share/GeoIP/ 目錄裡,會有三個檔案GeoIP.dat, GeoLiteCity.dat, GeoIPASNum.dat。

  4. 更新apache2的geoip設置:nano /etc/apache2/mods-enabled/geoip.conf
    GeoIPEnable On
    GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
    GeoIPDBFile /usr/share/GeoIP/GeoLiteCity.dat
    GeoIPDBFile /usr/share/GeoIP/GeoIPASNum.dat基本上就已經設定完成。
  5. 重新啟動apache2
    apachectl -t
    sudo systemctl restart apache2.service

最後做一個範本試試看:

<?php 
$geoip_country_code = getenv(GEOIP_COUNTRY_CODE);
$geoip_country_name = getenv(GEOIP_COUNTRY_NAME);
$geoip_region = getenv(GEOIP_REGION);
$geoip_city = getenv(GEOIP_CITY);
$geoip_postal_code = getenv(GEOIP_POSTAL_CODE);
$geoip_latitude = getenv(GEOIP_LATITUDE);
$geoip_longitude = getenv(GEOIP_LONGITUDE);
 
echo 'Country code: '.$geoip_country_code.'&lt;br&gt;';
echo 'Country name: '.$geoip_country_name.'&lt;br&gt;';
echo 'Region: '.$geoip_region.'&lt;br&gt;';
echo 'City: '.$geoip_city.'&lt;br&gt;';
echo 'Postal code: '.$geoip_postal_code.'&lt;br&gt;';
echo 'Latitude: '.$geoip_latitude.'&lt;br&gt;';
echo 'Longitude: '.$geoip_longitude.'&lt;br&gt;'; 
?>

大功告成!!

MongoDB Replica Set設置,採用MongoDB 3.4

安裝MongoDB 3.4 for CentOS 7

vi /etc/yum.repos.d/mongodb.repo
mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc

然後在執行

yum install -y mongodb-org

另外,需要將selinux(/etc/selinux/config)設定為SELINUX=Passive或Disable,詳細可參考:
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/

MongoDB Replica Set介紹

MongoDB 算是一個很發展非常成熟的專案,大多數的系統裝起 MongoDB 應該都不會有太大的困難,今天介紹一下進階一點點的用法,Replica Set。資料庫系統做高可用 Replication (副本) 模式算是很常見的架構,在大陸稱為「主備模式」主要提供一份資料庫即時映射的副本,好讓主要的服務資料庫發生異常時可以接手工作。同時,另一個優勢就是可以進行資料備援,或者用來進行查詢。此外,當資料庫大到一定的程度,傳統的 dump 工具將很難完成任務,備援的方法就可以靠 Replication 來完成。

現在的 Open Source 系統發展得很快,官方提供的版本就早已經支援 Replication,想想以前的 PostgreSQL 在 5.x 的時候還要自己 Patch 第三方 Project 進行編譯,比起來真的省事多了。

官方有提供三種 Replica Set 架構 (Pattern),如下:

  • Three Member Replica Sets
  • Replica Sets with Four or More Members
  • Geographically Distributed Replica Sets

第一種 Three Member Replica Sets 是最常用的架構,由三個 MongoDB 節點組成,每個節點其實都是 Mongod 服務。第二種由更多的節點組成,備援能力更強,但我沒有研究,無從介紹。最後一種 Distributed Replica Sets 主要滿足異地備援的需求,這個聽起來不錯。

今天來介紹 MongoDB 最典型的副本架構,主要由三個節點構成,如下:

正常情況對 Primary 節點進行讀寫,資料會自動複製 (Replication) 到另外兩組 Secondary 節點,這些節點彼此透過 Heartbeat (每隔一段時間試探節點是否存活的方式) 檢測狀態,正常的情況每 2 秒會送出 Heartbeat,若是超過 10 秒沒有回覆,那就是 GG 了。如下:

當主要連線的節點發生故障時,會選出一台 Secondary 成為 Primary 接手工作,這樣的能力稱為 Automatic Failover,如下:

安裝與設定MongoDB Replica Set

大概知道工作原理以後,那麼我們來看看如何設定 Replica Set 架構。

開始之前我們先在 /etc/hosts 定義這三台要安裝的 hostname 與 IP Address,當然如果您想透過 DNS 服務來管理也是可以的。

vi /etc/hosts
10.21.1.45 mongsh1
10.21.1.46 mongsh2
10.21.1.44 mongsh3 

建立一個讓 Replica Set 專用的全新資料庫目錄

mkdir -p /home/mongod
chown -R mongodb:mongodb /home/mongod

三台伺服器皆需要做此設定,以方便確認資料庫的目錄以及位址。

設定 Replica Set 服務的 Mongod 設定檔(先不啟用驗證模式)

vi /etc/mongod.co
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

storage:
  dbPath: /home/mongod
  journal:
    enabled: true

processManagement:
  fork: true  
  pidFilePath: /var/run/mongodb/mongod.pid  # location of pidfile

net:
  port: 27019
  bindIp: 0.0.0.0  

這裡我們將 Replica Set 服務設定在 27019 Port,主要是因為之後會繼續建立 Sharding 架構,刻意避開標準的 27017 Port,保留 27017 Port 給之後的 Mongo Router 使用。如果您不打算建構 Sharding,那就直接使用 27017 即可,讓應用程式端不需要修改就可以使用。修改完設定檔後記得重新啟動 mongod 服務:

systemctl start mongod

先連線進到第一台 mongod 設定管理者帳密,上述可先在第一台伺服器設置(primary)

mongo mongsh1:27019
use admin
db.createUser( {
    user: "myUserAdmin",
    pwd: "",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  });
db.createUser( {
    user: "siteRootAdmin",
    pwd: "",
    roles: [ { role: "root", db: "admin" } ]
  });

也可以多新增一個admin帳號

db.createUser( {
    user: "admin",
    pwd: "",
    roles: [ { role: "root", db: "admin" } ]
  });

接著,透過以下命令建立一個 Key,並且複製到每一台機器 (mongsh1, mongsh2, mongsh3),之後每個 Mongod 實體會透過這把 Key 進行資料同步,接下來的動作比較複雜,順序不可以搞錯。很多人在這裡搞不定驗證功能,索性關閉驗證服務,這樣其實比較沒有保障,乖乖啟用驗證還是比較好的。

openssl rand -base64 741 > /home/mongod/mongodb-keyfile
chmod 600 /home/mongod/mongodb-keyfile
chown mongodb.mongodb /home/mongod/mongodb-keyfile

記得把這把 Key 放到每一台機器的 /home/mongodb-keyfile 檔案中。接下來我們就要啟用 Replica Set 與認證模式囉。再度編輯 /etc/mongod.conf 設定檔:

vim /etc/mongod.conf
security:
  keyFile: /var/lib/mongo/mongodb-keyfile
replication:
  replSetName: rs

在另外兩台伺服器可以修改設定檔為下

systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log
storage:
  dbPath: /home/mongod
  journal:
    enabled: true
processManagement:
  fork: true  
  pidFilePath: /var/run/mongodb/mongod.pid  # location of pidfile
net:
  port: 27019
  bindIp: 0.0.0.0  
security:
  keyFile: /home/mongod/mongodb-keyfile
replication:
 replSetName: bes

重新啟動 mongod 服務(另外兩台也要喔)

systemctl restart mongod

連線至剛剛的第一台 Mongod 並初始化 Replica Set,如下:

mongo mongsh1:27019
use admin
db.auth("siteRootAdmin", "");
rs.initiate()
rs.conf()

注意:正常完成時會有下面訊息出現:

接著新增另外兩台 Replica Set 節點,輸入以下命令:

rs.add("mongsh2:27019")
rs.add("mongsh3:27019")
rs.status()

注意:正常完成時會有下面訊息出現:

bes:PRIMARY> rs.status()
{
	"set" : "bes",
	"date" : ISODate("2017-09-09T14:51:02.381Z"),
	"myState" : 1,
	"term" : NumberLong(3),
	"heartbeatIntervalMillis" : NumberLong(2000),
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		},
		"appliedOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		}
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "mongsh1:27019",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 4051,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"electionTime" : Timestamp(1504964638, 1),
			"electionDate" : ISODate("2017-09-09T13:43:58Z"),
			"configVersion" : 67972,
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "mongsh2:27019",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 2961,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"optimeDurableDate" : ISODate("2017-09-09T14:50:59Z"),
			"lastHeartbeat" : ISODate("2017-09-09T14:51:00.676Z"),
			"lastHeartbeatRecv" : ISODate("2017-09-09T14:51:01.607Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "mongsh1:27019",
			"configVersion" : 67972
		},
		{
			"_id" : 2,
			"name" : "mongsh3:27019",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 2961,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"optimeDurableDate" : ISODate("2017-09-09T14:50:59Z"),
			"lastHeartbeat" : ISODate("2017-09-09T14:51:00.676Z"),
			"lastHeartbeatRecv" : ISODate("2017-09-09T14:51:01.606Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "mongsh1:27019",
			"configVersion" : 67972
		}
	],
	"ok" : 1
}
bes:PRIMARY> 

這樣就完成了,但如果出現有Statup誒
如果有伺服器出現:
“stateStr” : “STARTUP”,

例如:

bes:PRIMARY> rs.status()
{
	"set" : "bes",
	"date" : ISODate("2017-09-09T14:51:02.381Z"),
	"myState" : 1,
	"term" : NumberLong(3),
	"heartbeatIntervalMillis" : NumberLong(2000),
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		},
		"appliedOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		}
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "mongsh1:27019",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 4051,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"electionTime" : Timestamp(1504964638, 1),
			"electionDate" : ISODate("2017-09-09T13:43:58Z"),
			"configVersion" : 67972,
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "mongsh2:27019",
			"health" : 1,
			"state" : 0,
			"stateStr" : "STARTUP",
			"uptime" : 2961,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"optimeDurableDate" : ISODate("2017-09-09T14:50:59Z"),
			"lastHeartbeat" : ISODate("2017-09-09T14:51:00.676Z"),
			"lastHeartbeatRecv" : ISODate("2017-09-09T14:51:01.607Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "mongsh1:27019",
			"configVersion" : 67972
		},
		{
			"_id" : 2,
			"name" : "mongsh3:27019",
			"health" : 1,
			"state" : 0,
			"stateStr" : "STARTUP",
			"uptime" : 2961,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"optimeDurableDate" : ISODate("2017-09-09T14:50:59Z"),
			"lastHeartbeat" : ISODate("2017-09-09T14:51:00.676Z"),
			"lastHeartbeatRecv" : ISODate("2017-09-09T14:51:01.606Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "mongsh1:27019",
			"configVersion" : 67972
		}
	],
	"ok" : 1
}
#mongo localhost:27019
bes:PRIMARY> (有時候出現是bes:SECONDARY>,都可以設置)
bes:PRIMARY>use admin
bes:PRIMARY>db.auth("siteRootAdmin","")
bes:PRIMARY>var cfg={_id:"bes",members:[{_id:0,host:"mongsh1:27019"},{_id:1,host:"mongsh2:27019"},{_id:2,host:"mongsh3:27019"}]}
bes:PRIMARY>rs.reconfig(cfg)
bes:PRIMARY>rs.status()

這樣就大功告成了!!!

 

Reference:

MongoDB Replica Set 高可用性架構搭建

mongodb 副本集搭建

Git 指令

注意事項

由 project/.git/config 可知: (若有更多, 亦可由此得知)

  • origin(remote) 是 Repository 的版本
  • master(branch) 是 local 端, 正在修改的版本

平常沒事不要去動到 origin, 如果動到, 可用 git reset –hard 回覆到沒修改的狀態.

Git 新增檔案

  • git add . # 將資料先暫存到 staging area, add 之後再新增的資料, 於此次 commit 不會含在裡面.
  • git add filename
  • git add modify-file # 修改過的檔案, 也要 add. (不然 commit 要加上 -a 的參數)
  • git add -u # 只加修改過的檔案, 新增的檔案不加入.
  • git add -i # 進入互動模式

Git 刪除檔案

  • git rm filename

Git 修改檔名、搬移目錄

  • git mv filename new-filename

Git status 看目前的狀態

  • git status # 看目前檔案的狀態

Git Commit

  • git commit
  • git commit -m ‘commit message’
  • git commit -a -m ‘commit -message’ # 將所有修改過得檔案都 commit, 但是 新增的檔案 還是得要先 add.
  • git commit -a -v # -v 可以看到檔案哪些內容有被更改, -a 把所有修改的檔案都 commit

Git 產生新的 branch

  • git branch # 列出目前有多少 branch
  • git branch new-branch # 產生新的 branch (名稱: new-branch), 若沒有特別指定, 會由目前所在的 branch / master 直接複製一份.
  • git branch new-branch master # 由 master 產生新的 branch(new-branch)
  • git branch new-branch v1 # 由 tag(v1) 產生新的 branch(new-branch)
  • git branch -d new-branch # 刪除 new-branch
  • git branch -D new-branch # 強制刪除 new-branch
  • git checkout -b new-branch test # 產生新的 branch, 並同時切換過去 new-branch
  • # 與 remote repository 有關
  • git branch -r # 列出所有 Repository branch
  • git branch -a # 列出所有 branch

Git checkout 切換 branch

  • git checkout branch-name # 切換到 branch-name
  • git checkout master # 切換到 master
  • git checkout -b new-branch master # 從 master 建立新的 new-branch, 並同時切換過去 new-branch
  • git checkout -b newbranch # 由現在的環境為基礎, 建立新的 branch
  • git checkout -b newbranch origin # 於 origin 的基礎, 建立新的 branch
  • git checkout filename # 還原檔案到 Repository 狀態
  • git checkout HEAD . # 將所有檔案都 checkout 出來(最後一次 commit 的版本), 注意, 若有修改的檔案都會被還原到上一版. (git checkout -f 亦可)
  • git checkout xxxx . # 將所有檔案都 checkout 出來(xxxx commit 的版本, xxxx 是 commit 的編號前四碼), 注意, 若有修改的檔案都會被還原到上一版.
  • git checkout — * # 恢復到上一次 Commit 的狀態(* 改成檔名, 就可以只恢復那個檔案)

Git diff

  • git diff master # 與 Master 有哪些資料不同
  • git diff –cached # 比較 staging area 跟本來的 Repository
  • git diff tag1 tag2 # tag1, 與 tag2 的 diff
  • git diff tag1:file1 tag2:file2 # tag1, 與 tag2 的 file1, file2 的 diff
  • git diff # 比較 目前位置 與 staging area
  • git diff –cached # 比較 staging area 與 Repository 差異
  • git diff HEAD # 比較目前位置 與 Repository 差別
  • git diff new-branch # 比較目前位置 與 branch(new-branch) 的差別
  • git diff –stat

Git Tag

  • git tag v1 ebff # log 是 commit ebff810c461ad1924fc422fd1d01db23d858773b 的內容, 設定簡短好記得 Tag: v1
  • git tag 中文 ebff # tag 也可以下中文, 任何文字都可以
  • git tag -d 中文 # 把 tag=中文 刪掉

Git log

  • git log # 將所有 log 秀出
  • git log –all # 秀出所有的 log (含 branch)
  • git log -p # 將所有 log 和修改過得檔案內容列出
  • git log -p filename # 將此檔案的 commit log 和 修改檔案內容差異部份列出
  • git log –name-only # 列出此次 log 有哪些檔案被修改
  • git log –stat –summary # 查每個版本間的更動檔案和行數
  • git log filename # 這個檔案的所有 log
  • git log directory # 這個目錄的所有 log
  • git log -S’foo()’ # log 裡面有 foo() 這字串的.
  • git log –no-merges # 不要秀出 merge 的 log
  • git log –since=”2 weeks ago” # 最後這 2週的 log
  • git log –pretty=oneline # 秀 log 的方式
  • git log –pretty=short # 秀 log 的方式
  • git log –pretty=format:’%h was %an, %ar, message: %s’
  • git log –pretty=format:’%h : %s’ –graph # 會有簡單的文字圖形化, 分支等.
  • git log –pretty=format:’%h : %s’ –topo-order –graph # 依照主分支排序
  • git log –pretty=format:’%h : %s’ –date-order –graph # 依照時間排序

Git show

  • git show ebff # 查 log 是 commit ebff810c461ad1924fc422fd1d01db23d858773b 的內容
  • git show v1 # 查 tag:v1 的修改內容
  • git show v1:test.txt # 查 tag:v1 的 test.txt 檔案修改內容
  • git show HEAD # 此版本修改的資料
  • git show HEAD^ # 前一版修改的資料
  • git show HEAD^^ # 前前一版修改的資料
  • git show HEAD~4 # 前前前前一版修改的資料

Git reset 還原

  • git reset –hard HEAD # 還原到最前面
  • git reset –hard HEAD~3
  • git reset –soft HEAD~3
  • git reset HEAD filename # 從 staging area 狀態回到 unstaging 或 untracked (檔案內容並不會改變)

Git grep

  • git grep “te” v1 # 查 v1 是否有 “te” 的字串
  • git grep “te” # 查現在版本是否有 “te” 的字串

Git stash 暫存

  • git stash # 丟進暫存區
  • git stash list # 列出所有暫存區的資料
  • git stash pop # 取出最新的一筆, 並移除.
  • git stash apply # 取出最新的一筆 stash 暫存資料. 但是 stash 資料不移除
  • git stash clear # 把 stash 都清掉

Git merge 合併

  • Straight merge 預設的合併模式,會有全部的被合併的 branch commits 記錄加上一個 merge-commit,看線圖會有兩條 Parents 線,並保留所有 commit log。
  • Squashed commit 壓縮成只有一個 merge-commit,不會有被合併的 log。SVN 的 merge 即是如此。
  • cherry-pick 只合併指定的 commit
  • rebase 變更 branch 的分支點:找到要合併的兩個 branch 的共同的祖先,然後先只用要被 merge 的 branch 來 commit 一遍,然後再用目前 branch 再 commit 上去。這方式僅適合還沒分享給別人的 local branch,因為等於砍掉重練 commit log。

指令操作

  • git merge <branch_name> # 合併另一個 branch,若沒有 conflict 衝突會直接 commit。若需要解決衝突則會再多一個 commit。
  • git merge –squash <branch_name> # 將另一個 branch 的 commit 合併為一筆,特別適合需要做實驗的 fixes bug 或 new feature,最後只留結果。合併完不會幫你先 commit。
  • git cherry-pick 321d76f # 只合併特定其中一個 commit。如果要合併多個,可以加上 -n 指令就不會先幫你 commit,這樣可以多 pick幾個要合併的 commit,最後再 git commit 即可。

Git blame

  • git blame filename # 關於此檔案的所有 commit 紀錄

Git 還原已被刪除的檔案

  • git ls-files -d # 查看已刪除的檔案
  • git ls-files -d | xargs git checkout — # 將已刪除的檔案還原

Git 維護

  • git gc # 整理前和整理後的差異, 可由: git count-objects 看到.
  • git gc –prune
  • git fsck –full

Git revert 資料還原

  • git revert HEAD # 回到前一次 commit 的狀態
  • git revert HEAD^ # 回到前前一次 commit 的狀態
  • git reset HEAD filename # 從 staging area 狀態回到 unstaging 或 untracked (檔案內容並不會改變)
  • git checkout filename # 從 unstaging 狀態回到最初 Repository 的檔案(檔案內容變回修改前)

Git Rollback 還原到上一版

  • git reset –soft HEAD^
  • 編輯 + git add filename
  • git commit -m ‘rollback’

以下與 遠端 Repository 相關

Git remote 維護遠端檔案

  • git remote
  • git remote add new-branch http://git.example.com.tw/project.git # 增加遠端 Repository 的 branch(origin -> project)
  • git remote show # 秀出現在有多少 Repository
  • git remote rm new-branch # 刪掉
  • git remote update # 更新所有 Repository branch
  • git branch -r # 列出所有 Repository branch

抓取 / 切換 Repository 的 branch

  • git fetch origin
  • git checkout –track -b reps-branch origin/reps-branch # 抓取 reps-branch, 並將此 branch 建立於 local 的 reps-branch

刪除 Repository 的 branch

  • git push origin :heads/reps-branch
  • git push origin –delete reps-branch

Git 學習筆記 (1):安裝、選項設定、在本地使用 Git 工具

如何在NGINX+DJANGO平台設置SSL連線

於Django應用程式裡採用HTTPS對於保護用戶數據非常重要。 如果網頁應用程序具有用戶身份驗證,就是使用HTTPS的最好的理由。 否則,用戶名和密碼將通過HTTP以純文本格式傳播。 這意味著如果用戶使用公共互聯網連接,並且他登錄您的應用程序,他很容易受到駭客偷襲。

重要的是不僅安全的登錄,密碼更改和支付頁面與HTTPS,以及整個應用程序。 以下說明,將指導完成所有必要的步驟,以正確保護您的Django應用程式。

建立一個SSL證書

第一步是為您的Django應用程式獲取SSL證書。 有幾個選項:您可以生成自己的證書,您可以從Let’s Encrypt獲得一個免費的證書,或者您可以從互聯網上的許多公司購買一個證書。

在本教程中,我將使用從Namecheap註冊的Positive SSL的簡單商業SSL證書。

產生一個CSR代碼

CSR代表證書簽名請求,它是一個通常在服務器端生成的base64編碼數據。因為我們將使用Nginx作為web服務器,我們將使用openssl。

通常CSR openssl配置默認包含如下內容:

公共名稱(應頒發域名證書)
國家
州(或省)
地點(或城市)
組織
組織單位(部)
電子郵件地址

請在ssh的terminal上執行下列指令來產生CSR代碼:

openssl req -new -newkey rsa:2048 -nodes -keyout simpleacademy.key -out simpleacademy.csr

請注意,simpleacademy可以改為自己網域的名字
接著輸入相關訊息:

Country Name (2 letter code) [AU]:TW
State or Province Name (full name) [Some-State]:Taiwan
Locality Name (eg, city) []:Taipei
Organization Name (eg, company) [Internet Widgits Pty Ltd]:The Solar Systems Limited
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:simple.academy
Email Address []:[email protected]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:Simple is Better Than Complex

完成後就會產生兩個檔案,CSR跟KEY兩個檔案。
然後可以到NameCheap的Positive SSL來啟動有效的SSL認證金鑰。其他內容不再多做說明

安裝有效SSL金鑰

將驗證過的CSR與KEY放置到ㄧ個目錄,例如:/etc/nginx/ssl。

接著修改virtualhost的設定。

upstream simple_academy_server {
  server unix:/opt/simple_academy/run/gunicorn.sock fail_timeout=0;
}

# Redirect all non-encrypted to encrypted
server {
    server_name simple.academy;
    listen 80;
    return 301 https://simple.academy$request_uri;
}

server {
    server_name simple.academy;

    listen 443;  # <-

    ssl on;  # <-
    ssl_certificate /etc/nginx/ssl/simpleacademy_cert_chain.crt;  # <-crt所在位置
    ssl_certificate_key /etc/nginx/ssl/simpleacademy.key;  # <-key所在位置

    client_max_body_size 4G;

    access_log /opt/simple_academy/logs/nginx-access.log;
    error_log /opt/simple_academy/logs/nginx-error.log;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;  # <-這個很重要,記得加入
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://simple_academy_server;
            break;
        }
    }
}

這樣基本上就完成了!!

Mikrotik RouterOS設定OpenVPN,支援Windows、macOS、Android、與iOS

設備:Mikrotik RouterBoard RB2011UiAS-RM
1111_l

RouterOS版本:v.6.37.3 Released on 2016-Nov-28

  1. 首先於RouterOS設置Certificate憑證,這是設定OpenVPN最重要的步驟,Mikrotik介紹兩種方式,詳情參考這個網頁,一種透過CACert.org,另一種由OpenVPN提供的工具easy-rsa工具來產生的certificate憑證。這裡介紹第二種easy-rsa的方式,並且在windows上的openvpn client來產生的憑證。
  2. 到OpenVPN網站下載OpenVPN Client for Windows,下載安裝後,假設安裝的目錄於C:\Program Files\OpenVPN
  3. 以Administrator(系統管理者)的權限打開cmd視窗,然後cd到C:\Program Files\OpenVPN\easy-rsa目錄。
  4. 執行以下指令:
      1. init-config (只要執行一次即可,主要是複製環境設置的批次程式)。
      2. vars(設定環境設置)
      3. clean-all清除
      4. build-dh(產生表頭DH檔案)
      5. build-ca(產生CA,Certificate Authority憑證)

    snip20161214_1
    snip20161214_2

  5. 產生的憑證存在於keys這個子目錄,D:\Program Files\OpenVPN\easy-rsa\keys,將這個目錄下的ca.crt與ca.key取出來,準備上傳到RouterOS。
    snip20161214_3
  6. 上傳到RouterOS的檔案夾之後,開啟終端機(terminal)執行下面兩個指令將憑證匯入到系統裡:
    [jerry@routeros] /certificate>import file=ca.crt
    [jerry@routeros] /certificate>import file=ca.key
  7. 在Winbos或網頁管理介面檢查是否匯入正常
    snip20161214_4
  8. 若匯入正常則前面標籤為KT。
  9. 接著設定OPENVPN,利用WINBOS/網頁,按下PPP –> OVPN Server,再依照下面圖示輸入並選擇:PORT, Mode, Certificate的憑證,以及最後面支援的認證加密方式即可。
    snip20161214_7
  10. 設定帳號、Profile、IP POOL、與防火牆就不在此多做敘述,可參考這個地方

Windows客戶端設置:

  1. 先下載客戶端軟體:點擊到下載處,下載後安裝過程不再敘述。
  2. 將RouterOS的ca.crt與ca.key兩個檔案下載,並存放到客戶端軟體安裝目錄下的config位置,例如D:\Program Files\OpenVPN\config,另外製作一個auth.cfg,這檔案存放登入的帳號密碼,格式如下:
    user1
    1234
    

    user1:帳號, 1234:密碼

  3. 在同一個目錄再製作設定檔,副檔名必須為ovpn例如client.ovpn,內容如下範例:
    client
    dev tun
    proto tcp
    remote "xxx.xxx.xxx.xxx" 1194
    ca ca.crt
    keepalive 10 120
    cipher AES-256-CBC
    auth SHA1
    auth-user-pass auth.cfg 
    verb 5
    ;push "redirect-gateway local def1"
    ;push redirect-gateway
    route 0.0.0.0 0.0.0.0 192.168.89.1
    
  4. remote 後面接routeros的網址,後面連接的Port位置。
  5. ca 就是告知憑證的地方
  6. auth-user-pass告知採用帳密方式登入,帳密則儲存於auth.cfg這個檔案。
  7. 一般採用push redirect-gateway或push redirect-gateway local def1就可以指定把所有流量導入vpn接口,但有時候採用無線網路或其他網路會更改WAN時無效,所以可以加入route指令強迫將default gateway轉入。
  8. 到此基本上已經完成,只要在下面的icon點擊,按右鍵在按下connect即可連線。

snip20161214_8

snip20161214_9

最後確認是否連線,只要打開cmd視窗,執行tracert www.hinet.net看看是否從routeros出去即可。

macOS客戶端設置:

    1. 首先,下載客戶端軟體:按這裡
    2. Tunnelblick.com是個開放原始碼的軟體,好用又方便,比OpenVPN Connect好用許多。
    3. 下載安裝後,仍採用ovpn設定檔進行匯入,設定檔的範例如下:
      client
      dev tun
      proto tcp
      remote xxx.xxx.xxx.xxx 998
      ca /Users/xxxxx/openvpn_files/ca.crt
      keepalive 10 120
      cipher AES-256-CBC
      auth SHA1
      auth-user-pass /Users/xxx/openvpn_files/auth.cfg
      verb 5
      push redirect-gateway
      
    4. 首先也是要把routeros的ca.crt與ca.key放到一個指定目錄,例如:自身的目錄底下做一個openvpn_files的子目錄,把ca.crt, ca.key放到這裡,另外,帳密檔案(前面已述)也放在同一個目錄,然後依照上面的設定檔指定位置即可。
    5. 另外,auth.cfg如windows所述,也要放在同一個目錄下。
    6. 最後用push redirect-gateway來告知流量都要往vpn導入,但是還有個地方必須設定才可以,在設定裡要把第一項,如下圖,打勾才行!!snip20161214_10
    7. 以上設定好基本上就已經完成,再依照下面方式點擊登入即可。

snip20161214_11

 

Android客戶端設置:

首先,須先製作一個設定檔,此設定檔可以提供Android與iOS來使用,除了類似Windows/macOS的寫法外,最主要把ca內容也寫進去,就不再提供ca.crt/ca.key兩個檔案了。因此,只要匯入此設定檔與auth.cfg即可。

client
dev tun
proto tcp
remote xxx.xxx.xxx.xxx 998
keepalive 10 120
cipher AES-256-CBC
auth SHA1
auth-user-pass auth.cfg
verb 5
redirect-gateway
<ca>
-----BEGIN CERTIFICATE-----
MIID6TCCA1KgAwIBAgIJAMdQ8zo5QJVoMA0GCSqGSIb3DQEBCwUAMIGqMQswCQYD
VQQGEwJUVzELMAkGA1UECBMCVFcxDzANBgNVBAcTBlRhaXBlaTEiMCAGA1UEChMZ
<<<< ca.crt裡面的內容拷貝複製到這個地方>>>>
yWXDkv30Z7gfDCiZcJcF5PfROJeDpPQoVIgRTOzCAz8N3+awWIkRLUyFCk3FWiBH
CO6mikuz8szxhtNNZZkntnEsFyjW3s0aGuYSzQAJ3Rp2XRiYm7X5sPerBGTL
-----END CERTIFICATE-----
</ca>

<key>
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOmHGjK2riMqBq4+
JgSUNJqKoz9fz9SY3Wsol423syUZNNX4htlLP/XtJ6U9r0f4Rqr+P/YaXb4c8AAc
<<<< ca.key裡面的內容拷貝複製到這個地方>>>>
gw7RBGga25wpEyRFyPIoGP5oG7uEsBlv0wRdzLr/7dqORIXWVXH01xkCQDpWw9zW
J+3h8UyEWKIaeIMsffxchQzjpxFqr5w/NBAcZdJUndExpPb5c6dDWT5la0wjo/un
up1QejfWdFR9vuU=
-----END PRIVATE KEY-----
</key>
接著到GOOGLE PLAY下載軟體:GOOGLE PLAY
然後,將此設定檔(xxx.ovpn)與auth.cfg透過usb,拷貝到一個目錄下,然後打開openvpn app,進行匯入
import --> import Profile from SD card,然後選擇所存放的目錄,找到該ovpn檔案,進行匯入即可。
接著按下Connect即可連線到RouterOS的VPN Server

iOS客戶端設置:

App下載網址:iTunes App Store

iOS的設定檔與Android可共用,就不再多述。只要將設定檔與auth.cfg匯入即可。方法如下:

將iPhone/iPad連到電腦,打開iTunes,然後將這設定檔與auth.cfg複製到OpenVPN的地方,如下所示,即可。

snip20161214_12 然後在iPhone/iPad打開openvpn,即會出現設定檔的名稱,加入即可。