30分钟,同一台ubuntu服务器下 安装discourse和wordpress站点 并配置ssl和nginx 要求客服开通25端口

架设思想:使用国外服务器,将根域名example.com用作wordpress,forum.example.com用作discourse,配置完成以后使用certbot一键申请ssl证书并开启自动续期。

这篇文章比较长,所以我们分成几个章节来介绍:

一、准备工作:选择一家ISP;
二、LEMP基础配置,用于nginx代理和wordpress业务;
三、wordpress站点安装和配置;
四、discourse站点安装和配置;
五、安装certbot申请ssl证书完成配置。

一、准备工作:选择一家ISP

用国外的主机呗,便宜,服务好,最重要的是按小时甚至按分钟付费,可以先充10刀试用,机房速度不满意分分钟删实例换一个。一切不支持按使用时间付费的ISP都是耍流氓,到时候速度不行想退货退不了又是噩梦。
目前国外支持按时间付费的ISP主要有GCP(谷歌)、AWS(亚马逊)、Azure(微软)、Vultr和DigitalOcean。

从性价比来说推荐Vultr和DigitalOcean这两家。

因为wordpress和discourse需要25端口发邮件,但很多ISP都默认禁用了25端口,以避免滥发广告邮件,如果要用的话有一定的机制取得,不然就只有用转发的形式。DigitalOcean目前的机制是平稳使用60天以后自动开放,Vultr是可以提交工单申请的。

此案例使用Vultr的5刀一个月的1核1G洛杉矶线路Ubuntu 18.04 x6主机,如果你要用同样的话,可以顺便点下面的链接,使用我的邀请链接注册,帮我贡献一个邀请任务,谢过:https://www.vultr.com/?ref=7465154

完成主机安装并SSH进入服务器后,可以先搭一个梯子 :grinning: :

wget --no-check-certificate https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocks-go.sh 
chmod +x shadowsocks-go.sh  
./shadowsocks-go.sh 2>&1 | tee shadowsocks-go.log 

如果服务器要多账号登录或者不想记root账户的复杂密码的话,可以设置一个普通账户:

adduser nidezhanghaoming

给这个账号赋予sudo权限:

usermod -aG sudo nidezhanghaoming

好,准备工作就介绍到这里。

别忘了,域名及二级域名A记录指向服务器公网ip。

二、LEMP基础配置,用于nginx代理和wordpress业务

WordPress需要一个Web服务器,一个数据库和PHP才能正常运行。所以需要设置LEMP堆栈(Linux,Nginx,MySQL和PHP),同时,Nginx也会用于让同一个服务器同时支持wordpress和discourse。

注意,如果是使用root账号不用加sudo,非root账号才需要加sudo。

开始配置Nginx吧!

sudo apt update
sudo apt install nginx

安装Mysql

sudo apt install mysql-server-5.7
sudo mysql_secure_installation

配置mysql

sudo mysql

添加一个数据库的root账户密码,记得修改代码中的password为你的密码。

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

使之生效

FLUSH PRIVILEGES;

新建一个数据库用于wordpress,wordpress改成你要的名字

CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

新建该数据库的管理员账号,wordpress改成你的数据库名,wordpressuser改成你想要的管理员名,password改成你的数据库密码

GRANT ALL ON wordpress.* TO 'wordpressuser'@'localhost' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;

退出mysql

exit

安装php

sudo apt install php-fpm php-mysql

新建一个Vhost文件并进行配置,example.com改成你的主域名

sudo nano /etc/nginx/sites-available/example.com

按以下配置设置Vhost文件,按上下键选择修改,完成后按 ctrl+o 再按 enter 确认修改,要退出的话按 ctrl+x

#不罗嗦,先把反向代理写好了。

upstream forum {
#监听8080端口流量,discourse的,下文的配置中会写
    server 127.0.0.1:8080 fail_timeout=0;
#监听4433端口流量,discourse的,下文的配置中会写
    server 127.0.0.1:4433 fail_timeout=0;
}
server {
#example.com改成你要设置的wordpress目录
        root /var/www/example.com;
        index index.php index.html index.htm index.nginx-debian.html;
#example.com改成你的主域名
        server_name example.com;

        location = /favicon.ico { log_not_found off; access_log off; }
        location = /robots.txt { log_not_found off; access_log off; allow all; }
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
        expires max;
        log_not_found off;
        }

        location / {
                try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        }

        location ~ /\.ht {
                deny all;
        }

    listen 80;

}

