如何使用 Gitlab 搭配 Gitlab CI/CD 進行自動化測試

如何對在 Gitlab 上面的專案進行 CI/CD 可以怎麼做呢? Gitlab 可以搭配 Gitlab CI/CD 來執行 CI/CD , Gitlab CI/CD 會依照所設定的設定檔將指令交由 Gitlab Runner 來執行進而完成整個 Pipeline ,在 Gitlab CI 的世界有幾個名詞。

  • Pipeline: 一個 CI/CD 的流程,串接多個 Job 與多個 Stage 組成,任何一個 Job 失敗都視為這個 Pipeline 失敗(除非該 Job 有設定為 allow fail )。
  • Stage: 階段,一個 Stage 可以由多個 Job 組成,同個 Stage 中的 Job 都必須通過才會執行下個 Stage 。
  • Job: 工作,依照 .gitlab-ci.yaml 所設定之設定交由 Gitlab Runner 來執行,並且提交這個 Job 的執行狀態(綠燈、橘燈、紅燈)。

在 repository 根目錄直接新增 .gitlab-ci.yaml 檔案,這邊有個範例給大家參考。

stages: // 定義這個 Pipeline 有的 Stage
  - build // Stage 名稱
  - test

Build: // Job 名稱
  stage: build // stage name 需要與上方的 stages 名稱一致
  image: composer // 這個 Job 需要使用的 docker image ,以範例來說使用的是 compose:latest
  cache:
    key: "$CI_COMMIT_REF_SLUG"
    paths:
      - vendor/
  script: // 需要執行的指令
    - composer install --ignore-platform-reqs
  artifacts: // 透過 artifacts 將 vendor 這個資料夾 pass 給下個 Stage 的 Job 使用
    expire_in: '10 mins'
    paths:
      - vendor/

Test:
  stage: test
  image: php:7.4-cli
  script:
    - ./vendor/bin/phpunit // 執行 PHPUnit 測試

通常在 Continuous Integration(CI) 階段我們會設計一些流程來進行專案的驗證,目的在於透過自動化導入檢測並且減少人為介入進而提升專案穩定度。

  • 專案安裝
  • 專案檢測(靜態程式碼分析、 coding style 檢查、 docker image best practice 檢測 …)
  • 專案測試
    • 單元測試 Unit Test
    • 整合測試 Acceptance Test
    • End-to-End Testing
  • 專案打包(在容器化世代通常會需要打包 docker image 供其他容器管理器進行使用)

當然在 CI 階段可以做的事情不只這些,就看專案的特性來進行調整即可,撰寫 .gitlab-ci.yaml 完成後執行 git push 推送到專案上就會生效了,即可在 Gitlab > Repo > CI/CD > Pipelines 看到執行結果。

https://gitlab.com/coosos810609/phpunit-demo-with-ci/pipelines/134780795

每個 Stage 中各自 Job 的執行狀態也可以直接點擊查看,畫面中可以看到會將設定在 .gitlab-ci.yaml 中的指令一一執行,並且將執行結果呈現在畫面中。

https://gitlab.com/coosos810609/phpunit-demo-with-ci/-/jobs/506685408

如果執行的過程中有任何的錯誤都可以透過這邊進行 Debug ,下篇再與大家分享如何優化所撰寫的 .gitlab-ci.yaml 檔案。

如何透過 Docker 來使用 Fluentd

首先先介紹一下 Fluentd 怎麼念,這個詞從我進 KKBOX 以來到現在一直都不知道怎麼念,但同事都是念「 Fluent and d 」所以我也跟著這樣念了,今天好奇查了一下真正的念法是「 Fluent dee 」或是可以唸成「 Fluent d 」,詳細可以參考這篇文章

Fluentd 是一套開源軟體的資料蒐集器,時常備用在蒐集各式各樣的 Log 然後整理拋送到另外一個地方,講這樣很玄可以參考下面這張圖。

可以看到 Fluentd 會蒐集各式各樣的 Log 像是 Apache 的 access log 、應用程式的 log 或是系統記錄等等,經過 Fluentd 的 filter 整理後轉送給各式各樣的 Output , Fluentd 支援太多的 Output 了,詳細可以直接到這個網站上面直接查詢,真的是想的到的服務都有。

