FILEEM

POWER OF DREAM

仅30分钟,在同一台设备安装discourse和wordpress

《仅30分钟,在同一台设备安装discourse和wordpress》

架设思想:使用国外服务器,将根域名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主机,如果你要用同样的话,可以顺便点下图,使用我的图片邀请链接注册,帮我贡献一个邀请任务,谢过:

《仅30分钟,在同一台设备安装discourse和wordpress》

对了,有个50美金的优惠券,不知道你看到的时候还有没有效:https://www.vultr.com/?ref=8152414-4F 这羊毛不薅白不薅。

《仅30分钟,在同一台设备安装discourse和wordpress》

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

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.com 和http://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

根据提示创建管理员账户

邮件转发

有时候服务器禁用了25端口,短期内也没法解决,比如DO要求服务器用60天以上才能开通。因此我们可以使用邮件转发的形式来解决。这里需要另外提供一台可以自助开通25端口的服务器,开通后,在discourse的邮件设置中填入另一台服务器的IP和端口,在那台服务器上监听此端口,再将请求转发到对应的邮件服务器。

和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

解锁完成,重启主机。

在配置中参考了以下文章:

https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-18-04

https://www.digitalocean.com/community/questions/need-help-with-installing-discourse-and-wordpress?comment=30922

https://www.digitalocean.com/community/tutorials/how-to-install-linux-nginx-mysql-php-lemp-stack-ubuntu-18-04

https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-lemp-on-ubuntu-18-04

https://meta.discoursecn.org/t/topic/1061

https://meta.discoursecn.org/t/%E4%B8%BA-Docker-%E5%AE%89%E8%A3%85%E7%9A%84-Discourse-%E5%A2%9E%E5%8A%A0-SSL-%E6%94%AF%E6%8C%81/63

https://meta.discoursecn.org/t/topic/26

https://meta.discoursecn.org/t/%E4%B8%BA-Linux-%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%AE%BE%E7%BD%AE-swap-%E6%96%87%E4%BB%B6/25

点赞