server {
#forum.example.com改成你要使用的discourse二级域名
      server_name forum.example.com;

      root /usr/share/nginx/html;
      index index.html index.htm;

      client_max_body_size 10G;

      location / {
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_redirect off;
          proxy_pass https://forum;
      }

    listen 80;

}

example.com改成你的主域名

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

测试nginx是否有错,如果有错根据提示修改。

sudo nginx -t

重新载入nginx

sudo systemctl reload nginx

安装其他的php扩展

sudo apt update
sudo apt install php-curl php-gd php-intl php-mbstring php-soap php-xml php-xmlrpc php-zip

重启php

sudo systemctl restart php7.2-fpm

三、wordpress站点安装和配置

在临时目录下载wordpress压缩包

cd /tmp
curl -LO https://wordpress.org/latest.tar.gz

解压缩

tar xzvf latest.tar.gz

将模板复制并改名为正式的配置文件

cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php

将临时目录的wordpress复制到你的网站目录,example.com改成你的主域名

sudo cp -a /tmp/wordpress/. /var/www/example.com

指定权限

sudo chown -R www-data:www-data /var/www/example.com

生成一段salt用于wordpress安装

curl -s https://api.wordpress.org/secret-key/1.1/salt/

打开wordpress配置文件,在相应字段填入你的数据库、用户名、密码、salt

sudo nano /var/www/example.com/wp-config.php

好,现在访问你的主域名,在网页上配置你的wordpress,不过你可以等等,discourse配置完成以后一气呵成。

四、discourse站点安装和配置

如果从上一步进入,还在tmp中,输入cd 回到根目录。

因为我使用了1G内存的服务器,还安了一个wordpress,低于discourse建议的2G内存,所以需要先为Linux服务器设置swap文件。

如果你的内存大于2G,可以跳过这swap的步骤。

创建一个空的 swap 文件

 sudo install -o root -g root -m 0600 /dev/null /swapfile

填充 1GB 至文件名为 swapfile 的文件中

 dd if=/dev/zero of=/swapfile bs=1k count=1024k

如果您想要 2GB

 dd if=/dev/zero of=/swapfile bs=1k count=2048k

告诉 Linux 这是 swap 文件:

 mkswap /swapfile

激活 swap

 swapon /swapfile

添加至文件系统表中,这样重启后系统才能找到它

 echo "/swapfile       swap    swap    auto      0       0" | sudo tee -a /etc/fstab

设置 swappiness 至 10,这样它只在急需内存时才会被使用

 sudo sysctl -w vm.swappiness=10
 echo vm.swappiness = 10 | sudo tee -a /etc/sysctl.conf

如果执行了上面的不用再重复执行下面的。。。
建立一个 2GB 的 swap 文件的可供拷贝粘贴的脚本:

sudo install -o root -g root -m 0600 /dev/null /swapfile
dd if=/dev/zero of=/swapfile bs=1k count=2048k
mkswap /swapfile
swapon /swapfile
echo "/swapfile       swap    swap    auto      0       0" | sudo tee -a /etc/fstab
sudo sysctl -w vm.swappiness=10
echo vm.swappiness = 10 | sudo tee -a /etc/sysctl.conf

基于docker开始安装discourse

安装docker

wget -qO- https://get.docker.io/ | sh

新建目录,下载discourse到指定目录,从示例中复制出app.yml

mkdir /var/discourse
git clone https://github.com/discourse/discourse_docker.git /var/discourse
cd /var/discourse
cp samples/standalone.yml containers/app.yml

编辑app.yml

nano containers/app.yml

将 expose 中的 - "80:80" 修改为 - "8080:80" , - "443:443" 修改为 - "4433:443" 。

将 params 中的 version 前的注释符号 # 去掉,然后设置其为最稳定的 stable(正式版)。

在 env 中增加 DISCOURSE_DEFAULT_LOCALE,并设为您想用的语言,比如简体中文 zh_CN。

添加Let’s Encrypt 注册用邮箱账号,和certbot中的一致。

LETSENCRYPT_ACCOUNT_EMAIL: email@example.com

将 DISCOURSE_DEVELOPER_EMAILS 改为您的邮件地址。

将 DISCOURSE_HOSTNAME 设置为 forum.example.com,意思是您想要您的 Discourse 可以通过 http://forum.example.com/ 访问。您需要更新您的 DNS 的 A 记录,使其指向您服务器的 IP 地址。