在 Docker 非常盛行的時代想要實做一個服務你不用自己架設,起一個 Docker 就可以了,下面會跟說明要如何進行測試,我將這次測試的原始碼放在這邊,有興趣可以直接 clone 下來玩玩。

首先需要先撰寫一個 fluent.conf 的設定檔讓 fluentd 執行使用,如下可以看到我有兩個來源分別是 apache-access.log 與 lumen.log 為了測試方便每次執行都會從頭開始讀取到結束,在輸出的部分我使用 file 來儲存並且透過 tag 與時間來區分我的 log 檔案。

<source>
  @type tail
  path /pod-data/apache-access.log
  pos_file /pod-data/apache-access.log.pos
  read_from_head true
  tag apache.access
  <parse>
    @type apache2
  </parse>
</source>

<source>
  @type tail
  path /pod-data/lumen.log
  pos_file /pod-data/lumen.log.pos
  read_from_head true
  tag lumen
  <parse>
    @type json
  </parse>
</source>

<match **>
  @type file
  path /fluentd/log/${tag}/${tag}.%Y%m%d
  <buffer tag,time>
    @type file
    flush_thread_count 8
    flush_at_shutdown true
    timekey_use_utc true
    timekey_wait 1m
    path /fluentd/log/buffer
  </buffer>
</match>

接著就是來使用 Docker 搭配我的設定檔來執行我的 Fluentd 測試。

> git clone https://github.com/hashman/docker-learning.git
> cd docker-learning/fluentd-demo
> docker run --rm --name fluentd -v ${PWD}/fluent.conf:/fluentd/etc/fluent.conf -v ${PWD}/dest_logs:/fluentd/log -v ${PWD}/src_logs:/pod-data fluent/fluentd:v1.10.1-debian-arm64-1.0

因為我是用 Raspberry Pi 來跑,所以我需要使用 arm base 的 docker image 來執行,如是 x86 / x64 的可以直接用 fluent/fluentd:v1.10.1-debian 這個 image tag 來使用就可以了,執行完成最終的 output 資料夾結構會長成這樣的分類。

├── dest_logs
│   ├── apache.access
│   │   └── apache.access.20200405_0.log
│   ├── buffer
│   │   ├── buffer.b5a2b33a4f6b37cbdd626aadd8b4d121f.log
│   │   └── buffer.b5a2b33a4f6b37cbdd626aadd8b4d121f.log.meta
│   └── lumen
│       └── lumen.20200405_0.log

相關的原始碼我有放在 Github 上面,有興趣可以抓下來玩玩,有任何問題歡迎留言或是 Github Issue 發問。

如何使用 gitlab-runner 進行 Pipeline Debug

安裝 gitlab-runner 的部分可以參考此篇文章,這邊就直接針對如何透過 gitlab-runner 指令來執行 .gitlab-ci.yml 特定的 pipeline 進行測試。

> cat .gitlab-ci.yml
...
Test elasticsearch on 6.x:
  stage: integration
  services:
   - name: elasticsearch:6.8.0
     alias: elasticsearch
  image: *image_ref56
  cache: *cache_ref56
  script:
      - make integration
  tags:
    - docker
...

從上面的 yaml 檔可以知道有一個 “Test elasticsearch on 6.x” 的 Pipeline ,而透過 gitlab-runner 指令可以直接模擬 Gitlab-CI 來執行這個 pipeline 。

> gitlab-runner exec docker --cache-shared --docker-privileged --docker-cache-dir /cache --builds-dir /builds --docker-privileged --docker-volumes /home/xxx/var/gitlab-runner/builds:/builds --docker-volumes /home/xxx/cache:/cache --docker-volumes /home/xxx/.ssh:/root/.ssh --docker-volumes /var/run/docker.sock:/var/run/docker.sock 'Test elasticsearch on 6.x'

就會看到與 Gitlab-CI 上一樣的執行結果了,上面的指定目錄再麻煩各位依照自己的環境進行調整。

此時想說有沒有可能在不進行 git push 的狀況下,也能透過 gitlab-runner 模擬 Gitlab-CI 的執行結果呢?

然而在我修改程式碼之後馬上執行了上面的指令,卻執行尚未修改前的程式,這是怎麼回事? gitlab-runner 有提供一個 --debug 的參數可以使用,或許可以發現些線索。

