Skip to content

Commit

Permalink
add auto cert
Browse files Browse the repository at this point in the history
  • Loading branch information
goozp committed Oct 29, 2020
1 parent d6cefaa commit f4f82c5
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 78 deletions.
19 changes: 0 additions & 19 deletions .circleci/config.yml

This file was deleted.

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ logs/
# upload dir
uploads/*

configs/config.yaml
# config path
configs/
!configs/config.yaml.example

# the theme building path
puti-themes/
Expand Down
27 changes: 11 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
<a href="https://github.com/puti-projects/puti/actions?query=workflow%3Abuild">
<img src="https://github.com/puti-projects/puti/workflows/build/badge.svg" alt="Github Actions">
</a>
<a href="https://circleci.com/gh/puti-projects/puti">
<img src="https://circleci.com/gh/puti-projects/puti.svg?style=svg" alt="CircleCI">
</a>
<a href="https://codecov.io/gh/puti-projects/puti">
<img src="https://codecov.io/gh/puti-projects/puti/branch/master/graph/badge.svg" />
</a>
Expand All @@ -36,17 +33,14 @@

## 状态

Puti 项目现在仍在开发中。因为是作者接触 Go 语言的第一个项目,所以代码质量不到位之处,将会在未来不断优化。

**开始模块化重构,除了继续完善功能,还将重构一些已实现的功能。目标是面向极客的下一代写作系统。**
Puti 项目现在仍在开发中,目标是面向极客的下一代写作系统。

## 环境依赖

- Golang 1.13+ (Build using modules)
- MySQL
- Nginx (Optional)

本项目使用了 Go Modules,所以建议使用 Go 1.13 以上版本;Nginx 为可选配置
本项目使用了 Go Modules,所以建议使用 Go 1.13 以上版本;项目不依赖 Nginx 之类的 Web Server, 但是你可以配置并且使用 Nginx

## 功能与计划

Expand Down Expand Up @@ -85,7 +79,7 @@ Puti 项目现在仍在开发中。因为是作者接触 Go 语言的第一个
* [ ] 邮件服务配置
* [ ] TOC (目前在前端主题实现)
* [ ] 配置图片裁切
* [X] HTTPS
* [X] HTTPS(支持自动 HTTPS)
* [x] WebServer 转发
* [ ] 头像接入
* [ ] OAuth
Expand All @@ -104,17 +98,18 @@ Puti 项目现在仍在开发中。因为是作者接触 Go 语言的第一个

### 配置

Puti 的配置文件位于configs下的config.yaml,初次使用可以从config.yaml.example 初始化配置文件。
Puti 的配置文件位于 `configs` 下的 `config.yaml`,初次使用可以从 `config.yaml.example` 初始化配置文件。
需要注意的配置:

| 配置 | 说明 |
| :----- | :----- |
| addr | HTTP 端口 |
| jwt_secret | Json web token 秘钥 |
| tls.https_open | 开启 HTTPS |
| tls.addr | HTTPS 端口 |
| tls.cert | SSL证书路径 |
| tls.key | SSL私钥路径 |
| server.http_port | HTTP 端口 |
| server.https_open | 是否开启 HTTPS |
| server.auto_cert | 是否开启自动 HTTPS |
| server.https_port | HTTPS 端口 |
| server.tls_cert | 如果不是自动 HTTPS,配置 SSL 证书路径 |
| server.tls_key | 如果不是自动 HTTPS,配置 SSL 私钥路径 |
| safety.jwt_secret | Json web token 秘钥 |
| db.name | 数据库名称 |
| db.addr | 数据库 HOST:PORT |
| db.username | 数据库登录名 |
Expand Down
23 changes: 10 additions & 13 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
<a href="https://github.com/puti-projects/puti/actions?query=workflow%3Abuild">
<img src="https://github.com/puti-projects/puti/workflows/build/badge.svg" alt="Github Actions">
</a>
<a href="https://circleci.com/gh/puti-projects/puti">
<img src="https://circleci.com/gh/puti-projects/puti.svg?style=svg" alt="CircleCI">
</a>
<a href="https://codecov.io/gh/puti-projects/puti">
<img src="https://codecov.io/gh/puti-projects/puti/branch/master/graph/badge.svg" />
</a>
Expand All @@ -35,15 +32,14 @@

## Project Status

This project is still developing. Because it is the first project of the author to contact the Go language, the quality of the code is not in place and will be optimized in the future. Your contribution is very welcome. Also, for these terrible English translations, welcome to improve.
This project is still developing, and the goal is the next generation writing system for geeks.

## Environmental requirements

- Golang 1.13+ (Build using modules)
- MySQL
- Nginx (Optional)

This project uses Go Modules, so it is recommended to use Go 1.13 or above; Nginx is optional.
This project uses Go Modules, so it is recommended to use Go 1.13 or above; The project does not rely on Web Server such as Nginx, but you can configure and use Nginx.

## Features

Expand Down Expand Up @@ -82,7 +78,7 @@ The project plan implementation and the functions that have been implemented are
* [ ] Mail service configuration
* [ ] Toc support (not theme)
* [ ] Configure image cropping
* [X] HTTPS
* [X] HTTPS (Support automatic HTTPS)
* [x] WebService forwarding
* [ ] Avatar access
* [ ] OAuth
Expand All @@ -106,12 +102,13 @@ Configuration to be aware of:

| Configuration | Description |
| :----- | :----- |
| addr | HTTP Port |
| jwt_secret | Json web token secret key |
| tls.https_open | Open HTTPS |
| tls.addr | HTTPS Port |
| tls.cert | SSL certificate path |
| tls.key | SSL private key path |
| server.http_port | HTTP Port |
| server.https_open | Open HTTPS |
| server.auto_cert | Open auto cert |
| server.https_port | HTTPS Port |
| server.tls_cert | If it is not automatic cert,the SSL certificate path |
| server.tls_key | If it is not automatic cert,the SSL private key path |
| safety.jwt_secret | Json web token secret key |
| db.name | Database name |
| db.addr | Database HOST:PORT |
| db.username | Database user |
Expand Down
9 changes: 5 additions & 4 deletions configs/config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ server:
http_port: 8000 # HTTP 绑定端口
https_open: false # 是否开启 HTTPS
https_port: 8080 # HTTPS 绑定端口
tls_cert: configs/server.crt
tls_key: configs/server.key
ping_url: http://127.0.0.1:8000 # pingServer 函数请求的API服务器的 ip:port
ping_max_num: 10 # pingServer 函数 try 的次数
auto_cert: true # 是否开启自动 https
tls_cert: configs/server.crt # 如果不开启自动 https,配置的证书
tls_key: configs/server.key # 如果不开启自动 https,配置的证书
puti_domain: # puti 主应用绑定的域名;例如:example.com
- puti.com

# safety
safety:
Expand Down
6 changes: 6 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Changelog

## v0.3.1 Auto HTTPS

### 功能和优化
- 目录优化、CI 优化,代码质量检查
- 增加自动 HTTPS(autocert),优化配置
- 简化部署
- 移除 Circle-CI,Github Action 取代

### Bug 修复
- 修复 GORM v2 带来的兼容性问题
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
go.uber.org/zap v1.16.0
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gorm.io/driver/mysql v1.0.1
gorm.io/gorm v1.20.1
gorm.io/driver/mysql v1.0.3
gorm.io/gorm v1.20.5
)
11 changes: 9 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand Down Expand Up @@ -285,6 +287,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down Expand Up @@ -381,11 +384,15 @@ gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gorm.io/driver/mysql v1.0.1 h1:omJoilUzyrAp0xNoio88lGJCroGdIOen9hq2A/+3ifw=
gorm.io/driver/mysql v1.0.1/go.mod h1:KtqSthtg55lFp3S5kUXqlGaelnWpKitn4k1xZTnoiPw=
gorm.io/driver/mysql v1.0.3 h1:+JKBYPfn1tygR1/of/Fh2T8iwuVwzt+PEJmKaXzMQXg=
gorm.io/driver/mysql v1.0.3/go.mod h1:twGxftLBlFgNVNakL7F+P/x9oYqoymG3YYT8cAfI9oI=
gorm.io/gorm v1.9.19/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.20.0 h1:qfIlyaZvrF7kMWY3jBdEBXkXJ2M5MFYMTppjILxS3fQ=
gorm.io/gorm v1.20.0/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.20.1 h1:+hOwlHDqvqmBIMflemMVPLJH7tZYK4RxFDBHEfJTup0=
gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.20.4 h1:fMFR+3bdgx2/vf6VXFgNcsjUL3kSD7ioOFvby3PYTgE=
gorm.io/gorm v1.20.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.20.5 h1:g3tpSF9kggASzReK+Z3dYei1IJODLqNUbOjSuCczY8g=
gorm.io/gorm v1.20.5/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
5 changes: 3 additions & 2 deletions internal/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ func InitConfig(cfg string) error {
}

c := &Config{vp}
c.readConfig()
if err := c.readConfig(); err != nil {
return err
}
c.watchConfigChange()

return nil
}

Expand Down
18 changes: 9 additions & 9 deletions internal/pkg/config/section.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package config

type ServerConfig struct {
Runmode string `mapstructure:"runmode"`
Name string `mapstructure:"name"`
HttpPort string `mapstructure:"http_port"`
HttpsOpen bool `mapstructure:"https_open"`
HttpsPort string `mapstructure:"https_port"`
TlsCert string `mapstructure:"tls_cert"`
TlsKey string `mapstructure:"tls_key"`
PingUrl string `mapstructure:"ping_url"`
PingMaxNum int `mapstructure:"ping_max_num"`
Runmode string `mapstructure:"runmode"`
Name string `mapstructure:"name"`
HttpPort string `mapstructure:"http_port"`
HttpsOpen bool `mapstructure:"https_open"`
HttpsPort string `mapstructure:"https_port"`
AutoCert bool `mapstructure:"auto_cert"`
TlsCert string `mapstructure:"tls_cert"`
TlsKey string `mapstructure:"tls_key"`
PutiDomain []string `mapstructure:"puti_domain"`
}

type SafetyConfig struct {
Expand Down
53 changes: 44 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/spf13/pflag"
"go.uber.org/zap"
"golang.org/x/crypto/acme/autocert"
)

var (
Expand Down Expand Up @@ -110,6 +111,7 @@ func httpServe(router *gin.Engine) {
signalHandle(srv)
}

// httpHandle handle HTTP
func httpHandle(router *gin.Engine) *http.Server {
srv := &http.Server{
Addr: ":" + config.Server.HttpPort,
Expand All @@ -126,26 +128,51 @@ func httpHandle(router *gin.Engine) *http.Server {
return srv
}

// httpsHandle handle HTTPS; there are two situation
// Situation 1. Open auto cert.
// Situation 2. Specify certification path.
func httpsHandle(router *gin.Engine) *http.Server {
if config.Server.TlsCert == "" || config.Server.TlsKey == "" {
logger.Errorf("https opened but cert and key can not be empty, failed to listen https port")
}

srv := &http.Server{
Addr: ":" + config.Server.HttpsPort,
Handler: router,
}

if config.Server.AutoCert {
// Open auto cert
// auto cert manager
m := &autocert.Manager{
Cache: autocert.DirCache(config.StaticPath("configs/")),
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist(config.Server.PutiDomain...),
}
// set auto cert config to tls config
srv.TLSConfig = m.TLSConfig()

// Listen and serve
serveTLS(srv, "", "")
} else {
// Specify certification path
if config.Server.TlsCert == "" || config.Server.TlsKey == "" {
logger.Errorf("https opened but cert and key can not be empty, failed to listen https port")
}

// Listen and serve
serveTLS(srv, config.Server.TlsCert, config.Server.TlsKey)
}
return srv
}

// serveTLS serve https for all situation
func serveTLS(srv *http.Server, certFile string, keyFile string) {
go func() {
logger.Info("start to listening the incoming https requests", zap.String("port", config.Server.HttpsPort))
if err := srv.ListenAndServeTLS(config.Server.TlsCert, config.Server.TlsKey); err != nil && err != http.ErrServerClosed {
if err := srv.ListenAndServeTLS(certFile, keyFile); err != nil && err != http.ErrServerClosed {
logger.Fatalf("server.ListenAndServeTLS err: %v", err)
}
}()

return srv
}

// signalHandle graceful shutdown based on http.server.Shutdown
func signalHandle(srv *http.Server) {
quit := make(chan os.Signal)
// receive syscall.SIGINT and syscall.SIGTERM signal
Expand All @@ -165,10 +192,18 @@ func signalHandle(srv *http.Server) {

// pingServer pings the http server to make sure the service is working.
func pingServer() error {
for i := 0; i < config.Server.PingMaxNum; i++ {
var pingURL string
if true == config.Server.HttpsOpen {
pingURL = "https://127.0.0.1:" + config.Server.HttpsPort + "/check/health"
} else {
pingURL = "http://127.0.0.1:" + config.Server.HttpPort + "/check/health"
}

for i := 0; i < 10; i++ {
// Ping the server by sending a GET request to `/health`.
resp, err := http.Get(config.Server.PingUrl + "/check/health")
resp, err := http.Get(pingURL)
if err == nil && resp.StatusCode == 200 {
logger.Info("the health check has been completed and the HTTP service is normal.", zap.String("ping url", pingURL))
return nil
}

Expand Down

0 comments on commit f4f82c5

Please sign in to comment.