templates 中添加web.template.yml和web.ssl.template.yml两个ssl模板,添加好的效果如下如下:

  • "templates/postgres.template.yml"
  • "templates/redis.template.yml"
  • "templates/sshd.template.yml"
  • "templates/web.template.yml"
  • "templates/web.ssl.template.yml"

将您邮件发送的验证信息填在 DISCOURSE_SMTP_ADDRESS、DISCOURSE_SMTP_PORT、DISCOURSE_SMTP_USER_NAME和DISCOURSE_SMTP_PASSWORD。如果需要的话请确定删掉了这几行前面的多余空格和 # 字符。

如果您在使用 1 GB 的服务器,将 UNICORN_WORKERS 设为 2,db_shared_buffers设为 128MB,以节省内存。

在hooks里添加好用的插件,solved和voting,添加到docker_manager.git下方,以后要安装插件也是在这里,添加好的效果如下:
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
- git clone https://github.com/discourse/discourse-solved.git
- git clone https://github.com/discourse/discourse-voting.git

完成app.yml这些编辑后,按下Ctrl+O之后再按Enter保存,再按Ctrl+X退出。

初始化 Discourse,可能花10分钟甚至更长的时间,请耐心等待。

./launcher bootstrap app

运行完成后,启动 Discourse

./launcher start app

好,现在分别进入http://example.comhttp://forum.example.com 就可以看到同一站点下的wordpress和discourse了,如果想要https,需要继续往下配置ssl。

五、安装certbot申请ssl证书完成配置

如果从上一步进入,还在/var/discourse 目录,输入cd 回到根目录。

首先,添加存储库:

sudo add-apt-repository ppa:certbot/certbot

安装Certbot的Nginx软件包:

sudo apt install python-certbot-nginx

使用Certbot自动完成SSL证书申请和配置,Certbot会自动修改你的nginx配置文件,替换example.com和forum.example.com为你的域名和二级域名。

sudo certbot --nginx -d example.com -d forum.example.com

按照英文的提示配置吧。

完成以后进入下一步。

证书使用周期有限,需要设置certbot自动续约证书:

sudo certbot renew --dry-run

打开nginx和vhost,可以查看到certbot对nginx的修改,最终配置好的文件如下:

sudo nano /etc/nginx/sites-available/example.com
upstream forum {
    server 127.0.0.1:8080 fail_timeout=0;
    server 127.0.0.1:4433 fail_timeout=0;
}
server {
        root /var/www/example.com;
        index index.php index.html index.htm index.nginx-debian.html;
        server_name example.com;

        location = /favicon.ico { log_not_found off; access_log off; }
        location = /robots.txt { log_not_found off; access_log off; allow all; }
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
        expires max;
        log_not_found off;
        }

        location / {
                try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        }

        location ~ /\.ht {
                deny all;
        }

    listen 443 ssl; # managed by Certbot
#    listen 80;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
      server_name forum.example.com;

      root /usr/share/nginx/html;
      index index.html index.htm;

      client_max_body_size 10G;

      location / {
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_redirect off;
          proxy_pass https://forum;
      }

    listen 443 ssl; # managed by Certbot
#    listen 80;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    if ($host = example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80;
        server_name example.com;
    return 404; # managed by Certbot


}