> gitlab-runner --debug exec docker --cache-shared --docker-privileged --docker-cache-dir /cache --builds-dir /builds --docker-privileged --docker-volumes /home/xxx/var/gitlab-runner/builds:/builds --docker-volumes /home/xxx/cache:/cache --docker-volumes /home/xxx/.ssh:/root/.ssh --docker-volumes /var/run/docker.sock:/var/run/docker.sock 'Test elasticsearch on 6.x'

...
Executing on /runner--project-0-concurrent-0-predefined-1 the #!/usr/bin/env bash

set -eo pipefail
set +o noclobber
: | eval $'export FF_CMD_DISABLE_DELAYED_ERROR_LEVEL_EXPANSION=$\'false\'\nexport FF_USE_LEGACY_BUILDS_DIR_FOR_DOCKER=$\'false\'\nexport FF_USE_LEGACY_VOLUMES_MOUNTING_ORDER=$\'false\'\nexport CI_RUNNER_SHORT_TOKEN=\'\'\nexport CI_BUILDS_DIR=$\'/builds\'\nexport CI_PROJECT_DIR=$\'/builds/0/project-0\'\nexport CI_CONCURRENT_ID=0\nexport CI_CONCURRENT_PROJECT_ID=0\nexport CI_SERVER=$\'yes\'\nexport CI=$\'true\'\nexport GITLAB_CI=$\'true\'\nexport CI_SERVER_NAME=$\'GitLab CI\'\nexport CI_SERVER_VERSION=\'\'\nexport CI_SERVER_REVISION=\'\'\nexport CI_PROJECT_ID=0\nexport CI_JOB_ID=1\nexport CI_JOB_NAME=$\'Test elasticsearch on 5.x\'\nexport CI_JOB_STAGE=$\'integration\'\nexport CI_JOB_TOKEN=\'\'\nexport CI_REPOSITORY_URL=$\'/home/xxx/repo/project-a\'\nexport CI_COMMIT_SHA=$\'74cd6c29f235b8be115fd54f97a163025ac49dfe\'\nexport CI_COMMIT_BEFORE_SHA=$\'88c146a08a8ed3cc6bc41b023ff064ea7d2c3b28\'\nexport CI_COMMIT_REF_NAME=$\'feature/boost-from-query\'\nexport COMPOSER_HOME=$\'/cache/composer\'\nexport CI_DISPOSABLE_ENVIRONMENT=$\'true\'\nexport CI_RUNNER_VERSION=$\'12.6.0~beta.2048.g59f07d78\'\nexport CI_RUNNER_REVISION=$\'59f07d78\'\nexport CI_RUNNER_EXECUTABLE_ARCH=$\'linux/amd64\'\nexport GIT_LFS_SKIP_SMUDGE=1\n$\'rm\' "-r" "-f" "/builds/0/project-0"\necho $\'\\x1b[32;1mFetching changes...\\x1b[0;m\'\n$\'mkdir\' "-p" "/builds/0/project-0.tmp/git-template"\n$\'git\' "config" "-f" "/builds/0/project-0.tmp/git-template/config" "fetch.recurseSubmodules" "false"\n$\'git\' "init" "/builds/0/project-0" "--template" "/builds/0/project-0.tmp/git-template"\n$\'cd\' "/builds/0/project-0"\n$\'rm\' "-f" ".git/index.lock"\n$\'rm\' "-f" ".git/shallow.lock"\n$\'rm\' "-f" ".git/HEAD.lock"\n$\'rm\' "-f" ".git/hooks/post-checkout"\nif $\'git\' "remote" "add" "origin" "/home/xxx/repo/project-a" >/dev/null 2>/dev/null; then\n  echo $\'\\x1b[32;1mCreated fresh repository.\\x1b[0;m\'\nelse\n  $\'git\' "remote" "set-url" "origin" "/home/xxx/repo/project-a"\nfi\n$\'git\' "fetch" "origin" "--prune"\necho $\'\\x1b[32;1mChecking out 74cd6c29 as feature/boost-from-query...\\x1b[0;m\'\n$\'git\' "checkout" "-f" "-q" "74cd6c29f235b8be115fd54f97a163025ac49dfe"\n$\'git\' "clean" "-ffdx"\nif $\'git\' "lfs" "version" >/dev/null 2>/dev/null; then\n  $\'git\' "lfs" "pull"\n  echo\nfi\necho $\'\\x1b[32;1mSkipping Git submodules setup\\x1b[0;m\'\n'
exit 0
...

