Ubuntu系统配置Nginx Node.js MongoDB环境

腾讯云最近上线了开发者实验室,主要的功能就是提供一台真实的 VPS,让你现场敲 Linux 命令来完成各种实验任务,比如现场搭建 Python 开发环境、基于 Ubuntu 搭建 WordPress 个人博客等等,所谓“让所有技术更容易入门”。

未分类

目前腾讯云这个服务是免费的,不过是限时免费。比如这篇文章讲的用 Ubuntu 搭建微信小程序服务,就是限制必须 3 个小时内完成实验。如果没完成又想保存学习进度的话,你就要花 65 元买下这个 VPS 才行,否则机器直接会被释放,并且过 24 小时后才能重新开始同样的实验。

未分类

咱看到这个服务就直接玩得不亦乐乎,一晚上直接把所有课程基本刷了一遍,给我的体验呢,感觉就像是程序员的密室逃脱游戏,非常有意思。当然了,既然是个“实验课”,它也会一步一步教你,所以并不是难。

这篇文章呢,算是自己做个 Mark。当然,也是给真正有需要搭建微信小程序服务的同学一点参考。本文的最终效果是成功部署 Node.js + Websocket 构建的网络版锤子剪刀布游戏。

对了,要去玩这个小程序实验的同学,最好有点 Linux 和 Node.js 基础,然后提前准备好一个域名和一个可用的域名 SSL 证书,因为小程序必须采用 HTTPS 访问,然后你还得再三个小时之内当场配置 HTTPS。

1、申请域名和 SSL 证书

(1)、域名服务商推荐 Godaddy / 阿里云 / Name.com,注册一个自己想要的域名。
(2)、由于小程序服务端必须使用 HTTPS 域名连接,所以关于 SSL 证书的申请请看这篇文章:http://devops.webres.wang/2017/07/nginx-config-ssl-force-301-https/

2、注册微信小程序账号

不管你曾经在微信公众平台注册过没有,反正就是要重新注册一个,因为服务号 / 公众号不能和小程序号互换,注册微信小程序账号:https://mp.weixin.qq.com/

3、设置微信公众平台

注册小程序账号进入后,点击设置->开发设置->服务器域名,把你自己注册的域名写入request合法域名和socket合法域名中,后面两个域名不用填。

这一步的原因是:如果在微信上运行的小程序想联网,必须采用这两个合法域名才可以连接,否则直接被微信阻止连接。

4、安装本地开发环境

(1)、开发微信小程序,首先得安装微信 web 开发者工具,下载:https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html
(2)、下载小程序源码:https://best66.me/wp-content/uploads/2017/07/lab-weapp-client-master.zip

重复一遍呀,这篇文章主要是介绍如何操作服务器并且从零开始搭建微信小程序服务,所以直接给小程序源码了。

5、配置本地开发环境

(1)、在微信 web 开发者工具添加项目,AppID 依旧在微信公众平台->设置->开发设置->开发者 ID 中。
(2)、项目名称随你
(3)、项目目录选择下载的 lab-weapp-client-master 中直接包含 app.js 的目录
(4)、在微信 web 开发者工具打开 app.js(这是一个全局配置文件),将 host 中的域名修改为你自己的域名

6、安装 Node.js

Node.js 是一个 JS 运行环境,通过它可以实现 JS 编写后端服务器。
(1)、连接你的 VPS
(2)、使用下面的命令安装 Node.js

sudo apt-get update  
sudo wget https://mc.qcloudimg.com/static/archive/262420521a966befe17dfa0070ddb272/node-v6.11.0.tar.gz
sudo tar xvf node-v6.11.0.tar.gz
cd node-v6.11.0
sudo ./configure # 自动配置编译
sudo make # 由于 apt-get 安装不到最新版,我们采用编译安装来安装 Node.js。这条命令会执行比较久。
sudo make install # 采用这条命令来编译安装,以便可以在任何地方使用 node 命令
sudo cp /usr/local/bin/node /usr/sbin/

(3)、安装完成后,使用下面的命令测试安装结果,会输出当前的 Node.js 版本:

node -v

7、上传后端源码并安装依赖组件

(1)、上传 data 文件夹到服务器根目录,点击下载。上传后,修改所有文件权限为 a+rw。
(2)、进入此工作目录

cd /data/release/webapp

(3)、在工作目录创建 package.json 文件,并修改文件的访问权限。

sudo touch package.json
sudo chmod a+r+w package.json

(4)、Node.js 的每个包应该有 package.json 描述文件,包含包名、包版本和依赖包等信息。我们修改 package.json 添加我们服务器包的名称和版本号,可参考下面的示例。vi 命令进入修改。

{
    "name": "webapp",
    "version": "1.0.0"
}

(5)、NPM 之于 Node,如同 homebrew 之于 OS X,apt-get 之于 Ubuntu。我们先安装 NPM 包管理工具。

sudo apt-get install npm

(6)、pm2 是一个带有负载均衡功能的 Node 应用的进程管理器,我们的应用最好是通过 pm2 来运行和管理,而不是使用原生的 Node 执行。使用下面的命令安装 pm2

sudo npm install -g pm2 # 全局安装 pm2 模块
# 如果安装时间太长,我们可以用淘宝的镜像来安装:
# sudo npm install -g pm2 --registry=https://registry.npm.taobao.org