server {
    if ($host = forum.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


      listen 80;
      server_name forum.example.com;
    return 404; # managed by Certbot


}

通过以下命令查看修改app.yml

nano /var/discourse/containers/app.yml

贴出我的app.yml 终极配置,供大家参考:

## this is the all-in-one, standalone Discourse Docker container template
##
## After making changes to this file, you MUST rebuild
## /var/discourse/launcher rebuild app
##
## BE *VERY* CAREFUL WHEN EDITING!
## YAML FILES ARE SUPER SUPER SENSITIVE TO MISTAKES IN WHITESPACE OR ALIGNMENT!
## visit http://www.yamllint.com/ to validate this file as needed

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
## Uncomment these two lines if you wish to add Lets Encrypt (https)
  - "templates/web.ssl.template.yml"
  - "templates/web.letsencrypt.ssl.template.yml"

## which TCP/IP ports should this container expose?
## If you want Discourse to share a port with another webserver like Apache or nginx,
## see https://meta.discourse.org/t/17247 for details
expose:
  - "8080:80"   # http
  - "4433:443" # https

params:
  db_default_text_search_config: "pg_catalog.english"

  ## Set db_shared_buffers to a max of 25% of the total memory.
  ## will be set automatically by bootstrap based on detected RAM, or you can override
  db_shared_buffers: "128MB"

  ## can improve sorting performance, but adds memory usage per-connection
  #db_work_mem: "40MB"

  ## Which Git revision should this container use? (default: tests-passed)
  version: stable

env:
  LANG: en_US.UTF-8
  DISCOURSE_DEFAULT_LOCALE: zh_CN

  ## How many concurrent web requests are supported? Depends on memory and CPU cores.
  ## will be set automatically by bootstrap based on detected CPUs, or you can override
  UNICORN_WORKERS: 1

  ## TODO: The domain name this Discourse instance will respond to
  ## Required. Discourse will not work with a bare IP number.
  DISCOURSE_HOSTNAME: 'forum.example.com'

  ## Uncomment if you want the container to be started with the same
  ## hostname (-h option) as specified above (default "$hostname-$config")
  #DOCKER_USE_HOSTNAME: true

  ## TODO: List of comma delimited emails that will be made admin and developer
  ## on initial signup example 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'admin@example.com'

  ## TODO: The SMTP mail server used to validate new accounts and send notifications
  # SMTP ADDRESS, username, and password are required
  # WARNING the char '#' in SMTP password can cause problems!
  DISCOURSE_SMTP_ADDRESS: smtp.example.com
  DISCOURSE_SMTP_PORT: 25
  DISCOURSE_SMTP_USER_NAME: admin@sexample.com
  DISCOURSE_SMTP_PASSWORD: password
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (optional, default true)

  ## If you added the Lets Encrypt template, uncomment below to get a free SSL certificate
  LETSENCRYPT_ACCOUNT_EMAIL: admin@example.com

  ## The CDN address for this Discourse instance (configured to pull)
  ## see https://meta.discourse.org/t/14857 for details
  #DISCOURSE_CDN_URL: //discourse-cdn.example.com

## The Docker container is stateless; all data is stored in /shared
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

## Plugins go here
## see https://meta.discourse.org/t/19157 for details
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/discourse/discourse-voting.git
## Any custom commands to run after building
run:
  - exec: echo "Beginning of custom commands"
  ## If you want to set the 'From' email address for your first registration, uncomment and change:
  ## After getting the first signup email, re-comment the line. It only needs to run once.
  #- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
  - exec: echo "End of custom commands"

完成以后,重建容器。

./launcher rebuild app

重启容器。

./launcher start app

再次输入域名,就会发现已经是https的域名了。

配置临时管理员账户

如果你的SMTP还未配置好,可以使用以下方式激活discourse的管理员账户:

./launcher enter app

使用以下命令

rake admin:create

根据提示创建管理员账户

和ISP沟通开通25端口:

ISP为了防垃圾邮件,默认是屏蔽了发邮件的25端口,所以要提工单,说明情况。

一来二去几封邮件就搞定了,下面贴出我和vultr客服的沟通记录,大家可以参考。等他告诉你已经解封以后记得在面板重启服务器。

Support - tickets - Open New Ticket:新建一个工单
我说:

Please unblock port 25. WordPress and Discourse need it open. Thanks!

很快回复了:


Thank you for your SMTP unblock request!

In order to combat spam and spam-like activities, we will need to review some additional information prior to removing the SMTP filter.

Please reply to this ticket with the following information:

1. The business name and organization URL(s) under which you offer services.
2. Describe, in as much detail as possible, the nature of the emails you intend to send.
3. The volume of email that you plan to deliver on a daily/monthly basis.

We need to know this in order to make an informed decision regarding your account settings and resource limits to ensure the integrity of our network/systems/online reputation.

根据他提的123回复

https://example.com is my personal blog and forum,

I Will use wordpress and discourse software to do it ,but when my friends register on my web, server will send an e-mail to confirm it useing port 25 

volume of email ...1-10/day and 100/month maybe... 

等一会儿对方回复:


Thank you for the information provided!

We have removed the default SMTP block on your account. Please restart any active instances via https://my.vultr.com for the change to take effect (restarting via the server itself _will_not_ work).

Also, keep in mind that marketing and bulk email is restricted in our platform. For reference, our ANTI-SPAM policy is listed here: https://www.vultr.com/legal/antispam_policy.php


解锁完成,重启主机。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容