後段可以看到一串指令將它整理一下。

Executing on /runner--project-0-concurrent-0-predefined-1 the #!/usr/bin/env bash

set -eo pipefail
set +o noclobber
: | eval $'
export FF_CMD_DISABLE_DELAYED_ERROR_LEVEL_EXPANSION=$\'false\'
export FF_USE_LEGACY_BUILDS_DIR_FOR_DOCKER=$\'false\'
export FF_USE_LEGACY_VOLUMES_MOUNTING_ORDER=$\'false\'
export CI_RUNNER_SHORT_TOKEN=\'\'
export CI_BUILDS_DIR=$\'/builds\'
export CI_PROJECT_DIR=$\'/builds/0/project-0\'
export CI_CONCURRENT_ID=0
export CI_CONCURRENT_PROJECT_ID=0
export CI_SERVER=$\'yes\'
export CI=$\'true\'
export GITLAB_CI=$\'true\'
export CI_SERVER_NAME=$\'GitLab CI\'
export CI_SERVER_VERSION=\'\'
export CI_SERVER_REVISION=\'\'
export CI_PROJECT_ID=0
export CI_JOB_ID=1
export CI_JOB_NAME=$\'Test elasticsearch on 5.x\'
export CI_JOB_STAGE=$\'integration\'
export CI_JOB_TOKEN=\'\'
export CI_REPOSITORY_URL=$\'/home/ubuntu/repo/project-a\'
export CI_COMMIT_SHA=$\'74cd6c29f235b8be115fd54f97a163025ac49dfe\'
export CI_COMMIT_BEFORE_SHA=$\'88c146a08a8ed3cc6bc41b023ff064ea7d2c3b28\'
export CI_COMMIT_REF_NAME=$\'feature/boost-from-query\'
export COMPOSER_HOME=$\'/cache/composer\'
export CI_DISPOSABLE_ENVIRONMENT=$\'true\'
export CI_RUNNER_VERSION=$\'12.6.0~beta.2048.g59f07d78\'
export CI_RUNNER_REVISION=$\'59f07d78\'
export CI_RUNNER_EXECUTABLE_ARCH=$\'linux/amd64\'
export GIT_LFS_SKIP_SMUDGE=1\n$\'rm\' "-r" "-f" "/builds/0/project-0"\necho $\'\\x1b[32;1mFetching changes...\\x1b[0;m\'\n$\'mkdir\' "-p" "/builds/0/project-0.tmp/git-template"\n$\'git\' "config" "-f" "/builds/0/project-0.tmp/git-template/config" "fetch.recurseSubmodules" "false"\n$\'git\' "init" "/builds/0/project-0" "--template" "/builds/0/project-0.tmp/git-template"\n$\'cd\' "/builds/0/project-0"\n$\'rm\' "-f" ".git/index.lock"\n$\'rm\' "-f" ".git/shallow.lock"\n$\'rm\' "-f" ".git/HEAD.lock"\n$\'rm\' "-f" ".git/hooks/post-checkout"\nif $\'git\' "remote" "add" "origin" "/home/xxx/repo/project-a" >/dev/null 2>/dev/null; then\n  echo $\'\\x1b[32;1mCreated fresh repository.\\x1b[0;m\'\nelse\n  $\'git\' "remote" "set-url" "origin" "/home/ubuntu/repo/project-a"\nfi\n$\'git\' "fetch" "origin" "--prune"\necho $\'\\x1b[32;1mChecking out 74cd6c29 as feature/boost-from-query...\\x1b[0;m\'\n$\'git\' "checkout" "-f" "-q" "74cd6c29f235b8be115fd54f97a163025ac49dfe"\n$\'git\' "clean" "-ffdx"\nif $\'git\' "lfs" "version" >/dev/null 2>/dev/null; then\n  $\'git\' "lfs" "pull"\n  echo\nfi\necho $\'\\x1b[32;1mSkipping Git submodules setup\\x1b[0;m\'\n'
exit 0

其中 GIT_LFS_SKIP_SMUDGE 環境參數後面執行的指令這邊吸引了我,將他整理一下…