我们顺便看看 pm2 支持的命令:

pm2 start app.js # 运行
pm2 logs # 查看工作日志
pm2 restart app #重启

(7)、我们的服务器源码里使用到了 Express 模块,这是一个 Node.js 的 MVC 框架。Express 的调用方法可以看看源码里的 app.js,它是应用的入口。下面的命令使用 NPM 来安装 Express。

cd /data/release/webapp
sudo npm install express --save # 这里一定要在工作目录执行这条命令,因为会自动更新 package.json 的依赖项

(8)、小程序不支持 Cookie 存储和跟踪,服务器需要自行实现会话层。这里我们的源码采用了 MongoDB 在后端存储会话数据、Node 的模块 connect-mongo 来连接数据库。配合腾讯在 Github 上发布的 Express 会话管理中间件 wafer-node-session 实现小程序会话(还支持 redis 等数据库,github)会话管理的相关源码依旧在 app.js 入口文件中,大家可以去研究。

使用 apt-get 在机器上安装 MongoDB 和客户端命令行工具:

sudo apt-get install mongodb-server mongodb -y 

安装结束后,可以使用下面的命令查看安装的版本:

sudo mongod --version
sudo mongo --version

安装 connect-mongo、wafer-node-session 模块:

cd /data/release/webapp
sudo npm install connect-mongo wafer-node-session --save

(9)、WebSocket 是新一代 Web 通讯技术,直接基于 80 端口和 443 端口。通过 WebSocket 我们可以实现玩家直接与服务器双向通信,不用重复进行握手,延时很低。这里我们需要 ws 模块实现 WebSocket。(源码中 websocket.js 用来和玩家直接双向通信,含有游戏入口。而 app.js 是整个 App 的入口,包含 websocket.js)

cd /data/release/webapp
sudo npm install --save ws

(10)、HumanPlayer.js 的源码中使用到了 co 模块进行协程管理,启动游戏服务前,需要先安装:

cd /data/release/webapp
sudo npm install co --save

8、配置 MongoDB

创建目录,用于 MongoDB 数据和日志存储:

sudo mkdir -p /data/mongodb
sudo mkdir -p /data/logs/mongodb

创建后,使用下面的命令来启动 MongoDB:

sudo mongod --fork --dbpath /data/mongodb --logpath /data/logs/mongodb/webapp.log

可以使用下面的命令来检查是否启动成功

netstat -ltp | grep 27017 # 注:27017 是 MongoDB 默认端口

登录本地 MongoDB 服务:

sudo mongo

登录后,创建一个用户 webapp:

use webapp;
db.addUser({ user: 'webapp', pwd: '你想要的密码', roles: ['dbAdmin', 'readWrite']});

创建完成后,使用 exit 退出命令行工具。

9、配置 config.js

config.js 是服务端应用配置文件,调用位置在 app.js 入口文件。config.js 可参考下面的修改。(注:请将 YORU_APP_ID 和 YOUR_APP_SECRET 替换为你申请的小程序对应的 AppID 和 AppSecret)

cd /data/release/webapp
vi config.js
module.exports = { 
    // 8765 是为了设置 Node.js 构建的 Web App 监听端口,使用 http://主机IP:8765/ 可以进行查看
    serverPort: '8765', 

    // 小程序 appId 和 appSecret 
    // 请到 https://mp.weixin.qq.com 获取 AppID 和 AppSecret
    appId: 'YORU_APP_ID', 
    appSecret: 'YOUR_APP_SECRET', 

    // mongodb 连接配置,生产环境请使用更复杂的用户名密码
    mongoHost: '127.0.0.1', 
    mongoPort: '27017', 
    // 27017 是 MongoDB 默认端口,我们没有修改
    mongoUser: 'webapp', 
    mongoPass: '替换为你刚刚设置的密码', 
    mongoDb: 'webapp'
};

10、安装配置 Nginx

微信小程序要求和服务器的通信都通过 HTTPS 进行,所以我们需要用 Nginx 实现 HTTPS,并反向代理到 Node 服务器来处理。

(1)、在 Ubuntu 上,可直接使用 apt-get 来安装 Nginx

sudo apt-get install nginx -y

(2)、安装完成后,使用 nginx 命令启动 Nginx:

sudo /etc/init.d/nginx start

现在我们可以通过 http://主机IP/ 来查看 Nginx 默认页面。

(3)、配置 HTTPS 反向代理

修改 /etc/nginx 目录的读写权限:

sudo chmod a+rw /etc/nginx

在 /etc/nginx/conf.d 目录创建 ssl.conf 文件:

cd /etc/nginx/conf.d
sudo touch ssl.conf
sudo chmod a+rw ssl.conf

将 ssl.conf 文件修改为如下内容(关于详细的 SSL 证书申请和配置请看这篇文章):

# 让 Nginx 代理支持 WebSocket 的配置
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
        listen 443;
        server_name www.example.com; # 改为绑定证书的域名

        # ssl 配置
        ssl on;
        ssl_certificate sshh.pem; # 改为自己申请得到的 crt 文件的名称
        ssl_certificate_key sshh.key; # 改为自己申请得到的 key 文件的名称
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        ssl_prefer_server_ciphers on;

        # WebSocket 配置
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # 反向代理
        location / {
            proxy_pass http://127.0.0.1:8765;
            # 8765 是刚刚通过 config.js 设置的通过 Node.js 构建的 Web App 的端口,可以使用 http://你的域名:8765/ 来查看,Nginx 代理以后,就可以直接使用 https://你的域名/ 来查看了
        }
    }

