??Ghost是基于Node.js構(gòu)建的開源博客平臺购撼。Ghost 具有易用的書寫界面和體驗,博客內(nèi)容默認采用 Markdown 語法書寫羊娃。由前 WordPress UI 部門主管 John O’Nolan 和 WordPress 高級工程師(女) Hannah Wolfe 創(chuàng)立蚌成,目的是為了給用戶提供一種更加純粹的內(nèi)容寫作與發(fā)布平臺抠艾。
官網(wǎng):https://ghost.org/
運行環(huán)境
本文使用傳統(tǒng)安裝方法氢惋,未使用從ghost1.x版本開始提供的安裝工具ghost-cli
主機系統(tǒng)版本:CentOS 7.4
Ghost版本:Ghost-1.14.0
使用nginx反向代理ghost
數(shù)據(jù)庫使用centos 7自帶的mariadb
安裝基礎(chǔ)包
[root@localhost ~]# yum -y install bash-completion bash-completion-extras epel-release
安裝nodejs
本文使用nodejs 長期支持LTS版
執(zhí)行nodejs的nodejs腳本羽历,這個腳本會自動在主機上面配置nodejs的yum倉庫和軟件包驗證用的密鑰
[root@localhost ~]# curl -sL https://rpm.nodesource.com/setup_7.x | sudo -E bash - #會生成一個 叫nodesource-el.repo的文件嗜侮。
安裝nodejs和依賴包
[root@localhost ~]# yum -y install gcc-c++ make nodejs #安裝nodejs和其依賴包
使用cnpm替代npm港令,如果使用內(nèi)地之外的服務(wù)器請忽略這一步。
[root@localhost ~]# npm install -g cnpm --registry=https://registry.npm.taobao.org #安裝
淘寶的cnpm
配置mariadb數(shù)據(jù)庫
安裝
[root@localhost ~]# yum -y install mariadb-server
修改配置文件
[root@localhost ~]# vim /etc/my.cnf
[mysqld] #修改mysqld配置段
skip_name_resolve=on #跳過主機名解析
innodb_file_per_table=on #每個innodb表使用一個單獨的文件儲存
character-set-server=utf8 #修改mysql默認字符集為utf8
init_connect='SET NAMES utf8'
collation-server=utf8_general_ci
[client]
default-character-set=utf8 #強制客戶端的字符集為utf8
[mysql]
default-character-set=utf8
啟動mariadb并設(shè)置為開機啟動
[root@localhost ~]# systemctl start mariadb #啟動mariadb
[root@localhost ~]# systemctl enable mariadb #設(shè)置為開機自啟動
執(zhí)行mysql的安全腳本
[root@localhost ~]# mysql_secure_installation
Enter current password for root (enter for none): #輸入root用戶的密碼锈颗,默認為空顷霹,直接回車。
OK, successfully used password, moving on...
Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.
Set root password? [Y/n] Y #是否設(shè)置root密碼
New password: #輸入新密碼
Re-enter new password: #再次輸入新密碼
Password updated successfully!
Reloading privilege tables..
... Success!
Remove anonymous users? [Y/n] Y #是否刪除匿名賬戶
... Success!
Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess at the root password from the network.
Disallow root login remotely? [Y/n] Y #是否禁止root用戶遠程登陸
... Success!
By default, MariaDB comes with a database named 'test' that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.
Remove test database and access to it? [Y/n] Y #是否刪除tset數(shù)據(jù)庫
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
Reload privilege tables now? [Y/n] Y #是否保存上面的設(shè)置
... Success!
為Ghost創(chuàng)建數(shù)據(jù)庫和用戶
[root@localhost ~]# mysql -uroot -p
Enter password:
MariaDB [(none)]> CREATE DATABASE ghost; #創(chuàng)建一個叫g(shù)host的庫
MariaDB [(none)]> GRANT ALL PRIVILEGES ON ghost.* TO 'ghostblog'@'%' IDENTIFIED BY 'ghost123';
#創(chuàng)建為ghost用戶授予ghost庫的所有權(quán)限击吱,如果沒有這個用戶將創(chuàng)建淋淀。
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> quit
配置Ghost
下載Ghost壓縮包,如果使用其他版本的ghost請去官網(wǎng)查找對應(yīng)版本的壓縮包下載路徑
[root@localhost app]# mkdir /app #創(chuàng)建一個目錄存放ghost文件
[root@localhost app]# cd /app
[root@localhost app]# wget -L https://github.com/TryGhost/Ghost/releases/download/1.20.3/Ghost-1.20.3.zip
解壓軟件
[root@localhost app]# yum -y install unzip #安裝解壓軟件
[root@localhost app]# unzip Ghost-1.20.3.zip -d ghost
修改配置文件
[root@localhost ghost]# vim core/server/config/defaults.json
{
"url": "http://域名", //網(wǎng)站的域名
"server": {
"host": "127.0.0.1", //ghost服務(wù)的地址
"port": 2368 //服務(wù)端口
},
"privacy": false,
"useMinFiles": true,
"paths": {
"contentPath": "content/"
},
"storage": {
"active": "LocalFileStorage"
},
"scheduling": {
"active": "SchedulingDefault"
},
"logging": {
"level": "info",
"rotation": {
"enabled": true,
"period": "1d",
"count": 10
},
"transports": ["stdout"]
},
"spam": {
"user_login": {
"minWait": 600000,
"maxWait": 604800000,
"freeRetries": 4
},
"user_reset": {
"minWait": 3600000,
"maxWait": 3600000,
"lifetime": 3600,
"freeRetries": 4
},
"global_reset": {
"minWait": 3600000,
"maxWait": 3600000,
"lifetime": 3600,
"freeRetries":4
},
"global_block": {
"minWait": 3600000,
"maxWait": 3600000,
"lifetime": 3600,
"freeRetries":99
},
"private_block": {
"minWait": 3600000,
"maxWait": 3600000,
"lifetime": 3600,
"freeRetries":99
}
},
"caching": {
"frontend": {
"maxAge": 0
},
"301": {
"maxAge": 31536000
},
"customRedirects": {
"maxAge": 31536000
},
"favicon": {
"maxAge": 86400
},
"sitemap": {
"maxAge": 3600
},
"robotstxt": {
"maxAge": 3600000
}
}
}
修改工作模式
[root@localhost ghost]# vim core/server/config/index.js
var Nconf = require('nconf'),
path = require('path'),
_debug = require('ghost-ignition').debug._base,
debug = _debug('ghost:config'),
localUtils = require('./utils'),
env = process.env.NODE_ENV || 'development', #將development修改為production
_private = {};
設(shè)置數(shù)據(jù)庫
[root@localhost ghost]# ls core/server/config/env/
config.development.json.bak config.production.json config.testing.json config.testing-mysql.json
[root@localhost ghost]# vim core/server/config/env/config.production.json
{
"database": {
"client": "mysql", //使用的數(shù)據(jù)庫客戶端
"connection": {
"host" : "127.0.0.1", //數(shù)據(jù)庫IP地址
"user" : "ghostblog", //數(shù)據(jù)庫用戶名
"password" : "ghost123", //密碼
"database" : "ghost", //數(shù)據(jù)庫
"charset":"utf8"
}
"debug": "false"
},
"paths": {
"contentPath": "content/"
},
"logging": {
"level": "info",
"rotation": {
"enabled": true
},
"transports": ["file", "stdout"]
},
//配置郵件服務(wù)
"mail": {
"transport": "SMTP",
"options": {
"auth": {
"user": "", //郵箱賬號
"pass": "" //郵箱密碼
}
}
},
//對象云存儲支持,ghost官方不支持使用對象存儲覆醇,需要安裝插件才能使用
//qn-store這款插件是給Ghost博客提供七牛云存儲支持
"storage": {
"active": "qn-store",
"qn-store": {
"accessKey": "",
"secretKey": "",
"bucket": "", //bucket名稱
"origin": "",
"fileKey": {
"safeString": "true",
"prefix": "YYYYMM/"
}
}
}
//upyun-ghost-store這款插件是給Ghost博客提供又拍云存儲支持朵纷。
storage: {
active: 'upyun-ghost-store',
'upyun-ghost-store': {
bucket: 'my-bucket', //bucket名稱
operator: 'somebody', //用戶名
password: 'secret', //密碼
domain: 'http://bucket.b0.upaiyun.com', //空間綁定的域名
filePath: '[blog]/YYYY/MM/' //文件遠端保存地址
}
}
}
安裝對象存儲插件
在content文件夾中創(chuàng)建一個名為storage的文件夾將git倉庫克隆至storage文件夾下
cd /app/ghost/content/storage
git clone https://github.com/Minwe/qn-store.git
安裝依賴包
cd qn-store
npm instal
注:upyun-ghost-store的安裝和qun-stor相同
安裝
[root@localhost app]# cd ghost/
[root@localhost ghost]# ls
content Gruntfile.js LICENSE package.json README.md
core index.js MigratorConfig.js PRIVACY.md yarn.lock
[root@localhost ghost]# cnpm install --production #使用cnpm安裝
初始化數(shù)據(jù)庫
[root@localhost ghost]# cnpm install -g knex-migrator
[root@localhost ghost]# knex-migrator init
{ method: 'insert',
options: {},
timeout: false,
cancelOnTimeout: false,
bindings: [ '1.14', '1-og-twitter-post.js', '1.5' ],
__knexQueryUid: '02b804ea-5f0e-4d2e-892e-c7aff980fb3b',
sql: 'insert into `migrations` (`currentVersion`, `name`, `version`) values (?, ?, ?)' }
{ method: 'select',
options: {},
timeout: false,
cancelOnTimeout: false,
bindings: [ '1-add-backup-client.js' ],
__knexQueryUid: '79e0dbb6-8a65-4e1c-adfe-6c45f103bddc',
sql: 'select * from `migrations` where `name` = ?' }
{ method: 'insert',
options: {},
timeout: false,
cancelOnTimeout: false,
bindings: [ '1.14', '1-add-backup-client.js', '1.7' ],
__knexQueryUid: 'c9a885b5-5791-4edc-af46-8f78af0075d3',
sql: 'insert into `migrations` (`currentVersion`, `name`, `version`) values (?, ?, ?)' }
{ method: 'select',
options: {},
timeout: false,
cancelOnTimeout: false,
bindings: [ '1-add-permissions-redirect.js' ],
__knexQueryUid: '7b543633-99bf-48c9-bf46-6bbd11229183',
sql: 'select * from `migrations` where `name` = ?' }
{ method: 'insert',
options: {},
timeout: false,
cancelOnTimeout: false,
bindings: [ '1.14', '1-add-permissions-redirect.js', '1.9' ],
__knexQueryUid: 'f859c944-5c5c-4235-a8b0-e7c921631fa9',
sql: 'insert into `migrations` (`currentVersion`, `name`, `version`) values (?, ?, ?)' }
[2017-10-15 20:46:10] INFO Finished database init!
啟動ghost
[root@localhost ghost]# node index.js
{ method: 'select',
options: {},
timeout: false,
cancelOnTimeout: false,
bindings: [ 'scheduled' ],
__knexQueryUid: 'acfa608c-1210-41b6-92fa-487c8c3674ca',
sql: 'select `id`, `published_at`, `created_at` from `posts` where `posts`.`status` = ?' }
[2017-10-15 12:46:38] INFO Ghost is running in production...
[2017-10-15 12:46:38] INFO Your blog is now available on http://域名:80/ #
[2017-10-15 12:46:38] INFO Ctrl+C to shut down #使用Ctrl+C 關(guān)閉ghost
[2017-10-15 12:46:38] INFO Ghost boot 2.01s #本次啟動時間
查看主機監(jiān)聽的TCP端口
[root@localhost ~]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 128 127.0.0.1:2368 *:*
LISTEN 0 50 *:3306 *:*
LISTEN 0 128 :::80 :::*
LISTEN 0 128 :::22 :::*
配置nginx反向代理ghost
配置一個yum倉庫,將倉庫地址指向nginx官網(wǎng)
[root@localhost ~]# vim /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx-repo
baseurl= http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
安裝nginx
[root@localhost ~]# yum -y install nginx
為ghost創(chuàng)建nginx配置文件
[root@localhost ~]# vim /etc/nginx/conf.d/ghost.conf
server {
listen 80 default_server;
listen [::]:80;
server_name www.guoziqiang.com;
location / {
proxy_set_header X-Real-IP $remote_addr; #定義一個請求首部永脓,值為客戶機的IP地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:2368;
}
}
啟動nginx
[root@localhost ghost]# systemctl start nginx
[root@localhost ghost]# systemctl enable nginx
登陸
進入后臺
使用pm2守護ghost進程
安裝pm2
[root@localhost ghost]# npm install -g pm2
創(chuàng)建一個任務(wù)
[root@localhost ghost]# pm2 start index.js --name "ghost" NODE_ENV=production
-------------
__/\\\\\\\\\\\\\____/\\\\____________/\\\\____/\\\\\\\\\_____
_\/\\\/////////\\\_\/\\\\\\________/\\\\\\__/\\\///////\\\___
_\/\\\_______\/\\\_\/\\\//\\\____/\\\//\\\_\///______\//\\\__
_\/\\\\\\\\\\\\\/__\/\\\\///\\\/\\\/_\/\\\___________/\\\/___
_\/\\\/////////____\/\\\__\///\\\/___\/\\\________/\\\//_____
_\/\\\_____________\/\\\____\///_____\/\\\_____/\\\//________
_\/\\\_____________\/\\\_____________\/\\\___/\\\/___________
_\/\\\_____________\/\\\_____________\/\\\__/\\\\\\\\\\\\\\\_
_\///______________\///______________\///__\///////////////__
Production Process Manager for Node.js apps
with a built-in Load Balancer.
Start and Daemonize any application:
$ pm2 start app.js
Load Balance 4 instances of api.js:
$ pm2 start api.js -i 4
Monitor in production:
$ pm2 monitor
Make pm2 auto-boot at server restart:
$ pm2 startup
To go further checkout:
http://pm2.io
-------------
[PM2] Spawning PM2 daemon with pm2_home=/root/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting /app/ghost/index.js in fork_mode (1 instance)
[PM2] Done.
[PM2][ERROR] script not found : /app/ghost/NODE_ENV=production
script not found : /app/ghost/NODE_ENV=production
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤
│ ghost │ 0 │ fork │ 4533 │ online │ 0 │ 0s │ 99% │ 16.3 MB │ root │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘
保存任務(wù)并設(shè)置開機自啟動
[root@localhost ghost]# pm2 save
[root@localhost ghost]# pm2 startup
查看任務(wù)
[root@localhost ghost]# pm2 list
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤
│ ghost │ 0 │ fork │ 3114 │ online │ 0 │ 41s │ 0% │ 72.3 MB │ root │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
查看某個任務(wù)的詳細信息
[root@localhost ghost]# pm2 describe ghost #ghost為任務(wù)名袍辞,也可以寫任務(wù)ID
Describing process with id 0 - name ghost
┌───────────────────┬───────────────────────────────────┐
│ status │ online │
│ name │ ghost │
│ restarts │ 0 │
│ uptime │ 2m │
│ script path │ /app/ghost/index.js │
│ script args │ N/A │
│ error log path │ /root/.pm2/logs/ghost-error-0.log │
│ out log path │ /root/.pm2/logs/ghost-out-0.log │
│ pid path │ /root/.pm2/pids/ghost-0.pid │
│ interpreter │ node │
│ interpreter args │ N/A │
│ script id │ 0 │
│ exec cwd │ /app/ghost │
│ exec mode │ fork_mode │
│ node.js version │ 6.11.4 │
│ watch & reload │ ? │
│ unstable restarts │ 0 │
│ created at │ 2017-10-15T13:57:25.418Z │
└───────────────────┴───────────────────────────────────┘
Code metrics value
┌────────────┬────────┐
│ Loop delay │ 2.53ms │
└────────────┴────────┘
Add your own code metrics: http://bit.ly/code-metrics
Use `pm2 logs ghost [--lines 1000]` to display logs
Use `pm2 monit` to monitor CPU and Memory usage ghost
啟動pm2的web接口
[root@localhost ghost]# pm2 web
Launching web interface on 0.0.0.0:9615
[PM2][WARN] Applications pm2-http-interface not running, starting...
[PM2] App [pm2-http-interface] launched (1 instances)
[PM2] Process launched
┌────────────────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
├────────────────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤
│ ghost │ 0 │ fork │ 3114 │ online │ 0 │ 6m │ 0% │ 78.3 MB │ root │ disabled │
│ pm2-http-interface │ 1 │ fork │ 3249 │ online │ 0 │ 0s │ 90% │ 5.8 MB │ root │ disabled │
└────────────────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app
pm2的些命令
$ pm2 start app.js # 啟動app.js應(yīng)用程序
$ pm2 start app.js -i 4 # cluster mode 模式啟動4個app.js的應(yīng)用實例,4個應(yīng)用程序會自動進行負載均衡
$ pm2 start app.js --name="api" # 啟動應(yīng)用程序并命名為 "api"
$ pm2 start app.js --watch # 當(dāng)文件變化時自動重啟應(yīng)用
$ pm2 start script.sh # 啟動 bash 腳本
$ pm2 list # 列表 PM2 啟動的所有的應(yīng)用程序
$ pm2 monit # 顯示每個應(yīng)用程序的CPU和內(nèi)存占用情況
$ pm2 show [app-name] # 顯示應(yīng)用程序的所有信息
$ pm2 logs # 顯示所有應(yīng)用程序的日志
$ pm2 logs [app-name] # 顯示指定應(yīng)用程序的日志
$ pm2 flush
$ pm2 web # 啟動pm2的web 接口
$ pm2 stop all # 停止所有的應(yīng)用程序
$ pm2 stop 0 # 停止 id為 0的指定應(yīng)用程序
$ pm2 restart all # 重啟所有應(yīng)用
$ pm2 reload all # 重啟 cluster mode下的所有應(yīng)用
$ pm2 gracefulReload all # Graceful reload all apps in cluster mode
$ pm2 delete all # 關(guān)閉并刪除所有應(yīng)用
$ pm2 delete 0 # 刪除指定應(yīng)用 id 0
$ pm2 scale api 10 # 把名字叫api的應(yīng)用擴展到10個實例
$ pm2 reset [app-name] # 重置重啟數(shù)量
$ pm2 startup # 創(chuàng)建開機自啟動命令
$ pm2 save # 保存當(dāng)前應(yīng)用列表
$ pm2 resurrect # 重新加載保存的應(yīng)用列表
$ pm2 update # Save processes, kill PM2 and restore processes
$ pm2 generate # 生成一個示例json配置文件
$ pm2 info # 查看要給應(yīng)用詳細信息