> rm -rf /builds/0/project-0
> echo git-template
> $git config -f /builds/0/project-0.tmp/git-template/config fetch.recurseSubmodules false
> $git init /builds/0/project-0 --template /builds/0/project-0.tmp/git-template
> cd /builds/0/project-0
> rm -f .git/index.lock
> rm -f .git/shallow.lock
> rm -f .git/HEAD.lock
> rm -f .git/hooks/post-checkout
> if 
    $git remote add origin /home/xxx/repo/project-a >/dev/null 2>/dev/null;
then
    echo $\\x1b[32;1mCreated fresh repository.\\x1b[0;m
else
    $git remote set-url origin /home/xxx/repo/project-a
fi
> $git fetch origin --prune
> echo \\x1b[32;1mChecking out 74cd6c29 as feature/boost-from-query...\\x1b[0
> $git checkout -f -q 74cd6c29f235b8be115fd54f97a163025ac49dfe
> $git clean -ffdx
> if
    $git lfs version >/dev/null 2>/dev/null;
then
    $git lfs pull
fi
> echo \\x1b[32;1mSkipping Git submodules setup\\x1b[0;m

其中可以看到在設定 git remote 路徑的時候,他是抓取實體專案路徑,也就是說,如果 code change 沒有下 git commit 就無法讓 runner 抓取到,這下簡單了,只要 git commit 就好… 測試後確認成功。

如何在自己的環境安裝 gitlab-runner 指令

有使用 Gitlab 的朋友對於 Gitlab-CI 應該都不陌生,透過 CI 可以幫助開發者進行測試或是部署,相當的方便,但往往在執行 CI 的時候出錯要 debug 都要一直 push code 很麻煩, Gitlab 有將他的 runner 開源並提供方法讓大家在自己的環境安裝 gitlab-runner ,下面就來跟大家說怎麼安裝。

如果你只是想要使用 gitlab-runner 的指令,可以直接透過這份文件進行安裝即可,但如果你會有需要使用不同版本的 gitlab-runner 的需求,就可以參考這份文件進行操作,如果此環境你沒有 sudo 權限或是想要看懶人版可以直接往下看 xD

gitlab-runner 是使用 Golang 寫的,所以需要先進行 Golang 相關配置與安裝。

更新你的 .profile, .bash_profile, .zshrc 看習慣放哪裡,我自己都會放在 .zshrc

> vim ~/.zshrc
...
export GOPATH=$HOME/Go
export PATH=$PATH:$GOPATH/bin:$HOME/local/go/bin
...
> exec zsh
> mkdir ~/Go
> mkdir ~/local

下載與安裝 Golang 。

> cd
> wget https://storage.googleapis.com/golang/go1.10.8.linux-amd64.tar.gz
> tar -C local -xzf go1.10.8.linux-amd64.tar.gz

完成之後你就會在你的 ~/local/go 這邊看到 go 的原始碼,也可以開始使用 go 了,接著來確認是否有成功安裝

> go version
go version go1.10.8 linux/amd64

看到上面訊息代表你的 go 語言有成功的安裝,接下來安裝 gitlab-runner

> go get gitlab.com/gitlab-org/gitlab-runner

執行完成後你可以看到 ~/Go/bin 裡面有個 gitlab-runner 的執行檔,就可以直接使用了,或是要使用 $GOPATH/src/gitlab.com/gitlab-org/gitlab-runner/.gopath/bin/gitlab-runner 也可以,至於為什麼要知道後面這個路徑呢?後面會提到,測試一下 gitlab-runner 是否安裝成功。

╭─hashmanlin@ubuntu ~/Go/bin
╰─➤  gitlab-runner -v
Version:      development version
Git revision: HEAD
Git branch:   HEAD
GO version:   go1.10.8
Built:        unknown
OS/Arch:      linux/amd64

這邊可以看到安裝成功了,但會發現 Version 是 development version ,如果希望指定版本怎麼辦?舉例想要使用 11.11.4 的版本。

╭─hashmanlin@ubuntu ~/Go/src/gitlab.com/gitlab-org/gitlab-runner  ‹master›
╰─➤  git checkout v11.11.4
Note: switching to 'v11.11.4'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at e828d3bc9 Update CHANGELOG for v11.11.4
╭─hashmanlin@ubuntu ~/Go/src/gitlab.com/gitlab-org/gitlab-runner  ‹e828d3bc9›
╰─➤  make deps
mkdir -p /home/hashmanlin/Go/src/gitlab.com/gitlab-org/gitlab-runner/.gopath/bin
touch /home/hashmanlin/Go/src/gitlab.com/gitlab-org/gitlab-runner/.gopath/.ok
go get github.com/golang/dep/cmd/dep
go get github.com/mitchellh/gox
go get github.com/vektra/mockery/.../
╭─hashmanlin@ubuntu ~/Go/src/gitlab.com/gitlab-org/gitlab-runner  ‹e828d3bc9›
╰─➤  make install
go install --ldflags="-X gitlab.com/gitlab-org/gitlab-runner/common.NAME=gitlab-runner -X gitlab.com/gitlab-org/gitlab-runner/common.VERSION=11.11.4 -X gitlab.com/gitlab-org/gitlab-runner/common.REVISION=e828d3bc -X gitlab.com/gitlab-org/gitlab-runner/common.BUILT=2019-12-02T12:42:34+0000 -X gitlab.com/gitlab-org/gitlab-runner/common.BRANCH= -s -w" gitlab.com/gitlab-org/gitlab-runner
╭─hashmanlin@ubuntu ~/Go/src/gitlab.com/gitlab-org/gitlab-runner  ‹e828d3bc9›
╰─➤  ./.gopath/bin/gitlab-runner -v
Version:      11.11.4
Git revision: e828d3bc
Git branch:
GO version:   go1.10.8
Built:        2019-12-02T12:42:34+0000
OS/Arch:      linux/amd64

至於為什麼 $GOPATH/bin/gitlab-runner 沒有被置換成 11.11.4 的版本呢?看了一下 gitlab-runnerMakefile 會把 $GOPATH 改為 .gopath 這個路徑,如果希望 $GOPATH/bin/gitlab-runner 也跟著置換可以考慮用 ln 的方式來處理。

╭─hashmanlin@ubuntu ~/Go/bin
╰─➤  rm gitlab-runner
╭─hashmanlin@ubuntu ~/Go/bin
╰─➤  rm gitlab-runner
╭─hashmanlin@ubuntu ~/Go/bin
╰─➤  ln /home/hashmanlin/Go/src/gitlab.com/gitlab-org/gitlab-runner/.gopath/bin/gitlab-runner gitlab-runner
╭─hashmanlin@ubuntu ~/Go/bin
╰─➤  cd
╭─hashmanlin@ubuntu ~
╰─➤  gitlab-runner -v
Version:      11.11.4
Git revision: e828d3bc
Git branch:
GO version:   go1.10.8
Built:        2019-12-02T12:42:34+0000
OS/Arch:      linux/amd64

這樣就可以執行特定版本的 gitlab-runner

Synology NAS 防火牆相關設定

什麼是防火牆

防火牆有如家的門窗等等,如果門戶大開,就是讓別人很輕易的就可以進去,所以當我們不在家裡,或是都會把家門關上有如設定上防火牆一樣的概念。 應用程式溝通都會在 Server 上面監聽一個連接埠(Port)透過這個 port 與外部網路進行溝通,原則上防火牆僅需要放行必須的 Port ,不會直接全開,全開可能其他的 Port 就能夠被有心人士進行操作。

Synology NAS 實體網路架設方式

目前自己的架設方式

  • 優點
    • 不用再做 Port Forwarding 等等的設定,所有的服務都可以直接被外網存取到
  • 缺點
    • 直接將 NAS 暴露在外網上
    • 如果只有一個固定 IP (通常家用網路只會預設免費一個固定 IP)就被 NAS 拿走了,就無法再架設其他服務了

其他人建議的做法

  • 優點
    • 固定 IP 會綁在小烏龜上面,如果內網還有其他的 Server 或是服務可以直接用 Port Forwarding 的方式鏡像到外網
    • NAS 沒有直接暴露外網
  • 缺點
    • 需要一個一個開 Port 才可以讓外部使用到服務,設定較為麻煩

如何設定 Synology 防火牆

設定位置在「控制台 -> 安全性 -> 防火牆」
如何開啟防火牆設定
點擊「編輯規則」即可進行防火牆設定
Hash 自己的防火牆設定
我自己的做法是採用白名單的做法,也就是有列出的項目放行,其他的全部不允許
  • Web service (80, 443) 直接開啟所有 IP 都可以使用
  • 內網所有服務放行
  • DSM 管理介面、Drive、Moment 等等服務都是選擇 Taiwan 才放行,如果有要出國出國前再將來源國家多開那個國家即可,或是透過 VPN 的方式連線回來台灣使用也行
設定 Port, IP
根據服務放行
幾年沒用 Synology NAS 後 DSM 進步不少,在防火牆的設定都可以選擇應用程式還有國家,都不太需要動什麼頭腦就可以設定完成了 另外提醒大家,防火牆不是絕對安全的,舉例,你開啟了 22 port 的 SSH 服務,結果你的密碼被 Hacker 猜到登入,更慘的是如果他所登入的帳號是管理員帳號,你的整台 NAS 都是他的了,如果想要把服務放在外部請三思而後行。

Hexo 採雷大小事

前言

在使用 Hexo 的過程中,總是會遇到官方文件沒有寫的很詳細、不知道該如何使用或是有問題的功能,這邊把我有遇到的採雷狀況記錄在這邊。

GitHub page custom domain 會跑掉

每當我重新 deploy 上去 github 後,custom domain 就會被清空,後來發現只要在 source 目錄下新增 CNAME這個檔案,內容是您所希望的 URL 如 hashman.tw or www.hashman.tw ,神奇的事情發生了,真的就不會被清空了。

依照 hexo next 上面的文件去進行 config 的設定,卻不 work

一開始直接都是更新根目錄上的 _config.yml 按著官方文件上面來操作,但 Blog 就是不會變更,最後發現原來是要修改 theme/next 中的 _config.yml 才是,修改後一切正常。

參考資料

使用 Hexo + GitHub

什麼是 Hexo

Hexo 是一套用 NodeJS 寫的 blog framework ,可以透過 hexo 的指令非常快速的建立文章,以下會有簡易指令教學

另外這有記錄我在使用 Hexo 時的採雷狀況與解決方法 – Hexo 採雷大小事

什麼是 GitHub Page

GitHub Page 提供所有 GitHub 的用戶可以直接將靜態網頁直接放上 GitHub 中,即可直接於 https://[account].github.io 查看網頁內容的服務。

如何使用 GitHub Page

直接於自己的 GitHub 帳號直接建立一個 [account].github.io 的 Public Repo ,於 Repo 中上傳靜態網頁即可在 https://[account].github.io 上查看網頁。

為什麼想要使用 Hexo + GitHub

  1. Hexo 為 Open Source 軟體可以非常自由的依照自己的需求去調整 Source Code 。
  2. 客製化的網址需求,雖說 LogDown 也可以,但… 需要付費才可以使用,其實還蠻貴的。
  3. GitHub Public Repository 無空間上限(嚴格來說不是無上限,請參考: GitHub – What is my disk quota?)。
  4. 主機交給 GitHub 管,只需要單純的上 Code 就好不需要去架設與管理主機,相對穩定。
  5. 多了個機會可以了解 GitHub Page 這個服務,詳細參考這裡
  6. 幫自己的 GitHub Contributions 多一點色彩,每更新一次 Blog 都會 deploy 到 GitHub 上,也就會增加自己的 Contributions 。

Hexo Command

// 第一次使用需要先 init hexo folder 與安裝套件
$ hexo init <folder> // init hexo folder
$ cd <folder>
$ npm install
// 新增文章
$ hexo new [layout] <title> // or hexo n [layout] <title>
// layout 可以不要填寫
// title 建議使用雙引號刮起來
// 產生靜態檔
$ hexo generate // or hexo g
// 發表草稿,這個功能我蠻少用的
$ hexo publish [layout] <filename>
// 啟用 hexo 伺服器
$ hexo server // or hexo s
// Deploy 至 remote
$ hexo deploy // or hexo d
// 清除快取檔案
$ hexo clean

Hash 使用 Blog 的歷史

參考資料

PHP … operator 使用方式

今天發現一個很酷的 php 5.6 以後的 feature

直接 show code 比較快

<?php
$string = "Controller@home";
test(...explode("@", $string));
function test($controller_name, $funciton_name)
{
    var_dump($controller_name, $funciton_name);
}
// print result
// string(10) "Controller"
// string(4) "home"

這個 operator 會直接將 explode 出來的 array 直接依序的放入 function 中