最后,我们运行入口文件:

pm2 start app.js

让 Nginx 重新加载配置使其生效:

sudo nginx -s reload

最终效果:

未分类

引用

大部分资料源于腾讯开发者实验室,我只是根据个人理解做了注释和顺序修改,所以,要感谢腾讯咯。

这篇文章花的时间很长,改动也非常多,如有错误,敬请指正!

Nginx申请并部署SSL证书 强制 301 重定向到 HTTPS

通常在网银、购物网站上登录的时候我们会看到地址栏显示一把绿色的锁,这表明我们正在通过 HTTPS 进行加密连接。

在这个 HTTPS Everywhere 的年代,百度、360 导航等网站为了防劫持也是纷纷全面开启了强制 HTTPS。Google 之前曾有承诺会给予 HTTPS 网站一定的权重增加,其 Search Console 也提供了良好的 HTTPS 支持。国内搜索引擎也渐渐跟上,尤其是百度站长平台还提供了 HTTPS 认证和 HTTPS 退场功能,可以一键快速无痛转换。再有,优酷站外 也提供了 HTTPS 的支持,可以说目前网上大部分主流资源都可以找到其对应 HTTPS 的形式,HTTPS 已经是势不可挡的潮流。

个人认为,凡是涉及到用户登录、会员注册、账号密码的网站服务都可以上 HTTPS,目前来说转换成本也不高,毕竟是真的已经到了 HTTPS Everywhere 的时代。

申请 SSL 证书

其实目前来说国内的 SSL 证书提供商已经快倒完了。360 旗下的沃通和 Startcom 因为发假证书和隐瞒收购的问题早在去年就被警告过,而且就在上个星期,火狐称准备完全取消对沃通、Startcom 和 CNNIC 的信任,也就是说,所有使用这些证书的网站都会报错,Google 和火狐都督促使用以上证书的网站立即更换证书。

个人建议可以使用阿里云或者腾讯云(下图)的 DV 证书,只需要验证域名所有权,目前可以免费申请免费续费,另外还有非常便宜的 Comodo PositiveSSL,单年 9 美元。

Nginx

  • 域名型 SSL 证书(DV SSL):信任等级普通,只需验证网站的真实性便可颁发证书保护网站;
  • 企业型 SSL 证书(OV SSL):信任等级强,须要验证企业的身份,审核严格,安全性更高;
  • 增强型 SSL 证书(EV SSL):信任等级最高,一般用于银行证券等金融机构,审核严格,安全性最高,同时可以激活绿色网址栏。

部署 SSL 证书

1、下载对应证书版本

Apache / IIS / Nginx 都有对应的证书版本,这里 LNMP 是下载 Nginx 版,解压以后可以看到一个 .key 文件和 .crt/.pem 文件

Nginx

2、上传证书

把上面的 .key 文件和 .crt/.pem 文件上传到 /root 目录中,命名为 ssl.crt/ssl.pem 和 ssl.key,或者其他你想要的名字都可以。

3、配置部署

LNMP 一键安装包的 Nginx 配置在 /usr/local/nginx/conf/vhost/ 目录中,找到对应站点域名的配置文件(如 best66.me.conf)。普通安装的 Nginx 配置文件在 /etc/nginx/nginx.conf。vi 命令进入修改。

将其修改为(以下属性中 ssl 开头的属性与证书配置有直接关系,其它属性请结合自己的实际情况复制或调整,以下是以阿里云的证书为例):

server {
    listen 443;
    server_name best66.me www.best66.me;
    ssl on;
    root html;
    index index.html index.htm;
        ssl_certificate /root/ssl.pem;
        ssl_certificate_key /root/ssl.key;
        ssl_session_timeout 5m;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
    location / {
        root html;
        index index.html index.htm;
    }
}

如果想要强制 HTTPS,请做如下修改:

server
{
    listen 80;
    server_name best66.me www.best66.me; # 修改为你的域名
    rewrite ^/(.*) https://best66.me/$1 permanent; # 如果你的网站是带 www 的,请在域名前添加 www
}
server
{
    listen 443;
    # ...... 其余配置同上
}

Nginx

以上就搞定咯。

docker安装部署gitlab 配置使用部外nginx

一、docker安装gitlab镜像

1,镜像信息

https://hub.docker.com/r/gitlab/gitlab-ce/

docker pull gitlab/gitlab-ce

2,启动镜像

sudo docker run --detach 
 --hostname git.tmy.com 
 --publish 8929:80 --publish 2289:22 
 --name gitlab 
 --restart always 
 --volume /data/gitlab/config:/etc/gitlab 
 --volume /data/gitlab/logs:/var/log/gitlab 
 --volume /data/gitlab/data:/var/opt/gitlab 
 gitlab/gitlab-ce:latest

文档地址:https://docs.gitlab.com/omnibus/docker/#run-the-image

3,访问本机安装的gitlab

127.0.0.1:8929 端口号为步骤2中设置的端口号。

此处不知何种原因,启动了需要等待几分钟才可以访问,知道的大神可以六个言交流下。

可以访问之后继续往下走。

二、配置使用外部的nginx服务器

1,关闭gitlab内部的nginx服务

官方文档地址:https://docs.gitlab.com/omnibus/settings/nginx.html#using-a-non-bundled-web-server

启动的时候映射出来的目录
vim /data/gitlab/config/gitlab.rb 

在配置文件最末尾加上配置
nginx['enable'] = false 
web_server['external_users'] = ['www-data']

使配置生效
docker exec gitlab gitlab-ctl reconfigure

2,配置本机上的nginx

新nginx虚拟机配置文件,我的虚拟机配置文件在/usr/local/nginx/conf/vhost

vim /usr/local/nginx/conf/vhost/git.tmy.com.conf

下载官方的配置文件

https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/nginx

配置文件有http 和 https两个版本,这里我选择了http第一个

## GitLab 8.3+
##
## Lines starting with two hashes (##) are comments with information.
## Lines starting with one hash (#) are configuration parameters that can be uncommented.
##
##################################
## CONTRIBUTING ##
##################################
##
## If you change this file in a Merge Request, please also create
## a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
##
###################################
## configuration ##
###################################
##
## See installation.md#using-https for additional HTTPS configuration details.

upstream gitlab-workhorse {
 server unix:/var/opt/gitlab/gitlab-workhorse/socket;
}

## Normal HTTP host
server {
 ## Either remove "default_server" from the listen line below,
 ## or delete the /etc/nginx/sites-enabled/default file. This will cause gitlab
 ## to be served if you visit any address that your server responds to, eg.
 ## the ip address of the server (http://x.x.x.x/)n 0.0.0.0:80 default_server;
 listen 0.0.0.0:80 default_server;
 listen [::]:80 default_server;
 server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
 server_tokens off; ## Don't show the nginx version number, a security best practice
 root /opt/gitlab/embedded/service/gitlab-rails/public;

 ## See app/controllers/application_controller.rb for headers set

 ## Individual nginx logs for this GitLab vhost
 access_log /var/log/nginx/gitlab_access.log;
 error_log /var/log/nginx/gitlab_error.log;

 location / {
 client_max_body_size 0;
 gzip off;

 ## https://github.com/gitlabhq/gitlabhq/issues/694
 ## Some requests take more than 30 seconds.
 proxy_read_timeout 300;
 proxy_connect_timeout 300;
 proxy_redirect off;

 proxy_http_version 1.1;

 proxy_set_header Host $http_host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto $scheme;

 proxy_pass http://gitlab-workhorse;
 }
}

将配置文件写入刚才创建的虚拟机文件配置文件中。修改

#找到
upstream gitlab-workhorse {
 server unix:/var/opt/gitlab/gitlab-workhorse/socket;
}
#修改为
upstream gitlab-workhorse {
 server unix:/data/gitlab/data/gitlab-workhorse/socket;
}
#找到
server_name YOUR_SERVER_FQDN;
#修改为
server_name git.tmy.com 【域名是你自己配置好的域名】
#找到
access_log /var/log/nginx/gitlab_access.log;
error_log /var/log/nginx/gitlab_error.log;
#改为
access_log /data/wwwlogs/gitlab_access.log;
error_log/data/wwwlogs/gitlab_error.log;
#上边是日志文件而已,改称你自己的就行

配置完成后检查nginx -t 是否正常,没问题重新载入配置即可。

三、修改目录权限

chown -R www:www /data/gitlab/data/gitlab-workhorse/

修改完成后访问git.tmy.com 即可进入gitlab的web界面了

centos7系统下配置nginx php-fpm负载均衡

三台Centos7服务器

主:192.168.199.174
从:192.168.199.170
从:192.168.199.191

均全新最小化安装,都关闭了防火墙和SELINUX

第一步

先在 主服务器 上安装Nginx,可以在改配置前直接开启服务访问看看有没有问题,然后利用Nginx做请求转发

yum -y install nginx
systemctl start nginx.service
vi /etc/nginx/conf.d/default.conf

default.conf 修改后,删掉了注释部分

upstream myServer{
    server 192.168.199.170:9000 max_fails=3 fail_timeout=10s;
    server 192.168.199.191:9000 max_fails=3 fail_timeout=10s;
}
server {
    listen       80;
    server_name  localhost;
    location / {
        root   /home/wwwroot;
        index  index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
    location ~ .php$ {
        root           /home/wwwroot;
        fastcgi_pass   myServer;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

重新启动 Nginx 服务,顺便实时查看 Nginx 的日志,以便了解访问情况

systemctl restart nginx.service
tail -f /var/log/nginx/error.log /var/log/nginx/access.log

第二步

在 从服务器 上安装PHP

# 安装一些需要的东西
yum -y install wget libxml2-devel libtool
# 下载PHP
wget -O php-7.1.7.tar.gz http://php.net/get/php-7.1.7.tar.gz/from/this/mirror
# 复制一份到另一个从服务器,输入yes和191的密码
scp php-7.1.7.tar.gz [email protected]:/usr/local
# 将PHP安装包放到/usr/local目录
mv php-7.1.7.tar.gz /usr/local


# 从这里起,两台从服务器执行操作都一样
# 另一台服务器记得先执行上面yum 的那一行
# 进入/usr/local 目录
cd /usr/local
# 解压PHP安装包
tar -xvf php-7.1.7.tar.gz
# 进入PHP安装文件夹目录
cd php-7.1.7
# 安装PHP
./configure --enable-fpm
make && make install
# 复制和重命名配置文件
cp php.ini-development ../php/php.ini
cp ../etc/php-fpm.conf.default ../etc/php-fpm.conf
mv ../etc/php-fpm.d/www.conf.default ../etc/php-fpm.d/www.conf
# 创建fpm的软链接放入bin目录下,方便随处可用
ln -s sapi/fpm/php-fpm ../bin/php-fpm

修改 /usr/local/etc/php-fpm.conf 配置文件,在最后一行

include=/usr/local/etc/php-fpm.d/*.conf

修改 /usr/local/etc/php-fpm.d/www.conf 配置文件

listen = 0.0.0.0:9000
request_terminate_timeout = 0

以上操作在两台从服务器操作好后,分别启动PHP-FPM

php-fpm

第三步

开始测试

首先分别在两台从服务器上创建测试文件

cd /home
mkdir wwwroot
cd wwwroot
vi 1.php
<?php
// 这里的170换成当前从服务器的IP
// 比如191那台,这里就写191
echo("170");

浏览器打开:http://192.168.199.174/1.php

  • 第一次打开:170

  • 第一次刷新:191

  • 第二次刷新:170

  • 第三次刷新:191

与此同时,主服务器那边 nginx 的 error.log 没有变化,而 access.log 文件一直在记录各种成功的请求。

第四步:

配合 Laravel 的优雅链接设置

先修改 主服务器 的 /etc/nginx/conf.d/default.conf

# 就改了这一个 location 里的东西
location / {
    root   /home/wwwroot;
    index  index.html index.htm;
    # 就加了下面一段
    try_files $uri $uri/ /index.php?$query_string;
}

然后在 从服务器 的 /home/wwwroot 目录下建立 index.php 文件

<?php
echo '填170或191 <br />';
var_dump($_REQUEST);
echo '<hr />';
var_dump($_SERVER);

然后OK了,自己去测试吧。

CentOS Nginx安装配置Let’s Encrypt CA证书

  • 创建存放整数的目录
mkdir /data/www/ssl
  • 创建 CSR 文件

接着就可以生成 CSR(Certificate Signing Request,证书签名请求)文件了。在这之前,还需要创建域名私钥(一定不要使用上面的账户私钥),根据证书不同类型,域名私钥也可以选择 RSA 和 ECC 两种不同类型。以下两种方式请根据实际情况二选一。

  1. 创建 RSA 私钥(兼容性好):
openssl genrsa 4096 > domain.key
  1. 创建 ECC 私钥(部分老旧操作系统、浏览器不支持。优点是证书体积小):
#secp256r1
openssl ecparam -genkey -name secp256r1 | openssl ec -out domain.key
#secp384r1
openssl ecparam -genkey -name secp384r1 | openssl ec -out domain.key

有了私钥文件,就可以生成 CSR 文件了。在 CSR 中推荐至少把域名带 www 和不带 www 的两种情况都加进去,其它子域可以根据需要添加(目前一张证书最多可以包含 100 个域名):

openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]nsubjectAltName=DNS:yoursite.com,DNS:www.yoursite.com")) > domain.csr
执行这一步时,如果提示找不到 /etc/ssl/openssl.cnf 文件,请看看 /usr/local/openssl/ssl/openssl.cnf 是否存在。如果还是不行,也可以使用交互方式创建 CSR(需要注意 Common Name 必须为你的域名):
openssl req -new -sha256 -key domain.key -out domain.csr
  • 添加nginx配置,支持验证服务

我们知道,CA 在签发 DV(Domain Validation)证书时,需要验证域名所有权。传统 CA 的验证方式一般是往 [email protected] 发验证邮件,而 Let’s Encrypt 是在你的服务器上生成一个随机验证文件,再通过创建 CSR 时指定的域名访问,如果可以访问则表明你对这个域名有控制权。首先创建用于存放验证文件的目录,例如:

mkdir /data/www/challenges/

然后配置一个 HTTP 服务监听80端口,以 Nginx 为例:

server {
    listen 80;
    # listen [::]:80 default_server;

    server_name www.yoursite.com yoursite.com;
    location ^~ /.well-known/acme-challenge/ {
        alias /home/xxx/www/challenges/;
        try_files $uri =404;
    }

    location / {
        return 301 https://$server_name$request_uri;
    }
}

以上配置优先查找 ~/www/challenges/ 目录下的文件,如果找不到就重定向到 HTTPS 地址。这个验证服务以后更新证书还要用到,建议一直保留。

  • 获取网站证书

先把 acme-tiny 脚本保存到之前的 ssl 目录:

wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py

指定账户私钥、CSR 以及验证目录,执行脚本:

python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir ~/www/challenges/ &gt; ./signed.crt

如果一切正常,当前目录下就会生成一个 signed.crt,这就是申请好的证书文件。
如果你把域名 DNS 解析放在国内,这一步很可能会遇到类似这样的错误:

ValueError: Wrote file to /home/xxx/www/challenges/oJbvpIhkwkBGBAQUklWJXyC8VbWAdQqlgpwUJkgC1Vg, but couldn't download http://www.yoursite.com/.well-known/acme-challenge/oJbvpIhkwkBGBAQUklWJXyC8VbWAdQqlgpwUJkgC1Vg

尝试更改到国外的dns

搞定网站证书后,还要下载 Let’s Encrypt 的中间证书。配置 HTTPS 证书时既不要漏掉中间证书,也不要包含根证书。在 Nginx 配置中,需要把中间证书和网站证书合在一起:

wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem &gt; intermediate.pem
cat signed.crt intermediate.pem &gt; chained.pem

为了后续能顺利启用 OCSP Stapling,我们再把根证书和中间证书合在一起:

wget -O - https://letsencrypt.org/certs/isrgrootx1.pem &gt; root.pem
cat intermediate.pem root.pem &gt; full_chained.pem
  • 配置nginx监听443端口
server {
    listen 443;
    client_max_body_size 4G; 
    server_name chinachenshun.com www.chinachenshun.com sdchenshun.com www.sdchenshun.com; 

    ssl on; 
    ssl_session_timeout 5m; 
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA; 
    ssl_session_cache shared:SSL:50m; 
    ssl_prefer_server_ciphers on; 
    ssl_certificate /data/www/ssl/chained.pem; 
    ssl_certificate_key /data/www/ssl/domain.key;
    ........
  • 配置自动更新

Let’s Encrypt 签发的证书只有 90 天有效期,需要写个自动更新的脚本叫做update_ca.sh,放到crontab执行定时任务,脚本如下:

#!/bin/bash
         cd /home/xxx/www/ssl/
         python acme_tiny.py --account-key account.key --csr domain.csr --acme-dir /home/xxx/www/challenges/ &gt; signed.crt || exit
         wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem &gt; intermediate.pem
         cat signed.crt intermediate.pem &gt; chained.pem
         service nginx reload

         vim /etc/crontab 加入以下内容,一个月执行一次:
         0 0 1 * * nobody /home/xxx/update_ca.sh &gt;/dev/null 2&gt;&amp;1

注意,为了安全,crond执行的用户角色是nobody,所以相关联的文件属组需要改成nobody,这样才有权限执行相应的读写。

saltstack快速批量安装nginx

本文讲介绍

使用sls安装nginx,并管理nginx的配置文件,当nginx配置文件被修改时,自动更新配置文件,并重启nginx

在master端上配置nginx.sls文件

 mkdir -p /srv/salt/nginx
 cd /srv/salt/nginx/
vim init.sls
nginx:
  pkg:
    - installed
  service:
    - running
    - enable: True
    - reload: True
    - watch:
      - pkg: nginx
      - file: /etc/nginx/nginx.conf
      - file: /etc/nginx/conf.d/default.conf
/etc/nginx/nginx.conf:
  file.managed:
    - source: salt://etc/nginx/nginx.conf
    - user: root
    - group: root
    - mode: 644
/etc/nginx/conf.d/default.conf:
  file.managed:
    - source: salt://etc/nginx/conf.d/default.conf
    - user: root
    - group: root
    - mode: 644

文件讲解

  • nginx: 这是要安装的包名,也是sls文件的id,不能重复
  • pkg: pkg是包管理模块,对应/usr/lib/python2.6/site-packages/salt/states下的模块pkg.py
  • installed installed是pkg模块下的函数,id(nginx)作为installed的参数进行调用
  • service: service是服务模块,对应/usr/lib/python2.6/site-packages/salt/states下的模块service.py, 由于service是一个key,其下的running, require, watch是列表形式的值,因此service之后有冒号
  • running running是service.py模块下的函数,id(nginx)作为running的参数进行调用
  • enable: True
  • reload: True
  • watch: watch: 表示对文件$file的监控,当master 向minion传递$file时,新的$file与minion上原有文件不一致时,会重启nginx服务
  • pkg: nginx
  • file: /etc/nginx/nginx.conf
  • file: /etc/nginx/conf.d/default.conf
  • /etc/nginx/nginx.conf: 这一行同样是id不能重复:表示传递到minion时所处的位置,同时也作为file.managed函数的参数
  • file.managed:
  • file.py模块的managed函数,下面的source,user, group, mode都是managed函数的参数
  • source: salt://etc/nginx/nginx.conf
  • source 是managed函数的参数,指定要传递到minion端的源文件. –
  • salt://etc/nginx/nginx.conf 表示/etc/nginx/nginx.conf在/srv/salt之下,/srv/salt是saltstack的根目录
  • user: root
    表示文件的属主
  • group: root
    表示文件的属组
  • mode: 644
    表示文件的权限

开始配置

1:在master端上安装nginx,方便生成nginx的配置文件

 yum -y install nginx

2:创建nginx同步目录

mkdir /srv/salt/etc/nginx/conf.d -p

3:拷贝nginx的配置文件到/srv/salt/etc/nginx/目录下

cp /etc/nginx/nginx.conf /srv/salt/etc/nginx/

4:拷贝default.conf配置文件到/srv/salt/nginx/conf.d/目录下

cp /etc/nginx/conf.d/default.conf /srv/salt/etc/nginx/conf.d/

5:开始安装

 salt '*' state.sls nginx

6:测试是否安装成功

salt '*' cmd.run 'rpm -qa | grep nginx'

接下来实现配置更新

手动更新配置文件

在master端将默认端口更改为8080
vim /srv/salt/etc/nginx/conf.d/default.conf

 listen       8080 default_server;

在minion端执行指令,观察
salt-call state.sls nginx

自动更新配置文件

定义pillar的主目录,同时创建pillar目录(master端)

vim /etc/salt/master   #找到以下内容取消注释
pillar_roots:
  base:
    - /srv/pillar
pillar_opts: True
mkdir -p /srv/pillar

定义入口文件top.sls

入口文件的作用一般是定义pillar的数据覆盖被控主机的有效范围,’*’代表任意主机,默认从 base 标签开始解析执行,下一级是操作的目标

cat /srv/pillar/top.sls
base:
  '*':
    - nginx    #指代的是nginx.sls文件

定义nginx文件,每分钟更新一次

install -d /srv/pillar/nginx
cd nginx/
cat init.sls
schedule:
 nginx:
    function: state.sls
    minutes: 1
    args:
        - 'nginx'
刷新被控主机的pillar信息
salt '*' saltutil.refresh_pillar
查看上面定义的nginx.sls数据项,出现以下内容表示成功
salt '*' pillar.data
192.168.31.166:
    ----------
    schedule:
        ----------
        nginx:
            ----------
            args:
                - nginx
            function:
                state.sls
            minutes:
                1
192.168.31.188:
    ----------
    schedule:
        ----------
        nginx:
            ----------
            args:
                - nginx
            function:
                state.sls
            minutes:
                1

测试

在master端将默认端口更改为666
vim /srv/salt/etc/nginx/conf.d/default.conf
 listen       666 default_server;
一分钟后在minion端查看端口:
netstat -tnl

Kubernetes(k8s)部署并测试nginx service

创建2个pod的nginx service

[root@node1 data]#  kubectl run nginx –replicas=2 –labels="run=load-balancer-example" –image=nginx:1.9  –port=80
deployment "nginx" created
[root@node1 yaml]# kubectl get pod –all-namespaces -o wide|grep nginx
default       nginx-3431010723-6kv1z                  1/1       Running   2          1h        10.244.5.6      node5
default       nginx-3431010723-bw22q                  1/1       Running   2          1h        10.244.3.14     node4
[root@node1 kube-config]# kubectl expose deployment nginx –type=NodePort –name=example-service
service "example-service" exposed
[root@node1 kube-config]# kubectl describe svc example-service
Name:            example-service
Namespace:        default
Labels:            run=load-balancer-example
Annotations:        <none>
Selector:        run=load-balancer-example
Type:            NodePort
IP:            10.105.170.116
Port:            <unset>    80/TCP
NodePort:        <unset>    30457/TCP
Endpoints:        10.244.3.14:80,10.244.5.6:80
Session Affinity:    None
Events:            <none>

测试nginx服务

[root@node1 yaml]# curl 10.105.170.116:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

浏览器访问都能显示nginx welcome界面

http://172.172.20.14:30457
http://172.172.20.15:30457

http://nodes:30457

Nginx

centos7安装配置gitlab(使用外部nginx)

1、安装依赖:

sudo yum install curl policycoreutils openssh-server openssh-clients
sudo systemctl enable sshd
sudo systemctl start sshd
sudo yum install postfix
sudo systemctl enable postfix
sudo systemctl start postfix
sudo firewall-cmd --permanent --add-service=http
sudo systemctl reload firewalld

2、添加gitlab源:

curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash

3、安装gitlab-ce

sudo yum install gitlab-ce

如果您不喜欢通过管道脚本安装存储库,您可以在这里找到整个脚本并手动选择并下载包并使用:

curl -LJO https://packages.gitlab.com/gitlab/gitlab-ce/packages/el/7/gitlab-ce-XXX.rpm/download
rpm -i gitlab-ce-XXX.rpm

4、配置gitlab:

sudo gitlab-ctl reconfigure
至此gitlab安装成功,默认用户名为root。

5、停止gitlab自带的nginx

打开文件$sudo vi /etc/gitlab/gitlab.rb。
将nginx['enable'] = ture改为nginx['enable'] = false
重启gitlab:sudo gitlab-ctl reconfigure。

6、修改gitlab域名:

打开/etc/gitlab/gitlab.rb文件,将external_url参数修改为自己的域名。

7、添加外部nginx的gitlab配置文件:

vim /etc/nginx/conf.d/gitlab.conf

添加以下内容:

upstream gitlab {
# 7.x 版本在此位置
# server unix:/var/opt/gitlab/gitlab-rails/tmp/sockets/gitlab.socket;
# 8.0 位置
server unix://var/opt/gitlab/gitlab-rails/sockets/gitlab.socket;
}

server {
 listen *:80;

 server_name gitlab.xuwanqiu.com; # 请修改为你的域名

 server_tokens off; # don't show the version number, a security best practice
 root /opt/gitlab/embedded/service/gitlab-rails/public;

 # Increase this if you want to upload large attachments
 # Or if you want to accept large git objects over http
 client_max_body_size 250m;

 # individual nginx logs for this gitlab vhost
 access_log /var/log/gitlab/nginx/gitlab_access.log;
 error_log /var/log/gitlab/nginx/gitlab_error.log;

 location / {
 # serve static files from defined root folder;.
 # @gitlab is a named location for the upstream fallback, see below
 try_files $uri $uri/index.html $uri.html @gitlab;
 }

 # if a file, which is not found in the root folder is requested,
 # then the proxy pass the request to the upsteam (gitlab unicorn)
 location @gitlab {
 # If you use https make sure you disable gzip compression
 # to be safe against BREACH attack

 proxy_read_timeout 300; # Some requests take more than 30 seconds.
 proxy_connect_timeout 300; # Some requests take more than 30 seconds.
 proxy_redirect off;

 proxy_set_header X-Forwarded-Proto $scheme;
 proxy_set_header Host $http_host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Frame-Options SAMEORIGIN;

 proxy_pass http://gitlab;
 }

 # Enable gzip compression as per rails guide: http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression
 # WARNING: If you are using relative urls do remove the block below
 # See config/application.rb under "Relative url support" for the list of
 # other files that need to be changed for relative url support
 location ~ ^/(assets)/ {
 root /opt/gitlab/embedded/service/gitlab-rails/public;
 # gzip_static on; # to serve pre-gzipped version
 expires max;
 add_header Cache-Control public;
 }

 error_page 502 /502.html;
}

参考资料:

http://blog.csdn.net/peterxiaoq/article/details/73330302
http://www.cnblogs.com/lixiuran/p/6761299.html
https://segmentfault.com/q/1010000003695935?_ea=337139
https://laravel-china.org/topics/2829/centos-7-install-gitlab-ce-community-edition-and-modify-the-default-nginx
https://about.gitlab.com/installation/#centos-7
https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md
http://jiankg.github.io/2015/06/12/%E5%9C%A8centos7%E4%B8%8A%E6%90%AD%E5%BB%BAgitlab%E7%9A%84%E6%AD%A3%E7%A1%AE%E5%A7%BF%E5%8A%BF/

awk查看统计Nginx访问日志

nginx日志最好实现每天定时切割下,特别是在访问量比较大的时候,方便查看与处理,如果没切割,可以用sed直接切割,

切割日志

查找7月17日访问log导出到17.log文件中:

cat gelin_web_access.log | egrep "17/Jul/2017" | sed  -n '/00:00:00/,/23:59:59/p' > /tmp/17.log

查看访问量前10的IP

awk '{print $1}' 17.log | sort | uniq -c | sort -nr | head -n 10 

查看访问前10的URL

awk '{print $11}' gelin_web_access.log | sort | uniq -c | sort -nr | head -n 10

查询访问最频繁的URL

awk '{print $7}' gelin_web_access.log | sort | uniq -c | sort -n -k 1 -r | more

查询访问最频繁的IP

awk '{print $1}' gelin_web_access.log | sort | uniq -c | sort -n -k 1 -r | more

根据访问IP统计UV

awk '{print $1}' gelin_web_access.log | sort | uniq -c | wc -l

统计访问URL统计PV

awk '{print $7}' gelin_web_access.log | wc -l

根据时间段统计查看日志

cat gelin_web_access.log | sed -n '/17/Jul/2017:12/,/17/Jul/2017:13/p' | more

Nginx配置basic_auth密码验证

为Nginx添加basic_auth,意思就是访问页面的时候需要弹出来一个用户和密码验证的东西,本文基于CentOS 6

1. 安装密码生成工具htpasswd并生成用户密码文件

yum install httpd-tools               #适用centos
sudo apt-get install apache2-utils    #适用ubuntu

生成用户密码文件

$ htpasswd -c /var/www/html/.htpasswd user1  #回车会要求输入两遍密码,会清除所有用户!
$ htpasswd -bc /var/www/html/.htpasswd user1 password  #不用回车,直接指定user1的密码为password
$ htpasswd -b /var/www/html/.htpasswd user2 password   #添加一个用户,如果用户已存在,则是修改密码
$ htpasswd -D /var/www/html/.htpasswd user2  #删除用户

2. 为Nginx添加basic_auth配置

server {
    listen        80;
#    root        /tmp;
#    index        index.html index.htm;
    server_name    zhukun.net www.zhukun.net;

    location / {
        auth_basic        "input you user name and password";
        auth_basic_user_file    /export/servers/.htpasswd;
        proxy_pass http://127.0.0.1:9000;
    }
}

然后再次访问zhukun.net时便会弹出验证框要求输入用户名和密码。

3. 可能遇到的问题

访问zhukun.net没有弹出验证框怎么办?
首先修改nginx.conf,将日志级别调为info,如下

$ cat /export/servers/nginx-1.12.1/conf/nginx.conf
.......
user  admin;
worker_processes  8;

error_log  logs/error.log info;
......

然后再次访问让其产error_log
看到error_log时会发现有如下错误产生

*69 no user/password was provided for basic authentication, client: 10.12.138.126, server: www.zhukun.net, request: "GET /date_lateral HTTP/1.1", host: "www.zhukun.net"

原因在于

The HTTP Basic authentication works as following:
*) A browser requests a page without user/password.
*) A server response with 401 page, sending realm as well.
   At this stage the 401 code appears in access_log and the message
   “no user/password …” appears in error_log.
*) The browser shows a realm/login/password prompt.
*) If a user will press cancel, then the browser will show the received
   401 page.
*) If the user enters login/password, then the browser repeats the request
   with login/password.

Then until you will exit the browser, it will send these login/password
with all requests in protected hierarchy.

error_page配置的401页面不存在或者指向问题导致的,可以注释掉401配置或者保证401配置指向的文件可用,然后basic_auth便会生效。